Modeling Transport Channel
This notebook demonstrates how to use HARQ and PDSCH to model a 5G downlink transport channel.
[1]:
import numpy as np
import time
from neoradium import BandwidthPart, PDSCH, HarqEntity, random
[2]:
bwp = BandwidthPart(numRbs=52, spacing=15) # First create a bandwidth part with 52 RBs and 15 kHz subcarrier spacing
snrDb = 5 # SNR (dB)
modulation="16QAM" # Modulation scheme
coderate = 490/1024 # Target code rate
# Create the PDSCH object
pdsch = PDSCH(bwp, numLayers=1, modulation=modulation)
pdsch.setDMRS(configType=2, additionalPos=2) # Specify the DMRS configuration
ldpc = pdsch.getLdpcCodec(coderate) # Create the LDPC coding object
# HARQ configuration:
harqType = "IR" # "IR" -> "Incremental Redundancy", "CC" -> "Chase Combining"
numProc = 16 # Number of HARQ processes
harq = HarqEntity(ldpc, harqType, numProc) # Create the HARQ entity
harq.print() # Print the HARQ entity's properties
rangen = random.getGenerator(123) # Create a new random generator to make results reproducible
numTransmissions = 100 # Number of transmissions to simulate
t0 = time.time() # Start the timer
# Print the header lines:
print("Tx Bits Rx Bits Throughput(%) TX Blocks RX Blocks BLER(%) Avg. Retransmissions time(Sec.)")
print("---------- ---------- ------------- --------- --------- ------- -------------------- ----------")
for t in range(numTransmissions):
pdsch.initGrid() # Create and initialize PDSCH's internal grid
txBlockSizes = pdsch.getTxBlockSize(coderate) # Transport Block Size
numBits = pdsch.getBitCapacity()[0] # Actual number of bits available in the resource grid
if harq.needNewData[0]: # New transmission
txBlock = rangen.bits(ldpc.txBlockSizes[0]) # Create random bits for the new transport block
else: # Retransmission
txBlock = None # Set transport block to None to indicate retransmission
# Let HARQ do the magic: This returns a bitstream, ready for transmission/retransmission
rateMatchedCodeBlocks = harq.encode(txBlock, numBits)
pdsch.setPdschData(rateMatchedCodeBlocks) # Map/modulate the data to the resource grid
rxGrid = pdsch.grid.addNoise(snrDb=snrDb) # Add AWGN
llrs = pdsch.getLLRs(rxGrid) # Demodulate the rxGrid to get LLRs
# HARQ handles retransmissions and returns the decoded transport block(s)
decodedTxBlocks, crcMatches = harq.decode(llrs)
# Print the statistics so far:
print("\r%-10d %-10d %-13.2f %-9d %-9d %-7.2f %-20.2f %-10.2f"
%(harq.totalTxBits, harq.totalRxBits, harq.throughput, harq.totalTxBlocks,
harq.totalRxBlocks, harq.bler, harq.meanRetransmissions, time.time()-t0), end='')
# Prepare for the next transmission
bwp.goNext()
harq.goNext()
# Print all statistics collected by the HARQ entity:
print("")
harq.printStats()
HARQ Entity Properties:
HARQ Type: IR
Num. Processes: 16
Num. Codewords: 1
RV sequence: [0, 2, 3, 1]
maxTries: 4
LDPC codec:
Num layers: 1
Num codewords: 1
numIter: 5
nRef: 0
Modulation: 16QAM
Coderate: 490/1024
TBS: 15624
numLayers: 1
Base Graph: 1
Code Block Size: 8448
Num Code Blocks: 2
Lifting Size: 384
Tx Bits Rx Bits Throughput(%) TX Blocks RX Blocks BLER(%) Avg. Retransmissions time(Sec.)
---------- ---------- ------------- --------- --------- ------- -------------------- ----------
1562400 749952 48.00 100 48 52.00 1.00 16.97
HARQ Entity Statistics:
numTxBits (per try): [812448 749952 0 0]
numRxBits (per try): [ 0 749952 0 0]
numTxBlocks (per try): [52 48 0 0]
numRxBlocks (per try): [ 0 48 0 0]
numTimeouts: 0
totalTxBlocks: 100
totalRxBlocks: 48
totalTxBits: 1562400
totalRxBits: 749952
throughput: 48.00%
bler: 52.00%
bler1st: 100.00%
Avg. retransmissions: 1.00
Avg. failed transmissions:1.00
[ ]:
[ ]: