Procedures to calcuclate TBS for PDSCH/PUSCH:
def getTbs(self, sch='pdsch', tp=0, rnti='c-rnti', tab='qam64', td=1, fd=1, mcs=0, layer=1, dmrs=0, xoh=0, scale=1):
self.ngwin.logEdit.append('---->inside getTbs: sch="%s", tp=%d, rnti="%s", tab="%s", td=%d, fd=%d, mcs=%d, layer=%d, dmrs=%d, xoh=%d, scale=%.2f' % (sch, tp, rnti, tab, td, fd, mcs, layer, dmrs, xoh, scale))
if rnti not in ('c-rnti', 'si-rnti', 'ra-rnti', 'tc-rnti', 'msg3'):
return None
if tab not in ('qam256', 'qam64', 'qam64LowSE'):
return None
#reset xoh to 0 for PDSCH when rnti='SI-RNTI', 'RA-RNTI' and for Msg3 PUSCH
#FIXME what's the case for rnti='TC-RNTI'(msg4)?
if rnti in ('si-rnti', 'ra-rnti', 'tc-rnti', 'msg3'):
xoh = 0
#reset scale to 1 for PDSCH when rnti is not 'RA-RNTI' and for PUSCH
if rnti != 'ra-rnti':
scale = 1
#refer to 3GPP 38.214 vf30
#5.1.3 Modulation order, target code rate, redundancy version and transport block size determination
#6.1.4 Modulation order, redundancy version and transport block size determination
#1st step: get Qm and R(x1024)
if sch == 'pdsch' or (sch == 'pusch' and tp == 0):
if rnti == 'c-rnti' and tab == 'qam256':
val = self.nrPdschMcsTabQam256[mcs]
if val is None:
return None
elif rnti == 'c-rnti' and tab == 'qam64LowSE':
val = self.nrPdschMcsTabQam64LowSE[mcs]
if val is None:
return None
else:
val = self.nrPdschMcsTabQam64[mcs]
if val is None:
return None
pass
elif sch == 'pusch' and tp == 1:
if rnti == 'c-rnti' and tab == 'qam256':
val = self.nrPdschMcsTabQam256[mcs]
if val is None:
return None
elif rnti == 'c-rnti' and tab == 'qam64LowSE':
val = self.nrPuschTpMcsTabQam64LowSE[mcs]
if val is None:
return None
else:
val = self.nrPuschTpMcsTabQam64[mcs]
if val is None:
return None
else:
return None
Qm, R = val
#FIXME what's the case for rnti='TC-RNTI'(msg4)?
if rnti in ('si-rnti', 'ra-rnti', 'tc-rnti') and Qm > 2:
self.ngwin.logEdit.append('<font color=red><b>[%s]Error</font>: The UE is not expected to decode a PDSCH scheduled with P-RNTI, RA-RNTI, SI-RNTI and Qm > 2! (FIXME)Assume the same rule applies to PDSCH scheduled with TC-RNTI.' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())))
return None
#2nd step: get N_RE
N_RE = self.numScPerPrb * td - dmrs - xoh
N_RE = min(156, N_RE) * fd
#3rd step: get N_info
N_info = math.ceil(scale * N_RE * R * Qm * layer / 1024)
if N_info <= 3824:
#4th step: get TBS
n = max(3, math.floor(math.log2(N_info)) - 6)
N_info = max(24, 2 ** n * math.floor(N_info / 2 ** n))
tbs = None
for i in self.nrTbsTabLessThan3824:
if i >= N_info:
tbs = i
break
else:
#5th step: get TBS
n = math.floor(math.log2(N_info - 24)) - 5
N_info = max(3840, 2 ** n * math.ceil((N_info - 24) / 2 ** n))
if R <= 256:
C = math.ceil((N_info + 24) / 3816)
tbs = 8 * C * math.ceil((N_info + 24) / (8 * C)) - 24
else:
if N_info > 8424:
C = math.ceil((N_info + 24) / 8424)
tbs = 8 * C * math.ceil((N_info + 24) / (8 * C)) - 24
else:
tbs = 8 * math.ceil((N_info + 24) / 8 ) - 24
if rnti == 'si-rnti' and tbs is not None and tbs > 2976:
self.ngwin.logEdit.append('<font color=red><b>[%s]Error</font>: The UE is not expected to receive a PDSCH assigned by a PDCCH with CRC scrambled by SI-RNTI with a TBS exceeding 2976 bits!' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())))
return None
return tbs
Example for calculate TBS for PDSCH scheduled with C-RNTI with DCI 1_1:
td = int(self.nrDci11PdschTimeAllocLEdit.text())
if self.nrDci11PdschFreqAllocTypeComb.currentText() == 'RA Type1':
fd = int(self.nrDci11PdschFreqAllocType1LRbsEdit.text())
else:
fd = sum([self.rbgsType0Pdsch[i] for i in range(self.bitwidthType0Pdsch) if self.nrDci11PdschFreqAllocFieldEdit.text()[i] == '1'])
tbs = []
if len(mcsSet) == 1:
tbs.append(self.getTbs(sch='pdsch', tp=0, rnti='c-rnti', tab=self.nrDedPdschCfgMcsTableComb.currentText(), td=td, fd=fd, mcs=mcsSet[0], layer=len(dmrsPorts), xoh=int(self.nrDedPdschCfgXOverheadComb.currentText()[3:]), scale=1))
elif len(mcsSet) == 2:
numAntPortsCw0 = math.floor(len(dmrsPorts) / 2)
tbs.append(self.getTbs(sch='pdsch', tp=0, rnti='c-rnti', tab=self.nrDedPdschCfgMcsTableComb.currentText(), td=td, fd=fd, mcs=mcsSet[0], layer=numAntPortsCw0, dmrs = 0, xoh=int(self.nrDedPdschCfgXOverheadComb.currentText()[3:]), scale=1))
tbs.append(self.getTbs(sch='pdsch', tp=0, rnti='c-rnti', tab=self.nrDedPdschCfgMcsTableComb.currentText(), td=td, fd=fd, mcs=mcsSet[1], layer=len(dmrsPorts)-numAntPortsCw0, dmrs = 0, xoh=int(self.nrDedPdschCfgXOverheadComb.currentText()[3:]), scale=1))
else:
return
There are still many internal logics left to be implemented: