* MR 1015: Multi-UE + more slots
This MR adds a multi-UE scheduler (proportional fair) for multiple UEs. Tested for two UEs, but should work for more. Additionally, it enables 12 DL slots and 2 UL slots (still fixed, will be read from the configuration file in a clean-up/follow-up MR). * MR 1019: NASMESH: support for kernel version >= 5.6.0 he syntax for ndo_tx_timeout in Linux Kernel has changed since 5.6.0 i.e it has changed * MR 1033: ue fixes 1. Write tx data to radio unit only on tx slots. 2. Fixed a bug in DL HARQ. 3. Disabled UE and some gNB side logs which were enabled (maybe by mistake) in previous MRs. 4. In UE, check if NDI toggled before reading SDU for PUSCH.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
Num_Threads_PUSCH = 8
|
||||
|
||||
|
||||
gNBs =
|
||||
@@ -251,6 +250,7 @@ L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
pusch_proc_threads = 8;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<testCase id="090102">
|
||||
<class>Initialize_OAI_UE</class>
|
||||
<desc>Initialize NR UE USRP</desc>
|
||||
<Initialize_OAI_UE_args>--phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 75 --rrc_config_path . --dlsch-parallel 4 </Initialize_OAI_UE_args>
|
||||
<Initialize_OAI_UE_args>--phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 50 --rrc_config_path . --dlsch-parallel 4 </Initialize_OAI_UE_args>
|
||||
<air_interface>NR</air_interface>
|
||||
</testCase>
|
||||
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ development], for FR2 does not exist yet.
|
||||
3) allocate a CCE for the UE (and return if it is not possible)
|
||||
4) Calculate DMRS stuff (nr_save_pusch_fields()) and the TBS.
|
||||
5) Mark used resources in vrb_map_UL.
|
||||
* loop through all users: get a free HARQ PID using select_ul_harq_pid() and
|
||||
* loop through all users: get a free HARQ PID and
|
||||
update statistics. Fill nFAPI structures directly for PUSCH, and call
|
||||
config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH messages.
|
||||
|
||||
|
||||
@@ -873,10 +873,7 @@ void init_gNB_proc(int inst) {
|
||||
gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
|
||||
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
|
||||
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
uint32_t num_threads_pusch;
|
||||
paramdef_t PUSCHThreads[] = NUM_THREADS_DESC;
|
||||
config_get( PUSCHThreads,sizeof(PUSCHThreads)/sizeof(paramdef_t),NULL);
|
||||
int threadCnt = min(numCPU, num_threads_pusch);
|
||||
int threadCnt = min(numCPU, gNB->pusch_proc_threads);
|
||||
char ul_pool[80];
|
||||
sprintf(ul_pool,"-1");
|
||||
int s_offset = 0;
|
||||
|
||||
+23
-10
@@ -642,8 +642,7 @@ void *UE_thread(void *arg) {
|
||||
UE->rx_offset_diff = computeSamplesShift(UE);
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
|
||||
UE->rx_offset_diff;
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)-
|
||||
UE->rx_offset_diff;
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff;
|
||||
}
|
||||
|
||||
AssertFatal(readBlockSize ==
|
||||
@@ -702,14 +701,28 @@ void *UE_thread(void *arg) {
|
||||
timing_advance = UE->timing_advance;
|
||||
}
|
||||
|
||||
AssertFatal( writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
writeTimestamp,
|
||||
txp,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
1),"");
|
||||
int flags = 0;
|
||||
int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH;
|
||||
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
|
||||
uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots +
|
||||
(mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0);
|
||||
uint8_t first_tx_slot = tdd_period - num_UL_slots;
|
||||
if (slot_tx_usrp%tdd_period==first_tx_slot)
|
||||
flags=2;
|
||||
else if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1)
|
||||
flags = 3;
|
||||
else if (slot_tx_usrp%tdd_period>first_tx_slot)
|
||||
flags = 1;
|
||||
|
||||
if (flags || IS_SOFTMODEM_RFSIM)
|
||||
AssertFatal( writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
writeTimestamp,
|
||||
txp,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
flags),"");
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
memset(txp[i], 0, writeBlockSize);
|
||||
|
||||
@@ -717,7 +730,7 @@ void *UE_thread(void *arg) {
|
||||
msgToPush->key=slot_nr;
|
||||
pushTpool(&(get_nrUE_params()->Tpool), msgToPush);
|
||||
|
||||
if ( IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) { //getenv("RFSIMULATOR")
|
||||
if (IS_SOFTMODEM_RFSIM) { //getenv("RFSIMULATOR")
|
||||
// FixMe: Wait previous thread is done, because race conditions seems too bad
|
||||
// in case of actual RF board, the overlap between threads mitigate the issue
|
||||
// We must receive one message, that proves the slot processing is done
|
||||
|
||||
@@ -1019,6 +1019,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
uint8_t tdd_period;//DL UL Transmission Periodicity. Value:0: ms0p5 1: ms0p625 2: ms1 3: ms1p25 4: ms2 5: ms2p5 6: ms5 7: ms10 8: ms3 9: ms4
|
||||
uint8_t tdd_period_in_slots;
|
||||
fapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list;
|
||||
|
||||
} fapi_nr_tdd_table_t;
|
||||
|
||||
@@ -630,30 +630,30 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
// The RNTI used for identifying the UE when receiving the PDU Value: 1 -> 65535.
|
||||
uint16_t RNTI[MAX_DCI_CORESET];
|
||||
uint16_t RNTI;
|
||||
// For a UE-specific search space it equals the higher-layer parameter PDCCH-DMRSScrambling-ID if configured,
|
||||
// otherwise it should be set to the phy cell ID. [TS38.211, sec 7.3.2.3] Value: 0->65535
|
||||
uint16_t ScramblingId[MAX_DCI_CORESET];
|
||||
uint16_t ScramblingId;
|
||||
// For a UE-specific search space where PDCCH-DMRSScrambling- ID is configured This param equals the CRNTI.
|
||||
// Otherwise, it should be set to 0. [TS38.211, sec 7.3.2.3] Value: 0 -> 65535
|
||||
uint16_t ScramblingRNTI[MAX_DCI_CORESET];
|
||||
uint16_t ScramblingRNTI;
|
||||
// CCE start Index used to send the DCI Value: 0->135
|
||||
uint8_t CceIndex[MAX_DCI_CORESET];
|
||||
uint8_t CceIndex;
|
||||
// Aggregation level used [TS38.211, sec 7.3.2.1] Value: 1,2,4,8,16
|
||||
uint8_t AggregationLevel[MAX_DCI_CORESET];
|
||||
uint8_t AggregationLevel;
|
||||
// Precoding and Beamforming structure See Table 3-43
|
||||
nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming[MAX_DCI_CORESET];
|
||||
nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming;
|
||||
// PDCCH power value used for PDCCH Format 1_0 with CRC scrambled by SI-RNTI, PI-RNTI or RA-RNTI.
|
||||
// This is ratio of SSB/PBCH EPRE to PDCCH and PDCCH DMRS EPRE [TS38.213, sec 4.1]
|
||||
// Value :0->17 Report title: 5G FAPI: PHY API Specification Issue date: 29 June 2019 Version: 222.10.17 68 Field Type Description representing -8 to 8 dB in 1dB steps
|
||||
uint8_t beta_PDCCH_1_0[MAX_DCI_CORESET];
|
||||
uint8_t beta_PDCCH_1_0;
|
||||
// PDCCH power value used for all other PDCCH Formats.
|
||||
// This is ratio of SSB/PBCH block EPRE to PDCCH and PDCCH DMRS EPRE [TS38.214, sec 4.1] Values: 0: -3dB,1: 0dB,2: 3dB,3: 6dB
|
||||
uint8_t powerControlOffsetSS[MAX_DCI_CORESET];
|
||||
uint8_t powerControlOffsetSS;
|
||||
// The total DCI length (in bits) including padding bits [TS38.212 sec 7.3.1] Range 0->DCI_PAYLOAD_BYTE_LEN*8
|
||||
uint16_t PayloadSizeBits[MAX_DCI_CORESET];
|
||||
uint16_t PayloadSizeBits;
|
||||
// DCI payload, where the actual size is defined by PayloadSizeBits. The bit order is as following bit0-bit7 are mapped to first byte of MSB - LSB
|
||||
uint8_t Payload[MAX_DCI_CORESET][DCI_PAYLOAD_BYTE_LEN];
|
||||
uint8_t Payload[DCI_PAYLOAD_BYTE_LEN];
|
||||
|
||||
} nfapi_nr_dl_dci_pdu_t;
|
||||
|
||||
@@ -698,7 +698,7 @@ typedef struct {
|
||||
///Number of DCIs in this CORESET.Value: 0->MaxDciPerSlot
|
||||
uint16_t numDlDci;
|
||||
///DL DCI PDU
|
||||
nfapi_nr_dl_dci_pdu_t dci_pdu;
|
||||
nfapi_nr_dl_dci_pdu_t dci_pdu[MAX_DCI_CORESET];
|
||||
} nfapi_nr_dl_tti_pdcch_pdu_rel15_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -250,9 +250,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
|
||||
|
||||
int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value;
|
||||
|
||||
printf("Before ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]);
|
||||
for (int ULSCH_id=0; ULSCH_id<NUMBER_OF_NR_ULSCH_MAX; ULSCH_id++) {
|
||||
printf("ULSCH_id %d : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]);
|
||||
pusch_vars[ULSCH_id] = (NR_gNB_PUSCH *)malloc16_clear( sizeof(NR_gNB_PUSCH) );
|
||||
pusch_vars[ULSCH_id]->rxdataF_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) );
|
||||
pusch_vars[ULSCH_id]->rxdataF_ext2 = (int32_t **)malloc16(Prx*sizeof(int32_t *) );
|
||||
@@ -269,7 +267,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
|
||||
pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(Prx*sizeof(int32_t *) );
|
||||
pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(Prx*sizeof(int32_t*) );
|
||||
|
||||
printf("ULSCH_id %d (before rx antenna alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]);
|
||||
for (i=0; i<Prx; i++) {
|
||||
pusch_vars[ULSCH_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot );
|
||||
pusch_vars[ULSCH_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot );
|
||||
@@ -286,16 +283,13 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
|
||||
pusch_vars[ULSCH_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 );
|
||||
pusch_vars[ULSCH_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(fp->N_RB_UL*12*7*2) );
|
||||
}
|
||||
printf("ULSCH_id %d (before llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]);
|
||||
pusch_vars[ULSCH_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
|
||||
printf("ULSCH_id %d (after llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]);
|
||||
pusch_vars[ULSCH_id]->ul_valid_re_per_slot = (int16_t *)malloc16_clear( sizeof(int16_t)*fp->symbols_per_slot);
|
||||
} //ulsch_id
|
||||
/*
|
||||
for (ulsch_id=0; ulsch_id<NUMBER_OF_UE_MAX; ulsch_id++)
|
||||
gNB->UE_stats_ptr[ulsch_id] = &gNB->UE_stats[ulsch_id];
|
||||
*/
|
||||
printf("After ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
* in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0
|
||||
* or the rb_offset for other coresets
|
||||
* in time: by its first slot and its first symbol*/
|
||||
const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d];
|
||||
|
||||
cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
|
||||
cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
|
||||
@@ -103,7 +104,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
LOG_D(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
|
||||
// DMRS length is per OFDM symbol
|
||||
uint32_t dmrs_length = n_rb*6; //2(QPSK)*3(per RB)*6(REG per CCE)
|
||||
uint32_t encoded_length = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*108; //2(QPSK)*9(per RB)*6(REG per CCE)
|
||||
uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE)
|
||||
LOG_D(PHY, "DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d)\n", dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType);
|
||||
dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset
|
||||
|
||||
@@ -125,19 +126,19 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
// CRC attachment + Scrambling + Channel coding + Rate matching
|
||||
uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
|
||||
|
||||
uint16_t n_RNTI = pdcch_pdu_rel15->dci_pdu.RNTI[d];
|
||||
uint16_t Nid = pdcch_pdu_rel15->dci_pdu.ScramblingId[d];
|
||||
uint16_t scrambling_RNTI = pdcch_pdu_rel15->dci_pdu.ScramblingRNTI[d];
|
||||
uint16_t n_RNTI = dci_pdu->RNTI;
|
||||
uint16_t Nid = dci_pdu->ScramblingId;
|
||||
uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI;
|
||||
|
||||
t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE,
|
||||
pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d],
|
||||
pdcch_pdu_rel15->dci_pdu.AggregationLevel[d],
|
||||
dci_pdu->PayloadSizeBits,
|
||||
dci_pdu->AggregationLevel,
|
||||
0,NULL);
|
||||
polar_encoder_fast((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d], (void*)encoder_output, n_RNTI,1,currentPtr);
|
||||
polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI,1,currentPtr);
|
||||
#ifdef DEBUG_CHANNEL_CODING
|
||||
printf("polar rnti %x,length %d, L %d\n",n_RNTI, pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d],pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]);
|
||||
printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]);
|
||||
printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n",
|
||||
((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[0], ((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[1]);
|
||||
((uint64_t*)dci_pdu->Payload)[0], ((uint64_t*)dci_pdu->Payload)[1]);
|
||||
printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5);
|
||||
|
||||
for (int i=0; i<encoded_length>>5; i++)
|
||||
@@ -173,7 +174,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
int reg_list_index = 0;
|
||||
int reg_list_order[NR_MAX_PDCCH_AGG_LEVEL] = {};
|
||||
for (int p = 0; p < NR_MAX_PDCCH_AGG_LEVEL; p++) {
|
||||
for(int p2 = 0; p2 < pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; p2++) {
|
||||
for(int p2 = 0; p2 < dci_pdu->AggregationLevel; p2++) {
|
||||
if(gNB->cce_list[d][p2].reg_list[0].reg_idx == p * NR_NB_REG_PER_CCE) {
|
||||
reg_list_order[reg_list_index] = p2;
|
||||
reg_list_index++;
|
||||
@@ -183,7 +184,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
|
||||
/*Mapping the encoded DCI along with the DMRS */
|
||||
for (int cce_count = 0; cce_count < pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; cce_count ++) {
|
||||
for (int cce_count = 0; cce_count < dci_pdu->AggregationLevel; cce_count ++) {
|
||||
|
||||
int8_t cce_idx = reg_list_order[cce_count];
|
||||
|
||||
@@ -239,9 +240,10 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
} // reg_in_cce_idx
|
||||
} // cce_count
|
||||
|
||||
LOG_D(PHY, "DCI: payloadSize = %d | payload = %llx\n",
|
||||
*pdcch_pdu_rel15->dci_pdu.PayloadSizeBits,*(unsigned long long*)pdcch_pdu_rel15->dci_pdu.Payload);
|
||||
|
||||
LOG_D(PHY,
|
||||
"DCI: payloadSize = %d | payload = %llx\n",
|
||||
dci_pdu->PayloadSizeBits,
|
||||
*(unsigned long long *)dci_pdu->Payload);
|
||||
} // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r
|
||||
AssertFatal(N_reg > 0,"N_reg cannot be 0\n");
|
||||
|
||||
for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++) {
|
||||
int L = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d];
|
||||
int L = pdcch_pdu_rel15->dci_pdu[d].AggregationLevel;
|
||||
|
||||
if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_MIB_SIB1)
|
||||
AssertFatal(L>=4, "Invalid aggregation level for SIB1 configured PDCCH %d\n", L);
|
||||
@@ -153,10 +153,10 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r
|
||||
C = N_reg/(bsize*R);
|
||||
}
|
||||
|
||||
LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu.CceIndex[d]);
|
||||
LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu[d].CceIndex);
|
||||
for (uint8_t cce_idx=0; cce_idx<L; cce_idx++) {
|
||||
cce = &gNB->cce_list[d][cce_idx];
|
||||
cce->cce_idx = pdcch_pdu_rel15->dci_pdu.CceIndex[d] + cce_idx;
|
||||
cce->cce_idx = pdcch_pdu_rel15->dci_pdu[d].CceIndex + cce_idx;
|
||||
LOG_D(PHY, "cce_idx %d\n", cce->cce_idx);
|
||||
|
||||
if (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) {
|
||||
@@ -236,25 +236,24 @@ void nr_fill_dci(PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) {
|
||||
|
||||
//uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i];
|
||||
//uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
|
||||
|
||||
int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu.RNTI[i],gNB,SEARCH_EXIST_OR_FREE);
|
||||
int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu[i].RNTI,gNB,SEARCH_EXIST_OR_FREE);
|
||||
if( (dlsch_id<0) || (dlsch_id>=NUMBER_OF_NR_DLSCH_MAX) ){
|
||||
LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu.RNTI[i],dlsch_id);
|
||||
LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu[i].RNTI,dlsch_id);
|
||||
return;
|
||||
}
|
||||
|
||||
dlsch = gNB->dlsch[dlsch_id][0];
|
||||
int num_slots_tdd = (gNB->frame_parms.slots_per_frame)>>(7-gNB->gNB_config.tdd_table.tdd_period.value);
|
||||
int harq_pid = slot % num_slots_tdd;
|
||||
int harq_pid = 0;
|
||||
|
||||
dlsch->slot_tx[slot] = 1;
|
||||
dlsch->harq_ids[frame%2][slot] = harq_pid;
|
||||
dlsch->harq_ids[frame % 2][slot] = 0;
|
||||
AssertFatal(harq_pid < 8 && harq_pid >= 0,
|
||||
"illegal harq_pid %d\n",harq_pid);
|
||||
|
||||
dlsch->harq_mask |= (1<<harq_pid);
|
||||
dlsch->rnti = pdcch_pdu_rel15->dci_pdu.RNTI[i];
|
||||
dlsch->rnti = pdcch_pdu_rel15->dci_pdu[i].RNTI;
|
||||
|
||||
// nr_fill_cce_list(gNB,0);
|
||||
/*
|
||||
@@ -300,7 +299,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) {
|
||||
|
||||
//uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i];
|
||||
//uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
|
||||
|
||||
// if there's no DL DCI then generate CCE list
|
||||
// nr_fill_cce_list(gNB,0);
|
||||
|
||||
@@ -136,8 +136,7 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
|
||||
dlsch = gNB->dlsch[dlsch_id][0];
|
||||
if (dlsch->slot_tx[slot] == 0) continue;
|
||||
|
||||
int harq_pid = dlsch->harq_ids[frame%2][slot];
|
||||
NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5];
|
||||
int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs;
|
||||
@@ -421,15 +420,8 @@ void dump_pdsch_stats(PHY_VARS_gNB *gNB) {
|
||||
|
||||
for (int i=0;i<NUMBER_OF_NR_SCH_STATS_MAX;i++)
|
||||
if (gNB->dlsch_stats[i].rnti > 0)
|
||||
LOG_I(PHY,"DLSCH RNTI %x: round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, current_Qm %d, current_RI %d, total_bytes TX %d\n",
|
||||
LOG_D(PHY,"DLSCH RNTI %x: current_Qm %d, current_RI %d, total_bytes TX %d\n",
|
||||
gNB->dlsch_stats[i].rnti,
|
||||
gNB->dlsch_stats[i].round_trials[0],
|
||||
(double)gNB->dlsch_stats[i].round_trials[1]/gNB->dlsch_stats[i].round_trials[0],
|
||||
gNB->dlsch_stats[i].round_trials[1],
|
||||
(double)gNB->dlsch_stats[i].round_trials[2]/gNB->dlsch_stats[i].round_trials[0],
|
||||
gNB->dlsch_stats[i].round_trials[2],
|
||||
(double)gNB->dlsch_stats[i].round_trials[3]/gNB->dlsch_stats[i].round_trials[0],
|
||||
gNB->dlsch_stats[i].round_trials[3],
|
||||
gNB->dlsch_stats[i].current_Qm,
|
||||
gNB->dlsch_stats[i].current_RI,
|
||||
gNB->dlsch_stats[i].total_bytes_tx);
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
|
||||
void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB)
|
||||
{
|
||||
int i;
|
||||
int r;
|
||||
|
||||
NR_gNB_DLSCH_t *dlsch = *dlschptr;
|
||||
@@ -63,76 +62,61 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB)
|
||||
a_segments = a_segments*N_RB;
|
||||
a_segments = a_segments/273 +1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY,"Freeing dlsch %p\n",dlsch);
|
||||
#endif
|
||||
|
||||
for (i=0; i<dlsch->Mdlharq; i++) {
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
if (harq->b) {
|
||||
free16(harq->b, a_segments * 1056);
|
||||
harq->b = NULL;
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY,"Freeing dlsch process %d\n",i);
|
||||
LOG_D(PHY, "Freeing harq->b (%p)\n", harq->b);
|
||||
#endif
|
||||
|
||||
if (dlsch->harq_processes[i]) {
|
||||
if (harq->e) {
|
||||
free16(harq->e, 14 * N_RB * 12 * 8);
|
||||
harq->e = NULL;
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY,"Freeing dlsch process %d (%p)\n",i,dlsch->harq_processes[i]);
|
||||
printf("Freeing dlsch process %d e (%p)\n", i, harq->e);
|
||||
#endif
|
||||
|
||||
if (dlsch->harq_processes[i]->b) {
|
||||
free16(dlsch->harq_processes[i]->b,a_segments*1056);
|
||||
dlsch->harq_processes[i]->b = NULL;
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY,"Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dlsch->harq_processes[i]->e) {
|
||||
free16(dlsch->harq_processes[i]->e,14*N_RB*12*8);
|
||||
dlsch->harq_processes[i]->e = NULL;
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
printf("Freeing dlsch process %d e (%p)\n",i,dlsch->harq_processes[i]->e);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dlsch->harq_processes[i]->f) {
|
||||
free16(dlsch->harq_processes[i]->f,14*N_RB*12*8);
|
||||
dlsch->harq_processes[i]->f = NULL;
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
printf("Freeing dlsch process %d f (%p)\n",i,dlsch->harq_processes[i]->f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY,"Freeing dlsch process %d c (%p)\n",i,dlsch->harq_processes[i]->c);
|
||||
#endif
|
||||
|
||||
for (r=0; r<a_segments; r++) {
|
||||
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY,"Freeing dlsch process %d c[%d] (%p)\n",i,r,dlsch->harq_processes[i]->c[r]);
|
||||
#endif
|
||||
|
||||
if (dlsch->harq_processes[i]->c[r]) {
|
||||
free16(dlsch->harq_processes[i]->c[r],1056);
|
||||
dlsch->harq_processes[i]->c[r] = NULL;
|
||||
}
|
||||
if (dlsch->harq_processes[i]->d[r]) {
|
||||
free16(dlsch->harq_processes[i]->d[r],3*8448);
|
||||
dlsch->harq_processes[i]->d[r] = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
free16(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t));
|
||||
dlsch->harq_processes[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free16(dlsch,sizeof(NR_gNB_DLSCH_t));
|
||||
*dlschptr = NULL;
|
||||
if (harq->f) {
|
||||
free16(harq->f, 14 * N_RB * 12 * 8);
|
||||
harq->f = NULL;
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
printf("Freeing dlsch process %d f (%p)\n", i, harq->f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY, "Freeing dlsch process %d c (%p)\n", i, harq->c);
|
||||
#endif
|
||||
|
||||
for (r = 0; r < a_segments; r++) {
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY, "Freeing dlsch process %d c[%d] (%p)\n", i, r, harq->c[r]);
|
||||
#endif
|
||||
|
||||
if (harq->c[r]) {
|
||||
free16(harq->c[r], 1056);
|
||||
harq->c[r] = NULL;
|
||||
}
|
||||
if (harq->d[r]) {
|
||||
free16(harq->d[r], 3 * 8448);
|
||||
harq->d[r] = NULL;
|
||||
}
|
||||
}
|
||||
free16(harq, sizeof(NR_DL_gNB_HARQ_t));
|
||||
harq = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free16(dlsch, sizeof(NR_gNB_DLSCH_t));
|
||||
*dlschptr = NULL;
|
||||
}
|
||||
|
||||
NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
|
||||
@@ -142,9 +126,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t abstraction_flag,
|
||||
uint16_t N_RB)
|
||||
{
|
||||
|
||||
NR_gNB_DLSCH_t *dlsch;
|
||||
unsigned char exit_flag = 0,i,r,aa,layer;
|
||||
unsigned char i,r,aa,layer;
|
||||
int re;
|
||||
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated
|
||||
|
||||
@@ -155,127 +137,74 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
|
||||
|
||||
NR_gNB_DLSCH_t *dlsch = malloc16(sizeof(NR_gNB_DLSCH_t));
|
||||
AssertFatal(dlsch, "cannot allocate dlsch\n");
|
||||
|
||||
bzero(dlsch,sizeof(NR_gNB_DLSCH_t));
|
||||
dlsch->Kmimo = Kmimo;
|
||||
dlsch->Mdlharq = Mdlharq;
|
||||
dlsch->Mlimit = 4;
|
||||
dlsch->Nsoft = Nsoft;
|
||||
|
||||
dlsch = (NR_gNB_DLSCH_t *)malloc16(sizeof(NR_gNB_DLSCH_t));
|
||||
for (layer=0; layer<NR_MAX_NB_LAYERS; layer++) {
|
||||
dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(64 * sizeof(int32_t *));
|
||||
|
||||
if (dlsch) {
|
||||
bzero(dlsch,sizeof(NR_gNB_DLSCH_t));
|
||||
dlsch->Kmimo = Kmimo;
|
||||
dlsch->Mdlharq = Mdlharq;
|
||||
dlsch->Mlimit = 4;
|
||||
dlsch->Nsoft = Nsoft;
|
||||
|
||||
for (layer=0; layer<NR_MAX_NB_LAYERS; layer++) {
|
||||
dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(64*sizeof(int32_t*));
|
||||
|
||||
for (aa=0; aa<64; aa++) {
|
||||
dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
|
||||
for (re=0;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
|
||||
dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
|
||||
}
|
||||
}
|
||||
|
||||
dlsch->txdataF[layer] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH/NR_MAX_NB_LAYERS)*sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH
|
||||
}
|
||||
|
||||
for (int q=0; q<NR_MAX_NB_CODEWORDS; q++)
|
||||
dlsch->mod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH*sizeof(int32_t));
|
||||
|
||||
dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(64*sizeof(int32_t*));
|
||||
for (aa=0; aa<64; aa++) {
|
||||
dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
|
||||
|
||||
}
|
||||
|
||||
for (i=0; i<20; i++) {
|
||||
dlsch->harq_ids[0][i] = 0;
|
||||
dlsch->harq_ids[1][i] = 0;
|
||||
}
|
||||
|
||||
for (i=0; i<Mdlharq; i++) {
|
||||
dlsch->harq_processes[i] = (NR_DL_gNB_HARQ_t *)malloc16(sizeof(NR_DL_gNB_HARQ_t));
|
||||
LOG_T(PHY, "Required mem size %d dlsch->harq_processes[%d] %p\n",
|
||||
dlsch_bytes, i,dlsch->harq_processes[i]);
|
||||
|
||||
if (dlsch->harq_processes[i]) {
|
||||
bzero(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t));
|
||||
// dlsch->harq_processes[i]->first_tx=1;
|
||||
dlsch->harq_processes[i]->b = (unsigned char*)malloc16(dlsch_bytes);
|
||||
dlsch->harq_processes[i]->pdu = (uint8_t*)malloc16(dlsch_bytes);
|
||||
if (dlsch->harq_processes[i]->pdu) {
|
||||
bzero(dlsch->harq_processes[i]->pdu,dlsch_bytes);
|
||||
nr_emulate_dlsch_payload(dlsch->harq_processes[i]->pdu, (dlsch_bytes)>>3);
|
||||
} else {
|
||||
LOG_D(PHY,"Can't allocate PDU\n");
|
||||
exit_flag=1;
|
||||
}
|
||||
|
||||
if (dlsch->harq_processes[i]->b) {
|
||||
bzero(dlsch->harq_processes[i]->b,dlsch_bytes);
|
||||
} else {
|
||||
LOG_D(PHY,"Can't get b\n");
|
||||
exit_flag=1;
|
||||
}
|
||||
|
||||
if (abstraction_flag==0) {
|
||||
for (r=0; r<a_segments; r++) {
|
||||
// account for filler in first segment and CRCs for multiple segment case
|
||||
// [hna] 8448 is the maximum CB size in NR
|
||||
// 68*348 = 68*(maximum size of Zc)
|
||||
// In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc)
|
||||
dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(8448);
|
||||
dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output
|
||||
if (dlsch->harq_processes[i]->c[r]) {
|
||||
bzero(dlsch->harq_processes[i]->c[r],8448);
|
||||
} else {
|
||||
LOG_D(PHY,"Can't get c\n");
|
||||
exit_flag=2;
|
||||
}
|
||||
if (dlsch->harq_processes[i]->d[r]) {
|
||||
bzero(dlsch->harq_processes[i]->d[r],(3*8448));
|
||||
} else {
|
||||
LOG_D(PHY,"Can't get d\n");
|
||||
exit_flag=2;
|
||||
}
|
||||
}
|
||||
dlsch->harq_processes[i]->e = (uint8_t*)malloc16(14*N_RB*12*8);
|
||||
if (dlsch->harq_processes[i]->e) {
|
||||
bzero(dlsch->harq_processes[i]->e,14*N_RB*12*8);
|
||||
} else {
|
||||
printf("Can't get e\n");
|
||||
exit_flag=1;
|
||||
}
|
||||
dlsch->harq_processes[i]->f = (uint8_t*)malloc16(14*N_RB*12*8);
|
||||
if (dlsch->harq_processes[i]->f) {
|
||||
bzero(dlsch->harq_processes[i]->f,14*N_RB*12*8);
|
||||
} else {
|
||||
printf("Can't get f\n");
|
||||
exit_flag=1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_D(PHY,"Can't get harq_p %d\n",i);
|
||||
exit_flag=3;
|
||||
for (aa = 0; aa < 64; aa++) {
|
||||
dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES * sizeof(int32_t));
|
||||
for (re = 0; re < OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
|
||||
dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
|
||||
}
|
||||
}
|
||||
|
||||
if (exit_flag==0) {
|
||||
for (i=0; i<Mdlharq; i++) {
|
||||
dlsch->harq_processes[i]->round=0;
|
||||
}
|
||||
|
||||
return(dlsch);
|
||||
}
|
||||
dlsch->txdataF[layer] =
|
||||
(int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH / NR_MAX_NB_LAYERS)
|
||||
* sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH
|
||||
}
|
||||
|
||||
LOG_D(PHY,"new_gNB_dlsch exit flag %d, size of %ld\n",
|
||||
exit_flag, sizeof(NR_gNB_DLSCH_t));
|
||||
for (int q = 0; q < NR_MAX_NB_CODEWORDS; q++)
|
||||
dlsch->mod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH * sizeof(int32_t));
|
||||
|
||||
free_gNB_dlsch(&dlsch,N_RB);
|
||||
dlsch->calib_dl_ch_estimates = (int32_t **)malloc16(64 * sizeof(int32_t *));
|
||||
for (aa = 0; aa < 64; aa++) {
|
||||
dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES * sizeof(int32_t));
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
for (i = 0; i < 20; i++) {
|
||||
dlsch->harq_ids[0][i] = 0;
|
||||
dlsch->harq_ids[1][i] = 0;
|
||||
}
|
||||
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
bzero(harq, sizeof(NR_DL_gNB_HARQ_t));
|
||||
|
||||
harq->b = malloc16(dlsch_bytes);
|
||||
AssertFatal(harq->b, "cannot allocate memory for harq->b\n");
|
||||
harq->pdu = malloc16(dlsch_bytes);
|
||||
AssertFatal(harq->pdu, "cannot allocate memory for harq->pdu\n");
|
||||
bzero(harq->pdu, dlsch_bytes);
|
||||
nr_emulate_dlsch_payload(harq->pdu, (dlsch_bytes) >> 3);
|
||||
bzero(harq->b, dlsch_bytes);
|
||||
|
||||
for (r = 0; r < a_segments; r++) {
|
||||
// account for filler in first segment and CRCs for multiple segment case
|
||||
// [hna] 8448 is the maximum CB size in NR
|
||||
// 68*348 = 68*(maximum size of Zc)
|
||||
// In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc)
|
||||
harq->c[r] = malloc16(8448);
|
||||
AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r);
|
||||
harq->d[r] = malloc16(68 * 384);
|
||||
AssertFatal(harq->d[r], "cannot allocate harq->d[%d]\n", r); // max size for coded output
|
||||
bzero(harq->c[r], 8448);
|
||||
bzero(harq->d[r], (3 * 8448));
|
||||
harq->e = malloc16(14 * N_RB * 12 * 8);
|
||||
AssertFatal(harq->e, "cannot allocate harq->e\n");
|
||||
bzero(harq->e, 14 * N_RB * 12 * 8);
|
||||
harq->f = malloc16(14 * N_RB * 12 * 8);
|
||||
AssertFatal(harq->f, "cannot allocate harq->f\n");
|
||||
bzero(harq->f, 14 * N_RB * 12 * 8);
|
||||
}
|
||||
|
||||
return(dlsch);
|
||||
}
|
||||
|
||||
void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch)
|
||||
@@ -284,28 +213,21 @@ void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch)
|
||||
unsigned char Mdlharq;
|
||||
unsigned char i,j,r;
|
||||
|
||||
if (dlsch) {
|
||||
Mdlharq = dlsch->Mdlharq;
|
||||
dlsch->rnti = 0;
|
||||
dlsch->active = 0;
|
||||
AssertFatal(dlsch!=NULL,"dlsch is null\n");
|
||||
Mdlharq = dlsch->Mdlharq;
|
||||
dlsch->rnti = 0;
|
||||
dlsch->active = 0;
|
||||
NR_DL_gNB_HARQ_t *harq=&dlsch->harq_process;
|
||||
|
||||
for (i=0; i<10; i++) {
|
||||
dlsch->harq_ids[0][i] = Mdlharq;
|
||||
dlsch->harq_ids[1][i] = Mdlharq;
|
||||
}
|
||||
for (i=0; i<Mdlharq; i++) {
|
||||
if (dlsch->harq_processes[i]) {
|
||||
// dlsch->harq_processes[i]->Ndi = 0;
|
||||
//dlsch->harq_processes[i]->status = 0;
|
||||
dlsch->harq_processes[i]->round = 0;
|
||||
|
||||
for (j=0; j<96; j++)
|
||||
for (r=0; r<MAX_NUM_NR_DLSCH_SEGMENTS; r++)
|
||||
if (dlsch->harq_processes[i]->d[r])
|
||||
dlsch->harq_processes[i]->d[r][j] = NR_NULL;
|
||||
|
||||
}
|
||||
}
|
||||
for (i=0; i<10; i++) {
|
||||
dlsch->harq_ids[0][i] = Mdlharq;
|
||||
dlsch->harq_ids[1][i] = Mdlharq;
|
||||
}
|
||||
for (i=0; i<Mdlharq; i++) {
|
||||
for (j=0; j<96; j++)
|
||||
for (r=0; r<MAX_NUM_NR_DLSCH_SEGMENTS; r++)
|
||||
if (harq->d[r])
|
||||
harq->d[r][j] = NR_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,13 +244,12 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
|
||||
unsigned int G;
|
||||
unsigned int crc=1;
|
||||
uint8_t harq_pid = dlsch->harq_ids[frame%2][slot];
|
||||
AssertFatal(harq_pid<8 && harq_pid>=0,"illegal harq_pid %d\b",harq_pid);
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15;
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
uint16_t nb_rb = rel15->rbSize;
|
||||
uint8_t nb_symb_sch = rel15->NrOfSymbols;
|
||||
uint32_t A, Kb, F=0;
|
||||
uint32_t *Zc = &dlsch->harq_processes[harq_pid]->Z;
|
||||
uint32_t *Zc = &dlsch->harq_process.Z;
|
||||
uint8_t mod_order = rel15->qamModOrder[0];
|
||||
uint16_t Kr=0,r;
|
||||
uint32_t r_offset=0;
|
||||
@@ -347,8 +268,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
float Coderate = 0.0;
|
||||
uint8_t Nl = 4;
|
||||
|
||||
dlsch->harq_processes[harq_pid]->round = nr_rv_round_map[rel15->rvIndex[0]];
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
|
||||
A = rel15->TBSize[0]<<3;
|
||||
@@ -367,174 +287,157 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
|
||||
if (stats) {
|
||||
stats->round_trials[dlsch->harq_processes[harq_pid]->round]++;
|
||||
stats->rnti = dlsch->rnti;
|
||||
if (dlsch->harq_processes[harq_pid]->round == 0){
|
||||
stats->total_bytes_tx += rel15->TBSize[0];
|
||||
stats->current_RI = rel15->nrOfLayers;
|
||||
stats->current_Qm = rel15->qamModOrder[0];
|
||||
}
|
||||
stats->total_bytes_tx += rel15->TBSize[0];
|
||||
stats->current_RI = rel15->nrOfLayers;
|
||||
stats->current_Qm = rel15->qamModOrder[0];
|
||||
}
|
||||
G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers);
|
||||
|
||||
LOG_D(PHY,"dlsch coding A %d G %d mod_order %d\n", A,G, mod_order);
|
||||
|
||||
// if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet
|
||||
if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY,"encoding thinks this is a new packet \n");
|
||||
#endif
|
||||
/*
|
||||
int i;
|
||||
LOG_D(PHY,"dlsch (tx): \n");
|
||||
for (i=0;i<(A>>3);i++)
|
||||
LOG_D(PHY,"%02x\n",a[i]);
|
||||
LOG_D(PHY,"\n");
|
||||
*/
|
||||
if (A > 3824) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
crc = crc24a(a,A)>>8;
|
||||
a[A>>3] = ((uint8_t*)&crc)[2];
|
||||
a[1+(A>>3)] = ((uint8_t*)&crc)[1];
|
||||
a[2+(A>>3)] = ((uint8_t*)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
|
||||
|
||||
harq->B = A+24;
|
||||
// harq->b = a;
|
||||
|
||||
if (A > 3824) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
crc = crc24a(a,A)>>8;
|
||||
a[A>>3] = ((uint8_t*)&crc)[2];
|
||||
a[1+(A>>3)] = ((uint8_t*)&crc)[1];
|
||||
a[2+(A>>3)] = ((uint8_t*)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
|
||||
|
||||
dlsch->harq_processes[harq_pid]->B = A+24;
|
||||
// dlsch->harq_processes[harq_pid]->b = a;
|
||||
|
||||
AssertFatal((A/8)+4 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,MAX_NR_DLSCH_PAYLOAD_BYTES);
|
||||
|
||||
memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); // why is this +4 if the CRC is only 3 bytes?
|
||||
}
|
||||
else {
|
||||
// Add 16-bit crc (polynomial A) to payload
|
||||
crc = crc16(a,A)>>16;
|
||||
a[A>>3] = ((uint8_t*)&crc)[1];
|
||||
a[1+(A>>3)] = ((uint8_t*)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
|
||||
|
||||
dlsch->harq_processes[harq_pid]->B = A+16;
|
||||
// dlsch->harq_processes[harq_pid]->b = a;
|
||||
|
||||
AssertFatal((A/8)+3 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,MAX_NR_DLSCH_PAYLOAD_BYTES);
|
||||
|
||||
memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+3); // using 3 bytes to mimic the case of 24 bit crc
|
||||
}
|
||||
if (R<1000)
|
||||
Coderate = (float) R /(float) 1024;
|
||||
else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools
|
||||
Coderate = (float) R /(float) 2048;
|
||||
|
||||
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25)
|
||||
dlsch->harq_processes[harq_pid]->BG = 2;
|
||||
else
|
||||
dlsch->harq_processes[harq_pid]->BG = 1;
|
||||
|
||||
start_meas(dlsch_segmentation_stats);
|
||||
Kb = nr_segmentation(dlsch->harq_processes[harq_pid]->b,
|
||||
dlsch->harq_processes[harq_pid]->c,
|
||||
dlsch->harq_processes[harq_pid]->B,
|
||||
&dlsch->harq_processes[harq_pid]->C,
|
||||
&dlsch->harq_processes[harq_pid]->K,
|
||||
Zc,
|
||||
&dlsch->harq_processes[harq_pid]->F,
|
||||
dlsch->harq_processes[harq_pid]->BG);
|
||||
stop_meas(dlsch_segmentation_stats);
|
||||
F = dlsch->harq_processes[harq_pid]->F;
|
||||
|
||||
Kr = dlsch->harq_processes[harq_pid]->K;
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
uint16_t Kr_bytes;
|
||||
Kr_bytes = Kr>>3;
|
||||
#endif
|
||||
|
||||
//printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,dlsch->harq_processes[harq_pid]->K,Kr,BG,dlsch->harq_processes[harq_pid]->C);
|
||||
|
||||
for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
|
||||
//d_tmp[r] = &dlsch->harq_processes[harq_pid]->d[r][0];
|
||||
//channel_input[r] = &dlsch->harq_processes[harq_pid]->d[r][0];
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY,"Encoder: B %d F %d \n",dlsch->harq_processes[harq_pid]->B, dlsch->harq_processes[harq_pid]->F);
|
||||
LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,dlsch->harq_processes[harq_pid]->C);
|
||||
LOG_D(PHY,"input %d %d %d %d %d \n", dlsch->harq_processes[harq_pid]->c[r][0], dlsch->harq_processes[harq_pid]->c[r][1], dlsch->harq_processes[harq_pid]->c[r][2],dlsch->harq_processes[harq_pid]->c[r][3], dlsch->harq_processes[harq_pid]->c[r][4]);
|
||||
for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){
|
||||
LOG_D(PHY,"%d ", dlsch->harq_processes[harq_pid]->c[r][cnt]);
|
||||
}
|
||||
LOG_D(PHY,"\n");
|
||||
|
||||
#endif
|
||||
//ldpc_encoder_orig((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],dlsch->harq_processes[harq_pid]->d[r],*Zc,Kb,Kr,BG,0);
|
||||
//ldpc_encoder_optim((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],(unsigned char*)&dlsch->harq_processes[harq_pid]->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL);
|
||||
}
|
||||
encoder_implemparams_t impp;
|
||||
impp.n_segments=dlsch->harq_processes[harq_pid]->C;
|
||||
impp.tprep = tprep;
|
||||
impp.tinput = tinput;
|
||||
impp.tparity = tparity;
|
||||
impp.toutput = toutput;
|
||||
|
||||
for(int j=0;j<(dlsch->harq_processes[harq_pid]->C/8+1);j++) {
|
||||
impp.macro_num=j;
|
||||
nrLDPC_encoder(dlsch->harq_processes[harq_pid]->c,dlsch->harq_processes[harq_pid]->d,*Zc,Kb,Kr,dlsch->harq_processes[harq_pid]->BG,&impp);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4);
|
||||
write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[0][0],(3*8*Kr_bytes)+12,1,4);
|
||||
#endif
|
||||
AssertFatal((A / 8) + 4 <= MAX_NR_DLSCH_PAYLOAD_BYTES,
|
||||
"A %d is too big (A/8+4 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 4,
|
||||
MAX_NR_DLSCH_PAYLOAD_BYTES);
|
||||
|
||||
memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
|
||||
}
|
||||
else {
|
||||
// Add 16-bit crc (polynomial A) to payload
|
||||
crc = crc16(a,A)>>16;
|
||||
a[A>>3] = ((uint8_t*)&crc)[1];
|
||||
a[1+(A>>3)] = ((uint8_t*)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
|
||||
|
||||
harq->B = A+16;
|
||||
// harq->b = a;
|
||||
|
||||
F = dlsch->harq_processes[harq_pid]->F;
|
||||
AssertFatal((A / 8) + 3 <= MAX_NR_DLSCH_PAYLOAD_BYTES,
|
||||
"A %d is too big (A/8+3 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 3,
|
||||
MAX_NR_DLSCH_PAYLOAD_BYTES);
|
||||
|
||||
Kr = dlsch->harq_processes[harq_pid]->K;
|
||||
for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
|
||||
memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
|
||||
}
|
||||
if (R<1000)
|
||||
Coderate = (float) R /(float) 1024;
|
||||
else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools
|
||||
Coderate = (float) R /(float) 2048;
|
||||
|
||||
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25)
|
||||
harq->BG = 2;
|
||||
else
|
||||
harq->BG = 1;
|
||||
|
||||
start_meas(dlsch_segmentation_stats);
|
||||
Kb = nr_segmentation(harq->b, harq->c, harq->B, &harq->C, &harq->K, Zc, &harq->F, harq->BG);
|
||||
stop_meas(dlsch_segmentation_stats);
|
||||
F = harq->F;
|
||||
|
||||
Kr = harq->K;
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
uint16_t Kr_bytes;
|
||||
Kr_bytes = Kr>>3;
|
||||
#endif
|
||||
|
||||
//printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,harq->K,Kr,BG,harq->C);
|
||||
|
||||
for (r=0; r<harq->C; r++) {
|
||||
//d_tmp[r] = &harq->d[r][0];
|
||||
//channel_input[r] = &harq->d[r][0];
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, harq->F);
|
||||
LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,harq->C);
|
||||
LOG_D(PHY,"input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2],harq->c[r][3], harq->c[r][4]);
|
||||
for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){
|
||||
LOG_D(PHY,"%d ", harq->c[r][cnt]);
|
||||
}
|
||||
LOG_D(PHY,"\n");
|
||||
|
||||
#endif
|
||||
//ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0);
|
||||
//ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL);
|
||||
}
|
||||
encoder_implemparams_t impp;
|
||||
impp.n_segments=harq->C;
|
||||
impp.tprep = tprep;
|
||||
impp.tinput = tinput;
|
||||
impp.tparity = tparity;
|
||||
impp.toutput = toutput;
|
||||
|
||||
for(int j=0;j<(harq->C/8+1);j++) {
|
||||
impp.macro_num=j;
|
||||
nrLDPC_encoder(harq->c,harq->d,*Zc,Kb,Kr,harq->BG,&impp);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
write_output("enc_input0.m","enc_in0",&harq->c[0][0],Kr_bytes,1,4);
|
||||
write_output("enc_output0.m","enc0",&harq->d[0][0],(3*8*Kr_bytes)+12,1,4);
|
||||
#endif
|
||||
|
||||
F = harq->F;
|
||||
|
||||
Kr = harq->K;
|
||||
for (r=0; r<harq->C; r++) {
|
||||
|
||||
if (F>0) {
|
||||
for (int k=(Kr-F-2*(*Zc)); k<Kr-2*(*Zc); k++) {
|
||||
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
|
||||
dlsch->harq_processes[harq_pid]->d[r][k] = NR_NULL;
|
||||
harq->d[r][k] = NR_NULL;
|
||||
//if (k<(Kr-F+8))
|
||||
//printf("r %d filler bits [%d] = %d \n", r,k, dlsch->harq_processes[harq_pid]->d[r][k]);
|
||||
//printf("r %d filler bits [%d] = %d \n", r,k, harq->d[r][k]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
|
||||
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
|
||||
#endif
|
||||
|
||||
E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15->nrOfLayers, r);
|
||||
|
||||
|
||||
E = nr_get_E(G, harq->C, mod_order, rel15->nrOfLayers, r);
|
||||
|
||||
//#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n",
|
||||
r,
|
||||
dlsch->harq_processes[harq_pid]->C,
|
||||
harq->C,
|
||||
G,
|
||||
E,
|
||||
F,
|
||||
Kr-F-2*(*Zc),
|
||||
mod_order,nb_rb);
|
||||
|
||||
|
||||
// for tbslbrm calculation according to 5.4.2.1 of 38.212
|
||||
if (rel15->nrOfLayers < Nl)
|
||||
Nl = rel15->nrOfLayers;
|
||||
|
||||
|
||||
Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl);
|
||||
|
||||
|
||||
start_meas(dlsch_rate_matching_stats);
|
||||
nr_rate_matching_ldpc(Ilbrm,
|
||||
Tbslbrm,
|
||||
dlsch->harq_processes[harq_pid]->BG,
|
||||
harq->BG,
|
||||
*Zc,
|
||||
dlsch->harq_processes[harq_pid]->d[r],
|
||||
dlsch->harq_processes[harq_pid]->e+r_offset,
|
||||
dlsch->harq_processes[harq_pid]->C,
|
||||
harq->d[r],
|
||||
harq->e+r_offset,
|
||||
harq->C,
|
||||
F,
|
||||
Kr-F-2*(*Zc),
|
||||
rel15->rvIndex[0],
|
||||
@@ -542,22 +445,22 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
stop_meas(dlsch_rate_matching_stats);
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output ratematching e[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset);
|
||||
printf("output ratematching e[%d]= %d r_offset %u\n", i,harq->e[i+r_offset], r_offset);
|
||||
#endif
|
||||
|
||||
start_meas(dlsch_interleaving_stats);
|
||||
nr_interleaving_ldpc(E,
|
||||
mod_order,
|
||||
dlsch->harq_processes[harq_pid]->e+r_offset,
|
||||
dlsch->harq_processes[harq_pid]->f+r_offset);
|
||||
harq->e+r_offset,
|
||||
harq->f+r_offset);
|
||||
stop_meas(dlsch_interleaving_stats);
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output interleaving f[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset);
|
||||
printf("output interleaving f[%d]= %d r_offset %u\n", i,harq->f[i+r_offset], r_offset);
|
||||
|
||||
if (r==dlsch->harq_processes[harq_pid]->C-1)
|
||||
write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,G,1,4);
|
||||
if (r==harq->C-1)
|
||||
write_output("enc_output.m","enc",harq->f,G,1,4);
|
||||
#endif
|
||||
|
||||
r_offset += E;
|
||||
|
||||
@@ -289,12 +289,12 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB,
|
||||
AssertFatal( (dlsch_id>=0) && (dlsch_id<NUMBER_OF_NR_DLSCH_MAX),
|
||||
"illegal or no dlsch_id found!!! rnti %04x dlsch_id %d\n",rel15->rnti,dlsch_id);
|
||||
NR_gNB_DLSCH_t *dlsch = gNB->dlsch[dlsch_id][0];
|
||||
NR_DL_gNB_HARQ_t **harq = dlsch->harq_processes;
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
/// DLSCH struct
|
||||
memcpy((void*)&harq[dlsch->harq_ids[frame%2][slot]]->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||||
memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||||
gNB->num_pdsch_rnti[slot]++;
|
||||
AssertFatal(sdu!=NULL,"sdu is null\n");
|
||||
harq[dlsch->harq_ids[frame%2][slot]]->pdu = sdu;
|
||||
harq->pdu = sdu;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -393,6 +393,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
|
||||
// first bit of bitmap for sr presence and second bit for acknack presence
|
||||
uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq>0)<<1);
|
||||
uci_pdu->pucch_format = 0; // format 0
|
||||
uci_pdu->rnti = pucch_pdu->rnti;
|
||||
uci_pdu->ul_cqi = cqi;
|
||||
uci_pdu->timing_advance = 0xffff; // currently not valid
|
||||
uci_pdu->rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(signal_energy_nodc(&rxdataF[0][pucch_pdu->start_symbol_index*frame_parms->ofdm_symbol_size+re_offset],12)));
|
||||
|
||||
@@ -203,7 +203,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint
|
||||
return(dlsch);
|
||||
}
|
||||
|
||||
LOG_I(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag);
|
||||
LOG_D(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag);
|
||||
free_nr_ue_dlsch(&dlsch,N_RB_DL);
|
||||
|
||||
return(NULL);
|
||||
@@ -577,7 +577,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
// Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int
|
||||
if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
|
||||
LOG_I(PHY,"Segment %u CRC OK\n\033[0m",r);
|
||||
LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r);
|
||||
if (r==0) {
|
||||
for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]);
|
||||
}
|
||||
@@ -617,13 +617,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
|
||||
if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break;
|
||||
LOG_I(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
|
||||
LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
|
||||
err_flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (err_flag == 1) {
|
||||
LOG_I(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n",
|
||||
LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n",
|
||||
phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round);
|
||||
|
||||
harq_process->harq_ack.ack = 0;
|
||||
@@ -639,7 +639,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
if(is_crnti)
|
||||
{
|
||||
LOG_I(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
|
||||
LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
|
||||
phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS);
|
||||
}
|
||||
|
||||
@@ -813,6 +813,9 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
nb_rb = harq_process->nb_rb;
|
||||
harq_process->trials[harq_process->round]++;
|
||||
|
||||
// HARQ stats
|
||||
phy_vars_ue->dl_stats[harq_process->round]++;
|
||||
|
||||
uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs
|
||||
|
||||
harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*length_dmrs, nb_rb_oh, 0, harq_process->Nl);
|
||||
@@ -826,7 +829,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
G = harq_process->G;
|
||||
|
||||
LOG_I(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
|
||||
LOG_D(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
|
||||
|
||||
proc->decoder_main_available = 1;
|
||||
proc->decoder_thread_available = 0;
|
||||
@@ -905,7 +908,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
return((1+dlsch->max_ldpc_iterations));
|
||||
}
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
|
||||
LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
|
||||
LOG_D(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
|
||||
|
||||
|
||||
notifiedFIFO_elt_t *res_dl;
|
||||
@@ -1079,7 +1082,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
#if UE_TIMING_TRACE
|
||||
start_meas(dlsch_turbo_decoding_stats);
|
||||
#endif
|
||||
LOG_I(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
|
||||
LOG_D(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
|
||||
|
||||
/*for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){
|
||||
inv_d[cnt] = (1)*harq_process->d[r][cnt];
|
||||
@@ -1119,7 +1122,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
ret = 2;
|
||||
}
|
||||
else {
|
||||
LOG_I(PHY,"CRC NOK\n");
|
||||
LOG_D(PHY,"CRC NOK\n");
|
||||
ret = 1+dlsch->max_ldpc_iterations;
|
||||
}
|
||||
|
||||
@@ -1160,7 +1163,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
|
||||
if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break;
|
||||
LOG_I(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
|
||||
LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
|
||||
err_flag = 1;
|
||||
}
|
||||
//} //loop r
|
||||
@@ -1181,7 +1184,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
}
|
||||
if(is_crnti)
|
||||
{
|
||||
LOG_I(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
|
||||
LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
|
||||
phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mlimit,harq_process->TBS);
|
||||
}
|
||||
|
||||
@@ -1332,7 +1335,7 @@ void nr_dlsch_decoding_process(void *arg)
|
||||
|
||||
p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[r];
|
||||
nb_symb_sch = harq_process->nb_symbols;
|
||||
LOG_I(PHY,"dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_slot_rx, proc->num_seg, r, harq_process->nb_symbols);
|
||||
LOG_D(PHY,"dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_slot_rx, proc->num_seg, r, harq_process->nb_symbols);
|
||||
|
||||
|
||||
nb_rb = harq_process->nb_rb;
|
||||
@@ -1351,7 +1354,7 @@ void nr_dlsch_decoding_process(void *arg)
|
||||
harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl);
|
||||
G = harq_process->G;
|
||||
|
||||
LOG_I(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
|
||||
LOG_D(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
|
||||
|
||||
if ((harq_process->R)<1024)
|
||||
Coderate = (float) (harq_process->R) /(float) 1024;
|
||||
@@ -1571,12 +1574,12 @@ void nr_dlsch_decoding_process(void *arg)
|
||||
ret = 2;
|
||||
}
|
||||
else {
|
||||
LOG_I(PHY,"Segment %u CRC NOK\n",r);
|
||||
LOG_D(PHY,"Segment %u CRC NOK\n",r);
|
||||
ret = 1+dlsch->max_ldpc_iterations;
|
||||
}
|
||||
|
||||
if (no_iteration_ldpc > 10)
|
||||
LOG_I(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc);
|
||||
LOG_D(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc);
|
||||
|
||||
|
||||
for (int m=0; m < Kr>>3; m ++)
|
||||
|
||||
@@ -94,8 +94,6 @@ typedef struct {
|
||||
uint32_t frame;
|
||||
/// Subframe where current HARQ round was sent
|
||||
uint32_t subframe;
|
||||
/// Index of current HARQ round for this DLSCH
|
||||
uint8_t round;
|
||||
/// MIMO mode for this DLSCH
|
||||
MIMO_mode_t mimo_mode;
|
||||
/// Concatenated sequences
|
||||
@@ -138,8 +136,8 @@ typedef struct {
|
||||
} NR_gNB_SCH_STATS_t;
|
||||
|
||||
typedef struct {
|
||||
/// Pointers to 16 HARQ processes for the DLSCH
|
||||
NR_DL_gNB_HARQ_t *harq_processes[NR_MAX_NB_HARQ_PROCESSES];
|
||||
/// Pointers to variables related to DLSCH harq process
|
||||
NR_DL_gNB_HARQ_t harq_process;
|
||||
/// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
|
||||
int32_t *txdataF[NR_MAX_NB_LAYERS];
|
||||
/// Modulated symbols buffer
|
||||
@@ -834,6 +832,7 @@ typedef struct PHY_VARS_gNB_s {
|
||||
notifiedFIFO_t *respDecode;
|
||||
tpool_t *threadPool;
|
||||
int nbDecode;
|
||||
uint8_t pusch_proc_threads;
|
||||
|
||||
} PHY_VARS_gNB;
|
||||
|
||||
|
||||
@@ -201,10 +201,10 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
|
||||
LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot);
|
||||
nr_generate_pdsch(gNB,frame, slot);
|
||||
if ((frame&127) == 0) dump_pdsch_stats(gNB);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
|
||||
}
|
||||
|
||||
if ((frame&127) == 0) dump_pdsch_stats(gNB);
|
||||
|
||||
//apply the OFDM symbol rotation here
|
||||
apply_nr_rotation(fp,(int16_t*) &gNB->common_vars.txdataF[0][txdataF_offset],slot,0,fp->Ncp==EXTENDED?12:14,fp->ofdm_symbol_size);
|
||||
|
||||
@@ -780,19 +780,15 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t
|
||||
|
||||
if (harq_status->ack == DL_ACKNACK_NO_SET) {
|
||||
LOG_E(PHY,"PUCCH Downlink acknowledgment has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
|
||||
return (0);
|
||||
}
|
||||
else if (harq_status->vDAI_DL == DL_DAI_NO_SET) {
|
||||
LOG_E(PHY,"PUCCH Downlink DAI has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
|
||||
return (0);
|
||||
}
|
||||
else if (harq_status->vDAI_DL > NR_DL_MAX_DAI) {
|
||||
LOG_E(PHY,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
|
||||
return (0);
|
||||
}
|
||||
else if (harq_status->send_harq_status == 0) {
|
||||
LOG_E(PHY,"PUCCH Downlink ack can not be transmitted : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
|
||||
return(0);
|
||||
LOG_D(PHY,"PUCCH Downlink ack can not be transmitted : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -808,6 +804,8 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t
|
||||
number_harq_feedback++;
|
||||
ack_data[code_word][dai_current - 1] = harq_status->ack;
|
||||
dai[code_word][dai_current - 1] = dai_current;
|
||||
harq_status->slot_for_feedback_ack = NR_MAX_SLOTS_PER_FRAME;
|
||||
harq_status->send_harq_status = 0;
|
||||
}
|
||||
if (do_reset == TRUE) {
|
||||
init_downlink_harq_status(ue->dlsch[thread_idx][gNB_id][code_word]->harq_processes[dl_harq_pid]);
|
||||
|
||||
@@ -427,7 +427,7 @@ int main(int argc, char **argv)
|
||||
UE->dlsch_ra[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0);
|
||||
unsigned char harq_pid = 0; //dlsch->harq_ids[subframe];
|
||||
NR_gNB_DLSCH_t *dlsch = gNB->dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
//time_stats_t *rm_stats, *te_stats, *i_stats;
|
||||
uint8_t is_crnti = 0, llr8_flag = 0;
|
||||
unsigned int TBS = 8424;
|
||||
@@ -519,7 +519,7 @@ int main(int argc, char **argv)
|
||||
|
||||
//if (i<16)
|
||||
// printf("encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]);
|
||||
if (dlsch->harq_processes[0]->f[i] == 0)
|
||||
if (dlsch->harq_process.f[i] == 0)
|
||||
modulated_input[i] = 1.0; ///sqrt(2); //QPSK
|
||||
else
|
||||
modulated_input[i] = -1.0; ///sqrt(2);
|
||||
@@ -547,7 +547,7 @@ int main(int argc, char **argv)
|
||||
else
|
||||
channel_output_uncoded[i] = 0;
|
||||
|
||||
if (channel_output_uncoded[i] != dlsch->harq_processes[harq_pid]->f[i])
|
||||
if (channel_output_uncoded[i] != dlsch->harq_process.f[i])
|
||||
errors_bit_uncoded = errors_bit_uncoded + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -186,8 +186,7 @@ void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dm
|
||||
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1;
|
||||
void nr_dlsim_preprocessor(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd) {
|
||||
sub_frame_t slot) {
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
AssertFatal(UE_info->num_UEs == 1, "can have only a single UE\n");
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[0];
|
||||
@@ -203,15 +202,25 @@ void nr_dlsim_preprocessor(module_id_t module_id,
|
||||
sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
|
||||
sched_ctrl->cce_index = 0;
|
||||
|
||||
/* set "any" value for PUCCH (simulator evaluates PDSCH only) */
|
||||
sched_ctrl->pucch_sched_idx = 0;
|
||||
sched_ctrl->pucch_occ_idx = 0;
|
||||
|
||||
sched_ctrl->rbStart = g_rbStart;
|
||||
sched_ctrl->rbSize = g_rbSize;
|
||||
sched_ctrl->mcs = g_mcsIndex;
|
||||
sched_ctrl->time_domain_allocation = 2;
|
||||
sched_ctrl->mcsTableIdx = g_mcsTableIdx;
|
||||
/* the simulator assumes the HARQ PID is equal to the slot number */
|
||||
sched_ctrl->dl_harq_pid = slot;
|
||||
/* The scheduler uses lists to track whether a HARQ process is
|
||||
* free/busy/awaiting retransmission, and updates the HARQ process states.
|
||||
* However, in the simulation, we never get ack or nack for any HARQ process,
|
||||
* thus the list and HARQ states don't match what the scheduler expects.
|
||||
* Therefore, below lines just "repair" everything so that the scheduler
|
||||
* won't remark that there is no HARQ feedback */
|
||||
sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process
|
||||
if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ...
|
||||
add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available
|
||||
else
|
||||
add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot); // ... make PID retransmission
|
||||
sched_ctrl->harq_processes[slot].is_waiting = false;
|
||||
AssertFatal(sched_ctrl->rbStart >= 0, "invalid rbStart %d\n", sched_ctrl->rbStart);
|
||||
AssertFatal(sched_ctrl->rbSize > 0, "invalid rbSize %d\n", sched_ctrl->rbSize);
|
||||
AssertFatal(sched_ctrl->mcs >= 0, "invalid sched_ctrl->mcs %d\n", sched_ctrl->mcs);
|
||||
@@ -671,6 +680,9 @@ int main(int argc, char **argv)
|
||||
rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
|
||||
phy_init_nr_gNB(gNB,0,0);
|
||||
N_RB_DL = gNB->frame_parms.N_RB_DL;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
|
||||
UE_info->num_UEs=1;
|
||||
|
||||
// stub to configure frame_parms
|
||||
// nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
|
||||
// call MAC to configure common parameters
|
||||
@@ -836,10 +848,10 @@ int main(int argc, char **argv)
|
||||
scheduled_response.thread_id = UE_proc.thread_id;
|
||||
|
||||
nr_ue_phy_config_request(&UE_mac->phy_config);
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
|
||||
//NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
|
||||
snrRun = 0;
|
||||
|
||||
|
||||
for (SNR = snr0; SNR < snr1; SNR += .2) {
|
||||
|
||||
varArray_t *table_tx=initVarArray(1000,sizeof(double));
|
||||
@@ -885,7 +897,7 @@ int main(int argc, char **argv)
|
||||
NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];
|
||||
|
||||
NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_processes[slot]->pdsch_pdu.pdsch_pdu_rel15;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
UE_harq_process->harq_ack.ack = 0;
|
||||
round = 0;
|
||||
@@ -901,15 +913,11 @@ int main(int argc, char **argv)
|
||||
|
||||
|
||||
UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round;
|
||||
gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round;
|
||||
for (int i=0; i<MAX_NUM_CORESET; i++)
|
||||
gNB_mac->UE_info.num_pdcch_cand[0][i] = 0;
|
||||
|
||||
if (css_flag == 0) {
|
||||
const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160};
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
const int num_slots_per_tdd = slots_per_frame[*scc->ssbSubcarrierSpacing] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity);
|
||||
nr_schedule_ue_spec(0, frame, slot, num_slots_per_tdd);
|
||||
nr_schedule_ue_spec(0, frame, slot);
|
||||
} else {
|
||||
nr_schedule_css_dlsch_phytest(0,frame,slot);
|
||||
}
|
||||
@@ -1053,8 +1061,8 @@ int main(int argc, char **argv)
|
||||
|
||||
for (i = 0; i < available_bits; i++) {
|
||||
|
||||
if(((gNB_dlsch->harq_processes[harq_pid]->f[i] == 0) && (UE_llr[i] <= 0)) ||
|
||||
((gNB_dlsch->harq_processes[harq_pid]->f[i] == 1) && (UE_llr[i] >= 0)))
|
||||
if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) ||
|
||||
((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0)))
|
||||
{
|
||||
if(errors_scrambling == 0) {
|
||||
LOG_D(PHY,"\n");
|
||||
@@ -1067,7 +1075,7 @@ int main(int argc, char **argv)
|
||||
for (i = 0; i < TBS; i++) {
|
||||
|
||||
estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
|
||||
test_input_bit[i] = (gNB_dlsch->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
|
||||
test_input_bit[i] = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
|
||||
|
||||
if (estimated_output_bit[i] != test_input_bit[i]) {
|
||||
if(errors_bit == 0)
|
||||
@@ -1107,9 +1115,9 @@ int main(int argc, char **argv)
|
||||
if (print_perf==1) {
|
||||
printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
|
||||
1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
|
||||
gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
|
||||
gNB->dlsch[0][0]->harq_processes[0]->K,
|
||||
gNB->dlsch[0][0]->harq_processes[0]->K/((gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
|
||||
gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
|
||||
gNB->dlsch[0][0]->harq_process.K,
|
||||
gNB->dlsch[0][0]->harq_process.K/((gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
|
||||
printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
|
||||
printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
|
||||
printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#define CONFIG_STRING_L1_LOCAL_N_PORTD "local_n_portd"
|
||||
#define CONFIG_STRING_L1_REMOTE_N_PORTD "remote_n_portd"
|
||||
#define CONFIG_STRING_L1_TRANSPORT_N_PREFERENCE "tr_n_preference"
|
||||
#define CONFIG_STRING_L1_PUSCH_PROC_THREADS "pusch_proc_threads"
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* L1 configuration parameters */
|
||||
@@ -61,6 +62,7 @@
|
||||
{CONFIG_STRING_L1_REMOTE_N_PORTC, NULL, 0, uptr:NULL, defintval:50030, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_LOCAL_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_REMOTE_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:1, TYPE_UINT, 0} \
|
||||
}
|
||||
#define L1_CC_IDX 0
|
||||
#define L1_TRANSPORT_N_PREFERENCE_IDX 1
|
||||
@@ -71,6 +73,7 @@
|
||||
#define L1_REMOTE_N_PORTC_IDX 6
|
||||
#define L1_LOCAL_N_PORTD_IDX 7
|
||||
#define L1_REMOTE_N_PORTD_IDX 8
|
||||
#define L1_PUSCH_PROC_THREADS 9
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
#include "nfapi_vnf.h"
|
||||
#include "nfapi_pnf.h"
|
||||
|
||||
#include "L1_paramdef.h"
|
||||
//#include "L1_paramdef.h"
|
||||
#include "L1_nr_paramdef.h"
|
||||
#include "MACRLC_paramdef.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
//#include "RRC_config_tools.h"
|
||||
@@ -399,6 +400,8 @@ void RCconfig_NR_L1(void) {
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
}
|
||||
|
||||
RC.gNB[j]->pusch_proc_threads = *(L1_ParamList.paramarray[j][L1_PUSCH_PROC_THREADS].uptr);
|
||||
|
||||
if(strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
|
||||
//sf_ahead = 2; // Need 4 subframe gap between RX and TX
|
||||
}else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
|
||||
|
||||
@@ -82,7 +82,6 @@ typedef enum {
|
||||
/* global parameters, not under a specific section */
|
||||
#define GNB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity"
|
||||
#define GNB_CONFIG_STRING_ACTIVE_GNBS "Active_gNBs"
|
||||
#define GNB_CONFIG_PUSCH_THREADS "Num_Threads_PUSCH"
|
||||
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* global configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -92,10 +91,6 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_ACTIVE_GNBS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRINGLIST, 0} \
|
||||
}
|
||||
|
||||
#define NUM_THREADS_DESC { \
|
||||
{GNB_CONFIG_PUSCH_THREADS, NULL, 0, uptr:&num_threads_pusch, defuintval:1, TYPE_UINT, 0} \
|
||||
}
|
||||
|
||||
#define GNB_ASN1_VERBOSITY_IDX 0
|
||||
#define GNB_ACTIVE_GNBS_IDX 1
|
||||
|
||||
|
||||
@@ -119,22 +119,22 @@ typedef NR_BSR_SHORT NR_BSR_SHORT_TRUNCATED;
|
||||
|
||||
// Long BSR for all logical channel group ID
|
||||
typedef struct {
|
||||
uint8_t Buffer_size7: 8;
|
||||
uint8_t Buffer_size6: 8;
|
||||
uint8_t Buffer_size5: 8;
|
||||
uint8_t Buffer_size4: 8;
|
||||
uint8_t Buffer_size3: 8;
|
||||
uint8_t Buffer_size2: 8;
|
||||
uint8_t Buffer_size1: 8;
|
||||
uint8_t Buffer_size0: 8;
|
||||
uint8_t LcgID0: 1;
|
||||
uint8_t LcgID1: 1;
|
||||
uint8_t LcgID2: 1;
|
||||
uint8_t LcgID3: 1;
|
||||
uint8_t LcgID4: 1;
|
||||
uint8_t LcgID5: 1;
|
||||
uint8_t LcgID6: 1;
|
||||
uint8_t LcgID7: 1;
|
||||
uint8_t LcgID0: 1; // octet 1 [0]
|
||||
uint8_t LcgID1: 1; // octet 1 [1]
|
||||
uint8_t LcgID2: 1; // octet 1 [2]
|
||||
uint8_t LcgID3: 1; // octet 1 [3]
|
||||
uint8_t LcgID4: 1; // octet 1 [4]
|
||||
uint8_t LcgID5: 1; // octet 1 [5]
|
||||
uint8_t LcgID6: 1; // octet 1 [6]
|
||||
uint8_t LcgID7: 1; // octet 1 [7]
|
||||
uint8_t Buffer_size0: 8; // octet 2 [7:0]
|
||||
uint8_t Buffer_size1: 8; // octet 3 [7:0]
|
||||
uint8_t Buffer_size2: 8; // octet 4 [7:0]
|
||||
uint8_t Buffer_size3: 8; // octet 5 [7:0]
|
||||
uint8_t Buffer_size4: 8; // octet 6 [7:0]
|
||||
uint8_t Buffer_size5: 8; // octet 7 [7:0]
|
||||
uint8_t Buffer_size6: 8; // octet 8 [7:0]
|
||||
uint8_t Buffer_size7: 8; // octet 9 [7:0]
|
||||
} __attribute__ ((__packed__)) NR_BSR_LONG;
|
||||
|
||||
typedef NR_BSR_LONG NR_BSR_LONG_TRUNCATED;
|
||||
|
||||
@@ -2382,9 +2382,9 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) {
|
||||
|
||||
// Set the transform precoding status according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16:
|
||||
// - "UE procedure for applying transform precoding on PUSCH"
|
||||
uint8_t get_transformPrecoding(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_PUSCH_Config_t *pusch_config,
|
||||
NR_BWP_Uplink_t *ubwp,
|
||||
uint8_t get_transformPrecoding(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_PUSCH_Config_t *pusch_config,
|
||||
const NR_BWP_Uplink_t *ubwp,
|
||||
uint8_t *dci_format,
|
||||
int rnti_type,
|
||||
uint8_t configuredGrant){
|
||||
@@ -2416,8 +2416,8 @@ uint8_t get_transformPrecoding(NR_ServingCellConfigCommon_t *scc,
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
dci_pdu_rel15_t *dci_pdu,
|
||||
nr_dci_format_t format,
|
||||
nr_rnti_type_t rnti_type,
|
||||
|
||||
@@ -53,8 +53,8 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
|
||||
|
||||
int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
|
||||
|
||||
uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
dci_pdu_rel15_t *dci_pdu,
|
||||
nr_dci_format_t format,
|
||||
nr_rnti_type_t rnti_type,
|
||||
@@ -150,9 +150,9 @@ uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Posi
|
||||
@param rnti_type rnti type
|
||||
@param configuredGrant indicates whether a configured grant was received or not
|
||||
@returns transformPrecoding value */
|
||||
uint8_t get_transformPrecoding(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_PUSCH_Config_t *pusch_config,
|
||||
NR_BWP_Uplink_t *ubwp,
|
||||
uint8_t get_transformPrecoding(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_PUSCH_Config_t *pusch_config,
|
||||
const NR_BWP_Uplink_t *ubwp,
|
||||
uint8_t *dci_format,
|
||||
int rnti_type,
|
||||
uint8_t configuredGrant);
|
||||
|
||||
@@ -82,6 +82,7 @@ int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg,
|
||||
}
|
||||
|
||||
int nb_slots_per_period = ((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME)/nb_periods_per_frame;
|
||||
cfg->tdd_table.tdd_period_in_slots = nb_slots_per_period;
|
||||
|
||||
if ( (nrofDownlinkSymbols + nrofUplinkSymbols) == 0 )
|
||||
AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots),
|
||||
|
||||
@@ -350,6 +350,8 @@ typedef struct {
|
||||
RA_config_t ra;
|
||||
/// SSB index from MIB decoding
|
||||
uint8_t mib_ssb;
|
||||
/// Last NDI of UL HARQ processes
|
||||
uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES];
|
||||
|
||||
//// FAPI-like interface message
|
||||
fapi_nr_ul_config_request_t *ul_config_request;
|
||||
|
||||
@@ -2046,7 +2046,7 @@ uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload,
|
||||
if (crnti) {
|
||||
// MAC CE fixed subheader
|
||||
mac_pdu_ptr->R = 0;
|
||||
mac_pdu_ptr->LCID = CRNTI;
|
||||
mac_pdu_ptr->LCID = UL_SCH_LCID_C_RNTI;
|
||||
mac_pdu_ptr++;
|
||||
|
||||
// C-RNTI MAC CE (2 octets)
|
||||
|
||||
@@ -889,7 +889,8 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
|
||||
uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1){
|
||||
// Push data from MAC to PHY only when NDI toggles
|
||||
if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){
|
||||
// Getting IP traffic to be transmitted
|
||||
data_existing = nr_ue_get_sdu(mod_id,
|
||||
cc_id,
|
||||
@@ -901,6 +902,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
&access_mode);
|
||||
}
|
||||
|
||||
mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator;
|
||||
//Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
|
||||
if (!IS_SOFTMODEM_NOS1 || !data_existing) {
|
||||
//Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
|
||||
|
||||
@@ -346,10 +346,18 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
}
|
||||
|
||||
RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL =
|
||||
calloc(n * 275, sizeof(uint16_t));
|
||||
calloc(n * MAX_BWP_SIZE, sizeof(uint16_t));
|
||||
AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL,
|
||||
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
|
||||
|
||||
for (int i = 0; i < MAX_NUM_BWP; ++i) {
|
||||
RC.nrmac[Mod_idP]->pucch_index_used[i] =
|
||||
calloc(n, sizeof(*RC.nrmac[Mod_idP]->pucch_index_used));
|
||||
AssertFatal(RC.nrmac[Mod_idP]->pucch_index_used[i],
|
||||
"could not allocate memory for RC.nrmac[]->pucch_index_used[%d]\n",
|
||||
i);
|
||||
}
|
||||
|
||||
LOG_I(MAC,"Configuring common parameters from NR ServingCellConfig\n");
|
||||
|
||||
config_common(Mod_idP,
|
||||
@@ -389,22 +397,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
||||
if (add_ue == 1 && get_softmodem_params()->phy_test) {
|
||||
const int UE_id = add_new_nr_ue(Mod_idP,rnti);
|
||||
UE_info->secondaryCellGroup[UE_id] = secondaryCellGroup;
|
||||
compute_csi_bitlen (secondaryCellGroup, UE_info, UE_id);
|
||||
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList =
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
|
||||
AssertFatal(bwpList->list.count == 1,
|
||||
"downlinkBWP_ToAddModList has %d BWP!\n",
|
||||
bwpList->list.count);
|
||||
const int bwp_id = 1;
|
||||
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
|
||||
struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList =
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList;
|
||||
AssertFatal(ubwpList->list.count == 1,
|
||||
"uplinkBWP_ToAddModList has %d BWP!\n",
|
||||
ubwpList->list.count);
|
||||
UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1];
|
||||
const int UE_id = add_new_nr_ue(Mod_idP, rnti, secondaryCellGroup);
|
||||
LOG_I(PHY,"Added new UE_id %d/%x with initial secondaryCellGroup\n",UE_id,rnti);
|
||||
} else if (add_ue == 1 && !get_softmodem_params()->phy_test) {
|
||||
/* TODO: should check for free RA process */
|
||||
|
||||
@@ -59,24 +59,31 @@ void clear_mac_stats(gNB_MAC_INST *gNB) {
|
||||
memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t));
|
||||
}
|
||||
|
||||
void dump_mac_stats(gNB_MAC_INST *gNB) {
|
||||
|
||||
void dump_mac_stats(gNB_MAC_INST *gNB)
|
||||
{
|
||||
NR_UE_info_t *UE_info = &gNB->UE_info;
|
||||
NR_mac_stats_t *stats;
|
||||
int lc_id;
|
||||
|
||||
for (int UE_id=0;UE_id<MAX_MOBILES_PER_GNB;UE_id++) {
|
||||
if (UE_info->active[UE_id]) {
|
||||
LOG_I(MAC, "UE %x\n", UE_info->rnti[UE_id]);
|
||||
stats = &UE_info->mac_stats[UE_id];
|
||||
LOG_I(MAC,"dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",stats->dlsch_rounds[0],stats->dlsch_rounds[1],stats->dlsch_rounds[2],stats->dlsch_rounds[3],stats->dlsch_errors);
|
||||
LOG_I(MAC,"dlsch_total_bytes %d\n",stats->dlsch_total_bytes);
|
||||
LOG_I(MAC,"ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",stats->ulsch_rounds[0],stats->ulsch_rounds[1],stats->ulsch_rounds[2],stats->ulsch_rounds[3],stats->ulsch_errors);
|
||||
LOG_I(MAC,"ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",stats->ulsch_total_bytes_scheduled,stats->ulsch_total_bytes_rx);
|
||||
for (lc_id=0;lc_id<63;lc_id++) {
|
||||
if (stats->lc_bytes_tx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes TX\n",lc_id,stats->lc_bytes_tx[lc_id]);
|
||||
if (stats->lc_bytes_rx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes RX\n",lc_id,stats->lc_bytes_rx[lc_id]);
|
||||
}
|
||||
int num = 1;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs);
|
||||
const NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
|
||||
LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",
|
||||
UE_id,
|
||||
stats->dlsch_rounds[0], stats->dlsch_rounds[1],
|
||||
stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors);
|
||||
LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes);
|
||||
LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",
|
||||
UE_id,
|
||||
stats->ulsch_rounds[0], stats->ulsch_rounds[1],
|
||||
stats->ulsch_rounds[2], stats->ulsch_rounds[3], stats->ulsch_errors);
|
||||
LOG_I(MAC,
|
||||
"UE %d: ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",
|
||||
UE_id,
|
||||
stats->ulsch_total_bytes_scheduled, stats->ulsch_total_bytes_rx);
|
||||
for (int lc_id = 0; lc_id < 63; lc_id++) {
|
||||
if (stats->lc_bytes_tx[lc_id] > 0)
|
||||
LOG_I(MAC, "UE %d: LCID %d: %d bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]);
|
||||
if (stats->lc_bytes_rx[lc_id] > 0)
|
||||
LOG_I(MAC, "UE %d: LCID %d: %d bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,6 +96,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
|
||||
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
|
||||
nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0];
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***)gNB->pdcch_pdu_idx[CC_idP];
|
||||
nfapi_nr_ul_tti_request_t *future_ul_tti_req =
|
||||
&gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots];
|
||||
nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0];
|
||||
@@ -103,6 +111,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
|
||||
DL_req[CC_idP].dl_tti_request_body.nPDUs = 0;
|
||||
DL_req[CC_idP].dl_tti_request_body.nGroup = 0;
|
||||
//DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000;
|
||||
memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET);
|
||||
|
||||
UL_dci_req[CC_idP].SFN = frameP;
|
||||
UL_dci_req[CC_idP].Slot = slotP;
|
||||
@@ -299,11 +308,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
|
||||
int nb_periods_per_frame;
|
||||
|
||||
const int UE_id = 0;
|
||||
const int bwp_id = 1;
|
||||
|
||||
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
|
||||
NR_UE_info_t *UE_info = &gNB->UE_info;
|
||||
NR_COMMON_channels_t *cc = gNB->common_channels;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
@@ -360,23 +367,27 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
|
||||
}
|
||||
|
||||
const uint64_t dlsch_in_slot_bitmap = (1 << 1) | (1 << 3);
|
||||
const uint64_t ulsch_in_slot_bitmap = (1 << 8);
|
||||
#define BIT(x) (1 << (x))
|
||||
const uint64_t dlsch_in_slot_bitmap = BIT( 1) | BIT( 2) | BIT( 3) | BIT( 4) | BIT( 5) | BIT( 6)
|
||||
| BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16);
|
||||
const uint64_t ulsch_in_slot_bitmap = BIT( 8) | BIT(18);
|
||||
|
||||
memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0
|
||||
memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1
|
||||
for (int i=0; i<MAX_NUM_CORESET; i++)
|
||||
RC.nrmac[module_idP]->UE_info.num_pdcch_cand[UE_id][i] = 0;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id])
|
||||
for (int i=0; i<MAX_NUM_CORESET; i++)
|
||||
UE_info->num_pdcch_cand[UE_id][i] = 0;
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
//mbsfn_status[CC_id] = 0;
|
||||
|
||||
// clear vrb_maps
|
||||
memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * 275);
|
||||
memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
// clear last scheduled slot's content (only)!
|
||||
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
const int last_slot = (slot + num_slots - 1) % num_slots;
|
||||
uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL;
|
||||
memset(&vrb_map_UL[last_slot * 275], 0, sizeof(uint16_t) * 275);
|
||||
memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
|
||||
clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot);
|
||||
}
|
||||
@@ -410,9 +421,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
// This schedule SR
|
||||
// TODO
|
||||
|
||||
// This schedule CSI measurement reporting
|
||||
if (UE_info->active[UE_id])
|
||||
nr_csi_meas_reporting(module_idP, UE_id, frame, slot, num_slots_per_tdd, nr_ulmix_slots, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]);
|
||||
// Schedule CSI measurement reporting: check in slot 0 for the whole frame
|
||||
if (slot == 0)
|
||||
nr_csi_meas_reporting(module_idP, frame, slot);
|
||||
|
||||
// This schedule RA procedure if not in phy_test mode
|
||||
// Otherwise already consider 5G already connected
|
||||
@@ -421,19 +432,16 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
}
|
||||
|
||||
// This schedules the DCI for Uplink and subsequently PUSCH
|
||||
if (slot < 10) {
|
||||
{
|
||||
nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap);
|
||||
}
|
||||
|
||||
// This schedules the DCI for Downlink and PDSCH
|
||||
if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd)
|
||||
&& slot < 10) {
|
||||
nr_schedule_ue_spec(module_idP, frame, slot, num_slots_per_tdd);
|
||||
}
|
||||
if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot))
|
||||
nr_schedule_ue_spec(module_idP, frame, slot);
|
||||
|
||||
|
||||
if (UE_info->active[UE_id])
|
||||
nr_schedule_pucch(module_idP, UE_id, nr_ulmix_slots, frame, slot);
|
||||
nr_schedule_pucch(module_idP, frame, slot);
|
||||
|
||||
stop_meas(&RC.nrmac[module_idP]->eNB_scheduler);
|
||||
|
||||
|
||||
@@ -645,7 +645,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
|
||||
}
|
||||
|
||||
uint16_t *vrb_map_UL =
|
||||
&RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * 275];
|
||||
&RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE];
|
||||
for (int i = 0; i < ra->msg3_nb_rb; ++i) {
|
||||
AssertFatal(!vrb_map_UL[i + ra->msg3_first_rb],
|
||||
"RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n",
|
||||
@@ -766,7 +766,7 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
sub_frame_t slotP)
|
||||
{
|
||||
|
||||
int dci_formats[2], rnti_types[2], mcsIndex;
|
||||
int mcsIndex;
|
||||
int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0;
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
|
||||
@@ -793,27 +793,55 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) {
|
||||
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body;
|
||||
nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
|
||||
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||||
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
|
||||
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
|
||||
memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||||
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
|
||||
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||||
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
// Checking if the DCI allocation is feasible in current subframe
|
||||
if (dl_req->nPDUs == NFAPI_NR_MAX_DL_TTI_PDUS) {
|
||||
if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
|
||||
LOG_I(MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, RA_rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t nr_of_candidates, aggregation_level;
|
||||
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
|
||||
NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1];
|
||||
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */);
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
0, // Y
|
||||
0, // m
|
||||
nr_of_candidates);
|
||||
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
|
||||
|
||||
/* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not
|
||||
* exist, create it. This is especially important if we have multiple RAs,
|
||||
* and the DLSCH has to reuse them, so we need to mark them */
|
||||
const int bwpid = bwp->bwp_Id;
|
||||
const int coresetid = coreset->controlResourceSetId;
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid];
|
||||
if (!pdcch_pdu_rel15) {
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||||
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
|
||||
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
dl_req->nPDUs += 1;
|
||||
pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
nr_configure_pdcch(pdcch_pdu_rel15, ss, coreset, scc, bwp);
|
||||
nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15;
|
||||
}
|
||||
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||||
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
|
||||
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||||
dl_req->nPDUs+=1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
LOG_I(MAC,"[gNB %d] [RAPROC] CC_id %d Frame %d, slotP %d: Generating RAR DCI, state %d\n", module_idP, CC_id, frameP, slotP, ra->state);
|
||||
|
||||
// This code from this point on will not work on initialBWP or CORESET0
|
||||
@@ -824,7 +852,6 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
ra->crnti);
|
||||
AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
|
||||
"downlinkBWP_ToAddModList has %d BWP!\n", ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
|
||||
NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1];
|
||||
NR_BWP_Uplink_t *ubwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1];
|
||||
|
||||
LOG_I(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
|
||||
@@ -837,7 +864,11 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
|
||||
pdsch_pdu_rel15->pduBitmap = 0;
|
||||
pdsch_pdu_rel15->rnti = RA_rnti;
|
||||
pdsch_pdu_rel15->pduIndex = 0;
|
||||
/* SCF222: PDU index incremented for each PDSCH PDU sent in TX control
|
||||
* message. This is used to associate control information to data and is
|
||||
* reset every slot. */
|
||||
const int pduindex = nr_mac->pdu_index[CC_id]++;
|
||||
pdsch_pdu_rel15->pduIndex = pduindex;
|
||||
|
||||
|
||||
pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
@@ -887,65 +918,61 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
|
||||
pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, NrOfSymbols);
|
||||
|
||||
dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
|
||||
dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
|
||||
/* Fill PDCCH DL DCI PDU */
|
||||
nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
|
||||
pdcch_pdu_rel15->numDlDci++;
|
||||
dci_pdu->RNTI = RA_rnti;
|
||||
/* TODO: remove next line */
|
||||
AssertFatal(ss->searchSpaceType->present != NR_SearchSpace__searchSpaceType_PR_ue_Specific,
|
||||
"shouldn't the RA SS be common?\n");
|
||||
dci_pdu->ScramblingId = *scc->physCellId;
|
||||
dci_pdu->ScramblingRNTI = 0;
|
||||
dci_pdu->AggregationLevel = aggregation_level;
|
||||
dci_pdu->CceIndex = CCEIndex;
|
||||
dci_pdu->beta_PDCCH_1_0 = 0;
|
||||
dci_pdu->powerControlOffsetSS = 1;
|
||||
|
||||
dci_pdu_rel15_t dci_payload;
|
||||
dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
|
||||
pdsch_pdu_rel15->rbStart,dci10_bw);
|
||||
dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment;
|
||||
dci_pdu_rel15[0].vrb_to_prb_mapping.val = 0;
|
||||
dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0];
|
||||
dci_pdu_rel15[0].tb_scaling = 0;
|
||||
dci_payload.time_domain_assignment.val = time_domain_assignment;
|
||||
dci_payload.vrb_to_prb_mapping.val = 0;
|
||||
dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0];
|
||||
dci_payload.tb_scaling = 0;
|
||||
|
||||
LOG_I(MAC, "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n",
|
||||
dci_pdu_rel15[0].frequency_domain_assignment.val,
|
||||
pdsch_pdu_rel15->rbStart,
|
||||
pdsch_pdu_rel15->rbSize,
|
||||
dci10_bw,
|
||||
dci_pdu_rel15[0].time_domain_assignment.val,
|
||||
dci_pdu_rel15[0].vrb_to_prb_mapping.val,
|
||||
dci_pdu_rel15[0].mcs,
|
||||
dci_pdu_rel15[0].tb_scaling);
|
||||
|
||||
uint8_t nr_of_candidates, aggregation_level;
|
||||
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
|
||||
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */);
|
||||
int CCEIndex = allocate_nr_CCEs(nr_mac,
|
||||
bwp,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
0, // Y
|
||||
0, // m
|
||||
nr_of_candidates);
|
||||
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
|
||||
return;
|
||||
}
|
||||
nr_configure_pdcch(nr_mac,
|
||||
pdcch_pdu_rel15,
|
||||
RA_rnti,
|
||||
ss,
|
||||
coreset,
|
||||
scc,
|
||||
bwp,
|
||||
aggregation_level,
|
||||
CCEIndex);
|
||||
LOG_I(MAC,
|
||||
"[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n",
|
||||
dci_payload.frequency_domain_assignment.val,
|
||||
pdsch_pdu_rel15->rbStart,
|
||||
pdsch_pdu_rel15->rbSize,
|
||||
dci10_bw,
|
||||
dci_payload.time_domain_assignment.val,
|
||||
dci_payload.vrb_to_prb_mapping.val,
|
||||
dci_payload.mcs,
|
||||
dci_payload.tb_scaling);
|
||||
|
||||
LOG_I(MAC, "Frame %d: Subframe %d : Adding common DL DCI for RA_RNTI %x\n", frameP, slotP, RA_rnti);
|
||||
|
||||
dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
|
||||
rnti_types[0] = NR_RNTI_RA;
|
||||
const int dci_format = NR_DL_DCI_FORMAT_1_0;
|
||||
const int rnti_type = NR_RNTI_RA;
|
||||
|
||||
LOG_I(MAC, "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
|
||||
pdcch_pdu_rel15->dci_pdu.RNTI[0],
|
||||
rnti_types[0],
|
||||
dci_formats[0],
|
||||
(unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
|
||||
pdcch_pdu_rel15->StartSymbolIndex,
|
||||
pdcch_pdu_rel15->DurationSymbols);
|
||||
LOG_I(MAC,
|
||||
"[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
|
||||
pdcch_pdu_rel15->dci_pdu[0].RNTI,
|
||||
rnti_type,
|
||||
dci_format,
|
||||
(unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
|
||||
pdcch_pdu_rel15->StartSymbolIndex,
|
||||
pdcch_pdu_rel15->DurationSymbols);
|
||||
|
||||
fill_dci_pdu_rel15(scc,ra->secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id);
|
||||
|
||||
dl_req->nPDUs+=2;
|
||||
fill_dci_pdu_rel15(scc,
|
||||
ra->secondaryCellGroup,
|
||||
dci_pdu,
|
||||
&dci_payload,
|
||||
dci_format,
|
||||
rnti_type,
|
||||
dci10_bw,
|
||||
ra->bwp_id);
|
||||
|
||||
// Program UL processing for Msg3
|
||||
nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra);
|
||||
@@ -955,11 +982,11 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
|
||||
|
||||
x_Overhead = 0;
|
||||
nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_pdu_rel15[0].tb_scaling);
|
||||
nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_payload.tb_scaling);
|
||||
|
||||
// DL TX request
|
||||
tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0];
|
||||
tx_req->PDU_index = nr_mac->pdu_index[CC_id]++;
|
||||
tx_req->PDU_index = pduindex;
|
||||
tx_req->num_TLV = 1;
|
||||
tx_req->TLVs[0].length = 8;
|
||||
nr_mac->TX_req[CC_id].SFN = frameP;
|
||||
|
||||
@@ -126,7 +126,12 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
|
||||
mib_sdu_length);
|
||||
|
||||
if ((frameP & 1023) < 80){
|
||||
LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length);
|
||||
LOG_D(MAC,
|
||||
"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",
|
||||
module_idP,
|
||||
frameP,
|
||||
CC_id,
|
||||
mib_sdu_length);
|
||||
}
|
||||
|
||||
dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
@@ -331,13 +336,19 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
|
||||
memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||||
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
|
||||
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
dl_req->nPDUs += 1;
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
nr_configure_pdcch(pdcch_pdu_rel15,
|
||||
gNB_mac->sched_ctrlCommon->search_space,
|
||||
gNB_mac->sched_ctrlCommon->coreset,
|
||||
scc,
|
||||
bwp);
|
||||
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
|
||||
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
|
||||
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||||
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
dl_req->nPDUs += 1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
|
||||
@@ -385,48 +396,50 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
|
||||
|
||||
LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos);
|
||||
|
||||
dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
|
||||
memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t) * MAX_DCI_CORESET);
|
||||
/* Fill PDCCH DL DCI PDU */
|
||||
nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
|
||||
pdcch_pdu_rel15->numDlDci++;
|
||||
dci_pdu->RNTI = SI_RNTI;
|
||||
dci_pdu->ScramblingId = *scc->physCellId;
|
||||
dci_pdu->ScramblingRNTI = 0;
|
||||
dci_pdu->AggregationLevel = gNB_mac->sched_ctrlCommon->aggregation_level;
|
||||
dci_pdu->CceIndex = gNB_mac->sched_ctrlCommon->cce_index;
|
||||
dci_pdu->beta_PDCCH_1_0 = 0;
|
||||
dci_pdu->powerControlOffsetSS = 1;
|
||||
|
||||
dci_pdu_rel15[0].bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id;
|
||||
/* DCI payload */
|
||||
dci_pdu_rel15_t dci_payload;
|
||||
memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t));
|
||||
|
||||
dci_payload.bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id;
|
||||
|
||||
// frequency domain assignment
|
||||
dci_pdu_rel15[0].frequency_domain_assignment.val =
|
||||
PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
|
||||
pdsch_pdu_rel15->rbStart,
|
||||
gNB_mac->type0_PDCCH_CSS_config.num_rbs);
|
||||
dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(
|
||||
pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, gNB_mac->type0_PDCCH_CSS_config.num_rbs);
|
||||
|
||||
dci_pdu_rel15[0].time_domain_assignment.val = gNB_mac->sched_ctrlCommon->time_domain_allocation;
|
||||
dci_pdu_rel15[0].mcs = gNB_mac->sched_ctrlCommon->mcs;
|
||||
dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0];
|
||||
dci_pdu_rel15[0].harq_pid = 0;
|
||||
dci_pdu_rel15[0].ndi = 0;
|
||||
dci_pdu_rel15[0].dai[0].val = 0;
|
||||
dci_pdu_rel15[0].tpc = 0; // table 7.2.1-1 in 38.213
|
||||
dci_pdu_rel15[0].pucch_resource_indicator = 0;
|
||||
dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = 0;
|
||||
dci_pdu_rel15[0].antenna_ports.val = 0;
|
||||
dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
|
||||
dci_payload.time_domain_assignment.val = gNB_mac->sched_ctrlCommon->time_domain_allocation;
|
||||
dci_payload.mcs = gNB_mac->sched_ctrlCommon->mcs;
|
||||
dci_payload.rv = pdsch_pdu_rel15->rvIndex[0];
|
||||
dci_payload.harq_pid = 0;
|
||||
dci_payload.ndi = 0;
|
||||
dci_payload.dai[0].val = 0;
|
||||
dci_payload.tpc = 0; // table 7.2.1-1 in 38.213
|
||||
dci_payload.pucch_resource_indicator = 0;
|
||||
dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0;
|
||||
dci_payload.antenna_ports.val = 0;
|
||||
dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
|
||||
|
||||
nr_configure_pdcch(gNB_mac,
|
||||
pdcch_pdu_rel15,
|
||||
SI_RNTI,
|
||||
gNB_mac->sched_ctrlCommon->search_space,
|
||||
gNB_mac->sched_ctrlCommon->coreset,
|
||||
scc,
|
||||
bwp,
|
||||
gNB_mac->sched_ctrlCommon->aggregation_level,
|
||||
gNB_mac->sched_ctrlCommon->cce_index);
|
||||
int dci_format = NR_DL_DCI_FORMAT_1_0;
|
||||
int rnti_type = NR_RNTI_SI;
|
||||
|
||||
int dci_formats[2];
|
||||
int rnti_types[2];
|
||||
|
||||
dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
|
||||
rnti_types[0] = NR_RNTI_SI;
|
||||
|
||||
fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id);
|
||||
|
||||
dl_req->nPDUs += 2;
|
||||
fill_dci_pdu_rel15(scc,
|
||||
secondaryCellGroup,
|
||||
&pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1],
|
||||
&dci_payload,
|
||||
dci_format,
|
||||
rnti_type,
|
||||
pdsch_pdu_rel15->BWPSize,
|
||||
gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id);
|
||||
|
||||
LOG_D(MAC,"BWPSize: %i\n", pdcch_pdu_rel15->BWPSize);
|
||||
LOG_D(MAC,"BWPStart: %i\n", pdcch_pdu_rel15->BWPStart);
|
||||
@@ -504,4 +517,4 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
gNB_mac->TX_req[CC_id].SFN = frameP;
|
||||
gNB_mac->TX_req[CC_id].Slot = slotP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -255,9 +255,10 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
|
||||
/* schedules whole bandwidth for first user, all the time */
|
||||
void nr_preprocessor_phytest(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd)
|
||||
sub_frame_t slot)
|
||||
{
|
||||
if (slot != 1)
|
||||
return;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
const int UE_id = 0;
|
||||
const int CC_id = 0;
|
||||
@@ -328,14 +329,25 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
__func__,
|
||||
UE_id);
|
||||
|
||||
nr_acknack_scheduling(module_id,
|
||||
UE_id,
|
||||
frame,
|
||||
slot,
|
||||
num_slots_per_tdd,
|
||||
&sched_ctrl->pucch_sched_idx,
|
||||
&sched_ctrl->pucch_occ_idx);
|
||||
AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n");
|
||||
const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot);
|
||||
if (!alloc) {
|
||||
LOG_D(MAC,
|
||||
"%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
|
||||
__func__,
|
||||
UE_id,
|
||||
rnti,
|
||||
frame,
|
||||
slot);
|
||||
UE_info->num_pdcch_cand[UE_id][cid]--;
|
||||
int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid];
|
||||
for (int i = 0; i < sched_ctrl->aggregation_level; i++)
|
||||
cce_list[sched_ctrl->cce_index + i] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
AssertFatal(alloc,
|
||||
"could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n",
|
||||
rnti, frame, slot);
|
||||
|
||||
sched_ctrl->rbStart = rbStart;
|
||||
sched_ctrl->rbSize = rbSize;
|
||||
@@ -350,13 +362,15 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
}
|
||||
sched_ctrl->mcs = 9;
|
||||
sched_ctrl->numDmrsCdmGrpsNoData = 1;
|
||||
/* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */
|
||||
sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
|
||||
|
||||
/* mark the corresponding RBs as used */
|
||||
for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
|
||||
vrb_map[rb + sched_ctrl->rbStart] = 1;
|
||||
}
|
||||
|
||||
void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
bool nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd,
|
||||
@@ -372,7 +386,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
__func__,
|
||||
UE_info->num_UEs);
|
||||
if (UE_info->num_UEs == 0)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const int UE_id = 0;
|
||||
const int CC_id = 0;
|
||||
@@ -387,15 +401,15 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
tda,
|
||||
tdaList->list.count);
|
||||
int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu);
|
||||
const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd);
|
||||
const int sched_slot = (slot + K2) % num_slots_per_tdd;
|
||||
const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
|
||||
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
|
||||
/* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE
|
||||
* limitations). Note that if K2 or the TDD configuration is changed, below
|
||||
* conditions might exclude each other and never be true */
|
||||
if (!(is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot) && sched_slot == 8))
|
||||
return;
|
||||
return false;
|
||||
|
||||
const int bw = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
|
||||
const int bw = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
uint16_t rbStart = 0;
|
||||
uint16_t rbSize = 50; /* due to OAI UE limitations */
|
||||
if (rbSize>bw)
|
||||
@@ -411,7 +425,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
frame,
|
||||
slot,
|
||||
i);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +452,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
nr_of_candidates);
|
||||
if (sched_ctrl->cce_index < 0) {
|
||||
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
UE_info->num_pdcch_cand[UE_id][cid]++;
|
||||
|
||||
@@ -465,6 +479,8 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
sched_pusch->mcs = mcs;
|
||||
sched_pusch->rbStart = rbStart;
|
||||
sched_pusch->rbSize = rbSize;
|
||||
/* get the PID of a HARQ process awaiting retransmission, or -1 for "any new" */
|
||||
sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
|
||||
|
||||
/* Calculate TBS from MCS */
|
||||
sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
|
||||
@@ -487,4 +503,5 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
/* mark the corresponding RBs as used */
|
||||
for (int rb = rbStart; rb < rbStart + rbSize; rb++)
|
||||
vrb_map_UL[rb] = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,64 +34,72 @@
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
void nr_fill_nfapi_pucch(module_id_t mod_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
const NR_sched_pucch_t *pucch,
|
||||
int UE_id)
|
||||
{
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
|
||||
nfapi_nr_ul_tti_request_t *future_ul_tti_req =
|
||||
&RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot];
|
||||
AssertFatal(future_ul_tti_req->SFN == pucch->frame
|
||||
&& future_ul_tti_req->Slot == pucch->ul_slot,
|
||||
"future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n",
|
||||
future_ul_tti_req->SFN,
|
||||
future_ul_tti_req->Slot,
|
||||
pucch->frame,
|
||||
pucch->ul_slot);
|
||||
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
|
||||
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu;
|
||||
memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t));
|
||||
future_ul_tti_req->n_pdus += 1;
|
||||
|
||||
LOG_D(MAC,
|
||||
"%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d on res %d\n",
|
||||
frame,
|
||||
slot,
|
||||
pucch->frame,
|
||||
pucch->ul_slot,
|
||||
pucch->sr_flag,
|
||||
pucch->dai_c,
|
||||
pucch->csi_bits,
|
||||
pucch->resource_indicator);
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
|
||||
nr_configure_pucch(pucch_pdu,
|
||||
scc,
|
||||
UE_info->UE_sched_ctrl[UE_id].active_ubwp,
|
||||
UE_info->rnti[UE_id],
|
||||
pucch->resource_indicator,
|
||||
pucch->csi_bits,
|
||||
pucch->dai_c,
|
||||
pucch->sr_flag);
|
||||
}
|
||||
|
||||
void nr_schedule_pucch(int Mod_idP,
|
||||
int UE_id,
|
||||
int nr_ulmix_slots,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP) {
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
||||
AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id);
|
||||
const NR_list_t *UE_list = &UE_info->list;
|
||||
|
||||
for (int k=0; k<nr_ulmix_slots; k++) {
|
||||
for (int l=0; l<2; l++) {
|
||||
NR_sched_pucch *curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const int n = sizeof(sched_ctrl->sched_pucch) / sizeof(*sched_ctrl->sched_pucch);
|
||||
for (int i = 0; i < n; i++) {
|
||||
NR_sched_pucch_t *curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[i];
|
||||
const uint16_t O_ack = curr_pucch->dai_c;
|
||||
const uint16_t O_csi = curr_pucch->csi_bits;
|
||||
const uint8_t O_sr = 0; // no SR in PUCCH implemented for now
|
||||
const uint8_t O_sr = curr_pucch->sr_flag;
|
||||
if (O_ack + O_csi + O_sr == 0
|
||||
|| frameP != curr_pucch->frame
|
||||
|| slotP != curr_pucch->ul_slot)
|
||||
continue;
|
||||
|
||||
nfapi_nr_ul_tti_request_t *future_ul_tti_req =
|
||||
&RC.nrmac[Mod_idP]->UL_tti_req_ahead[0][curr_pucch->ul_slot];
|
||||
AssertFatal(future_ul_tti_req->SFN == curr_pucch->frame
|
||||
&& future_ul_tti_req->Slot == curr_pucch->ul_slot,
|
||||
"future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n",
|
||||
future_ul_tti_req->SFN,
|
||||
future_ul_tti_req->Slot,
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot);
|
||||
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
|
||||
future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu;
|
||||
memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t));
|
||||
future_ul_tti_req->n_pdus += 1;
|
||||
|
||||
LOG_D(MAC,
|
||||
"%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d, k %d l %d\n",
|
||||
frameP,
|
||||
slotP,
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
O_sr,
|
||||
O_ack,
|
||||
O_csi,
|
||||
k, l);
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
|
||||
nr_configure_pucch(pucch_pdu,
|
||||
scc,
|
||||
UE_info->UE_sched_ctrl[UE_id].active_ubwp,
|
||||
UE_info->rnti[UE_id],
|
||||
curr_pucch->resource_indicator,
|
||||
O_csi,
|
||||
O_ack,
|
||||
O_sr);
|
||||
|
||||
memset(&UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
|
||||
0,
|
||||
sizeof(NR_sched_pucch));
|
||||
nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,107 +180,136 @@ void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t
|
||||
}
|
||||
|
||||
|
||||
uint16_t nr_get_csi_bitlen(int Mod_idP,
|
||||
int UE_id,
|
||||
uint8_t csi_report_id) {
|
||||
|
||||
uint16_t csi_bitlen =0;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
||||
CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL;
|
||||
|
||||
CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]);
|
||||
csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
|
||||
CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
|
||||
(CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report);
|
||||
|
||||
return csi_bitlen;
|
||||
uint16_t nr_get_csi_bitlen(const nr_csi_report_t *csi_report)
|
||||
{
|
||||
const CRI_SSBRI_RSRP_bitlen_t *bitlen = &csi_report->CSI_report_bitlen[0];
|
||||
return bitlen->cri_ssbri_bitlen * bitlen->nb_ssbri_cri
|
||||
+ bitlen->rsrp_bitlen
|
||||
+ bitlen->diff_rsrp_bitlen * (bitlen->nb_ssbri_cri - 1) * csi_report->nb_of_csi_ssb_report;
|
||||
}
|
||||
|
||||
|
||||
void nr_csi_meas_reporting(int Mod_idP,
|
||||
int UE_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int slots_per_tdd,
|
||||
int ul_slots,
|
||||
int n_slots_frame) {
|
||||
sub_frame_t slot)
|
||||
{
|
||||
NR_ServingCellConfigCommon_t *scc =
|
||||
RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
|
||||
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
||||
NR_sched_pucch *curr_pucch;
|
||||
NR_PUCCH_ResourceSet_t *pucchresset;
|
||||
NR_CSI_ReportConfig_t *csirep;
|
||||
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
|
||||
NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
|
||||
NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];
|
||||
NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
NR_list_t *UE_list = &UE_info->list;
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
const NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
|
||||
AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count > 0,
|
||||
"NO CSI report configuration available");
|
||||
NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
|
||||
AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available");
|
||||
for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
|
||||
const NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
|
||||
for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
|
||||
AssertFatal(csirep->reportConfigType.choice.periodic,
|
||||
"Only periodic CSI reporting is implemented currently\n");
|
||||
int period, offset;
|
||||
csi_period_offset(csirep, &period, &offset);
|
||||
const int sched_slot = (period + offset) % n_slots_frame;
|
||||
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
|
||||
// preparation is done in first slot of tdd period
|
||||
if (frame % (period / n_slots_frame) != offset / n_slots_frame)
|
||||
continue;
|
||||
LOG_D(MAC, "CSI in frame %d slot %d\n", frame, sched_slot);
|
||||
|
||||
csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
|
||||
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
|
||||
const int n = pucchresset->resourceList.list.count;
|
||||
int res_index = 0;
|
||||
for (; res_index < n; res_index++)
|
||||
if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource)
|
||||
break;
|
||||
AssertFatal(res_index < n,
|
||||
"CSI resource not found among PUCCH resources\n");
|
||||
|
||||
AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently");
|
||||
int period, offset, sched_slot;
|
||||
csi_period_offset(csirep,&period,&offset);
|
||||
sched_slot = (period+offset)%n_slots_frame;
|
||||
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
|
||||
// preparation is done in first slot of tdd period
|
||||
if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) {
|
||||
|
||||
// we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack)
|
||||
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[(sched_slot%slots_per_tdd)-slots_per_tdd+ul_slots][0];
|
||||
|
||||
NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
|
||||
|
||||
int found = -1;
|
||||
pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
|
||||
int n_list = pucchresset->resourceList.list.count;
|
||||
for (int i=0; i<n_list; i++) {
|
||||
if (*pucchresset->resourceList.list.array[i] == pucchcsires->pucch_Resource)
|
||||
found = i;
|
||||
}
|
||||
AssertFatal(found>-1,"CSI resource not found among PUCCH resources");
|
||||
|
||||
curr_pucch->resource_indicator = found;
|
||||
|
||||
n_list = pucch_Config->resourceToAddModList->list.count;
|
||||
|
||||
// going through the list of PUCCH resources to find the one indexed by resource_id
|
||||
for (int i=0; i<n_list; i++) {
|
||||
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[i];
|
||||
if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) {
|
||||
switch(pucchres->format.present){
|
||||
case NR_PUCCH_Resource__format_PR_format2:
|
||||
if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
|
||||
curr_pucch->simultaneous_harqcsi = false;
|
||||
else
|
||||
curr_pucch->simultaneous_harqcsi = true;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3:
|
||||
if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
|
||||
curr_pucch->simultaneous_harqcsi = false;
|
||||
else
|
||||
curr_pucch->simultaneous_harqcsi = true;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format4:
|
||||
if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
|
||||
curr_pucch->simultaneous_harqcsi = false;
|
||||
else
|
||||
curr_pucch->simultaneous_harqcsi = true;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid PUCCH format type");
|
||||
}
|
||||
}
|
||||
}
|
||||
curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size
|
||||
// find free PUCCH that is in order with possibly existing PUCCH
|
||||
// schedulings (other CSI, SR)
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2];
|
||||
AssertFatal(curr_pucch->csi_bits == 0
|
||||
&& !curr_pucch->sr_flag
|
||||
&& curr_pucch->dai_c == 0,
|
||||
"PUCCH not free at index 2 for UE %04x\n",
|
||||
UE_info->rnti[UE_id]);
|
||||
curr_pucch->frame = frame;
|
||||
curr_pucch->ul_slot = sched_slot;
|
||||
curr_pucch->resource_indicator = res_index;
|
||||
curr_pucch->csi_bits +=
|
||||
nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]);
|
||||
|
||||
// going through the list of PUCCH resources to find the one indexed by resource_id
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
|
||||
const int m = pucch_Config->resourceToAddModList->list.count;
|
||||
for (int j = 0; j < m; j++) {
|
||||
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j];
|
||||
if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index])
|
||||
continue;
|
||||
int start = pucchres->startingPRB;
|
||||
int len = 1;
|
||||
uint64_t mask = 0;
|
||||
switch(pucchres->format.present){
|
||||
case NR_PUCCH_Resource__format_PR_format2:
|
||||
len = pucchres->format.choice.format2->nrofPRBs;
|
||||
mask = ((1 << pucchres->format.choice.format2->nrofSymbols) - 1) << pucchres->format.choice.format2->startingSymbolIndex;
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3:
|
||||
len = pucchres->format.choice.format3->nrofPRBs;
|
||||
mask = ((1 << pucchres->format.choice.format3->nrofSymbols) - 1) << pucchres->format.choice.format3->startingSymbolIndex;
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format4:
|
||||
mask = ((1 << pucchres->format.choice.format4->nrofSymbols) - 1) << pucchres->format.choice.format4->startingSymbolIndex;
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Invalid PUCCH format type\n");
|
||||
}
|
||||
// verify resources are free
|
||||
for (int i = start; i < start + len; ++i) {
|
||||
vrb_map_UL[i] |= mask;
|
||||
}
|
||||
AssertFatal(!curr_pucch->simultaneous_harqcsi,
|
||||
"UE %04x has simultaneous HARQ/CSI configured, but we don't support that\n",
|
||||
UE_info->rnti[UE_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_dl_harq(module_id_t mod_id,
|
||||
int UE_id,
|
||||
int8_t harq_pid,
|
||||
bool success)
|
||||
{
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
NR_UE_harq_t *harq = &UE_info->UE_sched_ctrl[UE_id].harq_processes[harq_pid];
|
||||
harq->feedback_slot = -1;
|
||||
harq->is_waiting = false;
|
||||
if (success) {
|
||||
add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid);
|
||||
harq->round = 0;
|
||||
harq->ndi ^= 1;
|
||||
} else if (harq->round == MAX_HARQ_ROUNDS) {
|
||||
add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid);
|
||||
harq->round = 0;
|
||||
harq->ndi ^= 1;
|
||||
NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
|
||||
stats->dlsch_errors++;
|
||||
LOG_D(MAC, "retransmission error for UE %d (total %d)\n", UE_id, stats->dlsch_errors);
|
||||
} else {
|
||||
add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].retrans_dl_harq, harq_pid);
|
||||
harq->round++;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
||||
frame_t frame,
|
||||
@@ -292,50 +329,36 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
||||
uci_01->ul_cqi,
|
||||
30);
|
||||
|
||||
// TODO
|
||||
int max_harq_rounds = 4; // TODO define macro
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
|
||||
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
if (((uci_01->pduBitmap >> 1) & 0x01)) {
|
||||
// handle harq
|
||||
int harq_idx_s = 0;
|
||||
|
||||
// iterate over received harq bits
|
||||
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
|
||||
// search for the right harq process
|
||||
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
|
||||
// if the gNB received ack with a good confidence
|
||||
if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
|
||||
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
|
||||
if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) &&
|
||||
(uci_01->harq->harq_confidence_level == 0)) {
|
||||
// toggle NDI and reset round
|
||||
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
|
||||
sched_ctrl->harq_processes[harq_idx].round = 0;
|
||||
}
|
||||
else
|
||||
sched_ctrl->harq_processes[harq_idx].round++;
|
||||
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
|
||||
harq_idx_s = harq_idx + 1;
|
||||
// if the max harq rounds was reached
|
||||
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
|
||||
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
|
||||
sched_ctrl->harq_processes[harq_idx].round = 0;
|
||||
UE_info->mac_stats[UE_id].dlsch_errors++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// if feedback slot processing is aborted
|
||||
else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
|
||||
&& (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
|
||||
&& sched_ctrl->harq_processes[harq_idx].is_waiting) {
|
||||
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
|
||||
sched_ctrl->harq_processes[harq_idx].round++;
|
||||
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
|
||||
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
|
||||
sched_ctrl->harq_processes[harq_idx].round = 0;
|
||||
}
|
||||
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
|
||||
}
|
||||
const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value;
|
||||
const uint8_t harq_confidence = uci_01->harq->harq_confidence_level;
|
||||
const int feedback_slot = (slot - 1 + num_slots) % num_slots;
|
||||
/* In case of realtime problems: we can only identify a HARQ process by
|
||||
* timing. If the HARQ process's feedback_slot is not the one we
|
||||
* expected, we assume that processing has been aborted and we need to
|
||||
* skip this HARQ process, which is what happens in the loop below. If
|
||||
* you don't experience real-time problems, you might simply revert the
|
||||
* commit that introduced these changes. */
|
||||
int8_t pid = sched_ctrl->feedback_dl_harq.head;
|
||||
DevAssert(pid >= 0);
|
||||
while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) {
|
||||
LOG_W(MAC,
|
||||
"expected feedback slot %d, but found %d instead\n",
|
||||
sched_ctrl->harq_processes[pid].feedback_slot,
|
||||
feedback_slot);
|
||||
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
handle_dl_harq(mod_id, UE_id, pid, 0);
|
||||
pid = sched_ctrl->feedback_dl_harq.head;
|
||||
DevAssert(pid >= 0);
|
||||
}
|
||||
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
|
||||
DevAssert(harq->is_waiting);
|
||||
handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,130 +381,243 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
|
||||
uci_234->ul_cqi,
|
||||
30);
|
||||
|
||||
// TODO
|
||||
int max_harq_rounds = 4; // TODO define macro
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
|
||||
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
if ((uci_234->pduBitmap >> 1) & 0x01) {
|
||||
int harq_idx_s = 0;
|
||||
int acknack;
|
||||
|
||||
// iterate over received harq bits
|
||||
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
|
||||
acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01;
|
||||
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) {
|
||||
// if the gNB received ack with a good confidence or if the max harq rounds was reached
|
||||
if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
|
||||
// TODO add some confidence level for when there is no CRC
|
||||
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
|
||||
if ((uci_234->harq.harq_crc != 1) && acknack) {
|
||||
// toggle NDI and reset round
|
||||
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
|
||||
sched_ctrl->harq_processes[harq_idx].round = 0;
|
||||
}
|
||||
else
|
||||
sched_ctrl->harq_processes[harq_idx].round++;
|
||||
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
|
||||
harq_idx_s = harq_idx + 1;
|
||||
// if the max harq rounds was reached
|
||||
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
|
||||
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
|
||||
sched_ctrl->harq_processes[harq_idx].round = 0;
|
||||
UE_info->mac_stats[UE_id].dlsch_errors++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// if feedback slot processing is aborted
|
||||
else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
|
||||
&& (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
|
||||
&& sched_ctrl->harq_processes[harq_idx].is_waiting) {
|
||||
sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
|
||||
sched_ctrl->harq_processes[harq_idx].round++;
|
||||
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
|
||||
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
|
||||
sched_ctrl->harq_processes[harq_idx].round = 0;
|
||||
}
|
||||
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
|
||||
}
|
||||
const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01;
|
||||
const int feedback_slot = (slot - 1 + num_slots) % num_slots;
|
||||
/* In case of realtime problems: we can only identify a HARQ process by
|
||||
* timing. If the HARQ process's feedback_slot is not the one we
|
||||
* expected, we assume that processing has been aborted and we need to
|
||||
* skip this HARQ process, which is what happens in the loop below. If
|
||||
* you don't experience real-time problems, you might simply revert the
|
||||
* commit that introduced these changes. */
|
||||
int8_t pid = sched_ctrl->feedback_dl_harq.head;
|
||||
DevAssert(pid >= 0);
|
||||
while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) {
|
||||
LOG_W(MAC,
|
||||
"expected feedback slot %d, but found %d instead\n",
|
||||
sched_ctrl->harq_processes[pid].feedback_slot,
|
||||
feedback_slot);
|
||||
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
handle_dl_harq(mod_id, UE_id, pid, 0);
|
||||
pid = sched_ctrl->feedback_dl_harq.head;
|
||||
DevAssert(pid >= 0);
|
||||
}
|
||||
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
|
||||
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
|
||||
DevAssert(harq->is_waiting);
|
||||
handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// function to update pucch scheduling parameters in UE list when a USS DL is scheduled
|
||||
void nr_acknack_scheduling(int Mod_idP,
|
||||
bool nr_acknack_scheduling(int mod_id,
|
||||
int UE_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP,
|
||||
int slots_per_tdd,
|
||||
int *pucch_id,
|
||||
int *pucch_occ) {
|
||||
frame_t frame,
|
||||
sub_frame_t slot)
|
||||
{
|
||||
const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
|
||||
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
const int nr_ulmix_slots = tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols != 0);
|
||||
const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0;
|
||||
const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots;
|
||||
const int first_ul_slot_tdd = tdd->nrofDownlinkSlots + nr_slots_period * (slot / nr_slots_period);
|
||||
const int CC_id = 0;
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
||||
NR_sched_pucch *curr_pucch;
|
||||
int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l;
|
||||
uint8_t pdsch_to_harq_feedback[8];
|
||||
int found = 0;
|
||||
int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0)
|
||||
nr_ulmix_slots++;
|
||||
AssertFatal(slot < first_ul_slot_tdd + (tdd->nrofUplinkSymbols != 0),
|
||||
"cannot handle multiple TDD periods (yet): slot %d first_ul_slot_tdd %d nrofUplinkSlots %ld\n",
|
||||
slot,
|
||||
first_ul_slot_tdd,
|
||||
tdd->nrofUplinkSlots);
|
||||
|
||||
bool csi_pres=false;
|
||||
for (k=0; k<nr_ulmix_slots; k++) {
|
||||
if(UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0)
|
||||
csi_pres=true;
|
||||
/* for the moment, we consider:
|
||||
* * only pucch_sched[0] holds HARQ (and SR)
|
||||
* * we do not multiplex with CSI, which is always in pucch_sched[2]
|
||||
* * SR uses format 0 and is allocated in the first UL (mixed) slot (and not
|
||||
* later)
|
||||
* * that the PUCCH resource set 0 (for up to 2 bits) points to the first N
|
||||
* PUCCH resources, where N is the number of resources in the PUCCH
|
||||
* resource set. This is used in pucch_index_used, which counts the used
|
||||
* resources by index, and not by their ID! */
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id];
|
||||
NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
|
||||
AssertFatal(pucch->csi_bits == 0,
|
||||
"%s(): csi_bits %d in sched_pucch[0]\n",
|
||||
__func__,
|
||||
pucch->csi_bits);
|
||||
|
||||
const int max_acknacks = 2;
|
||||
AssertFatal(pucch->dai_c + pucch->sr_flag <= max_acknacks,
|
||||
"illegal number of bits in PUCCH of UE %d\n",
|
||||
UE_id);
|
||||
/* if the currently allocated PUCCH of this UE is full, allocate it */
|
||||
if (pucch->sr_flag + pucch->dai_c == max_acknacks) {
|
||||
/* advance the UL slot information in PUCCH by one so we won't schedule in
|
||||
* the same slot again */
|
||||
const int f = pucch->frame;
|
||||
const int s = pucch->ul_slot;
|
||||
nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id);
|
||||
memset(pucch, 0, sizeof(*pucch));
|
||||
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
|
||||
pucch->ul_slot = (s + 1) % n_slots_frame;
|
||||
// we assume that only two indices over the array sched_pucch exist
|
||||
const NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[2];
|
||||
// skip the CSI PUCCH if it is present and if in the next frame/slot
|
||||
if (csi_pucch->csi_bits > 0
|
||||
&& csi_pucch->frame == pucch->frame
|
||||
&& csi_pucch->ul_slot == pucch->ul_slot) {
|
||||
AssertFatal(!csi_pucch->simultaneous_harqcsi,
|
||||
"%s(): %d.%d cannot handle simultaneous_harqcsi, but found for UE %d\n",
|
||||
__func__,
|
||||
pucch->frame,
|
||||
pucch->ul_slot,
|
||||
UE_id);
|
||||
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
|
||||
pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f;
|
||||
pucch->ul_slot = (s + 2) % n_slots_frame;
|
||||
}
|
||||
}
|
||||
|
||||
// As a preference always schedule ack nacks in PUCCH0 (max 2 per slots)
|
||||
// Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot
|
||||
if (csi_pres)
|
||||
max_acknacks=10;
|
||||
else
|
||||
max_acknacks=2;
|
||||
/* if the UE's next PUCCH occasion is after the possible UL slots (within the
|
||||
* same frame) or wrapped around to the next frame, then we assume there is
|
||||
* no possible PUCCH allocation anymore */
|
||||
if ((pucch->frame == frame
|
||||
&& (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots))
|
||||
|| (pucch->frame == frame + 1))
|
||||
return false;
|
||||
|
||||
// this is hardcoded for now as ue specific
|
||||
NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
|
||||
get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback);
|
||||
uint8_t pdsch_to_harq_feedback[8];
|
||||
get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback);
|
||||
|
||||
// for each possible ul or mixed slot
|
||||
for (k=0; k<nr_ulmix_slots; k++) {
|
||||
for (l=0; l<1; l++) { // scheduling 2 PUCCH in a single slot does not work with the phone, currently
|
||||
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
|
||||
//if it is possible to schedule acknack in current pucch (no exclusive csi pucch)
|
||||
if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) {
|
||||
// if there is free room in current pucch structure
|
||||
if (curr_pucch->dai_c<max_acknacks) {
|
||||
pucch_res = get_pucch_resource(UE_info,UE_id,k,l);
|
||||
if (pucch_res>-1){
|
||||
curr_pucch->resource_indicator = pucch_res;
|
||||
curr_pucch->frame = frameP;
|
||||
// first pucch occasion in first UL or MIXED slot
|
||||
first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
|
||||
i = 0;
|
||||
while (i<8 && found == 0) { // look if timing indicator is among allowed values
|
||||
if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
|
||||
found = 1;
|
||||
if (found == 0) i++;
|
||||
}
|
||||
if (found == 1) {
|
||||
// computing slot in which pucch is scheduled
|
||||
curr_pucch->dai_c++;
|
||||
curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
|
||||
curr_pucch->timing_indicator = i; // index in the list of timing indicators
|
||||
*pucch_id = k;
|
||||
*pucch_occ = l;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* there is a scheduled SR or HARQ. Check whether we can use it for this
|
||||
* ACKNACK */
|
||||
if (pucch->sr_flag + pucch->dai_c > 0) {
|
||||
/* this UE already has a PUCCH occasion */
|
||||
DevAssert(pucch->frame == frame);
|
||||
|
||||
// Find the right timing_indicator value.
|
||||
int i = 0;
|
||||
while (i < 8) {
|
||||
if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot)
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
if (i >= 8) {
|
||||
// we cannot reach this timing anymore, allocate and try again
|
||||
const int f = pucch->frame;
|
||||
const int s = pucch->ul_slot;
|
||||
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id);
|
||||
memset(pucch, 0, sizeof(*pucch));
|
||||
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
|
||||
pucch->ul_slot = (s + 1) % n_slots_frame;
|
||||
return nr_acknack_scheduling(mod_id, UE_id, frame, slot);
|
||||
}
|
||||
|
||||
pucch->timing_indicator = i;
|
||||
pucch->dai_c++;
|
||||
// retain old resource indicator, and we are good
|
||||
return true;
|
||||
}
|
||||
|
||||
/* we need to find a new PUCCH occasion */
|
||||
|
||||
NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||
DevAssert(pucch_Config->resourceToAddModList->list.count > 0);
|
||||
DevAssert(pucch_Config->resourceSetToAddModList->list.count > 0);
|
||||
const int n_res = pucch_Config->resourceSetToAddModList->list.array[0]->resourceList.list.count;
|
||||
int *pucch_index_used = RC.nrmac[mod_id]->pucch_index_used[sched_ctrl->active_ubwp->bwp_Id];
|
||||
|
||||
/* if time information is outdated (e.g., last PUCCH occasion in last frame),
|
||||
* set to first possible UL occasion in this frame. Note that if such UE is
|
||||
* scheduled a lot and used all AckNacks, pucch->frame might have been
|
||||
* wrapped around to next frame */
|
||||
if (frame != pucch->frame || pucch->ul_slot < first_ul_slot_tdd) {
|
||||
DevAssert(pucch->sr_flag + pucch->dai_c == 0);
|
||||
AssertFatal(frame + 1 != pucch->frame,
|
||||
"frame wrap around not handled in %s() yet\n",
|
||||
__func__);
|
||||
pucch->frame = frame;
|
||||
pucch->ul_slot = first_ul_slot_tdd;
|
||||
}
|
||||
|
||||
// increase to first slot in which PUCCH resources are available
|
||||
while (pucch_index_used[pucch->ul_slot] >= n_res) {
|
||||
pucch->ul_slot++;
|
||||
/* if there is no free resource anymore, abort search */
|
||||
if ((pucch->frame == frame
|
||||
&& pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)
|
||||
|| (pucch->frame == frame + 1)) {
|
||||
LOG_E(MAC,
|
||||
"%4d.%2d no free PUCCH resources anymore while searching for UE %d\n",
|
||||
frame,
|
||||
slot,
|
||||
UE_id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n");
|
||||
|
||||
// advance ul_slot if it is not reachable by UE
|
||||
pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]);
|
||||
|
||||
// Find the right timing_indicator value.
|
||||
int i = 0;
|
||||
while (i < 8) {
|
||||
if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot)
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
if (i >= 8) {
|
||||
LOG_W(MAC,
|
||||
"%4d.%2d could not find pdsch_to_harq_feedback for UE %d: earliest "
|
||||
"ack slot %d\n",
|
||||
frame,
|
||||
slot,
|
||||
UE_id,
|
||||
pucch->ul_slot);
|
||||
return false;
|
||||
}
|
||||
pucch->timing_indicator = i; // index in the list of timing indicators
|
||||
|
||||
pucch->dai_c++;
|
||||
const int pucch_res = pucch_index_used[pucch->ul_slot];
|
||||
pucch->resource_indicator = pucch_res;
|
||||
pucch_index_used[pucch->ul_slot] += 1;
|
||||
AssertFatal(pucch_index_used[pucch->ul_slot] <= n_res,
|
||||
"UE %d in %4d.%2d: pucch_index_used is %d (%d available)\n",
|
||||
UE_id,
|
||||
pucch->frame,
|
||||
pucch->ul_slot,
|
||||
pucch_index_used[pucch->ul_slot],
|
||||
n_res);
|
||||
|
||||
/* verify that at that slot and symbol, resources are free. We only do this
|
||||
* for initialCyclicShift 0 (we assume it always has that one), so other
|
||||
* initialCyclicShifts can overlap with ICS 0!*/
|
||||
const NR_PUCCH_Resource_t *resource =
|
||||
pucch_Config->resourceToAddModList->list.array[pucch_res];
|
||||
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||
if (resource->format.choice.format0->initialCyclicShift == 0) {
|
||||
uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE];
|
||||
const uint16_t symb = 1 << resource->format.choice.format0->startingSymbolIndex;
|
||||
AssertFatal((vrb_map_UL[resource->startingPRB] & symb) == 0,
|
||||
"symbol %x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d\n",
|
||||
symb, resource->startingPRB, pucch->ul_slot);
|
||||
vrb_map_UL[resource->startingPRB] |= symb;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||
void csi_period_offset(const NR_CSI_ReportConfig_t *csirep,
|
||||
int *period, int *offset) {
|
||||
|
||||
NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present;
|
||||
@@ -532,24 +668,6 @@ void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) {
|
||||
|
||||
// to be updated later, for now simple implementation
|
||||
// use the second allocation just in case there is csi in the first
|
||||
// in that case use second resource (for a different symbol) see 9.2 in 38.213
|
||||
if (l==1) {
|
||||
if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint16_t compute_pucch_prb_size(uint8_t format,
|
||||
uint8_t nr_prbs,
|
||||
uint16_t O_tot,
|
||||
|
||||
@@ -33,6 +33,33 @@
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
|
||||
//38.321 Table 6.1.3.1-1
|
||||
const uint32_t NR_SHORT_BSR_TABLE[32] = {
|
||||
0, 10, 14, 20, 28, 38, 53, 74,
|
||||
102, 142, 198, 276, 384, 535, 745, 1038,
|
||||
1446, 2014, 2806, 3909, 5446, 7587, 10570, 14726,
|
||||
20516, 28581, 39818, 55474, 77284, 107669, 150000, 300000
|
||||
};
|
||||
|
||||
//38.321 Table 6.1.3.1-2
|
||||
const uint32_t NR_LONG_BSR_TABLE[256] ={
|
||||
0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26,
|
||||
28, 30, 32, 34, 36, 38, 40, 43, 46, 49, 52, 55, 59, 62, 66, 71,
|
||||
75, 80, 85, 91, 97, 103, 110, 117, 124, 132, 141, 150, 160, 170, 181, 193,
|
||||
205, 218, 233, 248, 264, 281, 299, 318, 339, 361, 384, 409, 436, 464, 494, 526,
|
||||
560, 597, 635, 677, 720, 767, 817, 870, 926, 987, 1051, 1119, 1191, 1269, 1351, 1439,
|
||||
1532, 1631, 1737, 1850, 1970, 2098, 2234, 2379, 2533, 2698, 2873, 3059, 3258, 3469, 3694, 3934,
|
||||
4189, 4461, 4751, 5059, 5387, 5737, 6109, 6506, 6928, 7378, 7857, 8367, 8910, 9488, 10104, 10760,
|
||||
11458, 12202, 12994, 13838, 14736, 15692, 16711, 17795, 18951, 20181, 21491, 22885, 24371, 25953, 27638, 29431,
|
||||
31342, 33376, 35543, 37850, 40307, 42923, 45709, 48676, 51836, 55200, 58784, 62599, 66663, 70990, 75598, 80505,
|
||||
85730, 91295, 97221, 103532, 110252, 117409, 125030, 133146, 141789, 150992, 160793, 171231, 182345, 194182, 206786, 220209,
|
||||
234503, 249725, 265935, 283197, 301579, 321155, 342002, 364202, 387842, 413018, 439827, 468377, 498780, 531156, 565634, 602350,
|
||||
641449, 683087, 727427, 774645, 824928, 878475, 935498, 996222, 1060888, 1129752, 1203085, 1281179, 1364342, 1452903, 1547213, 1647644,
|
||||
1754595, 1868488, 1989774, 2118933, 2256475, 2402946, 2558924, 2725027, 2901912, 3090279, 3290873, 3504487, 3731968, 3974215, 4232186, 4506902,
|
||||
4799451, 5110989, 5442750, 5796046, 6172275, 6572925, 6999582, 7453933, 7937777, 8453028, 9001725, 9586039, 10208280, 10870913, 11576557, 12328006,
|
||||
13128233, 13980403, 14887889, 15854280, 16883401, 17979324, 19146385, 20389201, 21712690, 23122088, 24622972, 26221280, 27923336, 29735875, 31666069, 33721553,
|
||||
35910462, 38241455, 40723756, 43367187, 46182206, 49179951, 52372284, 55771835, 59392055, 63247269, 67352729, 71724679, 76380419, 81338368, 162676736, 4294967295
|
||||
};
|
||||
|
||||
void nr_process_mac_pdu(
|
||||
module_id_t module_idP,
|
||||
@@ -51,6 +78,13 @@ void nr_process_mac_pdu(
|
||||
uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len;
|
||||
|
||||
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
|
||||
int UE_id = find_nr_UE_id(module_idP, rnti);
|
||||
if (UE_id == -1) {
|
||||
LOG_E(MAC, "%s() UE_id == -1\n",__func__);
|
||||
return;
|
||||
}
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
// For both DL/UL-SCH
|
||||
// Except:
|
||||
// - UL/DL-SCH: fixed-size MAC CE(known by LCID)
|
||||
@@ -84,6 +118,9 @@ void nr_process_mac_pdu(
|
||||
|
||||
LOG_D(MAC, "LCID received at gNB side: %d \n", rx_lcid);
|
||||
|
||||
unsigned char *ce_ptr;
|
||||
int n_Lcg = 0;
|
||||
|
||||
switch(rx_lcid){
|
||||
// MAC CE
|
||||
|
||||
@@ -97,32 +134,25 @@ void nr_process_mac_pdu(
|
||||
case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION:
|
||||
// 38.321 Ch6.1.3.7
|
||||
break;
|
||||
case UL_SCH_LCID_S_BSR:
|
||||
//38.321 section 6.1.3.1
|
||||
//fixed length
|
||||
mac_ce_len =1;
|
||||
/* Extract short BSR value */
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_S_BSR:
|
||||
case UL_SCH_LCID_S_TRUNCATED_BSR:
|
||||
//38.321 section 6.1.3.1
|
||||
//fixed length
|
||||
mac_ce_len =1;
|
||||
/* Extract short truncated BSR value */
|
||||
/* Extract short BSR value */
|
||||
ce_ptr = &pdu_ptr[mac_subheader_len];
|
||||
NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr;
|
||||
sched_ctrl->estimated_ul_buffer = 0;
|
||||
sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size];
|
||||
LOG_D(MAC, "SHORT BSR, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n",
|
||||
bsr_s->LcgID,
|
||||
bsr_s->Buffer_size,
|
||||
NR_SHORT_BSR_TABLE[bsr_s->Buffer_size],
|
||||
sched_ctrl->estimated_ul_buffer);
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_L_BSR:
|
||||
//38.321 section 6.1.3.1
|
||||
//variable length
|
||||
mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
|
||||
mac_subheader_len = 2;
|
||||
if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
/* Extract long BSR value */
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_L_TRUNCATED_BSR:
|
||||
//38.321 section 6.1.3.1
|
||||
//variable length
|
||||
@@ -132,9 +162,27 @@ void nr_process_mac_pdu(
|
||||
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
|
||||
mac_subheader_len = 3;
|
||||
}
|
||||
/* Extract long truncated BSR value */
|
||||
break;
|
||||
/* Extract long BSR value */
|
||||
ce_ptr = &pdu_ptr[mac_subheader_len];
|
||||
NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr;
|
||||
sched_ctrl->estimated_ul_buffer = 0;
|
||||
|
||||
n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 +
|
||||
bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0;
|
||||
|
||||
LOG_D(MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n",
|
||||
bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4,
|
||||
bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0);
|
||||
|
||||
for (int n = 0; n < n_Lcg; n++){
|
||||
LOG_D(MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d",
|
||||
n, n_Lcg, pdu_ptr[mac_subheader_len + 1 + n],
|
||||
NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]]);
|
||||
sched_ctrl->estimated_ul_buffer +=
|
||||
NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_C_RNTI:
|
||||
//38.321 section 6.1.3.2
|
||||
@@ -230,17 +278,28 @@ void nr_process_mac_pdu(
|
||||
1,
|
||||
NULL);
|
||||
|
||||
/* Updated estimated buffer when receiving data */
|
||||
if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len)
|
||||
sched_ctrl->estimated_ul_buffer -= mac_sdu_len;
|
||||
else
|
||||
sched_ctrl->estimated_ul_buffer = 0;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
LOG_D(MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len );
|
||||
|
||||
if (pdu_len < 0) {
|
||||
LOG_E(MAC, "%s() residual mac pdu length < 0!, pdu_len: %d\n", __func__, pdu_len);
|
||||
LOG_E(MAC, "MAC PDU ");
|
||||
for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes
|
||||
printf("%02x ", pdu_ptr[i]);
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -259,45 +318,51 @@ void handle_nr_ul_harq(module_id_t mod_id,
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
|
||||
int max_harq_rounds = 4; // TODO define macro
|
||||
uint8_t hrq_id = crc_pdu->harq_id;
|
||||
NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id];
|
||||
if (cur_harq->state==ACTIVE_SCHED) {
|
||||
if (!crc_pdu->tb_crc_status) {
|
||||
cur_harq->ndi ^= 1;
|
||||
cur_harq->round = 0;
|
||||
cur_harq->state = INACTIVE; // passed -> make inactive. can be used by scheduder for next grant
|
||||
LOG_D(MAC,
|
||||
"Ulharq id %d crc passed for RNTI %04x\n",
|
||||
hrq_id,
|
||||
crc_pdu->rnti);
|
||||
} else {
|
||||
cur_harq->round++;
|
||||
cur_harq->state = ACTIVE_NOT_SCHED;
|
||||
LOG_D(MAC,
|
||||
"Ulharq id %d crc failed for RNTI %04x\n",
|
||||
hrq_id,
|
||||
crc_pdu->rnti);
|
||||
}
|
||||
|
||||
if (!(cur_harq->round<max_harq_rounds)) {
|
||||
cur_harq->ndi ^= 1;
|
||||
cur_harq->state = INACTIVE; // failed after 4 rounds -> make inactive
|
||||
cur_harq->round = 0;
|
||||
LOG_D(MAC,
|
||||
"RNTI %04x: Ulharq id %d crc failed in all rounds\n",
|
||||
crc_pdu->rnti,
|
||||
hrq_id);
|
||||
UE_info->mac_stats[UE_id].ulsch_errors++;
|
||||
}
|
||||
return;
|
||||
} else
|
||||
int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
|
||||
while (crc_pdu->harq_id != harq_pid || harq_pid < 0) {
|
||||
LOG_W(MAC,
|
||||
"Incorrect ULSCH HARQ PID %d or invalid state %d for RNTI %04x "
|
||||
"(ignore this warning for RA)\n",
|
||||
hrq_id,
|
||||
cur_harq->state,
|
||||
"Unexpected ULSCH HARQ PID %d (have %d) for RNTI %04x (ignore this warning for RA)\n",
|
||||
crc_pdu->harq_id,
|
||||
harq_pid,
|
||||
crc_pdu->rnti);
|
||||
if (harq_pid < 0)
|
||||
return;
|
||||
|
||||
remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
|
||||
sched_ctrl->ul_harq_processes[harq_pid].round++;
|
||||
add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
|
||||
harq_pid = sched_ctrl->feedback_ul_harq.head;
|
||||
}
|
||||
remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
|
||||
NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid];
|
||||
DevAssert(harq->is_waiting);
|
||||
harq->feedback_slot = -1;
|
||||
harq->is_waiting = false;
|
||||
if (!crc_pdu->tb_crc_status) {
|
||||
harq->ndi ^= 1;
|
||||
harq->round = 0;
|
||||
LOG_D(MAC,
|
||||
"Ulharq id %d crc passed for RNTI %04x\n",
|
||||
harq_pid,
|
||||
crc_pdu->rnti);
|
||||
add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
|
||||
} else if (harq->round == MAX_HARQ_ROUNDS) {
|
||||
harq->ndi ^= 1;
|
||||
harq->round = 0;
|
||||
LOG_D(MAC,
|
||||
"RNTI %04x: Ulharq id %d crc failed in all rounds\n",
|
||||
crc_pdu->rnti,
|
||||
harq_pid);
|
||||
UE_info->mac_stats[UE_id].ulsch_errors++;
|
||||
add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
|
||||
} else {
|
||||
harq->round++;
|
||||
LOG_D(MAC,
|
||||
"Ulharq id %d crc failed for RNTI %04x\n",
|
||||
harq_pid,
|
||||
crc_pdu->rnti);
|
||||
add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -313,25 +378,21 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
const uint16_t timing_advance,
|
||||
const uint8_t ul_cqi,
|
||||
const uint16_t rssi){
|
||||
int current_rnti = 0, UE_id = -1, harq_pid = 0;
|
||||
gNB_MAC_INST *gNB_mac = NULL;
|
||||
NR_UE_info_t *UE_info = NULL;
|
||||
NR_UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP];
|
||||
NR_UE_info_t *UE_info = &gNB_mac->UE_info;
|
||||
|
||||
current_rnti = rntiP;
|
||||
UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti);
|
||||
gNB_mac = RC.nrmac[gnb_mod_idP];
|
||||
UE_info = &gNB_mac->UE_info;
|
||||
int target_snrx10 = gNB_mac->pusch_target_snrx10;
|
||||
|
||||
if (sduP != NULL) {
|
||||
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
|
||||
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
|
||||
T_BUFFER(sduP, sdu_lenP));
|
||||
}
|
||||
const int current_rnti = rntiP;
|
||||
const int UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti);
|
||||
const int target_snrx10 = gNB_mac->pusch_target_snrx10;
|
||||
|
||||
if (UE_id != -1) {
|
||||
UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
|
||||
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const int8_t harq_pid = UE_scheduling_control->feedback_ul_harq.head;
|
||||
|
||||
if (sduP)
|
||||
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
|
||||
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(harq_pid),
|
||||
T_BUFFER(sduP, sdu_lenP));
|
||||
|
||||
UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP;
|
||||
LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d\n",
|
||||
@@ -370,15 +431,30 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
|
||||
if (sduP != NULL){
|
||||
LOG_D(MAC, "Received PDU at MAC gNB \n");
|
||||
|
||||
UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
|
||||
if (UE_scheduling_control->sched_ul_bytes < 0)
|
||||
UE_scheduling_control->sched_ul_bytes = 0;
|
||||
|
||||
nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP);
|
||||
}
|
||||
else {
|
||||
|
||||
NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
|
||||
/* reduce sched_ul_bytes when cur_harq->round == 3 */
|
||||
if (cur_harq->round == 3){
|
||||
UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
|
||||
if (UE_scheduling_control->sched_ul_bytes < 0)
|
||||
UE_scheduling_control->sched_ul_bytes = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!sduP) // check that CRC passed
|
||||
return;
|
||||
|
||||
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
|
||||
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
|
||||
T_BUFFER(sduP, sdu_lenP));
|
||||
|
||||
/* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3)
|
||||
* and check the corresponding UE's RNTI match, in which case we activate
|
||||
* it. */
|
||||
@@ -395,21 +471,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
current_rnti);
|
||||
continue;
|
||||
}
|
||||
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti);
|
||||
UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
|
||||
compute_csi_bitlen(ra->secondaryCellGroup, UE_info, UE_id);
|
||||
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->secondaryCellGroup);
|
||||
UE_info->UE_beam_index[UE_id] = ra->beam_id;
|
||||
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
|
||||
AssertFatal(bwpList->list.count == 1,
|
||||
"downlinkBWP_ToAddModList has %d BWP!\n",
|
||||
bwpList->list.count);
|
||||
const int bwp_id = 1;
|
||||
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
|
||||
struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList;
|
||||
AssertFatal(ubwpList->list.count == 1,
|
||||
"uplinkBWP_ToAddModList has %d BWP!\n",
|
||||
ubwpList->list.count);
|
||||
UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1];
|
||||
LOG_I(MAC,
|
||||
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
|
||||
"adding UE MAC Context UE_id %d/RNTI %04x\n",
|
||||
@@ -445,30 +508,256 @@ long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) {
|
||||
const uint8_t max_ul_harq_pids = 3; // temp: for testing
|
||||
// schedule active harq processes
|
||||
for (uint8_t hrq_id = 0; hrq_id < max_ul_harq_pids; hrq_id++) {
|
||||
NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id];
|
||||
if (cur_harq->state == ACTIVE_NOT_SCHED) {
|
||||
LOG_D(MAC, "Found ulharq id %d, scheduling it for retransmission\n", hrq_id);
|
||||
return hrq_id;
|
||||
}
|
||||
}
|
||||
|
||||
// schedule new harq processes
|
||||
for (uint8_t hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) {
|
||||
NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id];
|
||||
if (cur_harq->state == INACTIVE) {
|
||||
LOG_D(MAC, "Found new ulharq id %d, scheduling it\n", hrq_id);
|
||||
return hrq_id;
|
||||
}
|
||||
}
|
||||
LOG_E(MAC, "All UL HARQ processes are busy. Cannot schedule ULSCH\n");
|
||||
return -1;
|
||||
int next_list_entry_looped(NR_list_t *list, int UE_id)
|
||||
{
|
||||
if (UE_id < 0)
|
||||
return list->head;
|
||||
return list->next[UE_id] < 0 ? list->head : list->next[UE_id];
|
||||
}
|
||||
|
||||
void nr_simple_ulsch_preprocessor(module_id_t module_id,
|
||||
float ul_thr_ue[MAX_MOBILES_PER_GNB];
|
||||
int bsr0ue = -1;
|
||||
void pf_ul(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd,
|
||||
NR_list_t *UE_list,
|
||||
int n_rb_sched,
|
||||
uint8_t *rballoc_mask,
|
||||
int max_num_ue) {
|
||||
|
||||
const int CC_id = 0;
|
||||
const int tda = 1;
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
const int min_rb = 5;
|
||||
float coeff_ue[MAX_MOBILES_PER_GNB];
|
||||
// UEs that could be scheduled
|
||||
int ue_array[MAX_MOBILES_PER_GNB];
|
||||
NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB };
|
||||
|
||||
/* Hack: currently, we do not have SR, and need to schedule UEs continuously.
|
||||
* To keep the wasted resources low, we switch UEs to be scheduled in a
|
||||
* round-robin fashion below, and only schedule a UE with BSR=0 if it is the
|
||||
* selected one */
|
||||
bsr0ue = next_list_entry_looped(UE_list, bsr0ue);
|
||||
|
||||
/* Loop UE_list to calculate throughput and coeff */
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
/* Calculate throughput */
|
||||
const float a = 0.0005f; // corresponds to 200ms window
|
||||
const uint32_t b = UE_info->mac_stats[UE_id].ulsch_current_bytes;
|
||||
ul_thr_ue[UE_id] = (1 - a) * ul_thr_ue[UE_id] + a * b;
|
||||
|
||||
/* Save PUSCH field */
|
||||
/* we want to avoid a lengthy deduction of DMRS and other parameters in
|
||||
* every TTI if we can save it, so check whether dci_format, TDA, or
|
||||
* num_dmrs_cdm_grps_no_data has changed and only then recompute */
|
||||
sched_ctrl->sched_pusch.time_domain_allocation = tda;
|
||||
sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, NR_SearchSpace__searchSpaceType_PR_ue_Specific);
|
||||
sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
|
||||
const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
|
||||
const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
|
||||
const uint8_t num_dmrs_cdm_grps_no_data = 1;
|
||||
NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
|
||||
if (ps->time_domain_allocation != tda
|
||||
|| ps->dci_format != dci_format
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
|
||||
nr_save_pusch_fields(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
|
||||
|
||||
/* Check if retransmission is necessary */
|
||||
sched_ctrl->sched_pusch.ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
|
||||
if (sched_ctrl->sched_pusch.ul_harq_pid >= 0) {
|
||||
/* RETRANSMISSION: Allocate retransmission*/
|
||||
/* Find free CCE */
|
||||
bool freeCCE = find_free_CCE(module_id, slot, UE_id);
|
||||
if (!freeCCE) {
|
||||
LOG_D(MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
|
||||
continue;
|
||||
}
|
||||
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
|
||||
max_num_ue--;
|
||||
if (max_num_ue < 0)
|
||||
return;
|
||||
|
||||
/* Save shced_frame and sched_slot before overwrite by previous PUSCH filed */
|
||||
NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[sched_ctrl->sched_pusch.ul_harq_pid];
|
||||
cur_harq->sched_pusch.frame = sched_ctrl->sched_pusch.frame;
|
||||
cur_harq->sched_pusch.slot = sched_ctrl->sched_pusch.slot;
|
||||
/* Get previous PSUCH filed info */
|
||||
sched_ctrl->sched_pusch = cur_harq->sched_pusch;
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
LOG_D(MAC, "%4d.%2d Allocate UL retransmission UE %d/RNTI %04x sched %4d.%2d (%d RBs)\n",
|
||||
frame, slot, UE_id, UE_info->rnti[UE_id],
|
||||
sched_pusch->frame, sched_pusch->slot,
|
||||
sched_pusch->rbSize);
|
||||
|
||||
while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
|
||||
if (rbStart + sched_pusch->rbSize >= bwpSize) {
|
||||
LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
|
||||
UE_id, UE_info->rnti[UE_id]);
|
||||
return;
|
||||
}
|
||||
sched_pusch->rbStart = rbStart;
|
||||
/* no need to recompute the TBS, it will be the same */
|
||||
|
||||
/* Mark the corresponding RBs as used */
|
||||
n_rb_sched -= sched_pusch->rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate TBS from MCS */
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
const int mcs = 9;
|
||||
sched_pusch->mcs = mcs;
|
||||
sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
|
||||
sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table);
|
||||
if (ps->pusch_Config->tp_pi2BPSK
|
||||
&& ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) {
|
||||
sched_pusch->R >>= 1;
|
||||
sched_pusch->Qm <<= 1;
|
||||
}
|
||||
|
||||
/* Check BSR and schedule UE if it is zero to avoid starvation, since we do
|
||||
* not have SR (yet) */
|
||||
if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0) {
|
||||
if (UE_id != bsr0ue)
|
||||
continue;
|
||||
/* if no data, pre-allocate 5RB */
|
||||
bool freeCCE = find_free_CCE(module_id, slot, UE_id);
|
||||
if (!freeCCE) {
|
||||
LOG_D(MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE_info->rnti[UE_id]);
|
||||
continue;
|
||||
}
|
||||
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
|
||||
max_num_ue--;
|
||||
if (max_num_ue < 0)
|
||||
return;
|
||||
|
||||
while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
|
||||
if (rbStart + min_rb >= bwpSize) {
|
||||
LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
|
||||
UE_id, UE_info->rnti[UE_id]);
|
||||
return;
|
||||
}
|
||||
sched_pusch->rbStart = rbStart;
|
||||
sched_pusch->rbSize = min_rb;
|
||||
sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
|
||||
sched_pusch->R,
|
||||
sched_pusch->rbSize,
|
||||
ps->nrOfSymbols,
|
||||
ps->N_PRB_DMRS * ps->num_dmrs_symb,
|
||||
0, // nb_rb_oh
|
||||
0,
|
||||
1 /* NrOfLayers */)
|
||||
>> 3;
|
||||
|
||||
/* Mark the corresponding RBs as used */
|
||||
n_rb_sched -= sched_pusch->rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create UE_sched for UEs eligibale for new data transmission*/
|
||||
add_tail_nr_list(&UE_sched, UE_id);
|
||||
|
||||
/* Calculate coefficient*/
|
||||
const uint32_t tbs = nr_compute_tbs(sched_pusch->Qm,
|
||||
sched_pusch->R,
|
||||
1, // rbSize
|
||||
ps->nrOfSymbols,
|
||||
ps->N_PRB_DMRS * ps->num_dmrs_symb,
|
||||
0, // nb_rb_oh
|
||||
0,
|
||||
1 /* NrOfLayers */)
|
||||
>> 3;
|
||||
coeff_ue[UE_id] = (float) tbs / ul_thr_ue[UE_id];
|
||||
LOG_D(MAC,"b %d, ul_thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n",
|
||||
b, UE_id, ul_thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]);
|
||||
}
|
||||
|
||||
|
||||
/* Loop UE_sched to find max coeff and allocate transmission */
|
||||
while (UE_sched.head >= 0 && max_num_ue> 0 && n_rb_sched > 0) {
|
||||
/* Find max coeff */
|
||||
int *max = &UE_sched.head; /* Find max coeff: assume head is max */
|
||||
int *p = &UE_sched.next[*max];
|
||||
while (*p >= 0) {
|
||||
/* Find max coeff: if the current one has larger coeff, save for later */
|
||||
if (coeff_ue[*p] > coeff_ue[*max])
|
||||
max = p;
|
||||
p = &UE_sched.next[*p];
|
||||
}
|
||||
/* Find max coeff: remove the max one: do not use remove_nr_list() since it
|
||||
* goes through the whole list every time. Note that UE_sched.tail might
|
||||
* not be set correctly anymore */
|
||||
const int UE_id = *max;
|
||||
p = &UE_sched.next[*max];
|
||||
*max = UE_sched.next[*max];
|
||||
*p = -1;
|
||||
|
||||
bool freeCCE = find_free_CCE(module_id, slot, UE_id);
|
||||
if (!freeCCE) {
|
||||
LOG_D(MAC, "%4d.%2d no free CCE for UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
|
||||
max_num_ue--;
|
||||
if (max_num_ue < 0)
|
||||
return;
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
|
||||
|
||||
while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
|
||||
sched_pusch->rbStart = rbStart;
|
||||
if (rbStart + min_rb >= bwpSize) {
|
||||
LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
|
||||
UE_id, UE_info->rnti[UE_id]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate the current scheduling bytes */
|
||||
const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0);
|
||||
uint16_t rbSize = min_rb - 1;
|
||||
do {
|
||||
rbSize++;
|
||||
sched_pusch->rbSize = rbSize;
|
||||
sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
|
||||
sched_pusch->R,
|
||||
sched_pusch->rbSize,
|
||||
sched_ctrl->pusch_save.nrOfSymbols,
|
||||
sched_ctrl->pusch_save.N_PRB_DMRS * sched_ctrl->pusch_save.num_dmrs_symb,
|
||||
0, // nb_rb_oh
|
||||
0,
|
||||
1 /* NrOfLayers */)
|
||||
>> 3;
|
||||
} while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart+rbSize] &&
|
||||
sched_pusch->tb_size < B);
|
||||
LOG_D(MAC,"rbSize %d, TBS %d, est buf %d, sched_ul %d, B %d\n",
|
||||
rbSize, sched_pusch->tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B);
|
||||
|
||||
/* Mark the corresponding RBs as used */
|
||||
n_rb_sched -= sched_pusch->rbSize;
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool nr_simple_ulsch_preprocessor(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd,
|
||||
@@ -479,17 +768,14 @@ void nr_simple_ulsch_preprocessor(module_id_t module_id,
|
||||
const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
|
||||
NR_UE_info_t *UE_info = &nr_mac->UE_info;
|
||||
|
||||
AssertFatal(UE_info->num_UEs <= 1,
|
||||
"%s() cannot handle more than one UE, but found %d\n",
|
||||
__func__,
|
||||
UE_info->num_UEs);
|
||||
if (UE_info->num_UEs == 0)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const int UE_id = 0;
|
||||
const int CC_id = 0;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
|
||||
/* NOT support different K2 in here, Get the K2 for first UE */
|
||||
int UE_id = UE_info->list.head;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const int tda = 1;
|
||||
const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList =
|
||||
sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
|
||||
@@ -497,94 +783,59 @@ void nr_simple_ulsch_preprocessor(module_id_t module_id,
|
||||
"time domain assignment %d >= %d\n",
|
||||
tda,
|
||||
tdaList->list.count);
|
||||
int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu);
|
||||
const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd);
|
||||
const int sched_slot = (slot + K2) % num_slots_per_tdd;
|
||||
if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot))
|
||||
return;
|
||||
|
||||
/* get first, largest unallocated region */
|
||||
uint16_t *vrb_map_UL =
|
||||
&RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * 275];
|
||||
uint16_t rbStart = 0;
|
||||
while (vrb_map_UL[rbStart]) rbStart++;
|
||||
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
uint16_t rbSize = 1;
|
||||
while (rbStart + rbSize < bwpSize && !vrb_map_UL[rbStart+rbSize])
|
||||
rbSize++;
|
||||
int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu);
|
||||
const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
|
||||
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
|
||||
if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot))
|
||||
return false;
|
||||
|
||||
sched_ctrl->sched_pusch.slot = sched_slot;
|
||||
sched_ctrl->sched_pusch.frame = sched_frame;
|
||||
|
||||
const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
|
||||
sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
|
||||
uint8_t nr_of_candidates;
|
||||
find_aggregation_candidates(&sched_ctrl->aggregation_level,
|
||||
&nr_of_candidates,
|
||||
sched_ctrl->search_space);
|
||||
sched_ctrl->coreset = get_coreset(
|
||||
sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
|
||||
const int cid = sched_ctrl->coreset->controlResourceSetId;
|
||||
const uint16_t Y = UE_info->Y[UE_id][cid][slot];
|
||||
const int m = UE_info->num_pdcch_cand[UE_id][cid];
|
||||
sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
|
||||
sched_ctrl->active_bwp,
|
||||
sched_ctrl->coreset,
|
||||
sched_ctrl->aggregation_level,
|
||||
Y,
|
||||
m,
|
||||
nr_of_candidates);
|
||||
if (sched_ctrl->cce_index < 0) {
|
||||
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__);
|
||||
return;
|
||||
/* Confirm all the UE have same K2 as the first UE */
|
||||
for (UE_id = UE_info->list.next[UE_id]; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
AssertFatal(K2 == get_K2(sched_ctrl->active_ubwp, tda, mu),
|
||||
"Different K2, %d(UE%d) != %ld(UE%d)\n", K2, 0, get_K2(sched_ctrl->active_ubwp, tda, mu), UE_id);
|
||||
sched_ctrl->sched_pusch.slot = sched_slot;
|
||||
sched_ctrl->sched_pusch.frame = sched_frame;
|
||||
}
|
||||
UE_info->num_pdcch_cand[UE_id][cid]++;
|
||||
|
||||
sched_ctrl->sched_pusch.time_domain_allocation = tda;
|
||||
const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
|
||||
const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
|
||||
const uint8_t num_dmrs_cdm_grps_no_data = 1;
|
||||
/* we want to avoid a lengthy deduction of DMRS and other parameters in
|
||||
* every TTI if we can save it, so check whether dci_format, TDA, or
|
||||
* num_dmrs_cdm_grps_no_data has changed and only then recompute */
|
||||
NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
|
||||
if (ps->time_domain_allocation != tda
|
||||
|| ps->dci_format != dci_format
|
||||
|| ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
|
||||
nr_save_pusch_fields(scc,
|
||||
sched_ctrl->active_ubwp,
|
||||
dci_format,
|
||||
tda,
|
||||
num_dmrs_cdm_grps_no_data,
|
||||
ps);
|
||||
|
||||
const int mcs = 9;
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
sched_pusch->mcs = mcs;
|
||||
sched_pusch->rbStart = rbStart;
|
||||
sched_pusch->rbSize = rbSize;
|
||||
|
||||
/* Calculate TBS from MCS */
|
||||
sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
|
||||
sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table);
|
||||
if (ps->pusch_Config->tp_pi2BPSK
|
||||
&& ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) {
|
||||
sched_pusch->R >>= 1;
|
||||
sched_pusch->Qm <<= 1;
|
||||
/* Change vrb_map_UL to rballoc_mask */
|
||||
uint16_t *vrb_map_UL =
|
||||
&RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
|
||||
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
int st = 0, e = 0, len = 0;
|
||||
for (int i = 0; i < bwpSize; i++) {
|
||||
while (vrb_map_UL[i] == 1)
|
||||
i++;
|
||||
st = i;
|
||||
while (vrb_map_UL[i] == 0)
|
||||
i++;
|
||||
if (i - st > len) {
|
||||
len = i - st;
|
||||
e = i - 1;
|
||||
}
|
||||
}
|
||||
sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
|
||||
sched_pusch->R,
|
||||
sched_pusch->rbSize,
|
||||
ps->nrOfSymbols,
|
||||
ps->N_PRB_DMRS * ps->num_dmrs_symb,
|
||||
0, // nb_rb_oh
|
||||
0,
|
||||
1 /* NrOfLayers */)
|
||||
>> 3;
|
||||
st = e - len + 1;
|
||||
|
||||
/* mark the corresponding RBs as used */
|
||||
for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
|
||||
vrb_map_UL[rb + sched_ctrl->sched_pusch.rbStart] = 1;
|
||||
uint8_t rballoc_mask[bwpSize];
|
||||
|
||||
/* Calculate mask: if any RB in vrb_map_UL is blocked (1), the current RB will be 0 */
|
||||
for (int i = 0; i < bwpSize; i++)
|
||||
rballoc_mask[i] = i >= st && i <= e;
|
||||
|
||||
/* proportional fair scheduling algorithm */
|
||||
pf_ul(module_id,
|
||||
frame,
|
||||
slot,
|
||||
num_slots_per_tdd,
|
||||
&UE_info->list,
|
||||
len,
|
||||
rballoc_mask,
|
||||
2);
|
||||
return true;
|
||||
}
|
||||
|
||||
void nr_schedule_ulsch(module_id_t module_id,
|
||||
@@ -593,14 +844,32 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
int num_slots_per_tdd,
|
||||
int ul_slots,
|
||||
uint64_t ulsch_in_slot_bitmap) {
|
||||
RC.nrmac[module_id]->pre_processor_ul(
|
||||
/* Uplink data ONLY can be scheduled when the current slot is downlink slot,
|
||||
* because we have to schedule the DCI0 first before schedule uplink data */
|
||||
if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot)) {
|
||||
LOG_D(MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot);
|
||||
return;
|
||||
}
|
||||
bool do_sched = RC.nrmac[module_id]->pre_processor_ul(
|
||||
module_id, frame, slot, num_slots_per_tdd, ulsch_in_slot_bitmap);
|
||||
if (!do_sched)
|
||||
return;
|
||||
|
||||
const int CC_id = 0;
|
||||
nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[CC_id];
|
||||
ul_dci_req->SFN = frame;
|
||||
ul_dci_req->Slot = slot;
|
||||
/* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each
|
||||
* allocated PDCCH so we can easily allocate UE's DCIs independent of any
|
||||
* CORESET order */
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {0};
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
const NR_UE_list_t *UE_list = &UE_info->list;
|
||||
const NR_list_t *UE_list = &UE_info->list;
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
UE_info->mac_stats[UE_id].ulsch_current_bytes = 0;
|
||||
/* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in
|
||||
* every TTI are pre-populated by the preprocessor and used below */
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
@@ -609,11 +878,29 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
|
||||
uint16_t rnti = UE_info->rnti[UE_id];
|
||||
|
||||
int8_t harq_id = select_ul_harq_pid(sched_ctrl);
|
||||
if (harq_id < 0) return;
|
||||
int8_t harq_id = sched_pusch->ul_harq_pid;
|
||||
if (harq_id < 0) {
|
||||
/* PP has not selected a specific HARQ Process, get a new one */
|
||||
harq_id = sched_ctrl->available_ul_harq.head;
|
||||
AssertFatal(harq_id >= 0,
|
||||
"no free HARQ process available for UE %d\n",
|
||||
UE_id);
|
||||
remove_front_nr_list(&sched_ctrl->available_ul_harq);
|
||||
sched_pusch->ul_harq_pid = harq_id;
|
||||
} else {
|
||||
/* PP selected a specific HARQ process. Check whether it will be a new
|
||||
* transmission or a retransmission, and remove from the corresponding
|
||||
* list */
|
||||
if (sched_ctrl->ul_harq_processes[harq_id].round == 0)
|
||||
remove_nr_list(&sched_ctrl->available_ul_harq, harq_id);
|
||||
else
|
||||
remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id);
|
||||
}
|
||||
NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id];
|
||||
cur_harq->state = ACTIVE_SCHED;
|
||||
cur_harq->last_tx_slot = sched_pusch->slot;
|
||||
DevAssert(!cur_harq->is_waiting);
|
||||
add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id);
|
||||
cur_harq->feedback_slot = sched_pusch->slot;
|
||||
cur_harq->is_waiting = true;
|
||||
|
||||
int rnti_types[2] = { NR_RNTI_C, 0 };
|
||||
|
||||
@@ -626,8 +913,11 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++;
|
||||
if (cur_harq->round == 0) {
|
||||
UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled += sched_pusch->tb_size;
|
||||
/* Save information on MCS, TBS etc for the current initial transmission
|
||||
* so we have access to it when retransmitting */
|
||||
cur_harq->sched_pusch = *sched_pusch;
|
||||
} else {
|
||||
LOG_W(MAC,
|
||||
LOG_D(MAC,
|
||||
"%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n",
|
||||
frame,
|
||||
slot,
|
||||
@@ -638,6 +928,8 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
cur_harq->round,
|
||||
cur_harq->ndi);
|
||||
}
|
||||
UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
|
||||
sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
|
||||
|
||||
LOG_D(MAC,
|
||||
"%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
|
||||
@@ -780,51 +1072,59 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
|
||||
}
|
||||
|
||||
nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[0];
|
||||
ul_dci_req->SFN = frame;
|
||||
ul_dci_req->Slot = slot;
|
||||
nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus];
|
||||
memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t));
|
||||
ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
|
||||
ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
ul_dci_req->numPdus += 1;
|
||||
/* look up the PDCCH PDU for this BWP and CORESET. If it does not exist,
|
||||
* create it */
|
||||
const int bwpid = sched_ctrl->active_bwp->bwp_Id;
|
||||
const int coresetid = sched_ctrl->coreset->controlResourceSetId;
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pdcch_pdu_bwp_coreset[bwpid][coresetid];
|
||||
if (!pdcch_pdu) {
|
||||
nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus];
|
||||
memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t));
|
||||
ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
|
||||
ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
ul_dci_req->numPdus += 1;
|
||||
nr_configure_pdcch(pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, sched_ctrl->active_bwp);
|
||||
pdcch_pdu_bwp_coreset[bwpid][coresetid] = pdcch_pdu;
|
||||
}
|
||||
|
||||
LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frame,slot);
|
||||
|
||||
nr_configure_pdcch(RC.nrmac[0],
|
||||
pdcch_pdu_rel15,
|
||||
rnti,
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
scc,
|
||||
sched_ctrl->active_bwp,
|
||||
sched_ctrl->aggregation_level,
|
||||
sched_ctrl->cce_index);
|
||||
/* Fill PDCCH DL DCI PDU */
|
||||
nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci];
|
||||
pdcch_pdu->numDlDci++;
|
||||
dci_pdu->RNTI = rnti;
|
||||
if (sched_ctrl->coreset->pdcch_DMRS_ScramblingID &&
|
||||
sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
|
||||
dci_pdu->ScramblingId = *sched_ctrl->coreset->pdcch_DMRS_ScramblingID;
|
||||
dci_pdu->ScramblingRNTI = rnti;
|
||||
} else {
|
||||
dci_pdu->ScramblingId = *scc->physCellId;
|
||||
dci_pdu->ScramblingRNTI = 0;
|
||||
}
|
||||
dci_pdu->AggregationLevel = sched_ctrl->aggregation_level;
|
||||
dci_pdu->CceIndex = sched_ctrl->cce_index;
|
||||
dci_pdu->beta_PDCCH_1_0 = 0;
|
||||
dci_pdu->powerControlOffsetSS = 1;
|
||||
|
||||
dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
|
||||
memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15));
|
||||
dci_pdu_rel15_t uldci_payload;
|
||||
memset(&uldci_payload, 0, sizeof(uldci_payload));
|
||||
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
|
||||
const int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count;
|
||||
// NOTE: below functions assume that dci_formats is an array corresponding
|
||||
// to all UL DCIs in the PDCCH, but for us it is a simple int. So before
|
||||
// having multiple UEs, the below need to be changed (IMO the functions
|
||||
// should fill for one DCI only and not handle all of them).
|
||||
config_uldci(sched_ctrl->active_ubwp,
|
||||
pusch_pdu,
|
||||
pdcch_pdu_rel15,
|
||||
&dci_pdu_rel15[0],
|
||||
&ps->dci_format,
|
||||
&uldci_payload,
|
||||
ps->dci_format,
|
||||
ps->time_domain_allocation,
|
||||
UE_info->UE_sched_ctrl[UE_id].tpc0,
|
||||
n_ubwp,
|
||||
sched_ctrl->active_bwp->bwp_Id);
|
||||
fill_dci_pdu_rel15(scc,
|
||||
secondaryCellGroup,
|
||||
pdcch_pdu_rel15,
|
||||
dci_pdu_rel15,
|
||||
&ps->dci_format,
|
||||
rnti_types,
|
||||
dci_pdu,
|
||||
&uldci_payload,
|
||||
ps->dci_format,
|
||||
rnti_types[0],
|
||||
pusch_pdu->bwp_size,
|
||||
sched_ctrl->active_bwp->bwp_Id);
|
||||
|
||||
|
||||
@@ -64,21 +64,9 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
|
||||
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
frame_t frame_rxP, sub_frame_t slot_rxP);
|
||||
|
||||
int nr_generate_dlsch_pdu(module_id_t Mod_idP,
|
||||
NR_UE_sched_ctrl_t *ue_sched_ctl,
|
||||
unsigned char *sdus_payload,
|
||||
unsigned char *mac_pdu,
|
||||
unsigned char num_sdus,
|
||||
unsigned short *sdu_lengths,
|
||||
unsigned char *sdu_lcids,
|
||||
unsigned char drx_cmd,
|
||||
unsigned char *ue_cont_res_id,
|
||||
unsigned short post_padding);
|
||||
|
||||
void nr_schedule_ue_spec(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd);
|
||||
sub_frame_t slot);
|
||||
|
||||
void schedule_control_sib1(module_id_t module_id,
|
||||
int CC_id,
|
||||
@@ -92,8 +80,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subfra
|
||||
/* \brief default preprocessor */
|
||||
void nr_simple_dlsch_preprocessor(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd);
|
||||
sub_frame_t slot);
|
||||
|
||||
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, uint8_t slots_per_frame);
|
||||
|
||||
@@ -105,7 +92,7 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
int ul_slots,
|
||||
uint64_t ulsch_in_slot_bitmap);
|
||||
|
||||
void nr_simple_ulsch_preprocessor(module_id_t module_id,
|
||||
bool nr_simple_ulsch_preprocessor(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd,
|
||||
@@ -159,11 +146,10 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs);
|
||||
* freq resources */
|
||||
void nr_preprocessor_phytest(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd);
|
||||
sub_frame_t slot);
|
||||
/* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a
|
||||
* fixed set of resources */
|
||||
void nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
bool nr_ul_preprocessor_phytest(module_id_t module_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd,
|
||||
@@ -173,22 +159,6 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframeP);
|
||||
|
||||
void nr_fill_nfapi_dl_pdu(int Mod_id,
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req,
|
||||
rnti_t rnti,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
NR_sched_pucch *pucch_sched,
|
||||
nfapi_nr_dmrs_type_e dmrsConfigType,
|
||||
uint16_t R,
|
||||
uint8_t Qm,
|
||||
uint32_t tbs,
|
||||
int StartSymbolIndex,
|
||||
int NrOfSymbols,
|
||||
int harq_pid,
|
||||
int ndi,
|
||||
int round);
|
||||
|
||||
void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
@@ -199,40 +169,30 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
|
||||
const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234);
|
||||
|
||||
|
||||
void config_uldci(NR_BWP_Uplink_t *ubwp,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
void config_uldci(const NR_BWP_Uplink_t *ubwp,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
int *dci_formats,
|
||||
int time_domain_assignment, uint8_t tpc,
|
||||
int n_ubwp, int bwp_id);
|
||||
int dci_format,
|
||||
int time_domain_assignment,
|
||||
uint8_t tpc,
|
||||
int n_ubwp,
|
||||
int bwp_id);
|
||||
|
||||
void nr_schedule_pucch(int Mod_idP,
|
||||
int UE_id,
|
||||
int nr_ulmix_slots,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP);
|
||||
|
||||
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
|
||||
void csi_period_offset(const NR_CSI_ReportConfig_t *csirep,
|
||||
int *period, int *offset);
|
||||
|
||||
void nr_csi_meas_reporting(int Mod_idP,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP);
|
||||
|
||||
bool nr_acknack_scheduling(int Mod_idP,
|
||||
int UE_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP,
|
||||
int slots_per_tdd,
|
||||
int ul_slots,
|
||||
int n_slots_frame);
|
||||
|
||||
void nr_acknack_scheduling(int Mod_idP,
|
||||
int UE_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP,
|
||||
int slots_per_tdd,
|
||||
int *pucch_id,
|
||||
int *pucch_occ);
|
||||
|
||||
int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l);
|
||||
sub_frame_t slotP);
|
||||
|
||||
void get_pdsch_to_harq_feedback(int Mod_idP,
|
||||
int UE_id,
|
||||
@@ -271,26 +231,22 @@ void find_search_space(int ss_type,
|
||||
NR_BWP_Downlink_t *bwp,
|
||||
NR_SearchSpace_t *ss);
|
||||
|
||||
void nr_configure_pdcch(gNB_MAC_INST *nr_mac,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
|
||||
uint16_t rnti,
|
||||
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
|
||||
NR_SearchSpace_t *ss,
|
||||
NR_ControlResourceSet_t *coreset,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
NR_BWP_Downlink_t *bwp,
|
||||
uint8_t aggregation_level,
|
||||
int CCEIndex);
|
||||
NR_BWP_Downlink_t *bwp);
|
||||
|
||||
void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
int *dci_formats,
|
||||
int *rnti_types,
|
||||
int dci_formats,
|
||||
int rnti_types,
|
||||
int N_RB,
|
||||
int bwp_id);
|
||||
|
||||
void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
void prepare_dci(const NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
dci_pdu_rel15_t *dci_pdu_rel15,
|
||||
nr_dci_format_t format,
|
||||
int bwp_id);
|
||||
@@ -337,14 +293,21 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB);
|
||||
|
||||
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
|
||||
|
||||
void dump_nr_ue_list(NR_UE_list_t *listP);
|
||||
void add_nr_ue_list(NR_UE_list_t *listP, int UE_id);
|
||||
/* Functions to manage an NR_list_t */
|
||||
void dump_nr_list(NR_list_t *listP);
|
||||
void create_nr_list(NR_list_t *listP, int len);
|
||||
void destroy_nr_list(NR_list_t *list);
|
||||
void add_nr_list(NR_list_t *listP, int id);
|
||||
void remove_nr_list(NR_list_t *listP, int id);
|
||||
void add_tail_nr_list(NR_list_t *listP, int id);
|
||||
void add_front_nr_list(NR_list_t *listP, int id);
|
||||
void remove_front_nr_list(NR_list_t *listP);
|
||||
|
||||
int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP);
|
||||
|
||||
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP);
|
||||
|
||||
int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP);
|
||||
int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secondaryCellGroup);
|
||||
|
||||
void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti);
|
||||
|
||||
@@ -438,4 +401,5 @@ int16_t ssb_index_from_prach(module_id_t module_idP,
|
||||
|
||||
void find_SSB_and_RO_available(module_id_t module_idP);
|
||||
|
||||
bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id);
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -113,18 +113,9 @@ void mac_top_init_gNB(void)
|
||||
|
||||
UE_info = &nrmac->UE_info;
|
||||
UE_info->num_UEs = 0;
|
||||
UE_info->list.head = -1;
|
||||
create_nr_list(&UE_info->list, MAX_MOBILES_PER_GNB);
|
||||
for (list_el = 0; list_el < MAX_MOBILES_PER_GNB; list_el++) {
|
||||
UE_info->list.next[list_el] = -1;
|
||||
UE_info->active[list_el] = false;
|
||||
for (int list_harq = 0; list_harq < NR_MAX_NB_HARQ_PROCESSES; list_harq++) {
|
||||
UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].round = 0;
|
||||
UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].ndi = 0;
|
||||
UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].is_waiting = 0;
|
||||
UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].round = 0;
|
||||
UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].ndi = 0;
|
||||
UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,10 +75,20 @@
|
||||
#define MAX_NUM_BWP 2
|
||||
#define MAX_NUM_CORESET 2
|
||||
#define MAX_NUM_CCE 90
|
||||
#define MAX_HARQ_ROUNDS 4
|
||||
/*!\brief Maximum number of random access process */
|
||||
#define NR_NB_RA_PROC_MAX 4
|
||||
#define MAX_NUM_OF_SSB 64
|
||||
|
||||
/*! \brief NR_list_t is a "list" (of users, HARQ processes, slices, ...).
|
||||
* Especially useful in the scheduler and to keep "classes" of users. */
|
||||
typedef struct {
|
||||
int head;
|
||||
int *next;
|
||||
int tail;
|
||||
int len;
|
||||
} NR_list_t;
|
||||
|
||||
typedef enum {
|
||||
RA_IDLE = 0,
|
||||
Msg2 = 1,
|
||||
@@ -282,7 +292,7 @@ typedef struct NR_sched_pucch {
|
||||
uint8_t dai_c;
|
||||
uint8_t timing_indicator;
|
||||
uint8_t resource_indicator;
|
||||
} NR_sched_pucch;
|
||||
} NR_sched_pucch_t;
|
||||
|
||||
/* this struct is a helper: as long as the TDA and DCI format remain the same
|
||||
* over the same uBWP and search space, there is no need to recalculate all
|
||||
@@ -326,13 +336,20 @@ typedef struct NR_sched_pusch {
|
||||
uint16_t R;
|
||||
uint8_t Qm;
|
||||
uint32_t tb_size;
|
||||
|
||||
/// UL HARQ PID to use for this UE, or -1 for "any new"
|
||||
int8_t ul_harq_pid;
|
||||
} NR_sched_pusch_t;
|
||||
|
||||
typedef struct NR_UE_harq {
|
||||
uint8_t is_waiting;
|
||||
bool is_waiting;
|
||||
uint8_t ndi;
|
||||
uint8_t round;
|
||||
uint16_t feedback_slot;
|
||||
|
||||
/* Transport block to be sent using this HARQ process */
|
||||
uint32_t tb[16384];
|
||||
uint32_t tb_size;
|
||||
} NR_UE_harq_t;
|
||||
|
||||
typedef struct NR_UE_old_sched {
|
||||
@@ -350,10 +367,13 @@ typedef enum {
|
||||
} NR_UL_harq_states_t;
|
||||
|
||||
typedef struct NR_UE_ul_harq {
|
||||
bool is_waiting;
|
||||
uint8_t ndi;
|
||||
uint8_t round;
|
||||
uint16_t last_tx_slot;
|
||||
NR_UL_harq_states_t state;
|
||||
uint16_t feedback_slot;
|
||||
|
||||
/// sched_pusch keeps information on MCS etc used for the initial transmission
|
||||
NR_sched_pusch_t sched_pusch;
|
||||
} NR_UE_ul_harq_t;
|
||||
|
||||
|
||||
@@ -387,10 +407,12 @@ typedef struct {
|
||||
/// the currently active BWP in UL
|
||||
NR_BWP_Uplink_t *active_ubwp;
|
||||
|
||||
NR_sched_pucch **sched_pucch;
|
||||
/// selected PUCCH index, if scheduled
|
||||
int pucch_sched_idx;
|
||||
int pucch_occ_idx;
|
||||
/// PUCCH scheduling information. Array of three, we assume for the moment:
|
||||
/// HARQ in the first field, SR in second, CSI in third (as fixed by RRC
|
||||
/// conf., i.e. if actually present). The order is important for
|
||||
/// nr_acknack_scheduling()!
|
||||
NR_sched_pucch_t sched_pucch[3];
|
||||
|
||||
NR_sched_pusch_save_t pusch_save;
|
||||
NR_sched_pusch_t sched_pusch;
|
||||
|
||||
@@ -404,6 +426,11 @@ typedef struct {
|
||||
uint16_t rbSize;
|
||||
uint16_t rbStart;
|
||||
|
||||
/// uplink bytes that are currently scheduled
|
||||
int sched_ul_bytes;
|
||||
/// estimation of the UL buffer size
|
||||
int estimated_ul_buffer;
|
||||
|
||||
// time-domain allocation for scheduled RBs
|
||||
int time_domain_allocation;
|
||||
|
||||
@@ -414,6 +441,8 @@ typedef struct {
|
||||
|
||||
/// Retransmission-related information
|
||||
NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES];
|
||||
/// DL HARQ PID to use for this UE, or -1 for "any new"
|
||||
int8_t dl_harq_pid;
|
||||
|
||||
uint16_t ta_frame;
|
||||
int16_t ta_update;
|
||||
@@ -421,8 +450,22 @@ typedef struct {
|
||||
uint8_t tpc0;
|
||||
uint8_t tpc1;
|
||||
uint16_t ul_rssi;
|
||||
/// information about every HARQ process
|
||||
NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES];
|
||||
/// HARQ processes that are free
|
||||
NR_list_t available_dl_harq;
|
||||
/// HARQ processes that await feedback
|
||||
NR_list_t feedback_dl_harq;
|
||||
/// HARQ processes that await retransmission
|
||||
NR_list_t retrans_dl_harq;
|
||||
/// information about every UL HARQ process
|
||||
NR_UE_ul_harq_t ul_harq_processes[NR_MAX_NB_HARQ_PROCESSES];
|
||||
/// UL HARQ processes that are free
|
||||
NR_list_t available_ul_harq;
|
||||
/// UL HARQ processes that await feedback
|
||||
NR_list_t feedback_ul_harq;
|
||||
/// UL HARQ processes that await retransmission
|
||||
NR_list_t retrans_ul_harq;
|
||||
int dummy;
|
||||
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
|
||||
} NR_UE_sched_ctrl_t;
|
||||
@@ -438,22 +481,15 @@ typedef struct {
|
||||
int dlsch_rounds[8];
|
||||
int dlsch_errors;
|
||||
int dlsch_total_bytes;
|
||||
int dlsch_current_bytes;
|
||||
int ulsch_rounds[8];
|
||||
int ulsch_errors;
|
||||
int ulsch_total_bytes_scheduled;
|
||||
int ulsch_total_bytes_rx;
|
||||
int ulsch_current_bytes;
|
||||
} NR_mac_stats_t;
|
||||
|
||||
|
||||
|
||||
/*! \brief UNR_E_list_t is a "list" of users within UE_info_t. Especial useful in
|
||||
* the scheduler and to keep "classes" of users. */
|
||||
typedef struct {
|
||||
int head;
|
||||
int next[MAX_MOBILES_PER_GNB];
|
||||
} NR_UE_list_t;
|
||||
|
||||
|
||||
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
|
||||
#define MAX_CSI_REPORTCONFIG 48
|
||||
typedef struct {
|
||||
@@ -461,7 +497,7 @@ typedef struct {
|
||||
nr_csi_report_t csi_report_template[MAX_MOBILES_PER_GNB][MAX_CSI_REPORTCONFIG];
|
||||
NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB];
|
||||
NR_mac_stats_t mac_stats[MAX_MOBILES_PER_GNB];
|
||||
NR_UE_list_t list;
|
||||
NR_list_t list;
|
||||
int num_UEs;
|
||||
|
||||
bool active[MAX_MOBILES_PER_GNB];
|
||||
@@ -477,9 +513,8 @@ typedef struct {
|
||||
|
||||
typedef void (*nr_pp_impl_dl)(module_id_t mod_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd);
|
||||
typedef void (*nr_pp_impl_ul)(module_id_t mod_id,
|
||||
sub_frame_t slot);
|
||||
typedef bool (*nr_pp_impl_ul)(module_id_t mod_id,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
int num_slots_per_tdd,
|
||||
@@ -510,6 +545,10 @@ typedef struct gNB_MAC_INST_s {
|
||||
nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX];
|
||||
/// NFAPI DL Config Request Structure
|
||||
nfapi_nr_dl_tti_request_t DL_req[NFAPI_CC_MAX];
|
||||
/// a PDCCH PDU groups DCIs per BWP and CORESET. The following structure
|
||||
/// keeps pointers to PDCCH PDUs within DL_req so that we can easily track
|
||||
/// PDCCH PDUs per CC/BWP/CORESET
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_idx[NFAPI_CC_MAX][MAX_NUM_BWP][MAX_NUM_CORESET];
|
||||
/// NFAPI UL TTI Request Structure, simple pointer into structure
|
||||
/// UL_tti_req_ahead for current frame/slot
|
||||
nfapi_nr_ul_tti_request_t *UL_tti_req[NFAPI_CC_MAX];
|
||||
@@ -550,6 +589,10 @@ typedef struct gNB_MAC_INST_s {
|
||||
time_stats_t schedule_pch;
|
||||
/// CCE lists
|
||||
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
|
||||
/// PUCCH: keep track of the resources has already been used by saving the
|
||||
/// highest index not yet been used in a given slot. Dynamically allocated
|
||||
/// so we can have it for every slot as a function of the numerology
|
||||
int *pucch_index_used[MAX_NUM_BWP];
|
||||
|
||||
/// DL preprocessor for differentiated scheduling
|
||||
nr_pp_impl_dl pre_processor_dl;
|
||||
|
||||
@@ -220,7 +220,7 @@ static void *enb_tun_read_thread(void *_)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("\n\n\n########## nas_sock_fd read returns len %d\n", len);
|
||||
LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len);
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager);
|
||||
@@ -264,7 +264,7 @@ static void *ue_tun_read_thread(void *_)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("\n\n\n########## nas_sock_fd read returns len %d\n", len);
|
||||
LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len);
|
||||
|
||||
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
|
||||
rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager);
|
||||
|
||||
@@ -1581,7 +1581,7 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
}
|
||||
|
||||
if (entity->tx_size + size > entity->tx_maxsize) {
|
||||
LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
|
||||
LOG_E(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -668,8 +668,8 @@ static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s)
|
||||
poll_byte = -1;
|
||||
max_retx_threshold = 8;
|
||||
sn_field_length = 12;
|
||||
nr_rlc_am = new_nr_rlc_entity_am(100000,
|
||||
100000,
|
||||
nr_rlc_am = new_nr_rlc_entity_am(10000000,
|
||||
10000000,
|
||||
deliver_sdu, ue,
|
||||
successful_delivery, ue,
|
||||
max_retx_reached, ue,
|
||||
@@ -751,8 +751,8 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_
|
||||
if (ue->drb[drb_id-1] != NULL) {
|
||||
LOG_W(RLC, "%s:%d:%s: DRB %d already exists for UE with RNTI %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
nr_rlc_am = new_nr_rlc_entity_am(100000,
|
||||
100000,
|
||||
nr_rlc_am = new_nr_rlc_entity_am(10000000,
|
||||
10000000,
|
||||
deliver_sdu, ue,
|
||||
successful_delivery, ue,
|
||||
max_retx_reached, ue,
|
||||
@@ -823,8 +823,8 @@ static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_
|
||||
if (ue->drb[drb_id-1] != NULL) {
|
||||
LOG_W(RLC, "DEBUG add_drb_um %s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
nr_rlc_um = new_nr_rlc_entity_um(1000000,
|
||||
1000000,
|
||||
nr_rlc_um = new_nr_rlc_entity_um(100000000,
|
||||
100000000,
|
||||
deliver_sdu, ue,
|
||||
t_reassembly,
|
||||
sn_field_length);
|
||||
|
||||
@@ -316,7 +316,11 @@ void oai_nw_drv_change_rx_flags(struct net_device *dev, int flags)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
|
||||
void oai_nw_drv_tx_timeout(struct net_device *dev, unsigned int txqueue)
|
||||
#else
|
||||
void oai_nw_drv_tx_timeout(struct net_device *dev)
|
||||
#endif
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
// Transmitter timeout, serious problems.
|
||||
|
||||
@@ -297,10 +297,10 @@ int nas_change_mtu(struct net_device *dev, int mtu)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0)
|
||||
void nas_tx_timeout(struct net_device *dev)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
|
||||
void nas_tx_timeout(struct net_device *dev, unsigned int txqueue)
|
||||
#else
|
||||
void nas_tx_timeout(struct net_device *dev, unsigned int x)
|
||||
void nas_tx_timeout(struct net_device *dev)
|
||||
#endif
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -302,7 +302,12 @@ void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP) {
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ue_ip_tx_timeout(struct net_device *dev_pP) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
|
||||
void ue_ip_tx_timeout(struct net_device *dev_pP, unsigned int txqueue)
|
||||
#else
|
||||
void ue_ip_tx_timeout(struct net_device *dev_pP)
|
||||
#endif
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
// Transmitter timeout, serious problems.
|
||||
ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
|
||||
|
||||
@@ -104,6 +104,9 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
|
||||
}
|
||||
|
||||
UL_info->uci_ind.num_ucis = 0;
|
||||
// mark corresponding PUCCH resources as free
|
||||
// NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs
|
||||
RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1177,7 +1177,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig;
|
||||
pdsch_servingcellconfig->codeBlockGroupTransmission = NULL;
|
||||
pdsch_servingcellconfig->xOverhead = NULL;
|
||||
pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NULL;
|
||||
pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = calloc(1, sizeof(*pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH));
|
||||
*pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16;
|
||||
pdsch_servingcellconfig->pucch_Cell= NULL;
|
||||
pdsch_servingcellconfig->ext1=calloc(1,sizeof(*pdsch_servingcellconfig->ext1));
|
||||
pdsch_servingcellconfig->ext1->maxMIMO_Layers = calloc(1,sizeof(*pdsch_servingcellconfig->ext1->maxMIMO_Layers));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
Num_Threads_PUSCH = 8;
|
||||
|
||||
gNBs =
|
||||
(
|
||||
@@ -234,6 +233,7 @@ L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
pusch_proc_threads = 8;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -246,7 +246,7 @@ RUs = (
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
Num_Threads_PUSCH = 8;
|
||||
|
||||
gNBs =
|
||||
(
|
||||
@@ -250,6 +249,7 @@ L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
pusch_proc_threads = 8;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user