CSI Compression and Reconstruction using CSINet for TDD Massive MIMO 5G Networks
Import Libraries
Import Python Libraries
[1]:
# %matplotlib widget
import matplotlib.pyplot as plt
import matplotlib as mpl
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import numpy as np
# from IPython.display import display, HTML
# display(HTML("<style>.container { width:80% !important; }</style>"))
Import 5G Toolkit Libraries
[2]:
from csiNet import CSINet
import sys
sys.path.append("../../")
from toolkit5G.PhysicalChannels.PDSCH import ComputeTransportBlockSize
from toolkit5G.PhysicalChannels import PDSCHLowerPhy, PDSCHUpperPhy, PDSCHDecoderLowerPhy, PDSCHDecoderUpperPhy
from toolkit5G.ChannelModels import AntennaArrays, SimulationLayout, ParameterGenerator, ChannelGenerator
from toolkit5G.Configurations import PDSCHLowerPhyConfiguration, PDSCHUpperPhyConfiguration
from toolkit5G.ChannelProcessing import AddNoise, ApplyChannel
from toolkit5G.SymbolMapping import Mapper, Demapper
Simulation Parameters
[3]:
# Carrier Frequency
carrierFrequency = 3.6*10**9
delaySpread = 100*(10**-9)
numBatches = 200 # Number of batches considered for simulation
scs = 30*10**3 # Subcarrier Spacing for simulation
numBSs = 1 # Number of BSs considered for simulation
# Number of UEs considered for simulation
numUEs = numBatches # For now we are assuming that the numbatches are captured via numUEs
numRB = 85 # Number of Resource mapping considered for simulation | # 1 RB = 12 subcarrier
slotNumber = int(np.random.randint(0,2**(scs/15000)*10)) # Index of the slot considered for simulation
terrain = "CDL-A" # Terrain
txAntStruture = np.array([1,1,32,1,1]) # Tx Antenna Structure
rxAntStruture = np.array([1,1,4,1,1]) # Tx Antenna Structure
Nfft = 1024 # FFTSize
print("************ Simulation Parameters *************")
print()
print(" numBatches: "+str(numBatches))
print(" numRB: "+str(numRB))
print(" fft Size: "+str(Nfft))
print(" numBSs: "+str(numBSs))
print(" numUEs: "+str(numUEs))
print(" scs: "+str(scs))
print(" slotNumber: "+str(slotNumber))
print(" terrain: "+str(terrain))
print("Tx Ant Struture: "+str(txAntStruture))
print("Rx Ant Struture: "+str(rxAntStruture))
print()
print("********************************************")
************ Simulation Parameters *************
numBatches: 200
numRB: 85
fft Size: 1024
numBSs: 1
numUEs: 200
scs: 30000
slotNumber: 0
terrain: CDL-A
Tx Ant Struture: [ 1 1 32 1 1]
Rx Ant Struture: [1 1 4 1 1]
********************************************
Wireless Channel Generation: CDL-A
[4]:
# Antenna Array at UE side
# assuming antenna element type to be "OMNI"
# with 2 panel and 2 single polarized antenna element per panel.
ueAntArray = AntennaArrays(antennaType = "OMNI", centerFrequency = carrierFrequency,
arrayStructure = rxAntStruture)
ueAntArray()
# # Radiation Pattern of Rx antenna element
# ueAntArray.displayAntennaRadiationPattern()
# Antenna Array at BS side
# assuming antenna element type to be "3GPP_38.901", a parabolic antenna
# with 4 panel and 4 single polarized antenna element per panel.
bsAntArray = AntennaArrays(antennaType = "3GPP_38.901", centerFrequency = carrierFrequency,
arrayStructure = txAntStruture)
bsAntArray()
# # Radiation Pattern of Tx antenna element
# bsAntArray[0].displayAntennaRadiationPattern()
# Layout Parameters
isd = 100 # inter site distance
minDist = 10 # min distance between each UE and BS
ueHt = 1.5 # UE height
bsHt = 25 # BS height
bslayoutType = "Hexagonal" # BS layout type
ueDropType = "Hexagonal" # UE drop type
htDist = "equal" # UE height distribution
ueDist = "equal" # UE Distribution per site
nSectorsPerSite = 1 # number of sectors per site
maxNumFloors = 1 # Max number of floors in an indoor object
minNumFloors = 1 # Min number of floors in an indoor object
heightOfRoom = 3 # height of room or ceiling in meters
indoorUEfract = 0.5 # Fraction of UEs located indoor
lengthOfIndoorObject = 3 # length of indoor object typically having rectangular geometry
widthOfIndoorObject = 3 # width of indoor object
# forceLOS = True # boolen flag if true forces every link to be in LOS state
forceLOS = False # boolen flag if true forces every link to be in LOS state
# simulation layout object
simLayoutObj = SimulationLayout(numOfBS = numBSs,
numOfUE = numUEs,
heightOfBS = bsHt,
heightOfUE = ueHt,
ISD = isd,
layoutType = bslayoutType,
ueDropMethod = ueDropType,
UEdistibution = ueDist,
UEheightDistribution = htDist,
numOfSectorsPerSite = nSectorsPerSite,
ueRoute = None)
simLayoutObj(terrain = terrain,
carrierFreq = carrierFrequency,
ueAntennaArray = ueAntArray,
bsAntennaArray = bsAntArray,
indoorUEfraction = indoorUEfract,
lengthOfIndoorObject = lengthOfIndoorObject,
widthOfIndoorObject = widthOfIndoorObject,
forceLOS = forceLOS)
# displaying the topology of simulation layout
fig, ax = simLayoutObj.display2DTopology()
paramGen = simLayoutObj.getParameterGenerator(delaySpread = delaySpread)
# paramGen.displayClusters((0,0,0), rayIndex = 0)
channel = paramGen.getChannel()
Hf = channel.ofdm(scs, Nfft, normalizeChannel = True)
Nt = bsAntArray.numAntennas # Number of BS Antennas
Nr = ueAntArray.numAntennas
print(" Number of BSs: "+str(numBSs))
print(" Shape of Channel: "+str(Hf.shape))
print("*****************************************************")
print()

Number of BSs: 1
Shape of Channel: (1, 1, 1, 200, 1024, 4, 32)
*****************************************************
Reconstrunction Performance of CSI-Net
[5]:
numSubcarrier = 32
codewordSize = 512
H = Hf[0,0,0,...,0,:].transpose(0,2,1)
csinet = CSINet()
model = csinet(Nt, numSubcarrier, codewordSize)
csinet.loadModel()
Hprep = csinet.preprocess(H)
Hrec = csinet.predict(Hprep)
Hest = csinet.postprocess(Hprep, Nfft)
7/7 [==============================] - 0s 7ms/step
[6]:
numChannels = 5
fig, ax = plt.subplots(2,numChannels, figsize = (12, 5))
idx = np.random.choice(np.arange(numBatches), size=numChannels, replace = False)
print(idx)
for n in range(numChannels):
ax[0,n].imshow(np.abs(Hprep[idx[n],0])**2 + np.abs(Hprep[idx[n],1])**2, cmap = "Greys", aspect = "auto")
ax[1,n].imshow(np.abs( Hrec[idx[n],0])**2 + np.abs( Hrec[idx[n],1])**2, cmap = "Greys", aspect = "auto")
plt.show()
[153 134 179 124 21]

[7]:
print("NMSE: "+str(np.sqrt(np.mean(np.abs(Hest-H)**2/(np.abs(H))**2))))
NMSE: 0.20250736648608653
PDSCH Parameters
[8]:
########################################## PDSCH Lower Physical Layer Parameters #########################################
pdschLowerPhyConfig = PDSCHLowerPhyConfiguration(rank = 1, startSymbol=2, numSymbols=12, pdschMappingType = "PDSCH-mapping-type-A",
maxLength = "len1", dmrsAdditionalPosition = "pos0", l0 = 0,
configurationType = "Configuration-type-1")
pdschMappingType = pdschLowerPhyConfig.pdschMappingType # "PDSCH mapping type A" or "PDSCH mapping type B"
maxLength = pdschLowerPhyConfig.maxLength
startSymbol = pdschLowerPhyConfig.startSymbol
numSymbols = pdschLowerPhyConfig.numSymbols
betaDMRS = pdschLowerPhyConfig.betaDMRS
configurationType = pdschLowerPhyConfig.configurationType # "Configuration-type-1" or "Configuration-type-2"
dmrsTypeAPosition = pdschLowerPhyConfig.dmrsTypeAPosition # "pos2" or "pos3"
dmrsAdditionalPosition = pdschLowerPhyConfig.dmrsAdditionalPosition # "pos2" or "pos3"
ld = pdschLowerPhyConfig.ld
l0 = pdschLowerPhyConfig.l0
l1 = pdschLowerPhyConfig.l1
rank = pdschLowerPhyConfig.rank
scramblingID = pdschLowerPhyConfig.scramblingID
nSCID = pdschLowerPhyConfig.nSCID
mcsIndex = 3
mcsTable = "pdschTable1"
########################################## PDSCH Parameters #########################################
pdschUpperPhyConfig = PDSCHUpperPhyConfiguration(pdschMappingType = pdschMappingType, configurationType = configurationType,
dmrsTypeAPosition = dmrsTypeAPosition, maxLength = maxLength, mcsIndex = mcsIndex,
mcsTable = mcsTable, dmrsAdditionalPosition = dmrsAdditionalPosition, l0 = l0,
ld = ld, l1 = l1, startSymbol = startSymbol, numSymbols = numSymbols, rank = rank,
numRB = numRB)
numTBs = pdschUpperPhyConfig.numTBs
numRB = pdschUpperPhyConfig.numRB
tbLen1 = pdschUpperPhyConfig.tbLen1
codeRate = pdschUpperPhyConfig.codeRate
modOrder = pdschUpperPhyConfig.modOrder
mcsIndex = pdschUpperPhyConfig.mcsIndex
mcsTable = pdschUpperPhyConfig.mcsTable
numlayers = pdschUpperPhyConfig.numlayers
scalingField = pdschUpperPhyConfig.scalingField
additionalOverhead = pdschUpperPhyConfig.additionalOverhead
dmrsREs = pdschUpperPhyConfig.dmrsREs
additionalOverhead = pdschUpperPhyConfig.additionalOverhead
numTargetBits1 = pdschUpperPhyConfig.numTargetBits1
if(numTBs == 2):
numTargetBits1 = pdschUpperPhyConfig.numTargetBits1
numTargetBits2 = pdschUpperPhyConfig.numTargetBits2
tbLen2 = pdschUpperPhyConfig.tbLen2
numTargetBits = pdschUpperPhyConfig.numTargetBits
************ PDSCH Parameters *************
pdschMappingType: PDSCH-mapping-type-A
startSymbol: 2
numSymbols: 12
betaDMRS: 1
rank: 1
configurationType: Configuration-type-1
maxLength: len1
dmrsTypeAPosition: pos2
dmrsAdditionalPosition: pos0
Duration, ld: 12
Start symbol, l0: 0
Start symbol-1, l1: 11
num of Layers: 1
********************************************
********************************************
tbsize-1: 5768
numTBs: 1
numCBs: 2
numLayers: 1 | LayerperTB: [1 0]
numRB: 85
coderate: 0.2451171875
modOrder: 2
additionalOverhead: 0
numberTargetBits: 23460
********************************************
PDSCH: Transmitter
[9]:
pdschUpperPhy = PDSCHUpperPhy(symbolsPerSlot = numSymbols, numRB = numRB, mcsIndex = mcsIndex,
numlayers = numlayers, scalingField = scalingField,
additionalOverhead = additionalOverhead, dmrsREs = dmrsREs,
numTBs=numTBs, pdschTable = mcsTable, verbose = False)
codeword = pdschUpperPhy(tblock = [None, None], rvid = [0, 0], enableLBRM = [False, False],
numBatch = numBatches, numBSs = numBSs)
rnti = np.random.randint(65536, size=numBSs*numBatches)
nID = np.random.randint(1024, size=numBSs*numBatches)
bits2 = codeword[1] if numTBs == 2 else None
pdschLowerPhyChain = PDSCHLowerPhy(pdschMappingType, configurationType, dmrsTypeAPosition,
maxLength, dmrsAdditionalPosition, l0, ld, l1)
resourceGrid = pdschLowerPhyChain(codeword[0], numRB, rank, slotNumber, scramblingID,
nSCID, rnti, nID, modOrder, startSymbol, bits2 = bits2)
## Load the resource Grid into the transmision Grid
txGrid = np.zeros(resourceGrid.shape[0:-1]+(Nfft,), dtype= np.complex64)
bwpOffset = np.random.randint(Nfft-numRB*12)
txGrid[...,bwpOffset:bwpOffset+numRB*12] = resourceGrid
fig, ax = pdschLowerPhyChain.displayDMRSGrid()
pdschLowerPhyChain.displayResourceGrid()

[9]:
(<Figure size 640x480 with 1 Axes>,
<Axes: xlabel='OFDM Symbol-Index', ylabel='Subcarrier-Index'>)

[10]:
fig, ax = plt.subplots(1,2)
ax[0].plot(np.abs(Hf[0,0,0,0,:,0,5]))
ax[0].grid()
ax[1].plot(np.abs(Hf[0,0,0,0,:,0,3]))
ax[1].grid()
plt.show()

SVD Based Beamforming: Perfect CSI
[11]:
# Digital Beamforming
[U, S, Vh] = np.linalg.svd(Hf)
precoder = np.conj(Vh.transpose(3,0,1,2,4,6,5)[...,0:rank])
combiner = np.conj((U*(1/S[...,np.newaxis,:].repeat(S.shape[-1], axis = -2)))[...,0:rank].transpose(3,0,1,2,4,6,5))
xBeam = (precoder@txGrid.transpose(0,1,3,4,2)[:,np.newaxis,...,np.newaxis])[...,0]
print("************ Beamforming Parameters *************")
print()
print(" Precoder Shape: "+str(precoder.shape))
print(" Combiner Shape: "+str(combiner.shape))
print(" Channel Shape: "+str(Hf.shape))
print("Eigen Matrix Shape: "+str(S.shape))
print("Beamformed Grid sh: "+str(xBeam.shape))
print()
print("********************************************")
************ Beamforming Parameters *************
Precoder Shape: (200, 1, 1, 1, 1024, 32, 1)
Combiner Shape: (200, 1, 1, 1, 1024, 1, 4)
Channel Shape: (1, 1, 1, 200, 1024, 4, 32)
Eigen Matrix Shape: (1, 1, 1, 200, 1024, 4)
Beamformed Grid sh: (200, 1, 1, 14, 1024, 32)
********************************************
Pass through Channel
[12]:
# Channel Dimensions: numBatches, numFrequencies, numSymbols(numSnapshots), numBSs, numUEs, numSamples/numFFTpoints, numRxAntennas, numTxAntennas
# Tx-Grid Dimensions: numBatches, numFrequencies, numSymbols(numSnapshots), numBSs, numSamples/numFFTpoints, numTxAntennas
# Rx-Grid Dimensions: numBatches, numFrequencies, numSymbols(numSnapshots), -- numUEs, numSamples/numFFTpoints, numRxAntennas
ptc = ApplyChannel(isFrequencyDomain = True, enableInterTxInterference = True, memoryConsumptionLevel = 0)
y = ptc(Hf[np.newaxis].transpose(4,0,1,2,3,5,6,7), xBeam.transpose(0,1,3,2,4,5))
print("************ Channel Parameters *************")
print()
print(" Channel Shape: "+str(Hf.shape))
print("Received Grid shape: "+str(y.shape))
print(" Beamformed Grid sh: "+str(xBeam.shape))
print()
print("********************************************")
************ Channel Parameters *************
Channel Shape: (1, 1, 1, 200, 1024, 4, 32)
Received Grid shape: (200, 1, 14, 1, 1024, 4)
Beamformed Grid sh: (200, 1, 1, 14, 1024, 32)
********************************************
Link Level Simulation: SVD based Beamforming using Perfect CSI
[13]:
numPoints = 10
SNRdB = np.linspace(-10.5, -5, numPoints, endpoint=True)
# SNRdB = np.linspace(-13.5, -7.5, numPoints, endpoint=True)
SNR = 10**(SNRdB/10)
codedBER = np.zeros(numPoints)
uncodedBER = np.zeros(numPoints)
bler = np.zeros(numPoints)
throughput = np.zeros(numPoints)
for i in range(numPoints):
print("********************************************************")
print("Simulation: ["+str(i)+"] for SNRdB = "+str(SNRdB[i]))
## Add noise to the received grid
yGrid = AddNoise(False)(y, 1/SNR[i], 0)
## Receiver Combining
rGrid = ((combiner@yGrid[...,np.newaxis])[:,0,...,0]).transpose(0,2,4,1,3)
## Extracting the Received Grid
rxGrid = rGrid[...,bwpOffset:bwpOffset+12*numRB]
## Receiver: Lower Physical layer
isChannelPerfect = False
pdschDecLowerPhy = PDSCHDecoderLowerPhy(modOrder, isChannelPerfect, isEqualized = True)
descrBits = pdschDecLowerPhy(rxGrid, pdschLowerPhyChain.pdschIndices, rnti,
nID, SNR[i], None, numTBs, hard_out = False)
## Receiver: Upper Physical layer
pdschUpPhyDec = PDSCHDecoderUpperPhy(numTBs = numTBs, mcsIndex = mcsIndex, symbolsPerSlot= numSymbols,
numRB = numRB, numLayers = numlayers, scalingField = scalingField,
additionalOverhead = additionalOverhead, dmrsREs = dmrsREs,
enableLBRM = [False, False], pdschTable = mcsTable, rvid = [0, 0], verbose=False)
bits = pdschUpPhyDec(descrBits)
## KPI computation
codedBER[i] = np.mean(np.abs(bits-pdschUpperPhy.tblock1))
uncodedBER[i] = np.mean(np.abs(codeword[0] - np.where(descrBits[0]>0,1,0)))
bler[i] = 1-np.mean(pdschUpPhyDec.crcCheckforCBs)
throughput[i] = (1-bler[i])*tbLen1*2000
print("Simulation: ["+str(i)+"] for codedBER = "+str(codedBER[i]))
print("Simulation: ["+str(i)+"] for uncodedBER = "+str(uncodedBER[i]))
print("Simulation: ["+str(i)+"] for BLER = "+str(bler[i]))
print("Simulation: ["+str(i)+"] for Throughput = "+str(throughput[i]))
print("********************************************************")
print()
********************************************************
Simulation: [0] for SNRdB = -10.5
Simulation: [0] for codedBER = 0.003271497919556172
Simulation: [0] for uncodedBER = 0.004089940323955669
Simulation: [0] for BLER = 1.0
Simulation: [0] for Throughput = 0.0
********************************************************
********************************************************
Simulation: [1] for SNRdB = -9.88888888888889
Simulation: [1] for codedBER = 0.0019166088765603328
Simulation: [1] for uncodedBER = 0.002438832054560955
Simulation: [1] for BLER = 1.0
Simulation: [1] for Throughput = 0.0
********************************************************
********************************************************
Simulation: [2] for SNRdB = -9.277777777777779
Simulation: [2] for codedBER = 0.0011243065187239944
Simulation: [2] for uncodedBER = 0.001499147485080989
Simulation: [2] for BLER = 0.955
Simulation: [2] for Throughput = 519120.00000000047
********************************************************
********************************************************
Simulation: [3] for SNRdB = -8.666666666666666
Simulation: [3] for codedBER = 0.0005989944521497919
Simulation: [3] for uncodedBER = 0.0008077578857630008
Simulation: [3] for BLER = 0.8425
Simulation: [3] for Throughput = 1816919.9999999995
********************************************************
********************************************************
Simulation: [4] for SNRdB = -8.055555555555555
Simulation: [4] for codedBER = 0.0002869278779472954
Simulation: [4] for uncodedBER = 0.00043350383631713557
Simulation: [4] for BLER = 0.5549999999999999
Simulation: [4] for Throughput = 5133520.0
********************************************************
********************************************************
Simulation: [5] for SNRdB = -7.444444444444445
Simulation: [5] for codedBER = 0.00013262829403606102
Simulation: [5] for uncodedBER = 0.00022953964194373402
Simulation: [5] for BLER = 0.3125
Simulation: [5] for Throughput = 7931000.0
********************************************************
********************************************************
Simulation: [6] for SNRdB = -6.833333333333333
Simulation: [6] for codedBER = 7.628294036061026e-05
Simulation: [6] for uncodedBER = 0.00012510656436487638
Simulation: [6] for BLER = 0.19499999999999995
Simulation: [6] for Throughput = 9286480.000000002
********************************************************
********************************************************
Simulation: [7] for SNRdB = -6.222222222222221
Simulation: [7] for codedBER = 2.340499306518724e-05
Simulation: [7] for uncodedBER = 6.457800511508951e-05
Simulation: [7] for BLER = 0.06499999999999995
Simulation: [7] for Throughput = 10786160.0
********************************************************
********************************************************
Simulation: [8] for SNRdB = -5.611111111111111
Simulation: [8] for codedBER = 0.0
Simulation: [8] for uncodedBER = 3.836317135549872e-05
Simulation: [8] for BLER = 0.0
Simulation: [8] for Throughput = 11536000.0
********************************************************
********************************************************
Simulation: [9] for SNRdB = -5.0
Simulation: [9] for codedBER = 0.0
Simulation: [9] for uncodedBER = 2.3231031543052003e-05
Simulation: [9] for BLER = 0.0
Simulation: [9] for Throughput = 11536000.0
********************************************************
SVD Based Beamforming: CSI Reconstructed using CSINet
[14]:
# Digital Beamforming
shape = Hf[0,0,0].shape
Hest = np.zeros((shape[0], shape[2], shape[3], shape[1]), dtype = np.complex64)
for nr in range(Nr):
H = Hf[0,0,0,...,nr,:].transpose(0,2,1)
Hprep = csinet.preprocess(H)
Hrec = csinet.predict(Hprep)
Hest[:,nr] = csinet.postprocess(Hprep, Nfft)
[U, S, Vh] = np.linalg.svd(Hest.transpose(0,3,1,2)[np.newaxis, np.newaxis,np.newaxis])
precoder = np.conj(Vh.transpose(3,0,1,2,4,6,5)[...,0:rank])
combiner = np.conj((U*(1/S[...,np.newaxis,:].repeat(S.shape[-1], axis = -2)))[...,0:rank].transpose(3,0,1,2,4,6,5))
xBeam = (precoder@txGrid.transpose(0,1,3,4,2)[:,np.newaxis,...,np.newaxis])[...,0]
print("************ Beamforming Parameters *************")
print()
print(" Precoder Shape: "+str(precoder.shape))
print(" Combiner Shape: "+str(combiner.shape))
print(" Channel Shape: "+str(Hf.shape))
print("Eigen Matrix Shape: "+str(S.shape))
print("Beamformed Grid sh: "+str(xBeam.shape))
print()
print("********************************************")
7/7 [==============================] - 0s 6ms/step
7/7 [==============================] - 0s 6ms/step
7/7 [==============================] - 0s 7ms/step
7/7 [==============================] - 0s 6ms/step
************ Beamforming Parameters *************
Precoder Shape: (200, 1, 1, 1, 1024, 32, 1)
Combiner Shape: (200, 1, 1, 1, 1024, 1, 4)
Channel Shape: (1, 1, 1, 200, 1024, 4, 32)
Eigen Matrix Shape: (1, 1, 1, 200, 1024, 4)
Beamformed Grid sh: (200, 1, 1, 14, 1024, 32)
********************************************
Pass through Wireless Channel
[15]:
# Channel Dimensions: numBatches, numFrequencies, numSymbols(numSnapshots), numBSs, numUEs, numSamples/numFFTpoints, numRxAntennas, numTxAntennas
# Tx-Grid Dimensions: numBatches, numFrequencies, numSymbols(numSnapshots), numBSs, numSamples/numFFTpoints, numTxAntennas
# Rx-Grid Dimensions: numBatches, numFrequencies, numSymbols(numSnapshots), -- numUEs, numSamples/numFFTpoints, numRxAntennas
ptc = ApplyChannel(isFrequencyDomain = True, enableInterTxInterference = True, memoryConsumptionLevel = 0)
y = ptc(Hf[np.newaxis].transpose(4,0,1,2,3,5,6,7), xBeam.transpose(0,1,3,2,4,5))
print("************ Channel Parameters *************")
print()
print(" Channel Shape: "+str(Hf.shape))
print("Received Grid shape: "+str(y.shape))
print(" Beamformed Grid sh: "+str(xBeam.shape))
print()
print("********************************************")
************ Channel Parameters *************
Channel Shape: (1, 1, 1, 200, 1024, 4, 32)
Received Grid shape: (200, 1, 14, 1, 1024, 4)
Beamformed Grid sh: (200, 1, 1, 14, 1024, 32)
********************************************
Link Level Simulation: SVD based Beamforming using Imperfect CSI
[16]:
numPoints = 10
SNRdB2 = np.linspace(-10, -5.35, numPoints, endpoint=True)
# SNRdB = np.linspace(-13.5, -7.5, numPoints, endpoint=True)
SNR2 = 10**(SNRdB2/10)
codedBER2 = np.zeros(numPoints)
uncodedBER2 = np.zeros(numPoints)
bler2 = np.zeros(numPoints)
throughput2 = np.zeros(numPoints)
for i in range(numPoints):
print("********************************************************")
print("Simulation: ["+str(i)+"] for SNRdB = "+str(SNRdB2[i]))
## Add noise to the received grid
yGrid = AddNoise(False)(y, 1/SNR2[i], 0)
## Receiver Combining
rGrid = ((combiner@yGrid[...,np.newaxis])[:,0,...,0]).transpose(0,2,4,1,3)
## Extracting the Received Grid
rxGrid = rGrid[...,bwpOffset:bwpOffset+12*numRB]
## Receiver: Lower Physical layer
isChannelPerfect = False
pdschDecLowerPhy = PDSCHDecoderLowerPhy(modOrder, isChannelPerfect, isEqualized = True)
descrBits = pdschDecLowerPhy(rxGrid, pdschLowerPhyChain.pdschIndices, rnti,
nID, SNR2[i], None, numTBs, hard_out = False)
## Receiver: Upper Physical layer
pdschUpPhyDec = PDSCHDecoderUpperPhy(numTBs = numTBs, mcsIndex = mcsIndex, symbolsPerSlot= numSymbols,
numRB = numRB, numLayers = numlayers, scalingField = scalingField,
additionalOverhead = additionalOverhead, dmrsREs = dmrsREs,
enableLBRM = [False, False], pdschTable = mcsTable, rvid = [0, 0], verbose=False)
bits = pdschUpPhyDec(descrBits)
## KPI computation
codedBER2[i] = np.mean(np.abs(bits-pdschUpperPhy.tblock1))
uncodedBER2[i] = np.mean(np.abs(codeword[0] - np.where(descrBits[0]>0,1,0)))
bler2[i] = 1 - np.mean(pdschUpPhyDec.crcCheckforCBs)
throughput2[i] = (1-bler2[i])*tbLen1*2000
print("Simulation: ["+str(i)+"] for codedBER = "+str(codedBER2[i]))
print("Simulation: ["+str(i)+"] for uncodedBER = "+str(uncodedBER2[i]))
print("Simulation: ["+str(i)+"] for BLER = "+str(bler2[i]))
print("Simulation: ["+str(i)+"] for Throughput = "+str(throughput2[i]))
print("********************************************************")
print()
********************************************************
Simulation: [0] for SNRdB = -10.0
Simulation: [0] for codedBER = 0.002643030513176144
Simulation: [0] for uncodedBER = 0.0033248081841432226
Simulation: [0] for BLER = 1.0
Simulation: [0] for Throughput = 0.0
********************************************************
********************************************************
Simulation: [1] for SNRdB = -9.483333333333333
Simulation: [1] for codedBER = 0.0017995839112343967
Simulation: [1] for uncodedBER = 0.002294543904518329
Simulation: [1] for BLER = 0.99
Simulation: [1] for Throughput = 115360.0000000001
********************************************************
********************************************************
Simulation: [2] for SNRdB = -8.966666666666667
Simulation: [2] for codedBER = 0.0012274618585298197
Simulation: [2] for uncodedBER = 0.001603154305200341
Simulation: [2] for BLER = 0.975
Simulation: [2] for Throughput = 288400.00000000023
********************************************************
********************************************************
Simulation: [3] for SNRdB = -8.45
Simulation: [3] for codedBER = 0.0008538488210818308
Simulation: [3] for uncodedBER = 0.0011327791986359761
Simulation: [3] for BLER = 0.9125
Simulation: [3] for Throughput = 1009400.0000000002
********************************************************
********************************************************
Simulation: [4] for SNRdB = -7.933333333333334
Simulation: [4] for codedBER = 0.0005799237170596394
Simulation: [4] for uncodedBER = 0.0008459079283887468
Simulation: [4] for BLER = 0.8325
Simulation: [4] for Throughput = 1932279.9999999998
********************************************************
********************************************************
Simulation: [5] for SNRdB = -7.416666666666666
Simulation: [5] for codedBER = 0.0004342926490984743
Simulation: [5] for uncodedBER = 0.0006432225063938619
Simulation: [5] for BLER = 0.7224999999999999
Simulation: [5] for Throughput = 3201240.000000001
********************************************************
********************************************************
Simulation: [6] for SNRdB = -6.8999999999999995
Simulation: [6] for codedBER = 0.00031206657420249653
Simulation: [6] for uncodedBER = 0.0005051150895140665
Simulation: [6] for BLER = 0.6074999999999999
Simulation: [6] for Throughput = 4527880.000000001
********************************************************
********************************************************
Simulation: [7] for SNRdB = -6.383333333333333
Simulation: [7] for codedBER = 0.00022798196948682387
Simulation: [7] for uncodedBER = 0.0004360613810741688
Simulation: [7] for BLER = 0.48750000000000004
Simulation: [7] for Throughput = 5912200.0
********************************************************
********************************************************
Simulation: [8] for SNRdB = -5.866666666666666
Simulation: [8] for codedBER = 6.934812760055479e-06
Simulation: [8] for uncodedBER = 0.0003923699914748508
Simulation: [8] for BLER = 0.020000000000000018
Simulation: [8] for Throughput = 11305280.0
********************************************************
********************************************************
Simulation: [9] for SNRdB = -5.35
Simulation: [9] for codedBER = 0.0
Simulation: [9] for uncodedBER = 0.0003610400682011935
Simulation: [9] for BLER = 0.0
Simulation: [9] for Throughput = 11536000.0
********************************************************
[17]:
np.mean(pdschUpPhyDec.crcCheckforCBs)
[17]:
1.0
Performance Evaluations
Throughput Evaluations
[18]:
fig, ax = plt.subplots()
ax.semilogy(SNRdB, throughput, "b", marker = "*", lw = 3, mec = "k", mfc = "r", ms = 12, label="Throughput [Perfect-CSI]")
ax.semilogy(SNRdB2, throughput2, "--r", marker = "o", lw = 3, mec = "w", mfc = "r", ms = 9, label="Throughput [CSINet]")
ax.set_xlabel("Signal to Noise Ratio (dB)")
ax.set_ylabel("Throughput (bits per second)")
ax.set_title("Data-rate Evaluation: SNR (dB) vs Throughput", fontsize = 16)
ax.legend(loc="best")
ax.set_xticks(SNRdB2, minor=False)
ax.xaxis.set_major_formatter(mpl.ticker.FormatStrFormatter('%.2f'))
ytck = 10**(np.arange(2, 9)).repeat(10)*np.tile(np.arange(1, 11), [7])
ax.set_yticks(ytck, minor=True)
ax.set_yticks(10**(np.arange(2, 8)), minor=False)
ax.set_ylim([10**2, 10**8])
# ax.set_xlim([0.999*SNRdB[0], 1.05*SNRdB[-1]])
ax.grid(which = 'minor', alpha = 0.5, linestyle = '--')
ax.grid(which = 'major', alpha = 0.65, color = "k")
plt.show()

BLER Evaluations
[19]:
fig, ax = plt.subplots()
ax.semilogy(SNRdB, bler, "g", marker = "X", lw = 3, mec = "k", mfc = "w", ms = 9, label="BLER [Perfect-CSI]")
ax.semilogy(SNRdB2, bler2, "--b", marker = "o", lw = 3, mec = "w", mfc = "r", ms = 9, label="BLER [CSI-Net]")
ax.legend(loc="best")
ax.set_xlabel("Signal to Noise Ratio (dB)")
ax.set_ylabel("Block (Bit) Error Rate")
ax.set_title("Reliability Evaluation: SNR (dB) vs B(L)ER", fontsize = 16)
# ax.set_xticks(SNRdB1)
ax.xaxis.set_major_formatter(mpl.ticker.FormatStrFormatter('%.2f'))
ytck = (0.1**(np.arange(1, 10))).repeat(9)*np.tile(np.arange(10, 1,-1), [9])
ytck = np.concatenate([[1],ytck])
ax.set_yticks(ytck, minor=True)
ax.set_yticks(0.1**(np.arange(0, 9)), minor=False)
ax.set_ylim([0.5*10**-5,1.2])
ax.grid(which = 'minor', alpha = 0.5, linestyle = '--')
ax.grid(which = 'major', alpha = 0.65, color = "k")
plt.show()

References
[ ]: