diff --git a/common/utils/oai_asn1.h b/common/utils/oai_asn1.h index 91d354ddbd..cc8392b0cf 100644 --- a/common/utils/oai_asn1.h +++ b/common/utils/oai_asn1.h @@ -85,7 +85,7 @@ if (eL == TARGET->list.array[iJ]->FIELD) \ break; \ } \ - if (iJ == TARGET->list.count) \ + if (iJ < TARGET->list.count) \ asn_sequence_del(&TARGET->list, iJ, 1); \ else \ LOG_E(NR_MAC, "Element not present in the list, impossible to release\n"); \ 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 d9d63a9704..b508246e07 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 @@ -27,6 +27,7 @@ #define NFAPI_UE_MAX_NUM_CB 8 #define NFAPI_MAX_NUM_UL_PDU 255 +#define NFAPI_MAX_NUM_CSI_RATEMATCH 4 /* typedef unsigned int uint32_t; @@ -436,6 +437,24 @@ typedef struct { fapi_nr_dl_config_dci_dl_pdu_rel15_t dci_config_rel15; } fapi_nr_dl_config_dci_pdu; +typedef struct { + uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4 + uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended + uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274 + uint16_t nr_of_rbs; // Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSI-FrequencyOccupation], Value: 24 -> 276 + uint8_t csi_type; // CSI Type [3GPP TS 38.211, sec 7.4.1.5], Value: 0:TRS; 1:CSI-RS NZP; 2:CSI-RS ZP + uint8_t row; // Row entry into the CSI Resource location table. [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 1-18 + uint16_t freq_domain; // Bitmap defining the frequencyDomainAllocation [3GPP TS 38.211, sec 7.4.1.5.3] [3GPP TS 38.331 CSIResourceMapping], Value: Up to the 12 LSBs, actual size is determined by the Row parameter + uint8_t symb_l0; // The time domain location l0 and firstOFDMSymbolInTimeDomain [3GPP TS 38.211, sec 7.4.1.5.3], Value: 0->13 + uint8_t symb_l1; // The time domain location l1 and firstOFDMSymbolInTimeDomain2 [3GPP TS 38.211, sec 7.4.1.5.3], Value: 2->12 + uint8_t cdm_type; // The cdm-Type field [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: noCDM; 1: fd-CDM2; 2: cdm4-FD2-TD2; 3: cdm8-FD2-TD4 + uint8_t freq_density; // The density field, p and comb offset (for dot5). [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: dot5 (even RB); 1: dot5 (odd RB); 2: one; 3: three + uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023 + uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS + uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS + uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1 +} fapi_nr_dl_config_csirs_pdu_rel15_t; + typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t; typedef struct { @@ -480,7 +499,7 @@ typedef struct { // to be check the fields needed to L1 with NR_DL_UE_HARQ_t and NR_UE_DLSCH_t // PTRS [TS38.214, sec 5.1.6.3] /// PT-RS antenna ports [TS38.214, sec 5.1.6.3] [TS38.211, table 7.4.1.2.2-1] Bitmap occupying the 6 LSBs with: bit 0: antenna port 1000 bit 5: antenna port 1005 and for each bit 0: PTRS port not used 1: PTRS port used - uint8_t PTRSPortIndex ; + uint8_t PTRSPortIndex; /// PT-RS time density [TS38.214, table 5.1.6.3-1] 0: 1 1: 2 2: 4 uint8_t PTRSTimeDensity; /// PT-RS frequency density [TS38.214, table 5.1.6.3-2] 0: 2 1: 4 @@ -498,6 +517,8 @@ typedef struct { uint16_t pduBitmap; uint32_t k1_feedback; uint8_t ldpcBaseGraph; + uint8_t numCsiRsForRateMatching; + fapi_nr_dl_config_csirs_pdu_rel15_t csiRsForRateMatching[NFAPI_MAX_NUM_CSI_RATEMATCH]; } fapi_nr_dl_config_dlsch_pdu_rel15_t; typedef struct { @@ -505,26 +526,6 @@ typedef struct { fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config_rel15; } fapi_nr_dl_config_dlsch_pdu; - -typedef struct { - uint8_t subcarrier_spacing; // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4 - uint8_t cyclic_prefix; // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended - uint16_t start_rb; // PRB where this CSI resource starts related to common resource block #0 (CRB#0). Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSIFrequencyOccupation], Value: 0 ->274 - uint16_t nr_of_rbs; // Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. [3GPP TS 38.331, sec 6.3.2 parameter CSI-FrequencyOccupation], Value: 24 -> 276 - uint8_t csi_type; // CSI Type [3GPP TS 38.211, sec 7.4.1.5], Value: 0:TRS; 1:CSI-RS NZP; 2:CSI-RS ZP - uint8_t row; // Row entry into the CSI Resource location table. [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 1-18 - uint16_t freq_domain; // Bitmap defining the frequencyDomainAllocation [3GPP TS 38.211, sec 7.4.1.5.3] [3GPP TS 38.331 CSIResourceMapping], Value: Up to the 12 LSBs, actual size is determined by the Row parameter - uint8_t symb_l0; // The time domain location l0 and firstOFDMSymbolInTimeDomain [3GPP TS 38.211, sec 7.4.1.5.3], Value: 0->13 - uint8_t symb_l1; // The time domain location l1 and firstOFDMSymbolInTimeDomain2 [3GPP TS 38.211, sec 7.4.1.5.3], Value: 2->12 - uint8_t cdm_type; // The cdm-Type field [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: noCDM; 1: fd-CDM2; 2: cdm4-FD2-TD2; 3: cdm8-FD2-TD4 - uint8_t freq_density; // The density field, p and comb offset (for dot5). [3GPP TS 38.211, sec 7.4.1.5.3 and table 7.4.1.5.3-1], Value: 0: dot5 (even RB); 1: dot5 (odd RB); 2: one; 3: three - uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023 - uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS - uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS - uint8_t measurement_bitmap; // bit 0 RSRP, bit 1 RI, bit 2 LI, bit 3 PMI, bit 4 CQI, bit 5 i1 -} fapi_nr_dl_config_csirs_pdu_rel15_t; - - typedef struct { uint16_t bwp_size; uint16_t bwp_start; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 52d45c938b..65612872d6 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -965,6 +965,73 @@ static void setup_puschconfig(NR_PUSCH_Config_t *source, NR_PUSCH_Config_t *targ } } +static void configure_csi_resourcemapping(NR_CSI_RS_ResourceMapping_t *target, NR_CSI_RS_ResourceMapping_t *source) +{ + if (target->frequencyDomainAllocation.present != source->frequencyDomainAllocation.present) { + UPDATE_NP_IE(target->frequencyDomainAllocation, + source->frequencyDomainAllocation, + struct NR_CSI_RS_ResourceMapping__frequencyDomainAllocation); + } + else { + switch (source->frequencyDomainAllocation.present) { + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1: + target->frequencyDomainAllocation.choice.row1.size = source->frequencyDomainAllocation.choice.row1.size; + target->frequencyDomainAllocation.choice.row1.bits_unused = source->frequencyDomainAllocation.choice.row1.bits_unused; + if (!target->frequencyDomainAllocation.choice.row1.buf) + target->frequencyDomainAllocation.choice.row1.buf = + calloc(target->frequencyDomainAllocation.choice.row1.size, sizeof(uint8_t)); + for (int i = 0; i < target->frequencyDomainAllocation.choice.row1.size; i++) + target->frequencyDomainAllocation.choice.row1.buf[i] = source->frequencyDomainAllocation.choice.row1.buf[i]; + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2: + target->frequencyDomainAllocation.choice.row2.size = source->frequencyDomainAllocation.choice.row2.size; + target->frequencyDomainAllocation.choice.row2.bits_unused = source->frequencyDomainAllocation.choice.row2.bits_unused; + if (!target->frequencyDomainAllocation.choice.row2.buf) + target->frequencyDomainAllocation.choice.row2.buf = + calloc(target->frequencyDomainAllocation.choice.row2.size, sizeof(uint8_t)); + for (int i = 0; i < target->frequencyDomainAllocation.choice.row2.size; i++) + target->frequencyDomainAllocation.choice.row2.buf[i] = source->frequencyDomainAllocation.choice.row2.buf[i]; + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4: + target->frequencyDomainAllocation.choice.row4.size = source->frequencyDomainAllocation.choice.row4.size; + target->frequencyDomainAllocation.choice.row4.bits_unused = source->frequencyDomainAllocation.choice.row4.bits_unused; + if (!target->frequencyDomainAllocation.choice.row4.buf) + target->frequencyDomainAllocation.choice.row4.buf = + calloc(target->frequencyDomainAllocation.choice.row4.size, sizeof(uint8_t)); + for (int i = 0; i < target->frequencyDomainAllocation.choice.row4.size; i++) + target->frequencyDomainAllocation.choice.row4.buf[i] = source->frequencyDomainAllocation.choice.row4.buf[i]; + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other: + target->frequencyDomainAllocation.choice.other.size = source->frequencyDomainAllocation.choice.other.size; + target->frequencyDomainAllocation.choice.other.bits_unused = source->frequencyDomainAllocation.choice.other.bits_unused; + if (!target->frequencyDomainAllocation.choice.other.buf) + target->frequencyDomainAllocation.choice.other.buf = + calloc(target->frequencyDomainAllocation.choice.other.size, sizeof(uint8_t)); + for (int i = 0; i < target->frequencyDomainAllocation.choice.other.size; i++) + target->frequencyDomainAllocation.choice.other.buf[i] = source->frequencyDomainAllocation.choice.other.buf[i]; + break; + default: + AssertFatal(false, "Invalid entry\n"); + } + } + target->nrofPorts = source->nrofPorts; + target->firstOFDMSymbolInTimeDomain = source->firstOFDMSymbolInTimeDomain; + UPDATE_IE(target->firstOFDMSymbolInTimeDomain2, source->firstOFDMSymbolInTimeDomain2, long); + target->cdm_Type = source->cdm_Type; + target->density = source->density; + target->freqBand = source->freqBand; +} + +static void config_zp_CSI_RS_Resource(NR_ZP_CSI_RS_Resource_t *target, NR_ZP_CSI_RS_Resource_t *source) +{ + target->zp_CSI_RS_ResourceId = source->zp_CSI_RS_ResourceId; + configure_csi_resourcemapping(&target->resourceMapping, &source->resourceMapping); + if (source->periodicityAndOffset) + UPDATE_IE(target->periodicityAndOffset, + source->periodicityAndOffset, + NR_CSI_ResourcePeriodicityAndOffset_t); +} + static void setup_pdschconfig(NR_PDSCH_Config_t *source, NR_PDSCH_Config_t *target) { UPDATE_IE(target->dataScramblingIdentityPDSCH, source->dataScramblingIdentityPDSCH, long); @@ -1022,7 +1089,25 @@ static void setup_pdschconfig(NR_PDSCH_Config_t *source, NR_PDSCH_Config_t *targ UPDATE_IE(target->mcs_Table, source->mcs_Table, long); UPDATE_IE(target->maxNrofCodeWordsScheduledByDCI, source->maxNrofCodeWordsScheduledByDCI, long); UPDATE_NP_IE(target->prb_BundlingType, source->prb_BundlingType, struct NR_PDSCH_Config__prb_BundlingType); - AssertFatal(source->zp_CSI_RS_ResourceToAddModList == NULL, "Not handled\n"); + if (source->zp_CSI_RS_ResourceToAddModList) { + if (!target->zp_CSI_RS_ResourceToAddModList) + target->zp_CSI_RS_ResourceToAddModList = calloc(1, sizeof(*target->zp_CSI_RS_ResourceToAddModList)); + ADDMOD_IE_FROMLIST_WFUNCTION(source->zp_CSI_RS_ResourceToAddModList, + target->zp_CSI_RS_ResourceToAddModList, + zp_CSI_RS_ResourceId, + NR_ZP_CSI_RS_Resource_t, + config_zp_CSI_RS_Resource); + } + if (source->zp_CSI_RS_ResourceToReleaseList) { + RELEASE_IE_FROMLIST(source->zp_CSI_RS_ResourceToReleaseList, + target->zp_CSI_RS_ResourceToAddModList, + zp_CSI_RS_ResourceId); + } + if (source->p_ZP_CSI_RS_ResourceSet) + HANDLE_SETUPRELEASE_IE(target->p_ZP_CSI_RS_ResourceSet, + source->p_ZP_CSI_RS_ResourceSet, + NR_ZP_CSI_RS_ResourceSet_t, + asn_DEF_NR_ZP_CSI_RS_ResourceSet); AssertFatal(source->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList == NULL, "Not handled\n"); AssertFatal(source->sp_ZP_CSI_RS_ResourceSetsToAddModList == NULL, "Not handled\n"); } @@ -1747,63 +1832,6 @@ static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroup } } -static void configure_csi_resourcemapping(NR_CSI_RS_ResourceMapping_t *target, NR_CSI_RS_ResourceMapping_t *source) -{ - if (target->frequencyDomainAllocation.present != source->frequencyDomainAllocation.present) { - UPDATE_NP_IE(target->frequencyDomainAllocation, - source->frequencyDomainAllocation, - struct NR_CSI_RS_ResourceMapping__frequencyDomainAllocation); - } - else { - switch (source->frequencyDomainAllocation.present) { - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1: - target->frequencyDomainAllocation.choice.row1.size = source->frequencyDomainAllocation.choice.row1.size; - target->frequencyDomainAllocation.choice.row1.bits_unused = source->frequencyDomainAllocation.choice.row1.bits_unused; - if (!target->frequencyDomainAllocation.choice.row1.buf) - target->frequencyDomainAllocation.choice.row1.buf = - calloc(target->frequencyDomainAllocation.choice.row1.size, sizeof(uint8_t)); - for (int i = 0; i < target->frequencyDomainAllocation.choice.row1.size; i++) - target->frequencyDomainAllocation.choice.row1.buf[i] = source->frequencyDomainAllocation.choice.row1.buf[i]; - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2: - target->frequencyDomainAllocation.choice.row2.size = source->frequencyDomainAllocation.choice.row2.size; - target->frequencyDomainAllocation.choice.row2.bits_unused = source->frequencyDomainAllocation.choice.row2.bits_unused; - if (!target->frequencyDomainAllocation.choice.row2.buf) - target->frequencyDomainAllocation.choice.row2.buf = - calloc(target->frequencyDomainAllocation.choice.row2.size, sizeof(uint8_t)); - for (int i = 0; i < target->frequencyDomainAllocation.choice.row2.size; i++) - target->frequencyDomainAllocation.choice.row2.buf[i] = source->frequencyDomainAllocation.choice.row2.buf[i]; - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4: - target->frequencyDomainAllocation.choice.row4.size = source->frequencyDomainAllocation.choice.row4.size; - target->frequencyDomainAllocation.choice.row4.bits_unused = source->frequencyDomainAllocation.choice.row4.bits_unused; - if (!target->frequencyDomainAllocation.choice.row4.buf) - target->frequencyDomainAllocation.choice.row4.buf = - calloc(target->frequencyDomainAllocation.choice.row4.size, sizeof(uint8_t)); - for (int i = 0; i < target->frequencyDomainAllocation.choice.row4.size; i++) - target->frequencyDomainAllocation.choice.row4.buf[i] = source->frequencyDomainAllocation.choice.row4.buf[i]; - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other: - target->frequencyDomainAllocation.choice.other.size = source->frequencyDomainAllocation.choice.other.size; - target->frequencyDomainAllocation.choice.other.bits_unused = source->frequencyDomainAllocation.choice.other.bits_unused; - if (!target->frequencyDomainAllocation.choice.other.buf) - target->frequencyDomainAllocation.choice.other.buf = - calloc(target->frequencyDomainAllocation.choice.other.size, sizeof(uint8_t)); - for (int i = 0; i < target->frequencyDomainAllocation.choice.other.size; i++) - target->frequencyDomainAllocation.choice.other.buf[i] = source->frequencyDomainAllocation.choice.other.buf[i]; - break; - default: - AssertFatal(false, "Invalid entry\n"); - } - } - target->nrofPorts = source->nrofPorts; - target->firstOFDMSymbolInTimeDomain = source->firstOFDMSymbolInTimeDomain; - UPDATE_IE(target->firstOFDMSymbolInTimeDomain2, source->firstOFDMSymbolInTimeDomain2, long); - target->cdm_Type = source->cdm_Type; - target->density = source->density; - target->freqBand = source->freqBand; -} - static void configure_csirs_resource(NR_NZP_CSI_RS_Resource_t *target, NR_NZP_CSI_RS_Resource_t *source) { configure_csi_resourcemapping(&target->resourceMapping, &source->resourceMapping); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 3ffcc3495c..49da1e6a88 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -252,6 +252,10 @@ and fills the PRACH PDU per each FD occasion. void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP); void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot); void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot); +void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, + NR_CSI_RS_ResourceMapping_t *resourceMapping, + uint32_t bwp_size, + uint32_t bwp_start); /* \brief This function schedules the Msg3 transmission @param diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index fcc5eb4d50..46a4ecfa1b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -230,6 +230,57 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id) mac->state = UE_SYNC; } +static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu, + fapi_nr_dl_config_request_t *dl_config, + int rnti_type, + int frame, + int slot, + int mu, + NR_PDSCH_Config_t *pdsch_config) +{ + // only for C-RNTI, MCS-C-RNTI, CS-RNTI (and only C-RNTI is supported for now) + if (rnti_type != TYPE_C_RNTI_) + return; + + if (pdsch_config && pdsch_config->zp_CSI_RS_ResourceToAddModList) { + for (int i = 0; i < pdsch_config->zp_CSI_RS_ResourceToAddModList->list.count; i++) { + NR_ZP_CSI_RS_Resource_t *zp_res = pdsch_config->zp_CSI_RS_ResourceToAddModList->list.array[i]; + NR_ZP_CSI_RS_ResourceId_t id = zp_res->zp_CSI_RS_ResourceId; + NR_SetupRelease_ZP_CSI_RS_ResourceSet_t *zp_set = pdsch_config->p_ZP_CSI_RS_ResourceSet; + AssertFatal(zp_set && zp_set->choice.setup, "Only periodic ZP resource set is implemented\n"); + bool found = false; + for (int j = 0; j < zp_set->choice.setup->zp_CSI_RS_ResourceIdList.list.count; j++) { + if (*zp_set->choice.setup->zp_CSI_RS_ResourceIdList.list.array[j] == id) { + found = true; + break; + } + } + AssertFatal(found, "Couldn't find periodic ZP resouce in set\n"); + AssertFatal(zp_res->periodicityAndOffset, "periodicityAndOffset cannot be null for periodic ZP resource\n"); + int period, offset; + csi_period_offset(NULL, zp_res->periodicityAndOffset, &period, &offset); + if((frame * nr_slots_per_frame[mu] + slot - offset) % period != 0) + continue; + AssertFatal(dlsch_pdu->numCsiRsForRateMatching < NFAPI_MAX_NUM_CSI_RATEMATCH, "csiRsForRateMatching out of bounds\n"); + fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu = &dlsch_pdu->csiRsForRateMatching[dlsch_pdu->numCsiRsForRateMatching]; + csi_pdu->csi_type = 2; // ZP-CSI + csi_pdu->subcarrier_spacing = mu; + configure_csi_resource_mapping(csi_pdu, &zp_res->resourceMapping, dlsch_pdu->BWPSize, dlsch_pdu->BWPStart); + dlsch_pdu->numCsiRsForRateMatching++; + } + } + + for (int i = 0; i < dl_config->number_pdus; i++) { + // This assumes that CSI-RS are scheduled before this moment which is true in current implementation + fapi_nr_dl_config_request_pdu_t *csi_req = &dl_config->dl_config_list[i]; + if (csi_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_CSI_RS) { + AssertFatal(dlsch_pdu->numCsiRsForRateMatching < NFAPI_MAX_NUM_CSI_RATEMATCH, "csiRsForRateMatching out of bounds\n"); + dlsch_pdu->csiRsForRateMatching[dlsch_pdu->numCsiRsForRateMatching] = csi_req->csirs_config_pdu.csirs_config_rel15; + dlsch_pdu->numCsiRsForRateMatching++; + } + } +} + int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, int cc_id, unsigned int gNB_index, @@ -631,8 +682,11 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->BWPSize = current_DL_BWP->BWPSize; dlsch_pdu->BWPStart = current_DL_BWP->BWPStart; } + + nr_rnti_type_t rnti_type = get_rnti_type(mac, dci_ind->rnti); + int mux_pattern = 1; - if (dci_ind->rnti == SI_RNTI) { + if (rnti_type == TYPE_SI_RNTI_) { NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config = mac->type0_PDCCH_CSS_config; mux_pattern = type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern; dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH; @@ -642,13 +696,17 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; } else { dlsch_pdu->SubcarrierSpacing = current_DL_BWP->scs; - if (mac->ra.RA_window_cnt >= 0 && dci_ind->rnti == mac->ra.ra_rnti) { + if (mac->ra.RA_window_cnt >= 0 && rnti_type == TYPE_RA_RNTI_) { dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; } else { dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; } } + dlsch_pdu->numCsiRsForRateMatching = 0; + configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, dlsch_pdu->SubcarrierSpacing, pdsch_config); + + /* IDENTIFIER_DCI_FORMATS */ /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ if (nr_ue_process_dci_freq_dom_resource_assignment(NULL, @@ -670,7 +728,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, int dmrs_typeA_pos = mac->dmrs_TypeA_Position; const int coreset_type = dci_ind->coreset_type == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; // 0 for coreset0, 1 otherwise; - nr_rnti_type_t rnti_type = get_rnti_type(mac, dci_ind->rnti); + NR_tda_info_t tda_info = get_dl_tda_info(current_DL_BWP, dci_ind->ss_type, dci->time_domain_assignment.val, @@ -839,7 +897,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, return -1; } - if (dci_ind->rnti != mac->ra.ra_rnti && dci_ind->rnti != SI_RNTI) { + if (rnti_type != TYPE_RA_RNTI_ && rnti_type != TYPE_SI_RNTI_) { AssertFatal(1 + dci->pdsch_to_harq_feedback_timing_indicator.val > DURATION_RX_TO_TX, "PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%d).\n", 1 + dci->pdsch_to_harq_feedback_timing_indicator.val, @@ -960,6 +1018,10 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, dlsch_pdu->BWPStart = current_DL_BWP->BWPStart; dlsch_pdu->SubcarrierSpacing = current_DL_BWP->scs; + nr_rnti_type_t rnti_type = get_rnti_type(mac, dci_ind->rnti); + dlsch_pdu->numCsiRsForRateMatching = 0; + configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, current_DL_BWP->scs, pdsch_Config); + /* IDENTIFIER_DCI_FORMATS */ /* CARRIER_IND */ /* BANDWIDTH_PART_IND */ @@ -981,7 +1043,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, int dmrs_typeA_pos = mac->dmrs_TypeA_Position; int mux_pattern = 1; const int coreset_type = dci_ind->coreset_type == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; // 0 for coreset0, 1 otherwise; - nr_rnti_type_t rnti_type = get_rnti_type(mac, dci_ind->rnti); + NR_tda_info_t tda_info = get_dl_tda_info(current_DL_BWP, dci_ind->ss_type, dci->time_domain_assignment.val, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 29b36d3e9d..7f7556b175 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1181,15 +1181,16 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info if (mac->state == UE_NOT_SYNC || mac->state == UE_DETACHING) return; - ue_dci_configuration(mac, dl_config, rx_frame, rx_slot); - - if (mac->ul_time_alignment.ta_apply != no_ta) - schedule_ta_command(dl_config, &mac->ul_time_alignment); if (mac->state == UE_CONNECTED) { nr_schedule_csirs_reception(mac, rx_frame, rx_slot); nr_schedule_csi_for_im(mac, rx_frame, rx_slot); } + ue_dci_configuration(mac, dl_config, rx_frame, rx_slot); + + if (mac->ul_time_alignment.ta_apply != no_ta) + schedule_ta_command(dl_config, &mac->ul_time_alignment); + nr_scheduled_response_t scheduled_response = {.dl_config = dl_config, .module_id = mac->ue_id, .CC_id = dl_info->cc_id, @@ -2402,6 +2403,113 @@ uint8_t set_csirs_measurement_bitmap(NR_CSI_MeasConfig_t *csi_measconfig, NR_CSI return meas_bitmap; } +void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, + NR_CSI_RS_ResourceMapping_t *resourceMapping, + uint32_t bwp_size, + uint32_t bwp_start) +{ + // According to last paragraph of TS 38.214 5.2.2.3.1 + if (resourceMapping->freqBand.startingRB < bwp_start) + csirs_config_pdu->start_rb = bwp_start; + else + csirs_config_pdu->start_rb = resourceMapping->freqBand.startingRB; + if (resourceMapping->freqBand.nrofRBs > (bwp_start + bwp_size - csirs_config_pdu->start_rb)) + csirs_config_pdu->nr_of_rbs = bwp_start + bwp_size - csirs_config_pdu->start_rb; + else + csirs_config_pdu->nr_of_rbs = resourceMapping->freqBand.nrofRBs; + AssertFatal(csirs_config_pdu->nr_of_rbs >= 24, "CSI-RS has %d RBs, but the minimum is 24\n", csirs_config_pdu->nr_of_rbs); + + csirs_config_pdu->symb_l0 = resourceMapping->firstOFDMSymbolInTimeDomain; + if (resourceMapping->firstOFDMSymbolInTimeDomain2) + csirs_config_pdu->symb_l1 = *resourceMapping->firstOFDMSymbolInTimeDomain2; + csirs_config_pdu->cdm_type = resourceMapping->cdm_Type; + + csirs_config_pdu->freq_density = resourceMapping->density.present; + if ((resourceMapping->density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5) + && (resourceMapping->density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs)) + csirs_config_pdu->freq_density--; + + switch(resourceMapping->frequencyDomainAllocation.present){ + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1: + csirs_config_pdu->row = 1; + csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.row1.buf[0]) >> 4) & 0x0f; + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2: + csirs_config_pdu->row = 2; + csirs_config_pdu->freq_domain = (((resourceMapping->frequencyDomainAllocation.choice.row2.buf[1] >> 4) & 0x0f) + | ((resourceMapping->frequencyDomainAllocation.choice.row2.buf[0] << 4) & 0xff0)); + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4: + csirs_config_pdu->row = 4; + csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.row4.buf[0]) >> 5) & 0x07; + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other: + csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.other.buf[0]) >> 2) & 0x3f; + // determining the row of table 7.4.1.5.3-1 in 38.211 + switch (resourceMapping->nrofPorts) { + case NR_CSI_RS_ResourceMapping__nrofPorts_p1: + AssertFatal(1 == 0, "Resource with 1 CSI port shouldn't be within other rows\n"); + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p2: + csirs_config_pdu->row = 3; + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p4: + csirs_config_pdu->row = 5; + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p8: + if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) + csirs_config_pdu->row = 8; + else { + int num_k = 0; + for (int k = 0; k < 6; k++) + num_k += (((csirs_config_pdu->freq_domain) >> k) & 0x01); + if (num_k == 4) + csirs_config_pdu->row = 6; + else + csirs_config_pdu->row = 7; + } + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p12: + if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) + csirs_config_pdu->row = 10; + else + csirs_config_pdu->row = 9; + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p16: + if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) + csirs_config_pdu->row = 12; + else + csirs_config_pdu->row = 11; + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p24: + if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) + csirs_config_pdu->row = 14; + else { + if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) + csirs_config_pdu->row = 15; + else + csirs_config_pdu->row = 13; + } + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p32: + if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) + csirs_config_pdu->row = 17; + else { + if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) + csirs_config_pdu->row = 18; + else + csirs_config_pdu->row = 16; + } + break; + default: + AssertFatal(false, "Invalid number of ports in CSI-RS resource\n"); + } + break; + default: + AssertFatal(false, "Invalid freqency domain allocation in CSI-RS resource\n"); + } +} + void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (!mac->sc_info.csi_MeasConfig) @@ -2433,117 +2541,20 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) LOG_D(MAC,"Scheduling reception of CSI-RS in frame %d slot %d\n", frame, slot); fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = &dl_config->dl_config_list[dl_config->number_pdus].csirs_config_pdu.csirs_config_rel15; csirs_config_pdu->measurement_bitmap = set_csirs_measurement_bitmap(csi_measconfig, csi_res_id); - NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping; csirs_config_pdu->subcarrier_spacing = mu; csirs_config_pdu->cyclic_prefix = current_DL_BWP->cyclicprefix ? *current_DL_BWP->cyclicprefix : 0; - // According to last paragraph of TS 38.214 5.2.2.3.1 - if (resourceMapping.freqBand.startingRB < bwp_start) { - csirs_config_pdu->start_rb = bwp_start; - } else { - csirs_config_pdu->start_rb = resourceMapping.freqBand.startingRB; - } - if (resourceMapping.freqBand.nrofRBs > (bwp_start + bwp_size - csirs_config_pdu->start_rb)) { - csirs_config_pdu->nr_of_rbs = bwp_start + bwp_size - csirs_config_pdu->start_rb; - } else { - csirs_config_pdu->nr_of_rbs = resourceMapping.freqBand.nrofRBs; - } - AssertFatal(csirs_config_pdu->nr_of_rbs >= 24, "CSI-RS has %d RBs, but the minimum is 24\n", csirs_config_pdu->nr_of_rbs); - csirs_config_pdu->csi_type = 1; // NZP-CSI-RS - csirs_config_pdu->symb_l0 = resourceMapping.firstOFDMSymbolInTimeDomain; - if (resourceMapping.firstOFDMSymbolInTimeDomain2) - csirs_config_pdu->symb_l1 = *resourceMapping.firstOFDMSymbolInTimeDomain2; - csirs_config_pdu->cdm_type = resourceMapping.cdm_Type; - csirs_config_pdu->freq_density = resourceMapping.density.present; - if ((resourceMapping.density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5) - && (resourceMapping.density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs)) - csirs_config_pdu->freq_density--; + csirs_config_pdu->scramb_id = nzpcsi->scramblingID; csirs_config_pdu->power_control_offset = nzpcsi->powerControlOffset + 8; if (nzpcsi->powerControlOffsetSS) csirs_config_pdu->power_control_offset_ss = *nzpcsi->powerControlOffsetSS; else csirs_config_pdu->power_control_offset_ss = 1; // 0 dB - switch(resourceMapping.frequencyDomainAllocation.present){ - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1: - csirs_config_pdu->row = 1; - csirs_config_pdu->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]) >> 4) & 0x0f; - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2: - csirs_config_pdu->row = 2; - csirs_config_pdu->freq_domain = (((resourceMapping.frequencyDomainAllocation.choice.row2.buf[1] >> 4) & 0x0f) - | ((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0] << 4) & 0xff0)); - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4: - csirs_config_pdu->row = 4; - csirs_config_pdu->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row4.buf[0]) >> 5) & 0x07; - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other: - csirs_config_pdu->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.other.buf[0]) >> 2) & 0x3f; - // determining the row of table 7.4.1.5.3-1 in 38.211 - switch (resourceMapping.nrofPorts) { - case NR_CSI_RS_ResourceMapping__nrofPorts_p1: - AssertFatal(1 == 0, "Resource with 1 CSI port shouldn't be within other rows\n"); - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p2: - csirs_config_pdu->row = 3; - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p4: - csirs_config_pdu->row = 5; - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p8: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) - csirs_config_pdu->row = 8; - else { - int num_k = 0; - for (int k = 0; k < 6; k++) - num_k += (((csirs_config_pdu->freq_domain) >> k) & 0x01); - if (num_k == 4) - csirs_config_pdu->row = 6; - else - csirs_config_pdu->row = 7; - } - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p12: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) - csirs_config_pdu->row = 10; - else - csirs_config_pdu->row = 9; - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p16: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) - csirs_config_pdu->row = 12; - else - csirs_config_pdu->row = 11; - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p24: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) - csirs_config_pdu->row = 14; - else { - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) - csirs_config_pdu->row = 15; - else - csirs_config_pdu->row = 13; - } - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p32: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) - csirs_config_pdu->row = 17; - else { - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) - csirs_config_pdu->row = 18; - else - csirs_config_pdu->row = 16; - } - break; - default: - AssertFatal(1 == 0, "Invalid number of ports in CSI-RS resource\n"); - } - break; - default: - AssertFatal(1 == 0, "Invalid freqency domain allocation in CSI-RS resource\n"); - } + + configure_csi_resource_mapping(csirs_config_pdu, &nzpcsi->resourceMapping, bwp_size, bwp_start); + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_CSI_RS; dl_config->number_pdus += 1; }