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 a98595fdd5..f76647d6af 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; @@ -437,6 +438,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 { @@ -481,7 +500,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 @@ -499,6 +518,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 { @@ -506,26 +527,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/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index c8afffa7d3..47afec9ef1 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -61,6 +61,21 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, uint32_t re_offset, uint8_t dmrs_type); +void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, + int32_t **dataF, + const int16_t amp, + nr_csi_info_t *nr_csi_info, + const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params, + const int slot, + uint8_t *N_cdm_groups, + uint8_t *CDM_group_size, + uint8_t *k_prime, + uint8_t *l_prime, + uint8_t *N_ports, + uint8_t *j_cdm, + uint8_t *k_overline, + uint8_t *l_overline); + void init_scrambling_luts(void); void nr_generate_modulation_table(void); diff --git a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c index 716a8b52be..001ad8ad87 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c @@ -19,23 +19,21 @@ * contact@openairinterface.org */ - -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_REFSIG/nr_refsig.h" //#define NR_CSIRS_DEBUG -void nr_init_csi_rs(const NR_DL_FRAME_PARMS *fp, uint32_t ***csi_rs, uint32_t Nid) { - uint32_t x1 = 0, x2 = 0; - uint8_t reset; - int csi_dmrs_init_length = ((fp->N_RB_DL<<4)>>5)+1; - for (uint8_t slot=0; slotslots_per_frame; slot++) { - for (uint8_t symb=0; symbsymbols_per_slot; symb++) { - reset = 1; - x2 = ((1<<10) * (fp->symbols_per_slot*slot+symb+1) * ((Nid<<1)+1) + (Nid)); - for (uint32_t n=0; nN_RB_DL << 4) >> 5) + 1; + for (int slot = 0; slot < fp->slots_per_frame; slot++) { + for (int symb = 0; symb < fp->symbols_per_slot; symb++) { + uint8_t reset = 1; + uint32_t x2 = ((1 << 10) * (fp->symbols_per_slot * slot + symb + 1) * ((Nid << 1) + 1) + Nid); + for (uint32_t n = 0; n < csi_dmrs_init_length; n++) { csi_rs[slot][symb][n] = lte_gold_generic(&x1, &x2, reset); reset = 0; } @@ -56,8 +54,8 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, uint8_t *N_ports, uint8_t *j_cdm, uint8_t *k_overline, - uint8_t *l_overline) { - + uint8_t *l_overline) +{ #ifdef NR_CSIRS_DEBUG LOG_I(NR_PHY, "csi_params->subcarrier_spacing = %i\n", csi_params->subcarrier_spacing); LOG_I(NR_PHY, "csi_params->cyclic_prefix = %i\n", csi_params->cyclic_prefix); @@ -75,19 +73,12 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, LOG_I(NR_PHY, "csi_params->power_control_offset_ss = %i\n", csi_params->power_control_offset_ss); #endif - int dataF_offset = slot*frame_parms->samples_per_slot_wCP; + int dataF_offset = slot * frame_parms->samples_per_slot_wCP; uint32_t **nr_gold_csi_rs = nr_csi_info->nr_gold_csi_rs[slot]; //*8(max allocation per RB)*2(QPSK)) - int csi_rs_length = frame_parms->N_RB_DL<<4; + int csi_rs_length = frame_parms->N_RB_DL << 4; int16_t mod_csi[frame_parms->symbols_per_slot][csi_rs_length>>1] __attribute__((aligned(16))); uint16_t b = csi_params->freq_domain; - uint16_t n, p, k, l, mprime, na, kpn; - uint8_t size, ports, kprime, lprime, i, gs; - uint8_t j[16], k_n[6], koverline[16], loverline[16]; - int found = 0; - int wf, wt, lp, kp, symb; - uint8_t fi = 0; - double rho, alpha; uint32_t beta = amp; nr_csi_info->csi_rs_generated_signal_bits = log2_approx(amp); @@ -99,469 +90,479 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, nr_init_csi_rs(frame_parms, nr_csi_info->nr_gold_csi_rs, csi_params->scramb_id); } - switch (csi_params->row) { + int size, ports, kprime, lprime; + int j[16], k_n[6], koverline[16], loverline[16]; + int found = 0; + int fi = 0; + // implementation of table 7.4.1.5.3-1 of 38.211 // lprime and kprime are the max value of l' and k' - case 1: - ports = 1; - kprime = 0; - lprime = 0; - size = 3; - while (found < 1) { - if ((b >> fi) & 0x01) { - k_n[found] = fi; - found++; + switch (csi_params->row) { + case 1: + ports = 1; + kprime = 0; + lprime = 0; + size = 3; + while (found < 1) { + if ((b >> fi) & 0x01) { + k_n[found] = fi; + found++; + } + else + fi++; } - else - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[0] + (i<<2); - } - break; - - case 2: - ports = 1; - kprime = 0; - lprime = 0; - size = 1; - while (found < 1) { - if ((b >> fi) & 0x01) { - k_n[found] = fi; - found++; - } - else - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[0]; - } - break; - - case 3: - ports = 2; - kprime = 1; - lprime = 0; - size = 1; - while (found < 1) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - else - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[0]; - } - break; - - case 4: - ports = 4; - kprime = 1; - lprime = 0; - size = 2; - while (found < 1) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<2; - found++; - } - else - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[0] + (i<<1); - } - break; - - case 5: - ports = 4; - kprime = 1; - lprime = 0; - size = 2; - while (found < 1) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - else - fi++; - } - for (i=0; isymb_l0 + i; - koverline[i] = k_n[0]; - } - break; - - case 6: - ports = 8; - kprime = 1; - lprime = 0; - size = 4; - while (found < 4) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[i]; - } - break; - - case 7: - ports = 8; - kprime = 1; - lprime = 0; - size = 4; - while (found < 2) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0 + (i>>1); - koverline[i] = k_n[i%2]; - } - break; - - case 8: - ports = 8; - kprime = 1; - lprime = 1; - size = 2; - while (found < 2) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[i]; - } - break; - - case 9: - ports = 12; - kprime = 1; - lprime = 0; - size = 6; - while (found < 6) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[i]; - } - break; - - case 10: - ports = 12; - kprime = 1; - lprime = 1; - size = 3; - while (found < 3) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[i]; - } - break; - - case 11: - ports = 16; - kprime = 1; - lprime = 0; - size = 8; - while (found < 4) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0 + (i>>2); - koverline[i] = k_n[i%4]; - } - break; - - case 12: - ports = 16; - kprime = 1; - lprime = 1; - size = 4; - while (found < 4) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[i]; - } - break; - - case 13: - ports = 24; - kprime = 1; - lprime = 0; - size = 12; - while (found < 3) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0 + i/3; - else - loverline[i] = csi_params->symb_l1 + i/9; - koverline[i] = k_n[i%3]; - } - break; - - case 14: - ports = 24; - kprime = 1; - lprime = 1; - size = 6; - while (found < 3) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0; - else - loverline[i] = csi_params->symb_l1; - koverline[i] = k_n[i%3]; - } - break; - - case 15: - ports = 24; - kprime = 1; - lprime = 3; - size = 3; - while (found < 3) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; + koverline[i] = k_n[0] + (i<<2); } - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[i]; - } - break; - - case 16: - ports = 32; - kprime = 1; - lprime = 0; - size = 16; - while (found < 4) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; + break; + case 2: + ports = 1; + kprime = 0; + lprime = 0; + size = 1; + while (found < 1) { + if ((b >> fi) & 0x01) { + k_n[found] = fi; + found++; + } + else + fi++; } - fi++; - } - for (i=0; isymb_l0 + (i>>2); - else - loverline[i] = csi_params->symb_l1 + (i/12); - koverline[i] = k_n[i%4]; - } - break; - - case 17: - ports = 32; - kprime = 1; - lprime = 1; - size = 8; - while (found < 4) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; - } - fi++; - } - for (i=0; isymb_l0; - else - loverline[i] = csi_params->symb_l1; - koverline[i] = k_n[i%4]; - } - break; - - case 18: - ports = 32; - kprime = 1; - lprime = 3; - size = 4; - while (found < 4) { - if ((b >> fi) & 0x01) { - k_n[found] = fi<<1; - found++; + koverline[i] = k_n[0]; } - fi++; - } - for (i=0; isymb_l0; - koverline[i] = k_n[i]; - } - break; - - default: - AssertFatal(0==1, "Row %d is not valid for CSI Table 7.4.1.5.3-1\n", csi_params->row); + break; + case 3: + ports = 2; + kprime = 1; + lprime = 0; + size = 1; + while (found < 1) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + else + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = 0; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[0]; + } + break; + case 4: + ports = 4; + kprime = 1; + lprime = 0; + size = 2; + while (found < 1) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 2; + found++; + } + else + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[0] + (i << 1); + } + break; + case 5: + ports = 4; + kprime = 1; + lprime = 0; + size = 2; + while (found < 1) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + else + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0 + i; + koverline[i] = k_n[0]; + } + break; + case 6: + ports = 8; + kprime = 1; + lprime = 0; + size = 4; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[i]; + } + break; + case 7: + ports = 8; + kprime = 1; + lprime = 0; + size = 4; + while (found < 2) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0 + (i >> 1); + koverline[i] = k_n[i % 2]; + } + break; + case 8: + ports = 8; + kprime = 1; + lprime = 1; + size = 2; + while (found < 2) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[i]; + } + break; + case 9: + ports = 12; + kprime = 1; + lprime = 0; + size = 6; + while (found < 6) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[i]; + } + break; + case 10: + ports = 12; + kprime = 1; + lprime = 1; + size = 3; + while (found < 3) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[i]; + } + break; + case 11: + ports = 16; + kprime = 1; + lprime = 0; + size = 8; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0 + (i >> 2); + koverline[i] = k_n[i % 4]; + } + break; + case 12: + ports = 16; + kprime = 1; + lprime = 1; + size = 4; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[i]; + } + break; + case 13: + ports = 24; + kprime = 1; + lprime = 0; + size = 12; + while (found < 3) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + if (i < 6) + loverline[i] = csi_params->symb_l0 + i / 3; + else + loverline[i] = csi_params->symb_l1 + i / 9; + koverline[i] = k_n[i % 3]; + } + break; + case 14: + ports = 24; + kprime = 1; + lprime = 1; + size = 6; + while (found < 3) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + if (i < 3) + loverline[i] = csi_params->symb_l0; + else + loverline[i] = csi_params->symb_l1; + koverline[i] = k_n[i%3]; + } + break; + case 15: + ports = 24; + kprime = 1; + lprime = 3; + size = 3; + while (found < 3) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[i]; + } + break; + case 16: + ports = 32; + kprime = 1; + lprime = 0; + size = 16; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + if (i < 8) + loverline[i] = csi_params->symb_l0 + (i>>2); + else + loverline[i] = csi_params->symb_l1 + (i/12); + koverline[i] = k_n[i % 4]; + } + break; + case 17: + ports = 32; + kprime = 1; + lprime = 1; + size = 8; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + if (i < 4) + loverline[i] = csi_params->symb_l0; + else + loverline[i] = csi_params->symb_l1; + koverline[i] = k_n[i % 4]; + } + break; + case 18: + ports = 32; + kprime = 1; + lprime = 3; + size = 4; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi << 1; + found++; + } + fi++; + } + for (int i = 0; i < size; i++) { + j[i] = i; + loverline[i] = csi_params->symb_l0; + koverline[i] = k_n[i]; + } + break; + default: + AssertFatal(false, "Row %d is not valid for CSI Table 7.4.1.5.3-1\n", csi_params->row); } #ifdef NR_CSIRS_DEBUG printf(" row %d, n. of ports %d\n k' ",csi_params->row,ports); - for (kp=0; kp<=kprime; kp++) + for (int kp = 0; kp <= kprime; kp++) printf("%d, ",kp); printf("l' "); - for (lp=0; lp<=lprime; lp++) - printf("%d, ",lp); + for (int lp = 0; lp <= lprime; lp++) + printf("%d, ", lp); printf("\n k overline "); - for (i=0; ifreq_density) { - - case 0: - rho = 0.5; - break; - - case 1: - rho = 0.5; - break; - - case 2: - rho = 1; - break; - - case 3: - rho = 3; - break; - - default: - AssertFatal(0==1, "Invalid frequency density index for CSI\n"); + case 0: + rho = 0.5; + break; + case 1: + rho = 0.5; + break; + case 2: + rho = 1; + break; + case 3: + rho = 3; + break; + default: + AssertFatal(false, "Invalid frequency density index for CSI\n"); } + double alpha = 0; if (ports == 1) alpha = rho; else - alpha = 2*rho; + alpha = 2 * rho; #ifdef NR_CSIRS_DEBUG - printf(" rho %f, alpha %f\n",rho,alpha); + printf(" rho %f, alpha %f\n", rho, alpha); #endif // CDM group size from CDM type index + int gs = 0; switch (csi_params->cdm_type) { - - case 0: - gs = 1; - break; - - case 1: - gs = 2; - break; - - case 2: - gs = 4; - break; - - case 3: - gs = 8; - break; - - default: - AssertFatal(0==1, "Invalid cdm type index for CSI\n"); + case 0: + gs = 1; + break; + case 1: + gs = 2; + break; + case 2: + gs = 4; + break; + case 3: + gs = 8; + break; + default: + AssertFatal(false, "Invalid cdm type index for CSI\n"); } - uint16_t csi_length; + int csi_length; if (rho < 1) { if (csi_params->freq_density == 0) { - csi_length = (((csi_params->start_rb + csi_params->nr_of_rbs)>>1)<start_rb + csi_params->nr_of_rbs) >> 1) << kprime) << 1; } else { - csi_length = ((((csi_params->start_rb + csi_params->nr_of_rbs)>>1)<start_rb + csi_params->nr_of_rbs) >> 1) << kprime) + 1) << 1; } } else { - csi_length = (((uint16_t) rho*(csi_params->start_rb + csi_params->nr_of_rbs))<start_rb + csi_params->nr_of_rbs)) << kprime) << 1; } #ifdef NR_CSIRS_DEBUG - printf(" start rb %d, nr of rbs %d, csi length %d\n", csi_params->start_rb, csi_params->nr_of_rbs, csi_length); + printf(" start rb %d, nr of rbs %d, csi length %d\n", csi_params->start_rb, csi_params->nr_of_rbs, csi_length); #endif + if (N_cdm_groups) + *N_cdm_groups = size; + if (CDM_group_size) + *CDM_group_size = gs; + if (k_prime) + *k_prime = kprime; + if (l_prime) + *l_prime = lprime; + if (N_ports) + *N_ports = ports; + if (j_cdm) + memcpy(j_cdm, j, 16 * sizeof(uint8_t)); + if (k_overline) + memcpy(k_overline, koverline, 16 * sizeof(uint8_t)); + if (l_overline) + memcpy(l_overline, loverline, 16 * sizeof(uint8_t)); - // TRS - if (csi_params->csi_type == 0) { - // ??? +#ifdef NR_CSIRS_DEBUG + if (N_ports) + LOG_I(NR_PHY, "nr_csi_info->N_ports = %d\n", *N_ports); + if (N_cdm_groups) + LOG_I(NR_PHY, "nr_csi_info->N_cdm_groups = %d\n", *N_cdm_groups); + if (CDM_group_size) + LOG_I(NR_PHY, "nr_csi_info->CDM_group_size = %d\n", *CDM_group_size); + if (k_prime) + LOG_I(NR_PHY, "nr_csi_info->kprime = %d\n", *k_prime); + if (l_prime) + LOG_I(NR_PHY, "nr_csi_info->lprime = %d\n", *l_prime); + if (N_cdm_groups) { + for(int ji = 0; ji < *N_cdm_groups; ji++) { + LOG_I(NR_PHY, "(CDM group %d) j = %d, koverline = %d, loverline = %d\n", ji, j[ji], koverline[ji], loverline[ji]); + } } +#endif - // NZP CSI RS - if (csi_params->csi_type == 1) { - // assuming amp is the amplitude of SSB channels - switch (csi_params->power_control_offset_ss) { + if (csi_params->csi_type == 2) // ZP-CSI + return; + + // assuming amp is the amplitude of SSB channels + switch (csi_params->power_control_offset_ss) { case 0: beta = (amp*ONE_OVER_SQRT2_Q15)>>15; break; @@ -572,73 +573,68 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, beta = (amp*ONE_OVER_SQRT2_Q15)>>14; break; case 3: - beta = amp<<1; + beta = amp << 1; break; default: - AssertFatal(0==1, "Invalid SS power offset density index for CSI\n"); - } + AssertFatal(false, "Invalid SS power offset density index for CSI\n"); + } - for (lp=0; lp<=lprime; lp++){ - symb = csi_params->symb_l0; - nr_modulation(nr_gold_csi_rs[symb+lp], csi_length, DMRS_MOD_ORDER, mod_csi[symb+lp]); - if ((csi_params->row == 5) || (csi_params->row == 7) || (csi_params->row == 11) || (csi_params->row == 13) || (csi_params->row == 16)) - nr_modulation(nr_gold_csi_rs[symb+1], csi_length, DMRS_MOD_ORDER, mod_csi[symb+1]); - if ((csi_params->row == 14) || (csi_params->row == 13) || (csi_params->row == 16) || (csi_params->row == 17)) { - symb = csi_params->symb_l1; - nr_modulation(nr_gold_csi_rs[symb+lp], csi_length, DMRS_MOD_ORDER, mod_csi[symb+lp]); - if ((csi_params->row == 13) || (csi_params->row == 16)) - nr_modulation(nr_gold_csi_rs[symb+1], csi_length, DMRS_MOD_ORDER, mod_csi[symb+1]); - } + for (int lp = 0; lp <= lprime; lp++) { + int symb = csi_params->symb_l0; + nr_modulation(nr_gold_csi_rs[symb + lp], csi_length, DMRS_MOD_ORDER, mod_csi[symb + lp]); + if ((csi_params->row == 5) || (csi_params->row == 7) || (csi_params->row == 11) || (csi_params->row == 13) || (csi_params->row == 16)) + nr_modulation(nr_gold_csi_rs[symb + 1], csi_length, DMRS_MOD_ORDER, mod_csi[symb + 1]); + if ((csi_params->row == 14) || (csi_params->row == 13) || (csi_params->row == 16) || (csi_params->row == 17)) { + symb = csi_params->symb_l1; + nr_modulation(nr_gold_csi_rs[symb + lp], csi_length, DMRS_MOD_ORDER, mod_csi[symb + lp]); + if ((csi_params->row == 13) || (csi_params->row == 16)) + nr_modulation(nr_gold_csi_rs[symb + 1], csi_length, DMRS_MOD_ORDER, mod_csi[symb + 1]); } } uint16_t start_sc = frame_parms->first_carrier_offset; // resource mapping according to 38.211 7.4.1.5.3 - for (n=csi_params->start_rb; n<(csi_params->start_rb+csi_params->nr_of_rbs); n++) { - if ( (csi_params->freq_density > 1) || (csi_params->freq_density == (n%2))) { // for freq density 0.5 checks if even or odd RB - for (int ji=0; jiofdm_symbol_size); // frequency index of current resource element + for (int n = csi_params->start_rb; n < (csi_params->start_rb + csi_params->nr_of_rbs); n++) { + if ((csi_params->freq_density > 1) || (csi_params->freq_density == (n % 2))) { // for freq density 0.5 checks if even or odd RB + for (int ji = 0; ji < size; ji++) { // loop over CDM groups + for (int s = 0 ; s < gs; s++) { // loop over each CDM group size + int p = s + j[ji] * gs; // port index + for (int kp = 0; kp <= kprime; kp++) { // loop over frequency resource elements within a group + // frequency index of current resource element + int k = (start_sc + (n * NR_NB_SC_PER_RB) + koverline[ji] + kp) % (frame_parms->ofdm_symbol_size); // wf according to tables 7.4.5.3-2 to 7.4.5.3-5 - if (kp == 0) - wf = 1; - else - wf = -2*(s%2)+1; - na = n*alpha; - kpn = (rho*koverline[ji])/NR_NB_SC_PER_RB; - mprime = na + kp + kpn; // sequence index - for (lp=0; lp<=lprime; lp++) { // loop over frequency resource elements within a group - l = lp + loverline[ji]; - // wt according to tables 7.4.5.3-2 to 7.4.5.3-5 + int wf = kp == 0 ? 1 : (-2 * (s % 2) + 1); + int na = n * alpha; + int kpn = (rho * koverline[ji]) / NR_NB_SC_PER_RB; + int mprime = na + kp + kpn; // sequence index + for (int lp = 0; lp <= lprime; lp++) { // loop over frequency resource elements within a group + int l = lp + loverline[ji]; + // wt according to tables 7.4.5.3-2 to 7.4.5.3-5 + int wt; if (s < 2) wt = 1; else if (s < 4) - wt = -2*(lp%2)+1; + wt = -2*(lp % 2) + 1; else if (s < 6) - wt = -2*(lp/2)+1; + wt = -2 * (lp / 2) + 1; else { if ((lp == 0) || (lp == 3)) wt = 1; else wt = -1; } - - // ZP CSI RS - if (csi_params->csi_type == 2) { - ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+(2*dataF_offset)] = 0; - ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)] = 0; - } - else { - ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+(2*dataF_offset)] = (beta*wt*wf*mod_csi[l][mprime<<1]) >> 15; - ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)] = (beta*wt*wf*mod_csi[l][(mprime<<1) + 1]) >> 15; - } + int index = ((l * frame_parms->ofdm_symbol_size + k) << 1) + (2 * dataF_offset); + ((int16_t*)dataF[p])[index] = (beta * wt * wf * mod_csi[l][mprime << 1]) >> 15; + ((int16_t*)dataF[p])[index + 1] = (beta * wt * wf * mod_csi[l][(mprime << 1) + 1]) >> 15; #ifdef NR_CSIRS_DEBUG - printf("l,k (%d,%d) seq. index %d \t port %d \t (%d,%d)\n",l,k,mprime,p+3000, - ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+(2*dataF_offset)], - ((int16_t*)dataF[p])[((l*frame_parms->ofdm_symbol_size + k)<<1)+1+(2*dataF_offset)]); + printf("l,k (%d,%d) seq. index %d \t port %d \t (%d,%d)\n", + l, + k, + mprime, + p + 3000, + ((int16_t*)dataF[p])[index], + ((int16_t*)dataF[p])[index + 1]); #endif } } @@ -646,25 +642,4 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, } } } - if (N_cdm_groups) *N_cdm_groups = size; - if (CDM_group_size) *CDM_group_size = gs; - if (k_prime) *k_prime = kprime; - if (l_prime) *l_prime = lprime; - if (N_ports) *N_ports = ports; - if (j_cdm) memcpy(j_cdm,j,16*sizeof(uint8_t)); - if (k_overline) memcpy(k_overline,koverline,16*sizeof(uint8_t)); - if (l_overline) memcpy(l_overline,loverline,16*sizeof(uint8_t)); - -#ifdef NR_CSIRS_DEBUG - if (N_ports) LOG_I(NR_PHY, "nr_csi_info->N_ports = %d\n", *N_ports); - if (N_cdm_groups) LOG_I(NR_PHY, "nr_csi_info->N_cdm_groups = %d\n", *N_cdm_groups); - if (CDM_group_size) LOG_I(NR_PHY, "nr_csi_info->CDM_group_size = %d\n", *CDM_group_size); - if (k_prime) LOG_I(NR_PHY, "nr_csi_info->kprime = %d\n", *k_prime); - if (l_prime) LOG_I(NR_PHY, "nr_csi_info->lprime = %d\n", *l_prime); - if (N_cdm_groups) { - for(int ji=0; ji<*N_cdm_groups; ji++) { - LOG_I(NR_PHY, "(CDM group %d) j = %d, koverline = %d, loverline = %d\n", ji, j[ji], koverline[ji], loverline[ji]); - } - } -#endif } diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 0f998ebee6..75d77f211a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -310,21 +310,6 @@ void init_prach_ru_list(RU_t *ru); void free_nr_ru_prach_entry(RU_t *ru, int prach_id); uint8_t get_nr_prach_duration(uint8_t prach_format); -void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, - int32_t **dataF, - const int16_t amp, - nr_csi_info_t *nr_csi_info, - const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params, - const int slot, - uint8_t *N_cdm_groups, - uint8_t *CDM_group_size, - uint8_t *k_prime, - uint8_t *l_prime, - uint8_t *N_ports, - uint8_t *j_cdm, - uint8_t *k_overline, - uint8_t *l_overline); - void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id); void nr_decode_pucch1(c16_t **rxdataF, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 0c3847baaf..89ad4bbc8f 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -28,7 +28,6 @@ #include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_REFSIG/nr_mod_table.h" #include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "nr_phy_common.h" #include "filt16a_32.h" #include "T.h" diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index fbb6113405..f8ca30e902 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -36,8 +36,8 @@ #include "executables/nr-softmodem-common.h" #include "nr_transport_proto_ue.h" #include "PHY/phy_extern_nr_ue.h" +#include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/nr/nr_common.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_ESTIMATION/filt16a_32.h" // Additional memory allocation, because of applying the filter and the memory offset to ensure memory alignment @@ -191,13 +191,13 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue, int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP], uint32_t *rsrp, int *rsrp_dBm, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { - - const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +{ + const NR_DL_FRAME_PARMS *fp = &ue->frame_parms; uint16_t meas_count = 0; uint32_t rsrp_sum = 0; - for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) { + for (int ant_rx = 0; ant_rx < fp->nb_antennas_rx; ant_rx++) { for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) { @@ -212,12 +212,12 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue, // loop over frequency resource elements within a group for (int kp = 0; kp <= k_prime; kp++) { - uint16_t k = (frame_parms->first_carrier_offset + (rb*NR_NB_SC_PER_RB)+k_overline[cdm_id] + kp) % frame_parms->ofdm_symbol_size; + uint16_t k = (fp->first_carrier_offset + (rb * NR_NB_SC_PER_RB) + k_overline[cdm_id] + kp) % fp->ofdm_symbol_size; // loop over time resource elements within a group for (int lp = 0; lp <= l_prime; lp++) { uint16_t symb = lp + l_overline[cdm_id]; - uint64_t symbol_offset = symb*frame_parms->ofdm_symbol_size; + uint64_t symbol_offset = symb * fp->ofdm_symbol_size; c16_t *rx_signal = &rxdataF[ant_rx][symbol_offset]; c16_t *rx_csi_rs_signal = (c16_t*)&csi_rs_received_signal[ant_rx][symbol_offset]; rx_csi_rs_signal[k].r = rx_signal[k].r; @@ -229,10 +229,11 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue, meas_count++; #ifdef NR_CSIRS_DEBUG - int dataF_offset = proc->nr_slot_rx*ue->frame_parms.samples_per_slot_wCP; + int dataF_offset = proc->nr_slot_rx * fp->samples_per_slot_wCP; uint16_t port_tx = s+j_cdm[cdm_id]*CDM_group_size; - c16_t *tx_csi_rs_signal = (c16_t*)&nr_csi_info->csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; - LOG_I(NR_PHY, "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n", + c16_t *tx_csi_rs_signal = (c16_t*)&nr_csi_info->csi_rs_generated_signal[port_tx][symbol_offset + dataF_offset]; + LOG_I(NR_PHY, + "l,k (%2d,%4d) |\tport_tx %d (%4d,%4d)\tant_rx %d (%4d,%4d)\n", symb, k, port_tx+3000, @@ -728,12 +729,12 @@ int nr_csi_rs_cqi_estimation(const uint32_t precoded_sinr, return 0; } -int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - const fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu, - uint32_t *interference_plus_noise_power, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { - +static void nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu, + uint32_t *interference_plus_noise_power, + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +{ const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; const uint16_t end_rb = csiim_config_pdu->start_rb + csiim_config_pdu->nr_of_rbs > csiim_config_pdu->bwp_size ? @@ -772,7 +773,7 @@ int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue, uint16_t sc0_offset = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; - for (int sc_idx = 0; sc_idx<4; sc_idx++) { + for (int sc_idx = 0; sc_idx < 4; sc_idx++) { uint16_t sc = sc0_offset + csiim_config_pdu->k_csiim[sc_idx]; if (sc >= frame_parms->ofdm_symbol_size) { @@ -785,34 +786,31 @@ int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue, sum_re += rx_signal[sc].r; sum_im += rx_signal[sc].i; - sum2_re += rx_signal[sc].r*rx_signal[sc].r; - sum2_im += rx_signal[sc].i*rx_signal[sc].i; + sum2_re += rx_signal[sc].r * rx_signal[sc].r; + sum2_im += rx_signal[sc].i * rx_signal[sc].i; count++; } } } } - int32_t power_re = sum2_re/count - (sum_re/count)*(sum_re/count); - int32_t power_im = sum2_im/count - (sum_im/count)*(sum_im/count); + int32_t power_re = sum2_re / count - (sum_re / count) * (sum_re / count); + int32_t power_im = sum2_im / count - (sum_im / count) * (sum_im / count); *interference_plus_noise_power = power_re + power_im; #ifdef NR_CSIIM_DEBUG LOG_I(NR_PHY, "interference_plus_noise_power based on CSI-IM = %i\n", *interference_plus_noise_power); #endif - - return 0; } -int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { int gNB_id = proc->gNB_id; - if(!ue->csiim_vars[gNB_id]->active) { - return -1; - } + if(!ue->csiim_vars[gNB_id]->active) + LOG_E(NR_PHY, "Scheduling reception of CSI-IM that is not active\n"); const fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu = (fapi_nr_dl_config_csiim_pdu_rel15_t*)&ue->csiim_vars[gNB_id]->csiim_config_pdu; @@ -828,8 +826,6 @@ int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, nr_csi_im_power_estimation(ue, proc, csiim_config_pdu, &ue->nr_csi_info->interference_plus_noise_power, rxdataF); ue->nr_csi_info->csi_im_meas_computed = true; - - return 0; } static nfapi_nr_dl_tti_csi_rs_pdu_rel15_t convert_csirs_pdu(const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 671764db17..be69351d8f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -30,7 +30,6 @@ */ #include "PHY/defs_nr_UE.h" #include "PHY/phy_extern.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "nr_transport_proto_ue.h" #include "PHY/sse_intrin.h" #include "T.h" @@ -159,6 +158,7 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, uint8_t Nl, NR_DL_FRAME_PARMS *frame_parms, uint16_t dlDmrsSymbPos, + uint32_t csi_res_bitmap, int chest_time_type); static void nr_dlsch_channel_level_median(uint32_t rx_size_symbol, @@ -239,6 +239,82 @@ void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, unsigned short nb_rb, int length); +static bool overlap_csi_symbol(fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu, int symbol) +{ + int num_l0 [18] = {1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 4, 2, 2, 4}; + for (int s = 0; s < num_l0[csi_pdu->row - 1]; s++) { + if (symbol == csi_pdu->symb_l0 + s) + return true; + } + // check also l1 if relevant + if (csi_pdu->row == 13 || csi_pdu->row == 14 || csi_pdu->row == 16 || csi_pdu->row == 17) { + for (int s = 0; s < 2; s++) { // two consecutive symbols including l1 + if (symbol == csi_pdu->symb_l1 + s) + return true; + } + } + return false; +} + +static uint32_t build_csi_overlap_bitmap(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, int symbol) +{ + // LS 16 bits for even RBs, MS 16 bits for odd RBs + uint32_t csi_res_bitmap = 0; + int num_k[18] = {1, 1, 1, 1, 1, 4, 2, 2, 6, 3, 4, 4, 3, 3, 3, 4, 4, 4}; + for (int i = 0; i < dlsch_config->numCsiRsForRateMatching; i++) { + fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu = &dlsch_config->csiRsForRateMatching[i]; + + if (!overlap_csi_symbol(csi_pdu, symbol)) + continue; + + int num_kp = 1; + int mult = 1; + int k0_step = 0; + int num_k0 = 1; + switch (csi_pdu->row) { + case 1: + k0_step = 4; + num_k0 = 3; + break; + case 2: + break; + case 4: + num_kp = 2; + mult = 4; + k0_step = 2; + num_k0 = 2; + break; + default: + num_kp = 2; + mult = 2; + } + int found = 0; + int bit = 0; + uint32_t temp_res_map = 0; + while (found < num_k[csi_pdu->row - 1]) { + if ((csi_pdu->freq_domain >> bit) & 0x01) { + for (int k0 = 0; k0 < num_k0; k0++) { + for (int kp = 0; kp < num_kp; kp++) { + int re = (bit * mult) + (k0 * k0_step) + kp; + temp_res_map |= (1 << re); + } + } + found++; + } + bit++; + AssertFatal(bit < 13, + "Couldn't find %d positive bits in bitmap %d for CSI freq. domain\n", + num_k[csi_pdu->row - 1], + csi_pdu->freq_domain); + } + if (csi_pdu->freq_density < 2) + csi_res_bitmap |= (temp_res_map << (16 * csi_pdu->freq_density)); + else + csi_res_bitmap |= (temp_res_map + (temp_res_map << 16)); + } + return csi_res_bitmap; +} + /* Main Function */ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, @@ -360,10 +436,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return(-1); } - if(symbol > ue->frame_parms.symbols_per_slot>>1) - { - slot = 1; - } + if(symbol > ue->frame_parms.symbols_per_slot >> 1) + slot = 1; uint8_t pilots = (dlsch_config->dlDmrsSymbPos >> symbol) & 1; uint8_t config_type = dlsch_config->dmrsConfigType; @@ -380,6 +454,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) c16_t rxdataF_ext[nbRx][rx_size_symbol]; memset(rxdataF_ext, 0, sizeof(rxdataF_ext)); + uint32_t csi_res_bitmap = build_csi_overlap_bitmap(dlsch_config, symbol); + + LOG_D(PHY, "%d.%d symbol %d csi overlap bitmap %d\n", frame, nr_slot_rx, symbol, csi_res_bitmap); + nr_dlsch_extract_rbs(ue->frame_parms.samples_per_slot_wCP, rxdataF, rx_size_symbol, @@ -396,6 +474,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, nl, frame_parms, dlsch_config->dlDmrsSymbPos, + csi_res_bitmap, ue->chest_time); if (meas_enabled) { stop_meas(&meas); @@ -576,9 +655,22 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, /* Check for PTRS bitmap and process it respectively */ if((pduBitmap & 0x1) && (dlsch[0].rnti_type == TYPE_C_RNTI_)) { - nr_pdsch_ptrs_processing( - ue, nbRx, ptrs_phase_per_slot, ptrs_re_per_slot, rx_size_symbol, rxdataF_comp, frame_parms, dlsch0_harq, dlsch1_harq, gNB_id, nr_slot_rx, symbol, (nb_rb_pdsch * 12), dlsch[0].rnti, dlsch); - dl_valid_re[symbol-1] -= ptrs_re_per_slot[0][symbol]; + nr_pdsch_ptrs_processing(ue, + nbRx, + ptrs_phase_per_slot, + ptrs_re_per_slot, + rx_size_symbol, + rxdataF_comp, + frame_parms, + dlsch0_harq, + dlsch1_harq, + gNB_id, + nr_slot_rx, + symbol, + (nb_rb_pdsch * 12), + dlsch[0].rnti, + dlsch); + dl_valid_re[symbol - 1] -= ptrs_re_per_slot[0][symbol]; } /* at last symbol in a slot calculate LLR's for whole slot */ if(symbol == (startSymbIdx + nbSymb -1)) { @@ -1099,15 +1191,30 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, uint8_t Nl, NR_DL_FRAME_PARMS *frame_parms, uint16_t dlDmrsSymbPos, + uint32_t csi_res_bitmap, int chest_time_type) { - if (config_type == NFAPI_NR_DMRS_TYPE1) { - AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2, - "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); - } else { + if (config_type == NFAPI_NR_DMRS_TYPE1) + AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2, "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); + else AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2 || n_dmrs_cdm_groups == 3, "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); - } + + uint32_t dmrs_rb_bitmap = 0xfff; // all REs taken by dmrs + if (config_type == NFAPI_NR_DMRS_TYPE1 && n_dmrs_cdm_groups == 1) + dmrs_rb_bitmap = 0x555; // alternating REs starting from 0 + if (config_type == NFAPI_NR_DMRS_TYPE2 && n_dmrs_cdm_groups == 1) + dmrs_rb_bitmap = 0xc3; // REs 0,1 and 6,7 + if (config_type == NFAPI_NR_DMRS_TYPE2 && n_dmrs_cdm_groups == 2) + dmrs_rb_bitmap = 0x3cf; // REs 0,1,2,3 and 6,7,8,9 + + // csi_res_bitmap LS 16 bits for even RBs, MS 16 bits for odd RBs + uint32_t csi_res_even = csi_res_bitmap & 0xfff; + uint32_t csi_res_odd = (csi_res_bitmap >> 16) & 0xfff; + AssertFatal((dmrs_rb_bitmap & csi_res_even) == 0, "DMRS RE overlapping with CSI RE, it shouldn't happen\n"); + AssertFatal((dmrs_rb_bitmap & csi_res_odd) == 0, "DMRS RE overlapping with CSI RE, it shouldn't happen\n"); + uint32_t dmrs_csi_overlap_even = csi_res_even + dmrs_rb_bitmap; + uint32_t dmrs_csi_overlap_odd = csi_res_odd + dmrs_rb_bitmap; const unsigned short start_re = (frame_parms->first_carrier_offset + start_rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size; int8_t validDmrsEst; @@ -1126,7 +1233,7 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, int32_t *dl_ch0 = &dl_ch_estimates[(l * frame_parms->nb_antennas_rx) + aarx][validDmrsEst * frame_parms->ofdm_symbol_size]; int32_t *dl_ch0_ext = dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; - if (pilots == 0) { //data symbol only + if (pilots == 0 && csi_res_bitmap == 0) { // data symbol only if (l == 0) { if (start_re + nb_rb_pdsch * NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { memcpy(rxF_ext, &rxF[start_re], nb_rb_pdsch * NR_NB_SC_PER_RB * sizeof(int32_t)); @@ -1139,65 +1246,24 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, } memcpy(dl_ch0_ext, dl_ch0, nb_rb_pdsch * NR_NB_SC_PER_RB * sizeof(int32_t)); } - else if (config_type == NFAPI_NR_DMRS_TYPE1){ - if (n_dmrs_cdm_groups == 1) { //data is multiplexed - if (l == 0) { - unsigned short k = start_re; - for (unsigned short j = 0; j < 6*nb_rb_pdsch; j += 3) { - rxF_ext[j] = rxF[k+1]; - rxF_ext[j+1] = rxF[k+3]; - rxF_ext[j+2] = rxF[k+5]; - k += 6; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; + else { + int j = 0; + int k = start_re; + for (int rb = 0; rb < nb_rb_pdsch; rb++) { + uint32_t overlap_map = rb % 2 ? dmrs_csi_overlap_odd : dmrs_csi_overlap_even; + for (int re = 0; re < 12; re++) { + if (((overlap_map >> re) & 0x01) == 0) { + // DATA RE + if (l == 0) + rxF_ext[j] = rxF[k]; + dl_ch0_ext[j] = dl_ch0[re]; + j++; } + k++; + if (k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; } - for (unsigned short j = 0; j < 6*nb_rb_pdsch; j += 3) { - dl_ch0_ext[j] = dl_ch0[1]; - dl_ch0_ext[j+1] = dl_ch0[3]; - dl_ch0_ext[j+2] = dl_ch0[5]; - dl_ch0 += 6; - } - } - } - else {//NFAPI_NR_DMRS_TYPE2 - if (n_dmrs_cdm_groups == 1) { //data is multiplexed - if (l == 0) { - unsigned short k = start_re; - for (unsigned short j = 0; j < 8*nb_rb_pdsch; j += 4) { - rxF_ext[j] = rxF[k+2]; - rxF_ext[j+1] = rxF[k+3]; - rxF_ext[j+2] = rxF[k+4]; - rxF_ext[j+3] = rxF[k+5]; - k += 6; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; - } - } - for (unsigned short j = 0; j < 8*nb_rb_pdsch; j += 4) { - dl_ch0_ext[j] = dl_ch0[2]; - dl_ch0_ext[j+1] = dl_ch0[3]; - dl_ch0_ext[j+2] = dl_ch0[4]; - dl_ch0_ext[j+3] = dl_ch0[5]; - dl_ch0 += 6; - } - } - else if (n_dmrs_cdm_groups == 2) { //data is multiplexed - if (l == 0) { - unsigned short k = start_re; - for (unsigned short j = 0; j < 4*nb_rb_pdsch; j += 2) { - rxF_ext[j] = rxF[k+4]; - rxF_ext[j+1] = rxF[k+5]; - k += 6; - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; - } - } - for (unsigned short j = 0; j < 4*nb_rb_pdsch; j += 2) { - dl_ch0_ext[j] = dl_ch0[4]; - dl_ch0_ext[j+1] = dl_ch0[5]; - dl_ch0 += 6; - } + dl_ch0 += 12; } } } diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 785aa409cb..4174e44238 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -149,9 +149,9 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, int n_ss, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); -int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); +void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index d3ce92da26..0f08604616 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -637,6 +637,54 @@ static void send_dl_done_to_tx_thread(notifiedFIFO_t *nf, int rx_slot) } } +static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config) +{ + uint32_t unav_res = 0; + for (int i = 0; i < dlsch_config->numCsiRsForRateMatching; i++) { + fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu = &dlsch_config->csiRsForRateMatching[i]; + // check overlapping symbols + int num_overlap_symb = 0; + // num of consecutive csi symbols from l0 included + int num_l0 [18] = {1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 4, 2, 2, 4}; + int num_symb = num_l0[csi_pdu->row - 1]; + for (int s = 0; s < num_symb; s++) { + int l0_symb = csi_pdu->symb_l0 + s; + if (l0_symb >= dlsch_config->start_symbol && l0_symb <= dlsch_config->start_symbol + dlsch_config->number_symbols) + num_overlap_symb++; + } + // check also l1 if relevant + if (csi_pdu->row == 13 || csi_pdu->row == 14 || csi_pdu->row == 16 || csi_pdu->row == 17) { + num_symb += 2; + for (int s = 0; s < 2; s++) { // two consecutive symbols including l1 + int l1_symb = csi_pdu->symb_l1 + s; + if (l1_symb >= dlsch_config->start_symbol && l1_symb <= dlsch_config->start_symbol + dlsch_config->number_symbols) + num_overlap_symb++; + } + } + if (num_overlap_symb == 0) + continue; + // check number overlapping prbs + // assuming CSI is spanning the whole BW + AssertFatal(dlsch_config->BWPSize <= csi_pdu->nr_of_rbs, "Assuming CSI-RS is spanning the whold BWP this shouldn't happen\n"); + int dlsch_start = dlsch_config->start_rb + dlsch_config->BWPStart; + int num_overlapping_prbs = dlsch_config->number_rbs; + if (num_overlapping_prbs < 1) + continue; // no overlapping prbs + if (csi_pdu->freq_density < 2) { // 0.5 density + num_overlapping_prbs /= 2; + // odd number of prbs and the start PRB is even/odd when CSI is in even/odd PRBs + if ((num_overlapping_prbs % 2) && ((dlsch_start % 2) == csi_pdu->freq_density)) + num_overlapping_prbs += 1; + } + // density is number or res per port per rb (over all symbols) + int ports [18] = {1, 1, 2, 4, 4, 8, 8, 8, 12, 12, 16, 16, 24, 24, 24, 32, 32, 32}; + int num_csi_res_per_prb = csi_pdu->freq_density == 3 ? 3 : 1; + num_csi_res_per_prb *= ports[csi_pdu->row - 1]; + unav_res += num_overlapping_prbs * num_csi_res_per_prb * num_overlap_symb / num_symb; + } + return unav_res; +} + static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], @@ -771,10 +819,10 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols); unav_res = n_ptrs * ptrsSymbPerSlot; } - int G1 = - nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[1].Nl); + unav_res += compute_csi_rm_unav_res(dlsch_config); + G = nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[1].Nl); start_meas(&ue->dlsch_unscrambling_stats); - nr_dlsch_unscrambling(llr[1], G1, 0, dlsch[1].dlsch_config.dlDataScramblingId, dlsch[1].rnti); + nr_dlsch_unscrambling(llr[1], G, 0, dlsch[1].dlsch_config.dlDataScramblingId, dlsch[1].rnti); stop_meas(&ue->dlsch_unscrambling_stats); start_meas(&ue->dlsch_decoding_stats); @@ -797,12 +845,14 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, stop_meas(&ue->dlsch_decoding_stats); if (cpumeas(CPUMEAS_GETSTATE)) { - LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats.p_time)/(cpuf*1000.0)); - } - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS); + LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", (ue->dlsch_unscrambling_stats.p_time) / (cpuf * 1000.0)); + LOG_D(PHY, + "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx % 1024, + nr_slot_rx, + (ue->dlsch_decoding_stats.p_time) / (cpuf * 1000.0)); + } + LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS); } // send to mac @@ -1004,24 +1054,50 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ start_meas(&meas); // do procedures for C-RNTI + bool slot_fep_map[14] = {0}; const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; __attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; + + // do procedures for CSI-IM + if ((ue->csiim_vars[gNB_id]) && (ue->csiim_vars[gNB_id]->active == 1)) { + for(int symb_idx = 0; symb_idx < 4; symb_idx++) { + int symb = ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx]; + if (!slot_fep_map[symb]) { + nr_slot_fep(ue, &ue->frame_parms, proc, symb, rxdataF, link_type_dl); + slot_fep_map[symb] = true; + } + } + nr_ue_csi_im_procedures(ue, proc, rxdataF); + ue->csiim_vars[gNB_id]->active = 0; + } + + // do procedures for CSI-RS + if ((ue->csirs_vars[gNB_id]) && (ue->csirs_vars[gNB_id]->active == 1)) { + for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { + if(is_csi_rs_in_symbol(ue->csirs_vars[gNB_id]->csirs_config_pdu, symb)) { + if (!slot_fep_map[symb]) { + nr_slot_fep(ue, &ue->frame_parms, proc, symb, rxdataF, link_type_dl); + slot_fep_map[symb] = true; + } + } + } + nr_ue_csi_rs_procedures(ue, proc, rxdataF); + ue->csirs_vars[gNB_id]->active = 0; + } + if (dlsch[0].active) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN); fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config; uint16_t nb_symb_sch = dlsch_config->number_symbols; uint16_t start_symb_sch = dlsch_config->start_symbol; - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); - //to update from pdsch config + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx % 1024, nr_slot_rx); - for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ - nr_slot_fep(ue, - &ue->frame_parms, - proc, - m, // to be updated from higher layer - rxdataF, - link_type_dl); + for (int m = start_symb_sch; m < (nb_symb_sch + start_symb_sch) ; m++) { + if (!slot_fep_map[m]) { + nr_slot_fep(ue, &ue->frame_parms, proc, m, rxdataF, link_type_dl); + slot_fep_map[m] = true; + } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT); @@ -1045,6 +1121,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols); unav_res = n_ptrs * ptrsSymbPerSlot; } + unav_res += compute_csi_rm_unav_res(dlsch_config); int G = nr_get_G(dlsch_config->number_rbs, dlsch_config->number_symbols, nb_re_dmrs, @@ -1097,36 +1174,6 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ free(llr[i]); } - // do procedures for CSI-IM - if ((ue->csiim_vars[gNB_id]) && (ue->csiim_vars[gNB_id]->active == 1)) { - int l_csiim[4] = {-1, -1, -1, -1}; - for(int symb_idx = 0; symb_idx < 4; symb_idx++) { - bool nr_slot_fep_done = false; - for (int symb_idx2 = 0; symb_idx2 < symb_idx; symb_idx2++) { - if (l_csiim[symb_idx2] == ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx]) { - nr_slot_fep_done = true; - } - } - l_csiim[symb_idx] = ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx]; - if(nr_slot_fep_done == false) { - nr_slot_fep(ue, &ue->frame_parms, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], rxdataF, link_type_dl); - } - } - nr_ue_csi_im_procedures(ue, proc, rxdataF); - ue->csiim_vars[gNB_id]->active = 0; - } - - // do procedures for CSI-RS - if ((ue->csirs_vars[gNB_id]) && (ue->csirs_vars[gNB_id]->active == 1)) { - for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { - if(is_csi_rs_in_symbol(ue->csirs_vars[gNB_id]->csirs_config_pdu,symb)) { - nr_slot_fep(ue, &ue->frame_parms, proc, symb, rxdataF, link_type_dl); - } - } - nr_ue_csi_rs_procedures(ue, proc, rxdataF); - ue->csirs_vars[gNB_id]->active = 0; - } - start_meas(&meas); if (nr_slot_rx==9) { diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 50577fc4f7..698499f5aa 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"); } @@ -1750,63 +1835,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 88973af849..4b29e01348 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -268,6 +268,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 82e7a541d5..2954cf246b 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, @@ -635,8 +686,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; @@ -646,13 +700,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, @@ -674,7 +732,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, @@ -845,7 +903,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, @@ -966,6 +1024,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 */ @@ -987,7 +1049,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 20b0e80f61..b88ca7e5f3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1197,15 +1197,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, @@ -2418,6 +2419,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) @@ -2449,117 +2557,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; }