diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 08cfd7303c676a7587eaab41c539a8b87596b0af..6c15ec29435f11ff33de8e775cbb20075f4b3306 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2822,6 +2822,7 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, dci_field_t srs_resource_indicator, nr_srs_feedback_t *srs_feedback, const uint8_t *nrOfLayers, + int *tpmi, uint32_t *val) { // It is only applicable to codebook based transmission. This field occupies 0 bits for non-codebook based @@ -2841,6 +2842,7 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, long max_rank = *pusch_Config->maxRank; long *ul_FullPowerTransmission = pusch_Config->ext1 ? pusch_Config->ext1->ul_FullPowerTransmission_r16 : NULL; long *codebookSubset = pusch_Config->codebookSubset; + int ul_tpmi = tpmi ? *tpmi : srs_feedback ? srs_feedback->tpmi : -1; if (pusch_antenna_ports == 2) { @@ -2854,21 +2856,21 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { nbits = 2; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 2,"TPMI %d is invalid!\n", srs_feedback->tpmi); - *val = srs_feedback->tpmi; + AssertFatal(ul_tpmi <= 2,"TPMI %d is invalid!\n", ul_tpmi); + *val = ul_tpmi; } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 1; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 1,"TPMI %d is invalid!\n", srs_feedback->tpmi); - *val = srs_feedback->tpmi; + AssertFatal(ul_tpmi <= 1,"TPMI %d is invalid!\n", ul_tpmi); + *val = ul_tpmi; } } else { nbits = 3; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 5,"TPMI %d is invalid!\n", srs_feedback->tpmi); - *val = srs_feedback->tpmi; + AssertFatal(ul_tpmi <= 5,"TPMI %d is invalid!\n", ul_tpmi); + *val = ul_tpmi; } } } @@ -2881,25 +2883,25 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, if (ul_FullPowerTransmission && *ul_FullPowerTransmission == NR_PUSCH_Config__ext1__ul_FullPowerTransmission_r16_fullpowerMode1) { nbits = 2; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 2) || (*nrOfLayers==2 && srs_feedback->tpmi == 0), - "TPMI %d is invalid!\n", srs_feedback->tpmi); - *val = *nrOfLayers==1 ? table_7_3_1_1_2_4A_1layer[srs_feedback->tpmi] : 2; + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 2) || (*nrOfLayers==2 && ul_tpmi == 0), + "TPMI %d is invalid!\n", ul_tpmi); + *val = *nrOfLayers==1 ? table_7_3_1_1_2_4A_1layer[ul_tpmi] : 2; } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 2; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 1) || (*nrOfLayers==2 && srs_feedback->tpmi == 0), - "TPMI %d is invalid!\n", srs_feedback->tpmi); - *val = *nrOfLayers==1 ? srs_feedback->tpmi : 2; + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 1) || (*nrOfLayers==2 && ul_tpmi == 0), + "TPMI %d is invalid!\n", ul_tpmi); + *val = *nrOfLayers==1 ? ul_tpmi : 2; } } else { nbits = 4; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 5) || (*nrOfLayers==2 && srs_feedback->tpmi <= 2), - "TPMI %d is invalid!\n", srs_feedback->tpmi); - *val = *nrOfLayers==1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[srs_feedback->tpmi] : - table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[srs_feedback->tpmi]; + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 5) || (*nrOfLayers==2 && ul_tpmi <= 2), + "TPMI %d is invalid!\n", ul_tpmi); + *val = *nrOfLayers==1 ? table_7_3_1_1_2_4_1layer_fullyAndPartialAndNonCoherent[ul_tpmi] : + table_7_3_1_1_2_4_2layers_fullyAndPartialAndNonCoherent[ul_tpmi]; } } } @@ -2918,36 +2920,36 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 3; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13, "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal(ul_tpmi <= 3 || ul_tpmi == 13, "TPMI %d is invalid!\n", ul_tpmi); } } else { nbits = 4; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 15, "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal(ul_tpmi <= 15, "TPMI %d is invalid!\n", ul_tpmi); } } if (val && srs_feedback) { - *val = table_7_3_1_1_2_3A[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_3A[ul_tpmi]; } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 2; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 3, "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal(ul_tpmi <= 3, "TPMI %d is invalid!\n", ul_tpmi); } } else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) { nbits = 4; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 11, "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal(ul_tpmi <= 11, "TPMI %d is invalid!\n", ul_tpmi); } } else { nbits = 5; if (val && srs_feedback) { - AssertFatal(srs_feedback->tpmi <= 27, "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal(ul_tpmi <= 27, "TPMI %d is invalid!\n", ul_tpmi); } } if (val && srs_feedback) { - *val = srs_feedback->tpmi; + *val = ul_tpmi; } } } else { @@ -2965,48 +2967,48 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 4; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi==13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6), - "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal((*nrOfLayers==1 && (ul_tpmi <= 3 || ul_tpmi==13)) || (*nrOfLayers==2 && ul_tpmi <= 6), + "TPMI %d is invalid!\n", ul_tpmi); } } else { nbits = 5; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13), - "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 15) || (*nrOfLayers==2 && ul_tpmi <= 13), + "TPMI %d is invalid!\n", ul_tpmi); } } if (val && srs_feedback) { - *val = *nrOfLayers==1 ? table_7_3_1_1_2_2A_1layer[srs_feedback->tpmi] : table_7_3_1_1_2_2A_2layers[srs_feedback->tpmi]; + *val = *nrOfLayers==1 ? table_7_3_1_1_2_2A_1layer[ul_tpmi] : table_7_3_1_1_2_2A_2layers[ul_tpmi]; } } else { if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 4; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && (srs_feedback->tpmi <= 3 || srs_feedback->tpmi == 13)) || (*nrOfLayers==2 && srs_feedback->tpmi <= 6) || - (*nrOfLayers==3 && srs_feedback->tpmi <= 1) || (*nrOfLayers==4 && srs_feedback->tpmi == 0), - "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal((*nrOfLayers==1 && (ul_tpmi <= 3 || ul_tpmi == 13)) || (*nrOfLayers==2 && ul_tpmi <= 6) || + (*nrOfLayers==3 && ul_tpmi <= 1) || (*nrOfLayers==4 && ul_tpmi == 0), + "TPMI %d is invalid!\n", ul_tpmi); } } else { nbits = 6; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 15) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) || - (*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2), - "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 15) || (*nrOfLayers==2 && ul_tpmi <= 13) || + (*nrOfLayers==3 && ul_tpmi <= 2) || (*nrOfLayers==4 && ul_tpmi <= 2), + "TPMI %d is invalid!\n", ul_tpmi); } } if (val && srs_feedback) { switch (*nrOfLayers) { case 1: - *val = table_7_3_1_1_2_2B_1layer[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2B_1layer[ul_tpmi]; break; case 2: - *val = table_7_3_1_1_2_2B_2layers[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2B_2layers[ul_tpmi]; break; case 3: - *val = table_7_3_1_1_2_2B_3layers[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2B_3layers[ul_tpmi]; break; case 4: - *val = table_7_3_1_1_2_2B_4layers[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2B_4layers[ul_tpmi]; break; default: LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers); @@ -3017,38 +3019,38 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) { nbits = 4; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 3) || (*nrOfLayers==2 && srs_feedback->tpmi <= 5) || - (*nrOfLayers==3 && srs_feedback->tpmi == 0) || (*nrOfLayers==4 && srs_feedback->tpmi == 0), - "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 3) || (*nrOfLayers==2 && ul_tpmi <= 5) || + (*nrOfLayers==3 && ul_tpmi == 0) || (*nrOfLayers==4 && ul_tpmi == 0), + "TPMI %d is invalid!\n", ul_tpmi); } } else if (codebookSubset && *codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent) { nbits = 5; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 11) || (*nrOfLayers==2 && srs_feedback->tpmi <= 13) || - (*nrOfLayers==3 && srs_feedback->tpmi <= 2) || (*nrOfLayers==4 && srs_feedback->tpmi <= 2), - "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 11) || (*nrOfLayers==2 && ul_tpmi <= 13) || + (*nrOfLayers==3 && ul_tpmi <= 2) || (*nrOfLayers==4 && ul_tpmi <= 2), + "TPMI %d is invalid!\n", ul_tpmi); } } else { nbits = 6; if (val && srs_feedback) { - AssertFatal((*nrOfLayers==1 && srs_feedback->tpmi <= 28) || (*nrOfLayers==2 && srs_feedback->tpmi <= 22) || - (*nrOfLayers==3 && srs_feedback->tpmi <= 7) || (*nrOfLayers==4 && srs_feedback->tpmi <= 5), - "TPMI %d is invalid!\n", srs_feedback->tpmi); + AssertFatal((*nrOfLayers==1 && ul_tpmi <= 28) || (*nrOfLayers==2 && ul_tpmi <= 22) || + (*nrOfLayers==3 && ul_tpmi <= 7) || (*nrOfLayers==4 && ul_tpmi <= 5), + "TPMI %d is invalid!\n", ul_tpmi); } } if (val && srs_feedback) { switch (*nrOfLayers) { case 1: - *val = table_7_3_1_1_2_2_1layer[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2_1layer[ul_tpmi]; break; case 2: - *val = table_7_3_1_1_2_2_2layers[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2_2layers[ul_tpmi]; break; case 3: - *val = table_7_3_1_1_2_2_3layers[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2_3layers[ul_tpmi]; break; case 4: - *val = table_7_3_1_1_2_2_4layers[srs_feedback->tpmi]; + *val = table_7_3_1_1_2_2_4layers[ul_tpmi]; break; default: LOG_E(NR_MAC,"Number of layers %d is invalid!\n", *nrOfLayers); @@ -3299,7 +3301,8 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, size += dci_pdu->srs_resource_indicator.nbits; LOG_D(NR_MAC, "dci_pdu->srs_resource_indicator.nbits %d\n", dci_pdu->srs_resource_indicator.nbits); // Precoding info and number of layers - dci_pdu->precoding_information.nbits = compute_precoding_information(pusch_Config, srs_config, dci_pdu->srs_resource_indicator, NULL, NULL, NULL); + dci_pdu->precoding_information.nbits = + compute_precoding_information(pusch_Config, srs_config, dci_pdu->srs_resource_indicator, NULL, NULL, NULL, NULL); size += dci_pdu->precoding_information.nbits; LOG_D(NR_MAC, "dci_pdu->precoding_informaiton.nbits=%d\n", dci_pdu->precoding_information.nbits); // Antenna ports diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index a4930aec4716f608b12ca1bc6791365b648ffa01..64f8853e3db8c5f32d34b3f082274ab5e402c10c 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -79,6 +79,7 @@ uint8_t compute_precoding_information(NR_PUSCH_Config_t *pusch_Config, dci_field_t srs_resource_indicator, nr_srs_feedback_t *srs_feedback, const uint8_t *nrOfLayers, + int *tpmi, uint32_t *val); NR_PDSCH_TimeDomainResourceAllocationList_t *get_dl_tdalist(const NR_UE_DL_BWP_t *DL_BWP, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index c7faf781791d5beacc9d84ebd5076422549e3031..edf0f8c25eb8c98594e7b47580a8fb9864c3772c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -894,6 +894,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, pusch_pdu, &uldci_payload, NULL, + NULL, ra->Msg3_tda_id, ra->msg3_TPC, 1, // Not toggling NDI in msg3 retransmissions diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 1f9cb9c0c120ed24a5581df571d4ea287e84b21f..2c51ee5f2184faf94d11a45478638fc217af36b4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -782,6 +782,7 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, const nfapi_nr_pusch_pdu_t *pusch_pdu, dci_pdu_rel15_t *dci_pdu_rel15, nr_srs_feedback_t *srs_feedback, + int *tpmi, int time_domain_assignment, uint8_t tpc, uint8_t ndi, @@ -830,6 +831,7 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, dci_pdu_rel15->srs_resource_indicator, srs_feedback, &pusch_pdu->nrOfLayers, + tpmi, &dci_pdu_rel15->precoding_information.val); // antenna_ports.val = 0 for transform precoder is disabled, dmrs-Type=1, maxLength=1, Rank=1/2/3/4 diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 0900148073d434518d4fdf3b42a051b4cbceb444..7f849253daffb41c676f49cdc809bf209f8ec62d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2256,6 +2256,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n uint16_t rnti = UE->rnti; sched_ctrl->SR = false; + int *tpmi = NULL; int8_t harq_id = sched_pusch->ul_harq_pid; if (harq_id < 0) { @@ -2297,6 +2298,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n * retransmissions */ cur_harq->sched_pusch.time_domain_allocation = sched_pusch->time_domain_allocation; cur_harq->sched_pusch.nrOfLayers = sched_pusch->nrOfLayers; + cur_harq->sched_pusch.tpmi = sched_pusch->tpmi; sched_ctrl->sched_ul_bytes += sched_pusch->tb_size; UE->mac_stats.ul.total_rbs += sched_pusch->rbSize; @@ -2397,6 +2399,10 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n else pusch_pdu->data_scrambling_id = *scc->physCellId; pusch_pdu->nrOfLayers = sched_pusch->nrOfLayers; + // If nrOfLayers is the same as in srs_feedback, we use the best TPMI, i.e. the one in srs_feedback. + // Otherwise, we use the valid TPMI that we saved in the first transmission. + if (pusch_pdu->nrOfLayers != (sched_ctrl->srs_feedback.ul_ri + 1)) + tpmi = &sched_pusch->tpmi; pusch_pdu->num_dmrs_cdm_grps_no_data = sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data; /* FAPI: DMRS */ @@ -2572,6 +2578,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n pusch_pdu, &uldci_payload, &sched_ctrl->srs_feedback, + tpmi, sched_pusch->time_domain_allocation, UE->UE_sched_ctrl.tpc0, cur_harq->ndi, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c5df1782fddfc5e26068359c8273ce4f235c4f3b..3e9f02d7ffb0f150a9457340f736e70e34082f75 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -163,6 +163,7 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, const nfapi_nr_pusch_pdu_t *pusch_pdu, dci_pdu_rel15_t *dci_pdu_rel15, nr_srs_feedback_t *srs_feedback, + int *tpmi, int time_domain_assignment, uint8_t tpc, uint8_t ndi, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 641f6d93d1a33d00506a20dec4c68bd37f40b170..54be4358a7cb9dc9e276d030b414fc79236b2709 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -422,6 +422,8 @@ typedef struct NR_sched_pusch { int8_t ul_harq_pid; uint8_t nrOfLayers; + int tpmi; + // time_domain_allocation is the index of a list of tda int time_domain_allocation; NR_tda_info_t tda_info;