diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 0aeeaf3afdd497fce65eaba91d5c0c14408a7990..1e76d2e949ea3d40da1d15a72aab1de7f5f065e6 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -191,67 +191,6 @@ int PRBalloc_to_locationandbandwidth(int NPRB,int RBstart) { return(PRBalloc_to_locationandbandwidth0(NPRB,RBstart,275)); } -/// Target code rate tables indexed by Imcs -/* TS 38.214 table 5.1.3.1-1 - MCS index table 1 for PDSCH */ -uint16_t nr_target_code_rate_table1[29] = {120, 157, 193, 251, 308, 379, 449, 526, 602, 679, 340, 378, 434, 490, 553, \ - 616, 658, 438, 466, 517, 567, 616, 666, 719, 772, 822, 873, 910, 948}; - -/* TS 38.214 table 5.1.3.1-2 - MCS index table 2 for PDSCH */ -// Imcs values 20 and 26 have been multiplied by 2 to avoid the floating point -uint16_t nr_target_code_rate_table2[28] = {120, 193, 308, 449, 602, 378, 434, 490, 553, 616, 658, 466, 517, 567, \ - 616, 666, 719, 772, 822, 873, 1365, 711, 754, 797, 841, 885, 1833, 948}; - -/* TS 38.214 table 5.1.3.1-3 - MCS index table 3 for PDSCH */ -uint16_t nr_target_code_rate_table3[29] = {30, 40, 50, 64, 78, 99, 120, 157, 193, 251, 308, 379, 449, 526, 602, 340, \ - 378, 434, 490, 553, 616, 438, 466, 517, 567, 616, 666, 719, 772}; - -uint16_t nr_tbs_table[93] = {24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 208, 224, 240, 256, 272, 288, 304, 320, \ - 336, 352, 368, 384, 408, 432, 456, 480, 504, 528, 552, 576, 608, 640, 672, 704, 736, 768, 808, 848, 888, 928, 984, 1032, 1064, 1128, 1160, 1192, 1224, 1256, \ - 1288, 1320, 1352, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 2024, 2088, 2152, 2216, 2280, 2408, 2472, 2536, 2600, 2664, 2728, 2792, 2856, 2976, \ - 3104, 3240, 3368, 3496, 3624, 3752, 3824}; - -uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx) { - switch(table_idx) { - case 1: - return (((Imcs<10)||(Imcs==29))?2:((Imcs<17)||(Imcs==30))?4:((Imcs<29)||(Imcs==31))?6:-1); - break; - - case 2: - return (((Imcs<5)||(Imcs==28))?2:((Imcs<11)||(Imcs==29))?4:((Imcs<20)||(Imcs==30))?6:((Imcs<28)||(Imcs==31))?8:-1); - break; - - case 3: - return (((Imcs<15)||(Imcs==29))?2:((Imcs<21)||(Imcs==30))?4:((Imcs<29)||(Imcs==31))?6:-1); - break; - - default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,3])\n", table_idx); - return(0); - break; - } -} - -uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx) { - switch(table_idx) { - case 1: - return (nr_target_code_rate_table1[Imcs]); - break; - - case 2: - return (nr_target_code_rate_table2[Imcs]); - break; - - case 3: - return (nr_target_code_rate_table3[Imcs]); - break; - - default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,3])\n", table_idx); - return(0); - break; - } -} - void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) { uint8_t count=0, start=0, start_set=0; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index a09532a56523cfd5cdcd0ce05865294da4b3b8d5..5258ce8809b66a45f737f032057a50ea88414db1 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -69,12 +69,6 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); int PRBalloc_to_locationandbandwidth(int NPRB,int RBstart); -extern uint16_t nr_target_code_rate_table1[29]; -extern uint16_t nr_target_code_rate_table2[28]; -extern uint16_t nr_target_code_rate_table3[29]; -extern uint16_t nr_tbs_table[93]; -uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx); -uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx); int get_subband_size(int NPRB,int size); void SLIV2SL(int SLIV,int *S,int *L); int get_dmrs_port(int nl, uint16_t dmrs_ports); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 50244ad718d054647d3f03a98c0d4091085757e0..7e443339f9dc85a1474c70f9164b7dcb753a3401 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -434,6 +434,9 @@ typedef struct { uint8_t mcs; uint8_t ndi; uint8_t rv; + uint16_t targetCodeRate; + uint8_t qamModOrder; + uint32_t TBS; uint8_t tb2_mcs; uint8_t tb2_ndi; uint8_t tb2_rv; diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 51cae1bd8cab1e5b4e2884ba8e39d0dd0346401b..9972a47ee7d9369eabdd7852ac10093cab9cc940 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -469,18 +469,6 @@ int32_t nr_segmentation(unsigned char *input_buffer, unsigned int *F, uint8_t BG); -/*!\fn uint32_t nr_compute_tbs -\brief This function returns the TBS in bits as per 6.1.4.2 of TS 38.214 -*/ -uint32_t nr_compute_tbs(uint16_t Qm, - uint16_t R, - uint16_t nb_rb, - uint16_t nb_symb_sch, - uint16_t nb_dmrs_prb, - uint16_t nb_rb_oh, - uint8_t tb_scaling, - uint8_t Nl); - void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f); void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index daa4ed17230af7ae0078a809797f1e3dfd343c52..bdf681c21d3dbb480dca1a4f16acb754bb62f8b3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -49,11 +49,6 @@ void nr_get_rbg_parms(NR_BWP_PARMS* bwp, uint8_t config_type); void nr_get_rbg_list(uint32_t bitmap, uint8_t n_rbg, uint8_t* rbg_list); - -uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx); - -uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx); - void nr_pdsch_codeword_scrambling(uint8_t *in, uint32_t size, uint8_t q, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 84ea27fb9c982027350217eb428bbb255bae29fd..8e97a8cbdce1e908de6c2b208c5ca7c444d49d28 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -306,7 +306,6 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, unsigned int crc=1; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; impp.Zc = &harq->Z; - float Coderate = 0.0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); uint32_t A = rel15->TBSize[0]<<3; unsigned char *a=harq->pdu; @@ -369,10 +368,9 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc } - if (rel15->targetCodeRate[0]<1000) - Coderate = (float)rel15->targetCodeRate[0] /(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)rel15->targetCodeRate[0] /(float) 2048; + // target_code_rate is in 0.1 units + float Coderate = (float) rel15->targetCodeRate[0] / 10240.0f; + LOG_D(PHY,"DLSCH Coderate %f\n",Coderate); if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) impp.BG = 2; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index 2daf2af1fb80922c90caacd2796ca39ff4eb4df8..74d19bf6f614666abf139fe31310cd0d2c351021 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -60,14 +60,6 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r); -uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx); - -uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx); - -uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx); - -uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx); - void compute_nr_prach_seq(uint8_t short_sequence, uint8_t num_sequences, uint8_t rootSequenceIndex, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 85355ec3aead5ad6f3c4ef0dda973552760dd75b..b9a1430be64672c978dcf31cda8cda401a4f9748 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -407,13 +407,10 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, phy_vars_gNB->nbDecode = 0; harq_process->processedSegments = 0; - - double Coderate = 0.0; // ------------------------------------------------------------------ uint16_t nb_rb = pusch_pdu->rb_size; uint8_t Qm = pusch_pdu->qam_mod_order; - uint16_t R = pusch_pdu->target_code_rate; uint8_t mcs = pusch_pdu->mcs_index; uint8_t n_layers = pusch_pdu->nrOfLayers; // ------------------------------------------------------------------ @@ -442,14 +439,12 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, A = (harq_process->TBS)<<3; - LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %d RV %d round %d\n", - harq_pid, A, G, mcs, n_layers, nb_rb, Qm, R, pusch_pdu->pusch_data.rv_index, harq_process->round); + // target_code_rate is in 0.1 units + float Coderate = (float) pusch_pdu->target_code_rate / 10240.0f; + + LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d\n", + harq_pid, A, G, mcs, n_layers, nb_rb, Qm, Coderate, pusch_pdu->pusch_data.rv_index, harq_process->round); - if (R<1024) - Coderate = (float) R /(float) 1024; - else - Coderate = (float) R /(float) 2048; - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ p_decParams->BG = 2; kc = 52; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index a832e8f29c9f1aebd2b9bc1d9f79df8829d00534..403f016e79bcc571ab70125306e398e929bf5f26 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -430,8 +430,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint16_t nb_symb_sch, uint8_t nr_slot_rx, uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag) { + uint8_t is_crnti) { uint32_t A,E; uint32_t G; uint32_t ret,offset; @@ -449,7 +448,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, LOG_D(PHY,"Round %d RV idx %d\n",harq_process->DLround,harq_process->rvidx); uint8_t kc; uint16_t nb_rb;// = 30; - double Coderate;// = 0.0; uint8_t dmrs_Type = harq_process->dmrsConfigType; AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); uint8_t nb_re_dmrs; @@ -499,21 +497,18 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, */ nb_rb = harq_process->nb_rb; harq_process->trials[harq_process->DLround]++; - 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*dmrs_length, nb_rb_oh, 0, harq_process->Nl); + A = harq_process->TBS; ret = dlsch->max_ldpc_iterations + 1; dlsch->last_iteration_cnt = ret; harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, dmrs_length, harq_process->Qm,harq_process->Nl); G = harq_process->G; - LOG_D(PHY,"%d.%d DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n", - frame,nr_slot_rx,harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); + // target_code_rate is in 0.1 units + float Coderate = (float) harq_process->R / 10240.0f; - if ((harq_process->R)<1024) - Coderate = (float) (harq_process->R) /(float) 1024; - else - Coderate = (float) (harq_process->R) /(float) 2048; + LOG_D(PHY,"%d.%d DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d Coderate %f\n", + frame,nr_slot_rx,harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, harq_process->mcs, harq_process->Nl, nb_symb_sch, nb_rb, harq_process->Qm, Coderate); if ((A <=292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 9cedc333569b4f3d86275135bc1d2018abb4db99..cd1bc9d3b2eea6ee05fb8221fa0f2f43cf78abfd 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -260,13 +260,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return -1; } - dlsch0_harq->Qm = nr_get_Qm_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); - dlsch0_harq->R = nr_get_code_rate_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); - if (dlsch0_harq->Qm == 0 || dlsch0_harq->R == 0) { - LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); - return -1; - } - #ifdef DEBUG_HARQ printf("[DEMOD] MIMO mode = %d\n", dlsch0_harq->mimo_mode); printf("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1); @@ -2600,7 +2593,7 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, } if (dlsch1_harq) { - switch (nr_get_Qm_dl(dlsch1_harq->mcs,dlsch1_harq->mcs_table)) { + switch (dlsch1_harq->Qm) { case 2 : if (rx_type==rx_standard) { nr_dlsch_qpsk_llr(frame_parms, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index f5df234dc660e246feef1ce3279ea3a4b51ce546..a342c93e7c74af549d6b85a2fc5309782474efbd 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1013,8 +1013,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint16_t nb_symb_sch, uint8_t nr_slot_rx, uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag); + uint8_t is_crnti); int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, NR_UE_ULSCH_t *ulsch, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 833e542eea5d6214e91ec8822bd49fe04840111a..d09f2554cc1465b2c68f824a320d234b77867702 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -192,14 +192,14 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, unsigned int crc = 1; NR_UL_UE_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; uint16_t nb_rb = harq_process->pusch_pdu.rb_size; - uint32_t A = harq_process->pusch_pdu.pusch_data.tb_size*8; + uint32_t A = harq_process->pusch_pdu.pusch_data.tb_size<<3; uint32_t *pz = &harq_process->Z; - uint8_t mod_order = nr_get_Qm_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table); - uint16_t R = nr_get_code_rate_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table); + uint8_t mod_order = harq_process->pusch_pdu.qam_mod_order; uint16_t Kr=0; uint32_t r_offset=0; uint32_t F=0; - float Coderate = 0.0; + // target_code_rate is in 0.1 units + float Coderate = (float) harq_process->pusch_pdu.target_code_rate / 10240.0f; /////////// ///////////////////////////////////////////////////////////////////////////////////////// @@ -207,7 +207,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, harq_process->pusch_pdu.nrOfLayers); - LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d\n", A, G, mod_order); + LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, mod_order, Coderate); LOG_D(NR_PHY, "harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n", harq_pid,harq_process->ndi,harq_process->pusch_pdu.pusch_data.new_data_indicator); @@ -264,11 +264,6 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ///////////////////////// b---->| block segmentation |---->c ///////////////////////// /////////// - if (R<1024) - Coderate = (float) R /(float) 1024; - else - Coderate = (float) R /(float) 2048; - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ harq_process->BG = 2; } diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 9ac08467d4711951cd3f14908c033313a01c8060..74f8c7b56a1fd531ef04b2b90a4c7e449521c95a 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -315,6 +315,9 @@ void configure_dlsch(NR_UE_DLSCH_t *dlsch0, dlsch0_harq->mcs = dlsch_config_pdu->mcs; dlsch0_harq->rvidx = dlsch_config_pdu->rv; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; + dlsch0_harq->R = dlsch_config_pdu->targetCodeRate; + dlsch0_harq->Qm = dlsch_config_pdu->qamModOrder; + dlsch0_harq->TBS = dlsch_config_pdu->TBS; dlsch0_harq->tbslbrm = dlsch_config_pdu->tbslbrm; dlsch0_harq->nscid = dlsch_config_pdu->nscid; dlsch0_harq->dlDmrsScramblingId = dlsch_config_pdu->dlDmrsScramblingId; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b50b3795ba52f70477f2619f0932e6a0f6407ae9..99731c8cb1916435a858e36f5d30ce72edf54bcf 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -802,8 +802,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nb_symb_sch, nr_slot_rx, harq_pid, - pdsch==PDSCH?1:0, - dlsch0->harq_processes[harq_pid]->TBS>256?1:0); + pdsch==PDSCH); LOG_T(PHY,"dlsch decoding, ret = %d\n", ret); @@ -879,8 +878,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nb_symb_sch, nr_slot_rx, harq_pid, - pdsch==PDSCH?1:0,//proc->decoder_switch, - dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + pdsch==PDSCH);//proc->decoder_switch LOG_T(PHY,"CW dlsch decoding, ret1 = %d\n", ret1); stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 8cd7543bf34e9dc3690e89bd28d1fd411178d42f..e81871b146b33c96e05eda711877d96108c84815 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -47,6 +47,7 @@ #include "openair1/SIMULATION/RF/rf.h" #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" #include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" //#define DEBUG_NR_DLSCHSIM @@ -430,13 +431,10 @@ int main(int argc, char **argv) NR_gNB_DLSCH_t *dlsch = msgDataTx.dlsch[0][0]; 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; + uint8_t is_crnti = 0; unsigned int TBS = 8424; - unsigned int available_bits; uint8_t nb_re_dmrs = 6; // No data in dmrs symbol uint16_t length_dmrs = 1; - unsigned char mod_order; - uint16_t rate; uint8_t Nl = 1; uint8_t rvidx = 0; dlsch->rnti = 1; @@ -444,9 +442,9 @@ int main(int argc, char **argv) dlsch->harq_processes[0]->rvidx = rvidx;*/ //printf("dlschsim harqid %d nb_rb %d, mscs %d\n",dlsch->harq_ids[subframe], // dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->mcs,dlsch->harq_processes[0]->Nl); - mod_order = nr_get_Qm_dl(Imcs, mcs_table); - rate = nr_get_code_rate_dl(Imcs, mcs_table); - available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1); + unsigned char mod_order = nr_get_Qm_dl(Imcs, mcs_table); + uint16_t rate = nr_get_code_rate_dl(Imcs, mcs_table); + unsigned int available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1); TBS = nr_compute_tbs(mod_order,rate, nb_rb, nb_symb_sch, nb_re_dmrs*length_dmrs, 0, 0, Nl); printf("available bits %u TBS %u mod_order %d\n", available_bits, TBS, mod_order); //dlsch->harq_ids[subframe]= 0; @@ -478,6 +476,7 @@ int main(int argc, char **argv) harq_process->Qm = mod_order; harq_process->rvidx = rvidx; harq_process->R = rate; + harq_process->TBS = TBS; harq_process->dmrsConfigType = NFAPI_NR_DMRS_TYPE1; harq_process->dlDmrsSymbPos = 4; harq_process->n_dmrs_cdm_groups = 1; @@ -498,8 +497,8 @@ int main(int argc, char **argv) //printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32)); // generate signal - unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32))); - bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32))); + bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); if (input_fd == NULL) { nr_dlsch_encoding(gNB, frame, slot, &dlsch->harq_process, frame_parms,output,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } @@ -551,7 +550,7 @@ int main(int argc, char **argv) ret = nr_dlsch_decoding(UE, &proc, 0, channel_output_fixed, &UE->frame_parms, dlsch0_ue, dlsch0_ue->harq_processes[0], frame, nb_symb_sch, - slot,harq_pid, is_crnti, llr8_flag); + slot,harq_pid, is_crnti); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT); diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 1eaeb6139bce8c1b319202c2e2136285982949cf..8a0a2d51441b383715a3ebae1f968b3b639025f3 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -47,6 +47,7 @@ #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" #include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" #include "common/utils/threadPool/thread-pool.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" //#define DEBUG_NR_ULSCHSIM @@ -461,7 +462,7 @@ int main(int argc, char **argv) rel15_ul->pusch_data.rv_index = rvidx; rel15_ul->nrOfLayers = Nl; rel15_ul->target_code_rate = code_rate; - rel15_ul->pusch_data.tb_size = TBS/8; + rel15_ul->pusch_data.tb_size = TBS>>3; /////////////////////////////////////////////////// double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc @@ -488,7 +489,9 @@ int main(int argc, char **argv) harq_process_ul_ue->pusch_pdu.nr_of_symbols = nb_symb_sch; harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb*nb_codewords; harq_process_ul_ue->pusch_pdu.pusch_data.rv_index = rvidx; - harq_process_ul_ue->pusch_pdu.pusch_data.tb_size = TBS/8; + harq_process_ul_ue->pusch_pdu.pusch_data.tb_size = TBS>>3; + harq_process_ul_ue->pusch_pdu.target_code_rate = code_rate; + harq_process_ul_ue->pusch_pdu.qam_mod_order = mod_order; unsigned char *test_input = harq_process_ul_ue->a; /////////// diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index bdff8da29873ade63f62502020c11fa95ed93f6a..6a0d48904da5d39e9b1ddb5fd302e47965850239 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1165,6 +1165,7 @@ int main(int argc, char **argv) ul_config.ul_config_list[0].pusch_config_pdu.nrOfLayers = precod_nbr_layers; ul_config.ul_config_list[0].pusch_config_pdu.dmrs_ports = ((1<<precod_nbr_layers)-1); ul_config.ul_config_list[0].pusch_config_pdu.absolute_delta_PUSCH = 0; + ul_config.ul_config_list[0].pusch_config_pdu.target_code_rate = code_rate; ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.tb_size = TBS/8; ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = trial & 0x1; diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index e634f077e269c030b2ab53da28f8f2ff7e216e1e..a7bc3e85454f200f7220c39c8e345475008c1dd0 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -62,12 +62,15 @@ #define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER "dl_bler_target_lower" -#define CONFIG_STRING_MACRLC_DL_RD2_BLER_THRESHOLD "dl_rd2_bler_threshold" #define CONFIG_STRING_MACRLC_DL_MAX_MCS "dl_max_mcs" +#define CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER "ul_bler_target_upper" +#define CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER "ul_bler_target_lower" +#define CONFIG_STRING_MACRLC_UL_MAX_MCS "ul_max_mcs" #define CONFIG_STRING_MACRLC_HARQ_ROUND_MAX "harq_round_max" #define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb" #define CONFIG_STRING_MACRLC_MIN_GRANT_MCS "min_grant_mcs" + /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* MacRLC configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -97,8 +100,10 @@ {CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER, "Lower threshold of BLER to increase DL MCS", 0, dblptr:NULL, defdblval:0.05, TYPE_DOUBLE, 0}, \ -{CONFIG_STRING_MACRLC_DL_RD2_BLER_THRESHOLD, "Threshold of RD2/RETX2 BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.01, TYPE_DOUBLE, 0}, \ {CONFIG_STRING_MACRLC_DL_MAX_MCS, "Maximum DL MCS that should be used", 0, u8ptr:NULL, defintval:28, TYPE_UINT8, 0}, \ +{CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease UL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \ +{CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER, "Lower threshold of BLER to increase UL MCS", 0, dblptr:NULL, defdblval:0.05, TYPE_DOUBLE, 0}, \ +{CONFIG_STRING_MACRLC_UL_MAX_MCS, "Maximum UL MCS that should be used", 0, u8ptr:NULL, defintval:9, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_HARQ_ROUND_MAX, "Maximum number of HARQ rounds", 0, u8ptr:NULL, defintval:4, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_MIN_GRANT_PRB, "Minimal Periodic ULSCH Grant PRBs", 0, u8ptr:NULL, defintval:5, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_MIN_GRANT_MCS, "Minimal Periodic ULSCH Grant MCS", 0, u8ptr:NULL, defintval:9, TYPE_UINT8, 0} \ @@ -127,10 +132,13 @@ #define MACRLC_PUSCHFAILURETHRES_IDX 21 #define MACRLC_DL_BLER_TARGET_UPPER_IDX 22 #define MACRLC_DL_BLER_TARGET_LOWER_IDX 23 -#define MACRLC_DL_RD2_BLER_THRESHOLD_IDX 24 -#define MACRLC_DL_MAX_MCS_IDX 25 -#define MACRLC_HARQ_ROUND_MAX_IDX 26 -#define MACRLC_MIN_GRANT_PRB_IDX 27 -#define MACRLC_MIN_GRANT_MCS_IDX 28 +#define MACRLC_DL_MAX_MCS_IDX 24 +#define MACRLC_UL_BLER_TARGET_UPPER_IDX 25 +#define MACRLC_UL_BLER_TARGET_LOWER_IDX 26 +#define MACRLC_UL_MAX_MCS_IDX 27 +#define MACRLC_HARQ_ROUND_MAX_IDX 28 +#define MACRLC_MIN_GRANT_PRB_IDX 29 +#define MACRLC_MIN_GRANT_MCS_IDX 30 + /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index c11d6b8092353c065864c083283dc3dcac49df6e..9292d1f96210f883899aed8725af726a5f01dd3f 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -873,10 +873,14 @@ void RCconfig_nr_macrlc() { AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); } RC.nrmac[j]->ulsch_max_frame_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_FRAME_INACTIVITY].uptr); - RC.nrmac[j]->dl_bler_target_upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr); - RC.nrmac[j]->dl_bler_target_lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr); - RC.nrmac[j]->dl_rd2_bler_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_RD2_BLER_THRESHOLD_IDX].dblptr); - RC.nrmac[j]->dl_max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr); + NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler; + dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr); + dl_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr); + dl_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr); + NR_bler_options_t *ul_bler_options = &RC.nrmac[j]->ul_bler; + ul_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_UPPER_IDX].dblptr); + ul_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_LOWER_IDX].dblptr); + ul_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MAX_MCS_IDX].u8ptr); RC.nrmac[j]->harq_round_max = *(MacRLC_ParamList.paramarray[j][MACRLC_HARQ_ROUND_MAX_IDX].u8ptr); RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr); RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c index 855b6e98224e6710776538e8d8bab850e3206acb..1acf23197c73509102f5450adffefe45ccc5eece 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c @@ -49,16 +49,15 @@ uint32_t nr_compute_tbs(uint16_t Qm, uint16_t nbp_re, nb_re; uint32_t nr_tbs=0; uint32_t Ninfo, Np_info, C; - uint8_t n, scale; + uint8_t n; LOG_D(NR_MAC, "In %s: nb_symb_sch %d, nb_dmrs_prb %d, nb_rb %d, nb_rb_oh %d, tb_scaling %d Nl %d\n", __FUNCTION__, nb_symb_sch, nb_dmrs_prb, nb_rb, nb_rb_oh, tb_scaling, Nl); nbp_re = NR_NB_SC_PER_RB * nb_symb_sch - nb_dmrs_prb - nb_rb_oh; nb_re = min(156, nbp_re) * nb_rb; - scale = (R>1024)?11:10; // Intermediate number of information bits - Ninfo = ((nb_re * R * Qm * Nl)>>scale)>>tb_scaling; - + // R is tabulated as 10 times the actual code rate + Ninfo = ((nb_re * R * Qm * Nl / 10)>>10)>>tb_scaling; if (Ninfo <=3824) { n = max(3, floor(log2(Ninfo)) - 6); @@ -73,7 +72,7 @@ uint32_t nr_compute_tbs(uint16_t Qm, n = log2(Ninfo-24)-5; Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n); - if (R <= 256) { + if (R <= 2560) { C = CEILIDIV((Np_info+24),3816); nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24; } else { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 9a0a4f5ae7b790aabe7f25695cc00f6933ea8062..e5cabb452155f7ac44bb9ad986d012d0b52eae3b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2095,17 +2095,15 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS*dmrs_length - N_PRB_oh; LOG_D(MAC, "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n", N_RE_prime, N_sh_symb, N_PRB_DMRS, N_PRB_oh); - uint16_t R; uint32_t TBS=0; - uint8_t table_idx, Qm; /*uint8_t mcs_table = config.pdsch_config.mcs_table.value; uint8_t ss_type = params_rel15.search_space_type; uint8_t dci_format = params_rel15.dci_format; get_table_idx(mcs_table, dci_format, rnti_type, ss_type);*/ - table_idx = 0; - R = nr_get_code_rate_dl(Imcs, table_idx); - Qm = nr_get_Qm_dl(Imcs, table_idx); + uint8_t table_idx = 0; + uint16_t R = nr_get_code_rate_dl(Imcs, table_idx); + uint8_t Qm = nr_get_Qm_dl(Imcs, table_idx); TBS = nr_compute_tbs(Qm, R, @@ -2126,25 +2124,25 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, TBS, N_PRB_DMRS, N_sh_symb, N_PRB_oh, R, Qm, table_idx,N_RE_prime*pdsch_rel15->rbSize*pdsch_rel15->NrOfCodewords ); } +// the following tables contain 10 times the value reported in 214 (in line with SCF specification and to avoid fractional values) //Table 5.1.3.1-1 of 38.214 -uint16_t Table_51311[29][2] = {{2,120},{2,157},{2,193},{2,251},{2,308},{2,379},{2,449},{2,526},{2,602},{2,679},{4,340},{4,378},{4,434},{4,490},{4,553},{4,616}, - {4,658},{6,438},{6,466},{6,517},{6,567},{6,616},{6,666},{6,719},{6,772},{6,822},{6,873}, {6,910}, {6,948}}; +uint16_t Table_51311[29][2] = {{2,1200},{2,1570},{2,1930},{2,2510},{2,3080},{2,3790},{2,4490},{2,5260},{2,6020},{2,6790},{4,3400},{4,3780},{4,4340},{4,4900},{4,5530},{4,6160}, + {4,6580},{6,4380},{6,4660},{6,5170},{6,5670},{6,6160},{6,6660},{6,7190},{6,7720},{6,8220},{6,8730}, {6,9100}, {6,9480}}; //Table 5.1.3.1-2 of 38.214 // Imcs values 20 and 26 have been multiplied by 2 to avoid the floating point -uint16_t Table_51312[28][2] = {{2,120},{2,193},{2,308},{2,449},{2,602},{4,378},{4,434},{4,490},{4,553},{4,616},{4,658},{6,466},{6,517},{6,567},{6,616},{6,666}, - {6,719},{6,772},{6,822},{6,873},{8,1365},{8,711},{8,754},{8,797},{8,841},{8,885},{8,1833},{8,948}}; +uint16_t Table_51312[28][2] = {{2,1200},{2,1930},{2,3080},{2,4490},{2,6020},{4,3780},{4,4340},{4,4900},{4,5530},{4,6160},{4,6580},{6,4660},{6,5170},{6,5670},{6,6160},{6,6660}, + {6,7190},{6,7720},{6,8220},{6,8730},{8,6825},{8,7110},{8,7540},{8,7970},{8,8410},{8,8850},{8,9165},{8,9480}}; //Table 5.1.3.1-3 of 38.214 -uint16_t Table_51313[29][2] = {{2,30},{2,40},{2,50},{2,64},{2,78},{2,99},{2,120},{2,157},{2,193},{2,251},{2,308},{2,379},{2,449},{2,526},{2,602},{4,340}, - {4,378},{4,434},{4,490},{4,553},{4,616},{6,438},{6,466},{6,517},{6,567},{6,616},{6,666}, {6,719}, {6,772}}; +uint16_t Table_51313[29][2] = {{2,300},{2,400},{2,500},{2,640},{2,780},{2,990},{2,1200},{2,1570},{2,1930},{2,2510},{2,3080},{2,3790},{2,4490},{2,5260},{2,6020},{4,3400}, + {4,3780},{4,4340},{4,4900},{4,5530},{4,6160},{6,4380},{6,4660},{6,5170},{6,5670},{6,6160},{6,6660},{6,7190},{6,7720}}; -uint16_t Table_61411[28][2] = {{2,120},{2,157},{2,193},{2,251},{2,308},{2,379},{2,449},{2,526},{2,602},{2,679},{4,340},{4,378},{4,434},{4,490},{4,553},{4,616}, - {4,658},{6,466},{6,517},{6,567},{6,616},{6,666},{6,719},{6,772},{6,822},{6,873}, {6,910}, {6,948}}; - -uint16_t Table_61412[28][2] = {{2,30},{2,40},{2,50},{2,64},{2,78},{2,99},{2,120},{2,157},{2,193},{2,251},{2,308},{2,379},{2,449},{2,526},{2,602},{2,679}, - {4,378},{4,434},{4,490},{4,553},{4,616},{4,658},{4,699},{4,772},{6,567},{6,616},{6,666}, {6,772}}; +uint16_t Table_61411[28][2] = {{2,1200},{2,1570},{2,1930},{2,2510},{2,3080},{2,3790},{2,4490},{2,5260},{2,6020},{2,6790},{4,3400},{4,3780},{4,4340},{4,4900},{4,5530},{4,6160}, + {4,6580},{6,4660},{6,5170},{6,5670},{6,6160},{6,6660},{6,7190},{6,7720},{6,8220},{6,8730},{6,9100},{6,9480}}; +uint16_t Table_61412[28][2] = {{2,300},{2,400},{2,500},{2,640},{2,780},{2,990},{2,1200},{2,1570},{2,1930},{2,2510},{2,3080},{2,3790},{2,4490},{2,5260},{2,6020},{2,6790}, + {4,3780},{4,4340},{4,4900},{4,5530},{4,6160},{4,6580},{4,6990},{4,7720},{6,5670},{6,6160},{6,6660},{6,7720}}; uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx) { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index ae6d1839b3bc2e9164b9cf0aad02f489229f18e4..a658c990bc181fcbc1ed51793d9b10730306ce84 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -121,6 +121,23 @@ int32_t get_l_prime(uint8_t duration_in_symbols, uint8_t mapping_type, pusch_dmr uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint8_t mcs_table); uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB); +uint32_t nr_compute_tbs(uint16_t Qm, + uint16_t R, + uint16_t nb_rb, + uint16_t nb_symb_sch, + uint16_t nb_dmrs_prb, + uint16_t nb_rb_oh, + uint8_t tb_scaling, + uint8_t Nl); + +/** \brief Computes Q based on I_MCS PDSCH and table_idx for downlink. Implements MCS Tables from 38.214. */ +uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx); +uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx); + +/** \brief Computes Q based on I_MCS PDSCH and table_idx for uplink. Implements MCS Tables from 38.214. */ +uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx); +uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx); + uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset); int get_bw_tbslbrm(NR_BWP_t *genericParameters, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index dca9e1db56657ac60757f39c1fb73597eb001652..06ffb1c285af42bcec7945ab78458d8afa92402c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -936,6 +936,23 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr return -1; } + dlsch_config_pdu_1_0->qamModOrder = nr_get_Qm_dl(dlsch_config_pdu_1_0->mcs, dlsch_config_pdu_1_0->mcs_table); + int R = nr_get_code_rate_dl(dlsch_config_pdu_1_0->mcs, dlsch_config_pdu_1_0->mcs_table); + dlsch_config_pdu_1_0->targetCodeRate = R; + if (dlsch_config_pdu_1_0->targetCodeRate == 0 || dlsch_config_pdu_1_0->qamModOrder == 0) { + LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); + return -1; + } + + int nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs + int nb_re_dmrs = ((dlsch_config_pdu_1_0->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6:4)*dlsch_config_pdu_1_0->n_dmrs_cdm_groups; + dlsch_config_pdu_1_0->TBS = nr_compute_tbs(dlsch_config_pdu_1_0->qamModOrder, + R, + dlsch_config_pdu_1_0->number_rbs, + dlsch_config_pdu_1_0->number_symbols, + nb_re_dmrs*get_num_dmrs(dlsch_config_pdu_1_0->dlDmrsSymbPos), + nb_rb_oh, 0, 1); + int bw_tbslbrm; if (mac->scc || mac->scc_SIB || mac->cg) { NR_BWP_t genericParameters = mac->scc ? mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters : @@ -1353,6 +1370,25 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dl_config->number_pdus = dl_config->number_pdus + 1; /* TODO same calculation for MCS table as done in UL */ dlsch_config_pdu_1_1->mcs_table = (pdsch_Config->mcs_Table) ? (*pdsch_Config->mcs_Table + 1) : 0; + dlsch_config_pdu_1_1->qamModOrder = nr_get_Qm_dl(dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table); + int R = nr_get_code_rate_dl(dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table); + dlsch_config_pdu_1_1->targetCodeRate = R; + if (dlsch_config_pdu_1_1->targetCodeRate == 0 || dlsch_config_pdu_1_1->qamModOrder == 0) { + LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); + return -1; + } + uint8_t Nl = 0; + for (int i = 0; i < 12; i++) { // max 12 ports + if ((dlsch_config_pdu_1_1->dmrs_ports>>i)&0x01) Nl += 1; + } + int nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs + int nb_re_dmrs = ((dmrs_type == NULL) ? 6:4)*dlsch_config_pdu_1_1->n_dmrs_cdm_groups; + dlsch_config_pdu_1_1->TBS = nr_compute_tbs(dlsch_config_pdu_1_1->qamModOrder, + R, + dlsch_config_pdu_1_1->number_rbs, + dlsch_config_pdu_1_1->number_symbols, + nb_re_dmrs*get_num_dmrs(dlsch_config_pdu_1_1->dlDmrsSymbPos), + nb_rb_oh, 0, Nl); // TBS_LBRM according to section 5.4.2.1 of 38.212 long *maxMIMO_Layers = mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 1e019a474412860923ef83c66d87fd28b42dfa9b..864f142fdcffa2decc02a4650862d101964a6974 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -840,10 +840,10 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, mappingtype, add_pos, dmrslength, pusch_config_pdu->start_symbol_index, mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position); - if ((mac->ULbwp[ul_bwp_id-1] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled)) - if (*dci_format != NR_UL_DCI_FORMAT_0_1) { + if (mac->ULbwp[ul_bwp_id-1] && (pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled)) { + if (*dci_format != NR_UL_DCI_FORMAT_0_1) pusch_config_pdu->num_dmrs_cdm_grps_no_data = 1; - } + } else if (*dci_format == NR_UL_DCI_FORMAT_0_0 || (mac->ULbwp[ul_bwp_id-1] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled)) pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; @@ -891,7 +891,8 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, rnti_types[rnti_type]); pusch_config_pdu->ul_dmrs_symb_pos = l_prime_mask; - pusch_config_pdu->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); + uint16_t R = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); + pusch_config_pdu->target_code_rate = R; pusch_config_pdu->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); if (pusch_config_pdu->target_code_rate == 0 || pusch_config_pdu->qam_mod_order == 0) { @@ -910,14 +911,13 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, // Compute TBS pusch_config_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_config_pdu->qam_mod_order, - pusch_config_pdu->target_code_rate, + R, pusch_config_pdu->rb_size, pusch_config_pdu->nr_of_symbols, nb_dmrs_re_per_rb*number_dmrs_symbols, N_PRB_oh, 0, // TBR to verify tb scaling - pusch_config_pdu->nrOfLayers)/8; - + pusch_config_pdu->nrOfLayers)>>3; return 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index d4cde4f3c34c29dafd9e7e7ca10bfca1579f1f3c..b524f6ab4e9ae8e64016314753e0343c5f45e42b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -551,9 +551,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].frame_type == FDD,"Dynamic TDD not handled yet\n"); for (int slot = 0; slot < n; ++slot) { - if (RC.nrmac[Mod_idP]->common_channels[0].frame_type == FDD || - (slot != 0)) - RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) < nr_dl_slots) << (slot % 64); + RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) < nr_dl_slots) << (slot % 64); RC.nrmac[Mod_idP]->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64); LOG_I(NR_MAC, "In %s: slot %d DL %d UL %d\n", @@ -591,31 +589,9 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, if (CellGroup) { - if (get_softmodem_params()->sa) { - calculate_preferred_dl_tda(Mod_idP, NULL); - } - const NR_ServingCellConfig_t *servingCellConfig = NULL; - if(CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) { + if(CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated; - const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList; - if(bwpList) { - AssertFatal(bwpList->list.count > 0, "downlinkBWP_ToAddModList has no BWPs!\n"); - for (int i = 0; i < bwpList->list.count; ++i) { - const NR_BWP_Downlink_t *bwp = bwpList->list.array[i]; - calculate_preferred_dl_tda(Mod_idP, bwp); - } - } - - const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList; - if(ubwpList) { - AssertFatal(ubwpList->list.count > 0, "uplinkBWP_ToAddModList no BWPs!\n"); - for (int i = 0; i < ubwpList->list.count; ++i) { - const NR_BWP_Uplink_t *ubwp = ubwpList->list.array[i]; - calculate_preferred_ul_tda(Mod_idP, ubwp); - } - } - } NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; if (add_ue == 1 && get_softmodem_params()->phy_test) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 9ac9f0d880ad9e68890a91466cd29b7f06bfab00..19db162d96a499dac4da86240d388052a6e6608e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -465,27 +465,24 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, int FR = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257 ? nr_FR2 : nr_FR1; - uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu]; - *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot - *msg2_frame = ((*msg2_slot>(rach_slot))? rach_frame : (rach_frame+1))%1024; + uint8_t start_next_period = rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot; + int eff_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot // we can't schedule msg2 before sl_ahead since prach - int eff_slot = *msg2_slot+(*msg2_frame-rach_frame)*nr_slots_per_frame[mu]; while ((eff_slot-rach_slot)<=sl_ahead) { - *msg2_slot = (*msg2_slot+tdd_period_slot)%nr_slots_per_frame[mu]; - *msg2_frame = ((*msg2_slot>(rach_slot))? rach_frame : (rach_frame+1))%1024; - eff_slot = *msg2_slot+(*msg2_frame-rach_frame)*nr_slots_per_frame[mu]; + eff_slot += tdd_period_slot; } if (FR==nr_FR2) { - int num_tdd_period = *msg2_slot/tdd_period_slot; + int num_tdd_period = (eff_slot%nr_slots_per_frame[mu])/tdd_period_slot; while((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=beam_index)) { - *msg2_slot = (*msg2_slot+tdd_period_slot)%nr_slots_per_frame[mu]; - *msg2_frame = ((*msg2_slot>(rach_slot))? rach_frame : (rach_frame+1))%1024; - num_tdd_period = *msg2_slot/tdd_period_slot; + eff_slot += tdd_period_slot; + num_tdd_period = (eff_slot % nr_slots_per_frame[mu])/tdd_period_slot; } if(tdd_beam_association[num_tdd_period] == -1) tdd_beam_association[num_tdd_period] = beam_index; } + *msg2_frame=(rach_frame + eff_slot/nr_slots_per_frame[mu])%1024; + *msg2_slot=eff_slot%nr_slots_per_frame[mu]; // go to previous slot if the current scheduled slot is beyond the response window // and if the slot is not among the PDCCH monitored ones (38.213 10.1) while (*msg2_frame > frame_limit @@ -1109,10 +1106,11 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, int TBS = 0; while(TBS<7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) mcsindex++; - pusch_pdu->target_code_rate = nr_get_code_rate_ul(mcsindex,pusch_pdu->mcs_table); + int R = nr_get_code_rate_ul(mcsindex,pusch_pdu->mcs_table); + pusch_pdu->target_code_rate = R; pusch_pdu->qam_mod_order = nr_get_Qm_ul(mcsindex,pusch_pdu->mcs_table); TBS = nr_compute_tbs(pusch_pdu->qam_mod_order, - pusch_pdu->target_code_rate, + R, pusch_pdu->rb_size, pusch_pdu->nr_of_symbols, num_dmrs_symb*12, // nb dmrs set for no data in dmrs symbol @@ -1200,20 +1198,13 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) -{ +void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) { - //TODO time domain assignment for msg2 needs to be improved - uint8_t time_domain_assignment; - if(cc->frame_type == TDD) - time_domain_assignment = 1; - else - time_domain_assignment = 0; int mcsIndex = -1; // initialization value int rbStart = 0; int rbSize = 8; @@ -1253,6 +1244,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Calculate number of symbols + int time_domain_assignment = get_dl_tda(nr_mac, scc, slotP); int startSymbolIndex, nrOfSymbols; const int startSymbolAndLength = pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); @@ -1799,7 +1791,8 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra pdsch_pdu_rel15->SubcarrierSpacing = genericParameters->subcarrierSpacing; pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; - pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcsIndex,mcsTableIdx); + int R = nr_get_code_rate_dl(mcsIndex,mcsTableIdx); + pdsch_pdu_rel15->targetCodeRate[0] = R; pdsch_pdu_rel15->qamModOrder[0] = 2; pdsch_pdu_rel15->mcsIndex[0] = mcsIndex; pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx; @@ -1981,8 +1974,8 @@ void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_fram if (harq->is_waiting == 0) { if (harq->round == 0) { - if (stats->dlsch_errors == 0) { - LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", UE_id, ra->rnti); + if (stats->dl.errors == 0) { + LOG_A(NR_MAC, "(ue %i, rnti 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", UE_id, ra->rnti); UE_info->active[UE_id] = true; UE_info->Msg4_ACKed[UE_id] = true; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index e2291b97458540c12033d0d7c008c0a339f5df7b..4fc4eae1a27c229d4c590fbee93e1b4e07eb325a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -53,105 +53,22 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp) { - gNB_MAC_INST *nrmac = RC.nrmac[module_id]; - const int bwp_id = bwp ? bwp->bwp_Id : 0; +const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { - if (nrmac->preferred_dl_tda[bwp_id]) - return; - - /* there is a mixed slot only when in TDD */ - NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon; - frame_type_t frame_type = nrmac->common_channels->frame_type; - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - const NR_TDD_UL_DL_Pattern_t *tdd = - scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - int symb_dlMixed = 0; - int nr_mix_slots = 0; - int nr_slots_period = n; - - if (tdd) { - symb_dlMixed = (1 << tdd->nrofDownlinkSymbols) - 1; - nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; - nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - } else - // if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration - AssertFatal(nrmac->common_channels->frame_type == FDD,"Dynamic TDD not handled yet\n"); - - int target_ss; - - if (bwp) { - target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - } else { - target_ss = NR_SearchSpace__searchSpaceType_PR_common; - } - - const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; - NR_SearchSpace_t *search_space = get_searchspace(sib1, - scc, - bwp ? bwp->bwp_Dedicated : NULL, - target_ss); - - NR_ControlResourceSet_t *coreset = get_coreset(module_id, scc, bwp ? bwp->bwp_Dedicated : NULL, search_space, target_ss); - // get coreset symbol "map" - const uint16_t symb_coreset = (1 << coreset->duration) - 1; - - NR_PDSCH_TimeDomainResourceAllocationList_t *tdaList = get_pdsch_TimeDomainAllocationList(bwp, - scc, - sib1); - AssertFatal(tdaList->list.count >= 1, "need to have at least one TDA for DL slots\n"); - - /* check that TDA index 0 fits into DL and does not overlap CORESET */ - const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_DL = tdaList->list.array[0]; - AssertFatal(!tdaP_DL->k0 || *tdaP_DL->k0 == 0, - "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n", - *tdaP_DL->k0); - int start, len; - SLIV2SL(tdaP_DL->startSymbolAndLength, &start, &len); - const uint16_t symb_tda = ((1 << len) - 1) << start; - // check whether coreset and TDA overlap: then we cannot use it. Note that - // here we assume that the coreset is scheduled every slot (which it - // currently is) and starting at symbol 0 - AssertFatal((symb_coreset & symb_tda) == 0, "TDA index 0 for DL overlaps with CORESET\n"); - /* check that TDA index 1 fits into DL part of mixed slot, if it exists */ - int tdaMi = -1; - - if (frame_type == TDD && tdaList->list.count > 1) { - const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1]; - AssertFatal(!tdaP_Mi->k0 || *tdaP_Mi->k0 == 0, - "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n", - *tdaP_Mi->k0); - int start, len; - SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len); - const uint16_t symb_tda = ((1 << len) - 1) << start; - - // check whether coreset and TDA overlap: then, we cannot use it. Also, - // check whether TDA is entirely within mixed slot DL. Note that - // here we assume that the coreset is scheduled every slot (which it - // currently is) - if ((symb_coreset & symb_tda) == 0 && (symb_dlMixed & symb_tda) == symb_tda) { - tdaMi = 1; - } else { - LOG_E(MAC, - "TDA index 1 DL overlaps with CORESET or is not entirely in mixed slot (symb_coreset %x symb_dlMixed %x symb_tda %x), won't schedule DL mixed slot\n", - symb_coreset, - symb_dlMixed, - symb_tda); - } - } - - nrmac->preferred_dl_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_dl_tda[bwp_id])); + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); - for (int i = 0; i < n; ++i) { - nrmac->preferred_dl_tda[bwp_id][i] = -1; + // Use special TDA in case of CSI-RS + const NR_UE_info_t *UE_info = &nrmac->UE_info; + if(UE_info->sched_csirs) + return 1; - if (frame_type == FDD || i % nr_slots_period < tdd->nrofDownlinkSlots) - nrmac->preferred_dl_tda[bwp_id][i] = 0; - else if (nr_mix_slots && i % nr_slots_period == tdd->nrofDownlinkSlots) - nrmac->preferred_dl_tda[bwp_id][i] = tdaMi; - - LOG_D(MAC, "slot %d preferred_dl_tda %d\n", i, nrmac->preferred_dl_tda[bwp_id][i]); + if (tdd && tdd->nrofDownlinkSymbols > 1) { // if there is a mixed slot where we can transmit DL + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; + if ((slot%nr_slots_period) == tdd->nrofDownlinkSlots) + return 2; } + return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } // Compute and write all MAC CEs and subheaders, and return number of written @@ -397,81 +314,6 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, return offset; } -#define BLER_UPDATE_FRAME 10 -#define BLER_FILTER 0.9f -int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t slot, int UE_id, int mcs_table) { - gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - int max_allowed_mcs = (mcs_table == 1) ? 27 : 28; - int max_mcs = nrmac->dl_max_mcs; - - if (nrmac->dl_max_mcs>max_allowed_mcs) - max_mcs = max_allowed_mcs; - - NR_DL_bler_stats_t *bler_stats = &nrmac->UE_info.UE_sched_ctrl[UE_id].dl_bler_stats; - - /* first call: everything is zero. Initialize to sensible default */ - if (bler_stats->last_frame_slot == 0 && bler_stats->mcs == 0) { - bler_stats->last_frame_slot = frame * n + slot; - bler_stats->mcs = 9; - bler_stats->bler = (nrmac->dl_bler_target_lower + nrmac->dl_bler_target_upper) / 2; - bler_stats->rd2_bler = nrmac->dl_rd2_bler_threshold; - } - - const int now = frame * n + slot; - int diff = now - bler_stats->last_frame_slot; - - if (diff < 0) // wrap around - diff += 1024 * n; - - const uint8_t old_mcs = bler_stats->mcs; - const NR_mac_stats_t *stats = &nrmac->UE_info.mac_stats[UE_id]; - - // TODO put back this condition when relevant - /*const int dret3x = stats->dlsch_rounds[3] - bler_stats->dlsch_rounds[3]; - if (dret3x > 0) { - if there is a third retransmission, decrease MCS for stabilization and - restart averaging window to stabilize transmission - bler_stats->last_frame_slot = now; - bler_stats->mcs = max(9, bler_stats->mcs - 1); - memcpy(bler_stats->dlsch_rounds, stats->dlsch_rounds, sizeof(stats->dlsch_rounds)); - LOG_D(MAC, "%4d.%2d: %d retx in 3rd round, setting MCS to %d and restarting window\n", frame, slot, dret3x, bler_stats->mcs); - return bler_stats->mcs; - }*/ - if (diff < BLER_UPDATE_FRAME * n) - return old_mcs; // no update - - // last update is longer than x frames ago - const int dtx = (int)(stats->dlsch_rounds[0] - bler_stats->dlsch_rounds[0]); - const int dretx = (int)(stats->dlsch_rounds[1] - bler_stats->dlsch_rounds[1]); - const int dretx2 = (int)(stats->dlsch_rounds[2] - bler_stats->dlsch_rounds[2]); - const float bler_window = dtx > 0 ? (float) dretx / dtx : bler_stats->bler; - const float rd2_bler_wnd = dtx > 0 ? (float) dretx2 / dtx : bler_stats->rd2_bler; - bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window; - bler_stats->rd2_bler = BLER_FILTER / 4 * bler_stats->rd2_bler + (1 - BLER_FILTER / 4) * rd2_bler_wnd; - int new_mcs = old_mcs; - - // TODO put back this condition when relevant - /* first ensure that number of 2nd retx is below threshold. If this is the - * case, use 1st retx to adjust faster - if (bler_stats->rd2_bler > nrmac->dl_rd2_bler_threshold && old_mcs > 6) { - new_mcs -= 2; - } else if (bler_stats->rd2_bler < nrmac->dl_rd2_bler_threshold) {*/ - if (bler_stats->bler < nrmac->dl_bler_target_lower && old_mcs < max_mcs && dtx > 9) - new_mcs += 1; - else if (bler_stats->bler > nrmac->dl_bler_target_upper && old_mcs > 6) - new_mcs -= 1; - - // else we are within threshold boundaries - bler_stats->last_frame_slot = now; - bler_stats->mcs = new_mcs; - memcpy(bler_stats->dlsch_rounds, stats->dlsch_rounds, sizeof(stats->dlsch_rounds)); - LOG_D(MAC, "%4d.%2d MCS %d -> %d (dtx %d, dretx %d, BLER wnd %.3f avg %.6f, dretx2 %d, RD2 BLER wnd %.3f avg %.6f)\n", - frame, slot, old_mcs, new_mcs, dtx, dretx, bler_window, bler_stats->bler, dretx2, rd2_bler_wnd, bler_stats->rd2_bler); - return new_mcs; -} - void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot) { @@ -566,7 +408,7 @@ bool allocate_dl_retransmission(module_id_t module_id, int rbStart = 0; // start wrt BWPstart NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; int rbSize = 0; - const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot]; + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); if (tda == retInfo->time_domain_allocation) { @@ -742,6 +584,7 @@ void pf_dl(module_id_t module_id, if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue; + const NR_mac_dir_stats_t *stats = &UE_info->mac_stats[UE_id].dl; NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ @@ -749,7 +592,7 @@ void pf_dl(module_id_t module_id, layers[UE_id] = ps->nrOfLayers; // initialization of layers to the previous value in the strcuture /* Calculate Throughput */ const float a = 0.0005f; // corresponds to 200ms window - const uint32_t b = UE_info->mac_stats[UE_id].dlsch_current_bytes; + const uint32_t b = stats->current_bytes; thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; /* retransmission */ @@ -772,8 +615,10 @@ void pf_dl(module_id_t module_id, continue; /* Calculate coeff */ - set_dl_mcs(sched_pdsch,sched_ctrl,&mac->dl_max_mcs,ps->mcsTableIdx); - sched_pdsch->mcs = get_mcs_from_bler(module_id, /* CC_id = */ 0, frame, slot, UE_id, ps->mcsTableIdx); + const NR_bler_options_t *bo = &mac->dl_bler; + const int max_mcs_table = ps->mcsTableIdx == 1 ? 27 : 28; + const int max_mcs = min(sched_ctrl->dl_max_mcs, max_mcs_table); + sched_pdsch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->dl_bler_stats, max_mcs, frame); layers[UE_id] = set_dl_nrOfLayers(sched_ctrl); const uint8_t Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); const uint16_t R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); @@ -910,7 +755,7 @@ void pf_dl(module_id_t module_id, if (max_num_ue < 0) return; /* MCS has been set above */ - const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot]; + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; @@ -982,12 +827,7 @@ void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t /* This is temporary and it assumes all UEs have the same BWP and TDA*/ int UE_id = UE_info->list.head; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int bwp_id = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0; - - if (!RC.nrmac[module_id]->preferred_dl_tda[bwp_id]) - return; - - const int tda = RC.nrmac[module_id]->preferred_dl_tda[bwp_id][slot]; + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); int startSymbolIndex, nrOfSymbols; const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList : @@ -1091,7 +931,7 @@ void nr_schedule_ue_spec(module_id_t module_id, if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue; NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; - UE_info->mac_stats[UE_id].dlsch_current_bytes = 0; + UE_info->mac_stats[UE_id].dl.current_bytes = 0; NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; NR_BWP_DownlinkDedicated_t *bwpd = @@ -1149,7 +989,7 @@ void nr_schedule_ue_spec(module_id_t module_id, harq->feedback_frame = pucch->frame; harq->feedback_slot = pucch->ul_slot; harq->is_waiting = true; - UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++; + UE_info->mac_stats[UE_id].dl.rounds[harq->round]++; LOG_D(NR_MAC, "%4d.%2d [DLSCH/PDSCH/PUCCH] UE %d RNTI %04x DCI L %d start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d nrOfLayers %d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) PUCCH allocation %d TPC %d\n", frame, @@ -1229,6 +1069,7 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->CyclicPrefix = genericParameters->cyclicPrefix ? *genericParameters->cyclicPrefix : 0; // Codeword information pdsch_pdu->NrOfCodewords = 1; + //number of information bits per 1024 coded bits expressed in 0.1 bit units pdsch_pdu->targetCodeRate[0] = R; pdsch_pdu->qamModOrder[0] = Qm; pdsch_pdu->mcsIndex[0] = sched_pdsch->mcs; @@ -1482,7 +1323,7 @@ void nr_schedule_ue_spec(module_id_t module_id, lcid_bytes += len; } - UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += lcid_bytes; + UE_info->mac_stats[UE_id].dl.lc_bytes[lcid] += lcid_bytes; } } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { /* we will need the large header, phy-test typically allocates all @@ -1520,8 +1361,10 @@ void nr_schedule_ue_spec(module_id_t module_id, buf=bufEnd; } - UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS; - UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS; + NR_mac_stats_t *mac_stats = &UE_info->mac_stats[UE_id]; + mac_stats->dl.total_bytes += TBS; + mac_stats->dl.current_bytes = TBS; + /* save retransmission information */ harq->sched_pdsch = *sched_pdsch; /* save which time allocation has been used, to be used on diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 33dd96d9bf19128aa218115a9f15e6b9fe66d966..8cca07a51a9b142ad9896911b835536c29008947 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -275,7 +275,8 @@ void nr_preprocessor_phytest(module_id_t module_id, __func__, UE_id); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int tda = sched_ctrl->active_bwp ? RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot] : 1; + + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; ps->nrOfLayers = target_dl_Nl; if (ps->time_domain_allocation != tda || ps->nrOfLayers != target_dl_Nl) @@ -435,18 +436,25 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int tda = sched_ctrl->active_ubwp ? RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 1; - if (tda < 0) - return false; const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - AssertFatal(tda < tdaList->list.count, + const int temp_tda = get_ul_tda(nr_mac, scc, slot); + if (temp_tda < 0) + return false; + AssertFatal(temp_tda < tdaList->list.count, "time domain assignment %d >= %d\n", - tda, + temp_tda, tdaList->list.count); - int K2 = get_K2(scc,NULL,sched_ctrl->active_ubwp, tda, mu); + int K2 = get_K2(scc,NULL,sched_ctrl->active_ubwp, temp_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]; + const int tda = get_ul_tda(nr_mac, scc, sched_slot); + if (tda < 0) + return false; + AssertFatal(tda < tdaList->list.count, + "time domain assignment %d >= %d\n", + tda, + tdaList->list.count); /* 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 */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 45327eda736dc80c645650b386d92ad0b1dd00ed..1e749a95923d9251bc2bc077df9c3c42105d6cff 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -113,18 +113,18 @@ uint8_t nr_ss_first_symb_idx_scs_120_120_mux3[4] = {4,8,2,6}; uint8_t nr_max_number_of_candidates_per_slot[4] = {44, 36, 22, 20}; uint8_t nr_max_number_of_cces_per_slot[4] = {56, 56, 48, 32}; -// CQI TABLES +// CQI TABLES (10 times the value in 214 to adequately compare with R) // Table 1 (38.214 5.2.2.1-2) -uint16_t cqi_table1[16][2] = {{0,0},{2,78},{2,120},{2,193},{2,308},{2,449},{2,602},{4,378}, - {4,490},{4,616},{6,466},{6,567},{6,666},{6,772},{6,873},{6,948}}; +uint16_t cqi_table1[16][2] = {{0,0},{2,780},{2,1200},{2,1930},{2,3080},{2,4490},{2,6020},{4,3780}, + {4,4900},{4,6160},{6,4660},{6,5670},{6,6660},{6,7720},{6,8730},{6,9480}}; // Table 2 (38.214 5.2.2.1-3) -uint16_t cqi_table2[16][2] = {{0,0},{2,78},{2,193},{2,449},{4,378},{4,490},{4,616},{6,466}, - {6,567},{6,666},{6,772},{6,873},{8,711},{8,797},{8,885},{8,948}}; +uint16_t cqi_table2[16][2] = {{0,0},{2,780},{2,1930},{2,4490},{4,3780},{4,4900},{4,6160},{6,4660}, + {6,5670},{6,6660},{6,7720},{6,8730},{8,7110},{8,7970},{8,8850},{8,9480}}; // Table 2 (38.214 5.2.2.1-4) -uint16_t cqi_table3[16][2] = {{0,0},{2,30},{2,50},{2,78},{2,120},{2,193},{2,308},{2,449}, - {2,602},{4,378},{4,490},{4,616},{6,466},{6,567},{6,666},{6,772}}; +uint16_t cqi_table3[16][2] = {{0,0},{2,300},{2,500},{2,780},{2,1200},{2,1930},{2,3080},{2,4490}, + {2,6020},{4,3780},{4,4900},{4,6160},{6,4660},{6,5670},{6,6660},{6,7720}}; static inline uint8_t get_max_candidates(uint8_t scs) { @@ -145,7 +145,6 @@ uint8_t set_dl_nrOfLayers(NR_UE_sched_ctrl_t *sched_ctrl) { } - uint16_t set_pm_index(NR_UE_sched_ctrl_t *sched_ctrl, int layers, int N1, int N2, @@ -169,51 +168,45 @@ uint16_t set_pm_index(NR_UE_sched_ctrl_t *sched_ctrl, AssertFatal(1==0,"More than 2 antenna ports not yet supported\n"); } +uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx) +{ + if (cqi_idx <= 0) { + LOG_E(NR_MAC, "invalid cqi_idx %d, default to MCS 9\n", cqi_idx); + return 9; + } -void set_dl_mcs(NR_sched_pdsch_t *sched_pdsch, - NR_UE_sched_ctrl_t *sched_ctrl, - uint8_t *target_mcs, - uint8_t mcs_table_idx) { - - if (sched_ctrl->set_mcs) { - // TODO for wideband case and multiple TB - int cqi_idx = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb; - uint16_t target_coderate,target_qm; - if (cqi_idx>0) { - int cqi_table = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cqi_table; - if (cqi_table != mcs_table_idx) - LOG_W(NR_MAC,"Indices of MCS tables don't correspond yet, cri_ri_li_pmi_cqi_report.cqi_table %d, mcs_table_index %d\n",cqi_table,mcs_table_idx); - switch (cqi_table) { - case 0: - target_qm = cqi_table1[cqi_idx][0]; - target_coderate = cqi_table1[cqi_idx][1]; - break; - case 1: - target_qm = cqi_table2[cqi_idx][0]; - target_coderate = cqi_table2[cqi_idx][1]; - break; - case 2: - target_qm = cqi_table3[cqi_idx][0]; - target_coderate = cqi_table3[cqi_idx][1]; - break; - default: - AssertFatal(1==0,"Invalid cqi table index %d\n",cqi_table); - } - int max_mcs = 28; - int R,Qm; - if (mcs_table_idx == 1) - max_mcs = 27; - for (int i=0; i<=max_mcs; i++) { - R = nr_get_code_rate_dl(i, mcs_table_idx); - Qm = nr_get_Qm_dl(i, mcs_table_idx); - if ((Qm == target_qm) && (target_coderate <= R)) { - *target_mcs = i; - break; - } - } - } - sched_ctrl->set_mcs = false; + if (mcs_table != cqi_table) { + LOG_E(NR_MAC, "indices of CQI (%d) and MCS (%d) tables don't correspond yet\n", cqi_table, mcs_table); + return 9; } + + uint16_t target_coderate, target_qm; + switch (cqi_table) { + case 0: + target_qm = cqi_table1[cqi_idx][0]; + target_coderate = cqi_table1[cqi_idx][1]; + break; + case 1: + target_qm = cqi_table2[cqi_idx][0]; + target_coderate = cqi_table2[cqi_idx][1]; + break; + case 2: + target_qm = cqi_table3[cqi_idx][0]; + target_coderate = cqi_table3[cqi_idx][1]; + break; + default: + AssertFatal(1==0,"Invalid cqi table index %d\n",cqi_table); + } + const int max_mcs = mcs_table == 1 ? 27 : 28; + for (int i = 0; i <= max_mcs; i++) { + const int R = nr_get_code_rate_dl(i, mcs_table); + const int Qm = nr_get_Qm_dl(i, mcs_table); + if (Qm == target_qm && target_coderate <= R) + return i; + } + + LOG_E(NR_MAC, "could not find maximum MCS from cqi_idx %d, default to 9\n", cqi_idx); + return 9; } void set_dl_dmrs_ports(NR_pdsch_semi_static_t *ps) { @@ -768,6 +761,51 @@ void nr_set_pusch_semi_static(const NR_SIB1_t *sib1, : num_dmrs_cdm_grps_no_data * 4; } +#define BLER_UPDATE_FRAME 10 +#define BLER_FILTER 0.9f +int get_mcs_from_bler(const NR_bler_options_t *bler_options, + const NR_mac_dir_stats_t *stats, + NR_bler_stats_t *bler_stats, + int max_mcs, + frame_t frame) +{ + /* first call: everything is zero. Initialize to sensible default */ + if (bler_stats->last_frame == 0 && bler_stats->mcs == 0) { + bler_stats->last_frame = frame; + bler_stats->mcs = 9; + bler_stats->bler = (bler_options->lower + bler_options->upper) / 2.0f; + } + int diff = frame - bler_stats->last_frame; + if (diff < 0) // wrap around + diff += 1024; + + max_mcs = min(max_mcs, bler_options->max_mcs); + const uint8_t old_mcs = min(bler_stats->mcs, max_mcs); + if (diff < BLER_UPDATE_FRAME) + return old_mcs; // no update + + // last update is longer than x frames ago + const int dtx = (int)(stats->rounds[0] - bler_stats->rounds[0]); + const int dretx = (int)(stats->rounds[1] - bler_stats->rounds[1]); + const float bler_window = dtx > 0 ? (float) dretx / dtx : bler_stats->bler; + bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window; + + int new_mcs = old_mcs; + if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && dtx > 9) + new_mcs += 1; + else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold + || (dtx <= 3 && old_mcs > 9)) // no activity + new_mcs -= 1; + // else we are within threshold boundaries + + bler_stats->last_frame = frame; + bler_stats->mcs = new_mcs; + memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds)); + LOG_D(MAC, "frame %4d MCS %d -> %d (dtx %d, dretx %d, BLER wnd %.3f avg %.6f)\n", + frame, old_mcs, new_mcs, dtx, dretx, bler_window, bler_stats->bler); + return new_mcs; +} + void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, nr_scs_e scs_common, nr_scs_e pdcch_scs, @@ -2359,7 +2397,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellG compute_csi_bitlen (CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE_info, UE_id, mod_idP); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; memset(sched_ctrl, 0, sizeof(*sched_ctrl)); - sched_ctrl->set_mcs = true; + sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */ sched_ctrl->set_pmi = false; sched_ctrl->ta_frame = 0; sched_ctrl->ta_update = 31; @@ -2659,6 +2697,8 @@ void nr_csirs_scheduling(int Mod_idP, gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map; + UE_info->sched_csirs = false; + 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]; @@ -2691,6 +2731,7 @@ void nr_csirs_scheduling(int Mod_idP, if((frame*n_slots_frame+slot-offset)%period == 0) { LOG_D(NR_MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot); + UE_info->sched_csirs = true; nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); @@ -2858,6 +2899,7 @@ void nr_csirs_scheduling(int Mod_idP, void nr_mac_update_timers(module_id_t module_id, frame_t frame, sub_frame_t slot) { + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; 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]) { @@ -2894,12 +2936,11 @@ void nr_mac_update_timers(module_id_t module_id, cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated ? cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP : NULL; - int **preferred_dl_tda = RC.nrmac[module_id]->preferred_dl_tda; + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; const uint8_t layers = set_dl_nrOfLayers(sched_ctrl); - const int tda = bwp && preferred_dl_tda[bwp->bwp_Id][slot] >= 0 ? - preferred_dl_tda[bwp->bwp_Id][slot] : (ps->time_domain_allocation >= 0 ? ps->time_domain_allocation : 0); + const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); nr_set_pdsch_semi_static(sib1, scc, @@ -2917,14 +2958,13 @@ void nr_mac_update_timers(module_id_t module_id, cg->spCellConfig->spCellConfigDedicated && cg->spCellConfig->spCellConfigDedicated->uplinkConfig ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP : NULL; - int **preferred_ul_tda = RC.nrmac[module_id]->preferred_ul_tda; + NR_pusch_semi_static_t *ups = &sched_ctrl->pusch_semi_static; int dci_format = get_dci_format(sched_ctrl); const uint8_t num_dmrs_cdm_grps_no_data = (ubwp || ubwpd) ? 1 : 2; const uint8_t nrOfLayers = 1; - const int utda = ubwp && preferred_ul_tda[ubwp->bwp_Id][slot] >= 0 ? - preferred_ul_tda[ubwp->bwp_Id][slot] : (ups->time_domain_allocation >= 0 ? ups->time_domain_allocation : 0); + const int utda = get_ul_tda(RC.nrmac[module_id], scc, slot); nr_set_pusch_semi_static(sib1, scc, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index a29aa8018cd5b679da1a3f7d3f82fe5cfd8f9cc2..b9292876e350101907409e9843e5c1f3166cd64b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -838,8 +838,8 @@ static void handle_dl_harq(module_id_t mod_id, harq->round = 0; harq->ndi ^= 1; NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; - stats->dlsch_errors++; - LOG_D(NR_MAC, "retransmission error for UE %d (total %"PRIu64")\n", UE_id, stats->dlsch_errors); + stats->dl.errors++; + LOG_D(NR_MAC, "retransmission error for UE %d (total %"PRIu64")\n", UE_id, stats->dl.errors); } else { LOG_D(PHY,"NACK for: pid %d, ue %x\n",harq_pid, UE_id); add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].retrans_dl_harq, harq_pid); @@ -1250,7 +1250,12 @@ void evaluate_cqi_report(uint8_t *payload, sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_2tb = temp_cqi; LOG_D(MAC,"Wide-band CQI for the second TB %d\n", temp_cqi); } - sched_ctrl->set_mcs = true; + + // TODO for wideband case and multiple TB + const int cqi_idx = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb; + const int mcs_table = sched_ctrl->pdsch_semi_static.mcsTableIdx; + const int cqi_table = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cqi_table; + sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_table, cqi_idx); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 7a34527166d687f6bbd850e186d12f368acc1638..591a549c0a21bb898bd9cae727c66d21630bdf18 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -46,138 +46,18 @@ int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl) { return(dci_format); } -void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp) -{ - gNB_MAC_INST *nrmac = RC.nrmac[module_id]; - const int bwp_id = ubwp->bwp_Id; - if (nrmac->preferred_ul_tda[bwp_id]) - return; +const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { /* there is a mixed slot only when in TDD */ - NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon; - frame_type_t frame_type = nrmac->common_channels->frame_type; - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - - NR_ServingCellConfigCommonSIB_t *scc_sib1 = nrmac->common_channels[0].sib1 ? - RC.nrmac[module_id]->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1->servingCellConfigCommon : NULL; - - AssertFatal(scc!=NULL || scc_sib1!=NULL,"We need one serving cell config common\n"); - - const int mu = scc ? scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing : - scc_sib1->uplinkConfigCommon->initialUplinkBWP.genericParameters.subcarrierSpacing; - - NR_TDD_UL_DL_Pattern_t *tdd = NULL; - if (scc && scc->tdd_UL_DL_ConfigurationCommon) { - tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; - } else if (scc_sib1 && scc_sib1->tdd_UL_DL_ConfigurationCommon) { - tdd = &scc_sib1->tdd_UL_DL_ConfigurationCommon->pattern1; - } - - /* Uplink symbols are at the end of the slot */ - int symb_ulMixed = 0; - int nr_mix_slots = 0; - int nr_slots_period = n; - if (tdd) { - symb_ulMixed = ((1 << tdd->nrofUplinkSymbols) - 1) << (14 - tdd->nrofUplinkSymbols); - nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; - nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - } - else - // if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration - AssertFatal(nrmac->common_channels->frame_type == FDD,"Dynamic TDD not handled yet\n"); - - const struct NR_PUCCH_Config__resourceToAddModList *resList = ubwp->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList; - // for the moment, just block any symbol that might hold a PUCCH, regardless - // of the RB. This is a big simplification, as most RBs will NOT have a PUCCH - // in the respective symbols, but it simplifies scheduling - uint16_t symb_pucch = 0; - for (int i = 0; i < resList->list.count; ++i) { - const NR_PUCCH_Resource_t *resource = resList->list.array[i]; - int nrofSymbols = 0; - int startingSymbolIndex = 0; - switch (resource->format.present) { - case NR_PUCCH_Resource__format_PR_format0: - nrofSymbols = resource->format.choice.format0->nrofSymbols; - startingSymbolIndex = resource->format.choice.format0->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format1: - nrofSymbols = resource->format.choice.format1->nrofSymbols; - startingSymbolIndex = resource->format.choice.format1->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format2: - nrofSymbols = resource->format.choice.format2->nrofSymbols; - startingSymbolIndex = resource->format.choice.format2->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format3: - nrofSymbols = resource->format.choice.format3->nrofSymbols; - startingSymbolIndex = resource->format.choice.format3->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format4: - nrofSymbols = resource->format.choice.format4->nrofSymbols; - startingSymbolIndex = resource->format.choice.format4->startingSymbolIndex; - break; - default: - AssertFatal(0, "found NR_PUCCH format index %d\n", resource->format.present); - break; - } - symb_pucch |= ((1 << nrofSymbols) - 1) << startingSymbolIndex; - } - - /* check that TDA index 1 fits into UL slot and does not overlap with PUCCH */ - const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_UL = tdaList->list.array[0]; - const int k2 = get_K2(scc, scc_sib1, (NR_BWP_Uplink_t*)ubwp,0, mu); - int start, len; - SLIV2SL(tdaP_UL->startSymbolAndLength, &start, &len); - const uint16_t symb_tda = ((1 << len) - 1) << start; - // check whether PUCCH and TDA overlap: then, we cannot use it. Note that - // here we assume that the PUCCH is scheduled in every slot, and on all RBs - // (which is mostly not true, this is a simplification) - AssertFatal((symb_pucch & symb_tda) == 0, "TDA index 0 for UL overlaps with PUCCH\n"); - - // get largest time domain allocation (TDA) for UL slot and UL in mixed slot - int tdaMi = -1; - if (nr_mix_slots>0) { - const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1]; - AssertFatal(k2 == get_K2(scc, scc_sib1, (NR_BWP_Uplink_t*)ubwp, 1, mu), - "scheduler cannot handle different k2 for UL slot (%d) and UL Mixed slot (%ld)\n", - k2, - get_K2(scc, scc_sib1, (NR_BWP_Uplink_t*)ubwp, 1, mu)); - SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len); - const uint16_t symb_tda_mi = ((1 << len) - 1) << start; - // check whether PUCCH and TDA overlap: then, we cannot use it. Also, check - // whether TDA is entirely within mixed slot, UL. Note that here we assume - // that the PUCCH is scheduled in every slot, and on all RBs (which is - // mostly not true, this is a simplification) - if ((symb_pucch & symb_tda_mi) == 0 && (symb_ulMixed & symb_tda_mi) == symb_tda_mi) { - tdaMi = 1; - } else { - LOG_E(NR_MAC, - "TDA index 1 UL overlaps with PUCCH or is not entirely in mixed slot (symb_pucch %x symb_ulMixed %x symb_tda_mi %x), won't schedule UL mixed slot\n", - symb_pucch, - symb_ulMixed, - symb_tda_mi); - } - } + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); - nrmac->preferred_ul_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_ul_tda[bwp_id])); - - for (int slot = 0; slot < n; ++slot) { - const int sched_slot = (slot + k2) % n; - nrmac->preferred_ul_tda[bwp_id][slot] = -1; - if (frame_type == FDD || sched_slot % nr_slots_period >= tdd->nrofDownlinkSlots + nr_mix_slots) - nrmac->preferred_ul_tda[bwp_id][slot] = 0; - else if (nr_mix_slots && sched_slot % nr_slots_period == tdd->nrofDownlinkSlots) - nrmac->preferred_ul_tda[bwp_id][slot] = tdaMi; - LOG_D(MAC, "DL slot %d UL slot %d preferred_ul_tda %d\n", slot, sched_slot, nrmac->preferred_ul_tda[bwp_id][slot]); - } - - if (tdd && k2 < tdd->nrofUplinkSlots) { - LOG_W(NR_MAC, - "k2 %d < tdd->nrofUplinkSlots %ld: not all UL slots can be scheduled\n", - k2, - tdd->nrofUplinkSlots); + if (tdd && tdd->nrofUplinkSymbols > 1) { // if there is uplink symbols in mixed slot + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; + if ((slot%nr_slots_period) == tdd->nrofDownlinkSlots) + return 1; } + return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } // For both UL-SCH except: @@ -464,7 +344,7 @@ int nr_process_mac_pdu(module_id_t module_idP, rx_lcid, module_idP, mac_len); - UE_info->mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_len; + UE_info->mac_stats[UE_id].ul.lc_bytes[rx_lcid] += mac_len; mac_rlc_data_ind(module_idP, UE_info->rnti[UE_id], @@ -526,7 +406,7 @@ void abort_nr_ul_harq(module_id_t mod_id, int UE_id, int8_t harq_pid) harq->ndi ^= 1; harq->round = 0; - UE_info->mac_stats[UE_id].ulsch_errors++; + UE_info->mac_stats[UE_id].ul.errors++; add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid); /* the transmission failed: the UE won't send the data we expected initially, @@ -637,7 +517,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_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; + UE_info->mac_stats[UE_id].ul.total_bytes += sdu_lenP; LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d TA %d sduP %p, rssi %d\n", gnb_mod_idP, harq_pid, @@ -980,7 +860,7 @@ bool allocate_ul_retransmission(module_id_t module_id, const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); const uint8_t nrOfLayers = 1; const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_bwp || ubwpd) ? 1 : 2; - const int tda = sched_ctrl->active_ubwp ? RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + const int tda = get_ul_tda(nr_mac, scc, retInfo->slot); LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda); LOG_D(NR_MAC,"num_dmrs_cdm_grps_no_data %d, tbs %d\n",num_dmrs_cdm_grps_no_data, retInfo->tb_size); if (tda == retInfo->time_domain_allocation) { @@ -1174,10 +1054,11 @@ void pf_ul(module_id_t module_id, const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static; + const NR_mac_dir_stats_t *stats = &UE_info->mac_stats[UE_id].ul; /* Calculate throughput */ const float a = 0.0005f; // corresponds to 200ms window - const uint32_t b = UE_info->mac_stats[UE_id].ulsch_current_bytes; + const uint32_t b = stats->current_bytes; ul_thr_ue[UE_id] = (1 - a) * ul_thr_ue[UE_id] + a * b; /* Check if retransmission is necessary */ @@ -1209,6 +1090,10 @@ void pf_ul(module_id_t module_id, continue; } + const NR_bler_options_t *bo = &nrmac->ul_bler; + const int max_mcs = bo->max_mcs; /* no per-user maximum MCS yet */ + sched_pusch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame); + /* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled * based on data to transmit) */ if (B == 0 && do_sched) { @@ -1249,7 +1134,7 @@ void pf_ul(module_id_t module_id, const uint8_t nrOfLayers = 1; const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2; int dci_format = get_dci_format(sched_ctrl); - const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + const int tda = get_ul_tda(nrmac, scc, sched_pusch->slot); if (ps->time_domain_allocation != tda || ps->dci_format != dci_format || ps->nrOfLayers != nrOfLayers @@ -1284,7 +1169,7 @@ void pf_ul(module_id_t module_id, sched_ctrl->aggregation_level); NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; - sched_pusch->mcs = nrmac->min_grant_mcs; + sched_pusch->mcs = min(nrmac->min_grant_mcs, sched_pusch->mcs); update_ul_ue_R_Qm(sched_pusch, ps); sched_pusch->rbStart = rbStart; sched_pusch->rbSize = min_rb; @@ -1310,7 +1195,6 @@ void pf_ul(module_id_t module_id, add_tail_nr_list(&UE_sched, UE_id); /* Calculate coefficient*/ - sched_pusch->mcs = nrmac->min_grant_mcs; const uint32_t tbs = ul_pf_tbs[ps->mcs_table][sched_pusch->mcs]; coeff_ue[UE_id] = (float) tbs / ul_thr_ue[UE_id]; LOG_D(NR_MAC,"b %d, ul_thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n", @@ -1389,7 +1273,7 @@ void pf_ul(module_id_t module_id, const uint8_t nrOfLayers = 1; const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2; int dci_format = get_dci_format(sched_ctrl); - const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + const int tda = get_ul_tda(nrmac, scc, sched_pusch->slot); if (ps->time_domain_allocation != tda || ps->dci_format != dci_format || ps->nrOfLayers != nrOfLayers @@ -1482,12 +1366,14 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t * schedule now (slot + k2 is not UL slot) */ int UE_id = UE_info->list.head; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int tda = sched_ctrl->active_ubwp ? nr_mac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; - if (tda < 0) - return false; - int K2 = get_K2(scc, scc_sib1, sched_ctrl->active_ubwp, tda, mu); + const int temp_tda = get_ul_tda(nr_mac, scc, slot); + int K2 = get_K2(scc, scc_sib1, sched_ctrl->active_ubwp, temp_tda, mu); const int sched_frame = (frame + (slot + K2 >= nr_slots_per_frame[mu])) & 1023; const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + const int tda = get_ul_tda(nr_mac, scc, sched_slot); + if (tda < 0) + return false; + DevAssert(K2 == get_K2(scc, scc_sib1, sched_ctrl->active_ubwp, tda, mu)); if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) return false; @@ -1599,7 +1485,7 @@ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(module_id_t module_id, int CC_id) if (mcs > 27 && mcsTableIdx == 1) continue; const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx); - const uint16_t R = nr_get_code_rate_dl(mcs, mcsTableIdx); + const uint16_t R = nr_get_code_rate_ul(mcs, mcsTableIdx); /* note: we do not update R/Qm based on low MCS or pi2BPSK */ ul_pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm, R, @@ -1652,7 +1538,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) cg->spCellConfig->spCellConfigDedicated->uplinkConfig ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP : NULL; - UE_info->mac_stats[UE_id].ulsch_current_bytes = 0; + NR_mac_stats_t *mac_stats = &UE_info->mac_stats[UE_id]; + mac_stats->ul.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 */ @@ -1696,10 +1583,10 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static; /* Statistics */ - AssertFatal(cur_harq->round < 8, "Indexing ulsch_rounds[%d] is out of bounds\n", cur_harq->round); - UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++; + AssertFatal(cur_harq->round < 8, "Indexing UL rounds[%d] is out of bounds\n", cur_harq->round); + mac_stats->ul.rounds[cur_harq->round]++; if (cur_harq->round == 0) { - UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled += sched_pusch->tb_size; + mac_stats->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; @@ -1719,7 +1606,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) cur_harq->round, cur_harq->ndi); } - UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size; + mac_stats->ul.current_bytes = sched_pusch->tb_size; sched_ctrl->last_ul_frame = sched_pusch->frame; sched_ctrl->last_ul_slot = sched_pusch->slot; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 6d1564159235e4b5496528056a67c23767709ab5..f568cf3f6500db888abb2eb0970519c0b818dacc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -388,13 +388,6 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, int x_overhead, uint8_t numdmrscdmgroupnodata, uint8_t tb_scaling); -/** \brief Computes Q based on I_MCS PDSCH and table_idx for downlink. Implements MCS Tables from 38.214. */ -uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx); -uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx); - -/** \brief Computes Q based on I_MCS PDSCH and table_idx for uplink. Implements MCS Tables from 38.214. */ -uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx); -uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx); int NRRIV2BW(int locationAndBandwidth,int N_RB); @@ -514,16 +507,13 @@ uint16_t set_pm_index(NR_UE_sched_ctrl_t *sched_ctrl, int xp_pdsch_antenna_ports, int codebook_mode); -void set_dl_mcs(NR_sched_pdsch_t *sched_pdsch, - NR_UE_sched_ctrl_t *sched_ctrl, - uint8_t *target_mcs, - uint8_t mcs_table_idx); +uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t set_dl_nrOfLayers(NR_UE_sched_ctrl_t *sched_ctrl); int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl); -void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp); -void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp); +const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); +const int get_ul_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id); @@ -538,6 +528,12 @@ bool nr_find_nb_rb(uint16_t Qm, uint32_t *tbs, uint16_t *nb_rb); +int get_mcs_from_bler(const NR_bler_options_t *bler_options, + const NR_mac_dir_stats_t *stats, + NR_bler_stats_t *bler_stats, + int max_mcs, + frame_t frame); + void nr_sr_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index e047494b5296666e55510465702e5f7a72429f68..4c14233a32ad9a658b1850db8713f4e063af8f51 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -102,9 +102,9 @@ void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp stroff+=sprintf(output+stroff,"UE %d: dlsch_rounds %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS %d\n", UE_id, - stats->dlsch_rounds[0], stats->dlsch_rounds[1], - stats->dlsch_rounds[2], stats->dlsch_rounds[3], - stats->dlsch_errors, + stats->dl.rounds[0], stats->dl.rounds[1], + stats->dl.rounds[2], stats->dl.rounds[3], + stats->dl.errors, stats->pucch0_DTX, sched_ctrl->dl_bler_stats.bler, sched_ctrl->dl_bler_stats.mcs); @@ -112,25 +112,27 @@ void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp stats->num_rsrp_meas = 0; stats->cumul_rsrp = 0; } - stroff+=sprintf(output+stroff,"UE %d: dlsch_total_bytes %"PRIu64"\n", UE_id, stats->dlsch_total_bytes); - stroff+=sprintf(output+stroff,"UE %d: ulsch_rounds %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64", ulsch_DTX %d, ulsch_errors %"PRIu64"\n", + stroff+=sprintf(output+stroff,"UE %d: dlsch_total_bytes %"PRIu64"\n", UE_id, stats->dl.total_bytes); + stroff+=sprintf(output+stroff,"UE %d: ulsch_rounds %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64", ulsch_DTX %d, ulsch_errors %"PRIu64", BLER %.5f MCS %d\n", UE_id, - stats->ulsch_rounds[0], stats->ulsch_rounds[1], - stats->ulsch_rounds[2], stats->ulsch_rounds[3], + stats->ul.rounds[0], stats->ul.rounds[1], + stats->ul.rounds[2], stats->ul.rounds[3], stats->ulsch_DTX, - stats->ulsch_errors); + stats->ul.errors, + sched_ctrl->ul_bler_stats.bler, + sched_ctrl->ul_bler_stats.mcs); stroff+=sprintf(output+stroff, "UE %d: ulsch_total_bytes_scheduled %"PRIu64", ulsch_total_bytes_received %"PRIu64"\n", UE_id, - stats->ulsch_total_bytes_scheduled, stats->ulsch_total_bytes_rx); + stats->ulsch_total_bytes_scheduled, stats->ul.total_bytes); for (int lc_id = 0; lc_id < 63; lc_id++) { - if (stats->lc_bytes_tx[lc_id] > 0) { - stroff+=sprintf(output+stroff, "UE %d: LCID %d: %"PRIu64" bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); - LOG_D(NR_MAC, "UE %d: LCID %d: %"PRIu64" bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); + if (stats->dl.lc_bytes[lc_id] > 0) { + stroff+=sprintf(output+stroff, "UE %d: LCID %d: %"PRIu64" bytes TX\n", UE_id, lc_id, stats->dl.lc_bytes[lc_id]); + LOG_D(NR_MAC, "UE %d: LCID %d: %"PRIu64" bytes TX\n", UE_id, lc_id, stats->dl.lc_bytes[lc_id]); } - if (stats->lc_bytes_rx[lc_id] > 0) { - stroff+=sprintf(output+stroff, "UE %d: LCID %d: %"PRIu64" bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); - LOG_D(NR_MAC, "UE %d: LCID %d: %"PRIu64" bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); + if (stats->ul.lc_bytes[lc_id] > 0) { + stroff+=sprintf(output+stroff, "UE %d: LCID %d: %"PRIu64" bytes RX\n", UE_id, lc_id, stats->ul.lc_bytes[lc_id]); + LOG_D(NR_MAC, "UE %d: LCID %d: %"PRIu64" bytes RX\n", UE_id, lc_id, stats->ul.lc_bytes[lc_id]); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 9d8e28da9719165f4af5bd7a16dd71a2f86991b0..4918e4ee0873460ffb06a20574253c3d5e037fb4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -459,13 +459,12 @@ typedef struct NR_UE_harq { //! fixme : need to enhace for the multiple TB CQI report -typedef struct NR_DL_bler_stats { - frame_t last_frame_slot; +typedef struct NR_bler_stats { + frame_t last_frame; float bler; - float rd2_bler; uint8_t mcs; - uint64_t dlsch_rounds[8]; -} NR_DL_bler_stats_t; + uint64_t rounds[8]; +} NR_bler_stats_t; // /*! As per spec 38.214 section 5.2.1.4.2 @@ -613,6 +612,9 @@ typedef struct { NR_pdsch_semi_static_t pdsch_semi_static; /// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI NR_sched_pdsch_t sched_pdsch; + /// UE-estimated maximum MCS (from CSI-RS) + uint8_t dl_max_mcs; + /// For UL synchronization: store last UL scheduling grant frame_t last_ul_frame; sub_frame_t last_ul_slot; @@ -624,7 +626,8 @@ typedef struct { mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID]; /// Estimation of HARQ from BLER - NR_DL_bler_stats_t dl_bler_stats; + NR_bler_stats_t dl_bler_stats; + NR_bler_stats_t ul_bler_stats; uint16_t ta_frame; int16_t ta_update; @@ -641,7 +644,6 @@ typedef struct { int ul_failure; struct CSI_Report CSI_report; bool SR; - bool set_mcs; bool set_pmi; /// information about every HARQ process NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; @@ -674,24 +676,29 @@ typedef struct { uicc_t *uicc; } NRUEcontext_t; -typedef struct { - uint64_t lc_bytes_tx[64]; - uint64_t lc_bytes_rx[64]; - uint64_t dlsch_rounds[8]; - uint64_t dlsch_errors; - uint64_t dlsch_total_bytes; - int dlsch_current_bytes; - uint64_t ulsch_rounds[8]; - uint64_t ulsch_errors; +typedef struct NR_mac_dir_stats { + uint64_t lc_bytes[64]; + uint64_t rounds[8]; + uint64_t errors; + uint64_t total_bytes; + uint32_t current_bytes; +} NR_mac_dir_stats_t; + +typedef struct NR_mac_stats { + NR_mac_dir_stats_t dl; + NR_mac_dir_stats_t ul; uint32_t ulsch_DTX; uint64_t ulsch_total_bytes_scheduled; - uint64_t ulsch_total_bytes_rx; - int ulsch_current_bytes; uint32_t pucch0_DTX; int cumul_rsrp; uint8_t num_rsrp_meas; } NR_mac_stats_t; +typedef struct NR_bler_options { + double upper; + double lower; + uint8_t max_mcs; +} NR_bler_options_t; /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ #define MAX_CSI_REPORTCONFIG 48 @@ -710,7 +717,8 @@ typedef struct { // UE selected beam index uint8_t UE_beam_index[MAX_MOBILES_PER_GNB]; bool Msg4_ACKed[MAX_MOBILES_PER_GNB]; - + /// Sched CSI-RS: scheduling decisions + bool sched_csirs; } NR_UE_info_t; typedef void (*nr_pp_impl_dl)(module_id_t mod_id, @@ -807,15 +815,8 @@ typedef struct gNB_MAC_INST_s { /// bitmap of DLSCH slots, can hold up to 160 slots uint64_t dlsch_slot_bitmap[3]; - /// Lookup for preferred time domain allocation for BWP, in DL, slots - /// dynamically allocated - int *preferred_dl_tda[MAX_NUM_BWP]; /// bitmap of ULSCH slots, can hold up to 160 slots uint64_t ulsch_slot_bitmap[3]; - /// Lookup for preferred time domain allocation for UL BWP, dynamically - /// allocated. The index refers to the DL slot, and the indicated TDA's k2 - /// points to the right UL slot - int *preferred_ul_tda[MAX_NUM_BWP]; /// maximum number of slots before a UE will be scheduled ULSCH automatically uint32_t ulsch_max_frame_inactivity; @@ -833,10 +834,8 @@ typedef struct gNB_MAC_INST_s { int xp_pdsch_antenna_ports; bool first_MIB; - double dl_bler_target_upper; - double dl_bler_target_lower; - double dl_rd2_bler_threshold; - uint8_t dl_max_mcs; + NR_bler_options_t dl_bler; + NR_bler_options_t ul_bler; uint8_t harq_round_max; uint8_t min_grant_prb; uint8_t min_grant_mcs; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index ef95443a5dc4e0a2bf9eb031fdf79a87d08f4794..e5c98eacd6f27c386dde23d0f2b050d9f82eb59a 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -321,8 +321,7 @@ void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc, int len_coreset = 1; if (curr_bwp < 48) len_coreset = 2; - - // setting default TDA for DL with + // setting default TDA for DL with TDA index 0 struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); // k0: Slot offset between DCI and its scheduled PDSCH (see TS 38.214 clause 5.1.2.1) When the field is absent the UE applies the value 0. //timedomainresourceallocation->k0 = calloc(1,sizeof(*timedomainresourceallocation->k0)); @@ -330,18 +329,20 @@ void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc, timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; timedomainresourceallocation->startSymbolAndLength = get_SLIV(len_coreset,14-len_coreset); // basic slot configuration starting in symbol 1 til the end of the slot ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation); + // setting TDA for CSI-RS symbol with index 1 + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation1 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation1->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation1->startSymbolAndLength = get_SLIV(len_coreset,14-len_coreset-1); // 1 symbol CSI-RS + ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation1); if(frame_type==TDD) { - // TDD if(scc->tdd_UL_DL_ConfigurationCommon) { int dl_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; if(dl_symb > 1) { - timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); - // k0: Slot offset between DCI and its scheduled PDSCH (see TS 38.214 clause 5.1.2.1) When the field is absent the UE applies the value 0. - //timedomainresourceallocation->k0 = calloc(1,sizeof(*timedomainresourceallocation->k0)); - //*timedomainresourceallocation->k0 = 0; - timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - timedomainresourceallocation->startSymbolAndLength = get_SLIV(len_coreset,dl_symb-len_coreset); // mixed slot configuration starting in symbol 1 til the end of the dl allocation - ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation); + // mixed slot TDA with TDA index 2 + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation2 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation2->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation2->startSymbolAndLength = get_SLIV(len_coreset,dl_symb-len_coreset); // mixed slot configuration starting in symbol 1 til the end of the dl allocation + ASN_SEQUENCE_ADD(&pdsch_TimeDomainAllocationList->list, timedomainresourceallocation2); } } } @@ -353,58 +354,45 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){ //TODO change to accomodate for SRS frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); - int temp_min_delay = 6; // k2 = 2 or 3 won'r work as well as higher values - if(frame_type==TDD && scc->tdd_UL_DL_ConfigurationCommon) { - - switch (scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity) { - case NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms2p5: // 30kHz SCS - case NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms2: // 60kHz SCS - case NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms1p25: // 60kHz SCS - case NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms1: // 120kHz SCS - case NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms0p625: // 120kHz SCS - case NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms0p5: // 120kHz SCS - temp_min_delay = 2; - break; - } - } - - int k2 = (min_fb_delay<temp_min_delay)?temp_min_delay:min_fb_delay; + const int k2 = min_fb_delay; uint8_t DELTA[4]= {2,3,4,6}; // Delta parameter for Msg3 int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + // UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); *pusch_timedomainresourceallocation->k2 = k2; pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0,13); // basic slot configuration starting in symbol 0 til the last but one symbol + pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0,13); ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); if(frame_type==TDD) { - - // TDD if(scc->tdd_UL_DL_ConfigurationCommon) { int ul_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation->k2 = k2; - pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one - ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); - - // for msg3 in the mixed slot - int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); - int nb_slots_per_period = ((1<<mu) * 10)/nb_periods_per_frame; - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation_msg3 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation_msg3->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu]; - if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay) - *pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period; - AssertFatal(*pusch_timedomainresourceallocation_msg3->k2<33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", - *pusch_timedomainresourceallocation_msg3->k2); - pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one - ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3); + if (ul_symb>1) { + // UL TDA index 1 for mixed slot (TDD) + pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation->k2 = k2; + pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); + + // UL TDA index 2 for msg3 in the mixed slot (TDD) + int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); + int nb_slots_per_period = ((1<<mu) * 10)/nb_periods_per_frame; + struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation_msg3 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation_msg3->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu]; + if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay) + *pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period; + AssertFatal(*pusch_timedomainresourceallocation_msg3->k2<33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", + *pusch_timedomainresourceallocation_msg3->k2); + pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3); + } } } } diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 731129b1d9bf3891962fe7d1eca516928f62fc0a..ba3bf0c4f30c10a52b78527807f3955c16279ad5 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -644,6 +644,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp break; case USRP_X300_DEV: case USRP_N300_DEV: + case USRP_X400_DEV: rxshift=2; break; default: