Implementation notes on 'msg3 pusch' and 'pusch scheduled by dci 0_1' tbs calculation procedures:
(1) PUSCH differs with PDSCH on following aspects:
*pusch may support 'transform precoding' and 'intra-slot frequency hopping'
*pusch supports both 'codebook' and 'non-codebook' transmission, while pdsch only supports non-codebook precoding(together with dmrs).
Note: 'cb'/'CB' refers to 'codebook', and 'noncb'/'nonCB' refers to 'non-codebook' in following text.
*tri(transmission rank indication, or rank) of pusch is determined by 'precoding info and number of layers' of dci 0_1 for cb-based pusch, and by 'sri' of dci 0_1 for noncb-based pusch; while tri of pdsch(aka, number of indicated 'dmrs ports') is solely determined by 'antenna port(s)' of dci 1_1
*'antenna port(s)' of dci 0_1 need to be used together with tri (or rank), which determine 'cdm groups without data', 'dmrs ports' and 'number of front-load symbols'
*For cb-pusch, high layers configures maxRank(1~4) explicitly; while for noncb-pusch, there is a implicit parameter--Lmax, which apprears in 38.212 Table 7.3.1.1.2-28~Table 7.3.1.1.2-31, which is the max supported layers per UE. so basically, Lmax is a UE capability. Problem is that I can't find any clue in 38.306 vf30(UE Capability).
Note: For simplicity, Lmax is designed as a configurable parameter.
*when ptrs is possible, ptrs for pdsch always use one antenna port, while ptrs for pusch can be configured to use 1 or 2 antenna port(s). Here is the basic logic:
if maxNrOfPorts=1:
use PTRS port 0, where #DMRS ports maybe 1~4, and use Table 7.3.1.1.2-25 together with ‘PTRS-DMRS association’ filed to determine corresponding DMRS port
if maxNrOfPorts=2:
if #DMRS ports = 1, use PTRS port 0, and use Table 7.3.1.1.2-25 and ‘PTRS-DMRS association’ field should be ‘00’
if #DMRS ports > 1, used PTRS port 0/1, and use Table 7.3.1.1.2-26 to determine corresponding DMRS port
Note1: To my understanding, the case of 'maxNrOfPorts=2 and #dmrs ports=1' should be considered as invalid scheduling result.
Note2: For the case of 'maxNrOfPorts=2 and #dmrs ports>1', it is simple for noncb-pusch; however, for cb-pusch, it seems the 38.214 hav an incomplete statement:
38.214 vf30----6.1.1.1 Codebook based UL transmission
Problem: nrOfSRS-Ports can only be n1/n2/n4, what's the case when tri(rank, #layers)=3?
(2)Special handing for DMRS overhead calculation for PUSCH:
#calculate dmrs overhead
mappingType = self.nrDci01PuschTimeAllocMappingTypeComb.currentText()
freqHop = self.nrDci01PuschFreqAllocFreqHopComb.currentText()
if freqHop == 'intra-slot':
#refer to 3GPP 38.211 vf30 6.4.1.1.3
#if the higher-layer parameter dmrs-AdditionalPosition is not set to 'pos0' and intra-slot frequency hopping is enabled according to clause 7.3.1.1.2 in [4, TS 38.212] and by higher layer, Tables 6.4.1.1.3-6 shall be used assuming dmrs-AdditionalPosition is equal to 'pos1' for each hop.
#refer to 3GPP 38.214 vf30 6.3
#In case of intra-slot frequency hopping is configured, the number of symbols in the first hop is given by floor(N_PUSCH_symb/2) , the number of symbols in the second hop is given by N_PUSCH_symb - floor(N_PUSCH_symb/2) , where N_PUSCH_symb is the length of the PUSCH transmission in OFDM symbols in one slot.
key1 = '%s_%s_%s_%s_1st' % (math.floor(td / 2), mappingType, self.nrMibDmRsTypeAPosComb.currentText()[3:] if mappingType == 'Type A' else '0', 'pos1' if self.nrDmrsDedPuschAddPosComb.currentText() != 'pos0' else 'pos0')
key2 = '%s_%s_%s_%s_2nd' % (td - math.floor(td / 2), mappingType, self.nrMibDmRsTypeAPosComb.currentText()[3:] if mappingType == 'Type A' else '0', 'pos1' if self.nrDmrsDedPuschAddPosComb.currentText() != 'pos0' else 'pos0')
if numDmrsSymbs == 1:
if not key1 in self.nrDmrsPuschPosOneSymbWithIntraSlotFh or not key2 in self.nrDmrsPuschPosOneSymbWithIntraSlotFh or self.nrDmrsPuschPosOneSymbWithIntraSlotFh[key1] is None or self.nrDmrsPuschPosOneSymbWithIntraSlotFh[key2] is None:
self.ngwin.logEdit.append('<font color=red><b>[%s]Error</font>: Invalid key(key_1stHop="%s", key_2ndHop="%s") when referring nrDmrsPuschPosOneSymbWithIntraSlotFh!' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), key1, key2))
return
val1 = self.nrDmrsPuschPosOneSymbWithIntraSlotFh[key1]
val2 = self.nrDmrsPuschPosOneSymbWithIntraSlotFh[key2]
else:
self.ngwin.logEdit.append('<font color=red><b>[%s]Error</font>: Only single-symbol front-load DM-RS for PUSCH is supported when intra-slot frequency hopping is enabled!' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())))
return
else:
key = '%s_%s_%s' % (td, self.nrDci01PuschTimeAllocMappingTypeComb.currentText(), self.nrDmrsDedPuschAddPosComb.currentText())
if numDmrsSymbs == 1:
if not key in self.nrDmrsPuschPosOneSymbWoIntraSlotFh.keys() or self.nrDmrsPuschPosOneSymbWoIntraSlotFh[key] is None:
self.ngwin.logEdit.append('<font color=red><b>[%s]Error</font>: Invalid key(="%s") when referring nrDmrsPuschPosOneSymbWoIntraSlotFh!' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), key))
return
val = self.nrDmrsPuschPosOneSymbWoIntraSlotFh[key]
else:
if not key in self.nrDmrsPuschPosTwoSymbsWoIntraSlotFh.keys() or self.nrDmrsPuschPosTwoSymbsWoIntraSlotFh[key] is None:
self.ngwin.logEdit.append('<font color=red><b>[%s]Error</font>: Invalid key(="%s") when referring nrDmrsPuschPosTwoSymbsWoIntraSlotFh!' % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), key))
return
val = self.nrDmrsPuschPosTwoSymbsWoIntraSlotFh[key]
if freqHop == 'intra-slot':
dmrsOh = (2 * cdmGroups) * (len(val1) + len(val2))
self.ngwin.logEdit.append('PUSCH(DCI 0_1) DMRS overhead: cdmGroupsWoData=%d, key1="%s", val1=%s, key2="%s", val2=%s' % (cdmGroups, key1, val1, key2, val2))
else:
dmrsOh = (2 * cdmGroups) * len(val)
self.ngwin.logEdit.append('PUSCH(DCI 0_1) DMRS overhead: cdmGroupsWoData=%d, key="%s", val=%s' % (cdmGroups, key, val))
TBS calculation is done generally, and code goes rapidly to 10k lines now^_^