From 9c8bdd6db5fdc44f3ab36a6045330c95244f8adb Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 20 Aug 2024 11:56:20 -0400 Subject: [PATCH 01/10] Add PUSCH timing stats --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 8 +++++--- openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h | 4 +++- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 9 +++++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 98c6dc3dfb..d4cf69d8f4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -116,6 +116,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, &harq_process->Z, &harq_process->F, harq_process->BG); + stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS); impp.n_segments = harq_process->C; impp.K = harq_process->K; impp.Kr = impp.K; @@ -126,7 +127,6 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); return(-1); } - stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT); #ifdef DEBUG_ULSCH_CODING @@ -149,19 +149,22 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); } - start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); if (ldpc_interface_offload.LDPCencoder) { for (int j = 0; j < impp.n_segments; j++) { impp.perCB[j].E_cb = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, j); } + start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); ldpc_interface_offload.LDPCencoder(harq_process->c, &harq_process->f, &impp); + stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); } else { if (ulsch->pusch_pdu.pusch_data.new_data_indicator) { + start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); for (int j = 0; j < (impp.n_segments / 8 + 1); j++) { impp.macro_num = j; impp.Kr = impp.K; ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp); } + stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); #ifdef DEBUG_ULSCH_CODING @@ -169,7 +172,6 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, write_output("ulsch_enc_output0.m", "enc0", &harq_process->d[0][0], (3 * 8 * Kr_bytes) + 12, 1, 4); #endif } - stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS); /////////////////////////////////////////////////////////////////////////////// for (int r = 0; r < impp.n_segments; r++) { // looping over C segments if (impp.F > 0) { diff --git a/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h b/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h index 6c667e3c1d..f89320087c 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h +++ b/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h @@ -45,11 +45,13 @@ FN(PHY_RX_PDCCH_STATS),\ FN(DLSCH_PROCEDURES_STATS),\ FN(PHY_PROC_TX),\ + FN(PUSCH_PROC_STATS),\ FN(ULSCH_SEGMENTATION_STATS),\ FN(ULSCH_LDPC_ENCODING_STATS),\ FN(ULSCH_RATE_MATCHING_STATS),\ FN(ULSCH_INTERLEAVING_STATS),\ - FN(ULSCH_ENCODING_STATS) + FN(ULSCH_ENCODING_STATS),\ + FN(OFDM_MOD_STATS) typedef enum { FOREACH_NR_PHY_CPU_MEAS(NOOP), diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index ce2c6c3153..8a0cde462e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -287,21 +287,26 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n start_meas_nr_ue_phy(ue, PHY_PROC_TX); - int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; - if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE) + const int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; + if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE) { + start_meas_nr_ue_phy(ue, PUSCH_PROC_STATS); nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, gNB_id, phy_data, (c16_t **)&txdataF); + stop_meas_nr_ue_phy(ue, PUSCH_PROC_STATS); + } ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF); pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF); LOG_D(PHY, "Sending Uplink data \n"); + start_meas_nr_ue_phy(ue, OFDM_MOD_STATS); nr_ue_pusch_common_procedures(ue, proc->nr_slot_tx, &ue->frame_parms, ue->frame_parms.nb_antennas_tx, (c16_t **)txdataF, link_type_ul); + stop_meas_nr_ue_phy(ue, OFDM_MOD_STATS); nr_ue_prach_procedures(ue, proc); From 2b7e0a05190b8f007ef8599e1447710e917b294b Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 6 Aug 2024 15:57:17 -0400 Subject: [PATCH 02/10] Change loop order to maximize cache hit It is better to write to memory that are grouped together to reduce probability of cache miss. This simple change improved the function's execution speed by 70%. Removed the unnecessary memset for the buffer. --- openair1/PHY/MODULATION/nr_modulation.c | 6 +++--- openair1/PHY/MODULATION/nr_modulation.h | 2 +- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index ad84245f86..3285dab149 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -318,10 +318,10 @@ void nr_layer_mapping(int nbCodes, } } -void nr_ue_layer_mapping(const c16_t *mod_symbs, const int n_layers, const int n_symbs, int sz, c16_t tx_layers[][sz]) +void nr_ue_layer_mapping(const c16_t *mod_symbs, const int n_layers, const int n_symbs, c16_t tx_layers[][n_symbs]) { - for (int i=0; i Date: Wed, 7 Aug 2024 20:15:45 -0400 Subject: [PATCH 03/10] multi dmrs amp by vector --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index b7afeb9035..c47d0da92c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -236,16 +236,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////// //////////////////////////////////////////////////////////////////////// - /////////////////////////DMRS Modulation///////////////////////// - /////////// - - uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4); - c16_t mod_dmrs[n_dmrs] __attribute((aligned(16))); - - /////////// - //////////////////////////////////////////////////////////////////////// - - /////////////////////////ULSCH layer mapping///////////////////////// /////////// const int sz = available_bits / mod_order / Nl; @@ -359,7 +349,12 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint8_t is_ptrs_sym = 0; uint16_t dmrs_idx = 0, ptrs_idx = 0; + uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb) * ((dmrs_type == pusch_dmrs_type1) ? 6 : 4); + c16_t mod_dmrs[n_dmrs] __attribute((aligned(16))); + c16_t mod_dmrs_amp[n_dmrs] __attribute((aligned(16))); + c16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation + c16_t mod_ptrs_amp[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation if ((ul_dmrs_symb_pos >> l) & 0x01) { is_dmrs_sym = 1; @@ -384,6 +379,10 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, n_dmrs * 2, DMRS_MOD_ORDER, (int16_t *)mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + + const int tmp = Wt[l_prime[0]] * Wf[k_prime] * AMP; + //todo: mult only needed + multadd_complex_vector_real_scalar((int16_t*)mod_dmrs,tmp,(int16_t*)mod_dmrs_amp,1,n_dmrs*2); } else { dmrs_idx = 0; } @@ -400,6 +399,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, slot, l); nr_modulation(gold, nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs); + const uint16_t beta_ptrs = 1; // temp value until power control is implemented + multadd_complex_vector_real_scalar((int16_t*)mod_ptrs,beta_ptrs*AMP,(int16_t*)mod_ptrs_amp,1,nb_rb); } } @@ -428,7 +429,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, if (pusch_pdu->transform_precoding == transformPrecoder_enabled) tx_precoding[nl][sample_offsetF] = c16mulRealShift(dmrs_seq[dmrs_idx], tmp, 15); else - tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_dmrs[dmrs_idx], tmp, 15); + tx_precoding[nl][sample_offsetF] = mod_dmrs_amp[dmrs_idx]; #ifdef DEBUG_PUSCH_MAPPING printf("DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n", @@ -448,8 +449,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, n += (k_prime) ? 0 : 1; } else if (is_ptrs == 1) { - uint16_t beta_ptrs = 1; // temp value until power control is implemented - tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_ptrs[ptrs_idx], beta_ptrs * AMP, 15); + tx_precoding[nl][sample_offsetF] = mod_ptrs_amp[ptrs_idx]; ptrs_idx++; } else if (!is_dmrs_sym || allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) { From 393363e253c74b5d094e0015da22ffa69b98521d Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Wed, 7 Aug 2024 20:16:08 -0400 Subject: [PATCH 04/10] Refactor PUSCH RE mapping RE mapping time is reduced by 10x. Functions are made generic to be later reused for PDSCH RE mapping at gNB. --- openair1/PHY/NR_REFSIG/ptrs_nr.c | 7 + openair1/PHY/NR_REFSIG/ptrs_nr.h | 2 + openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 626 +++++++++++++++------ openair1/PHY/TOOLS/cmult_sv.c | 27 +- openair1/PHY/TOOLS/tools_defs.h | 5 + openair1/SIMULATION/NR_PHY/ulsim.c | 11 - 6 files changed, 500 insertions(+), 178 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.c b/openair1/PHY/NR_REFSIG/ptrs_nr.c index 80d99088a1..eae3cebb01 100644 --- a/openair1/PHY/NR_REFSIG/ptrs_nr.c +++ b/openair1/PHY/NR_REFSIG/ptrs_nr.c @@ -85,6 +85,13 @@ void set_ptrs_symb_idx(uint16_t *ptrs_symbols, } } +unsigned int get_first_ptrs_re(const rnti_t rnti, const uint8_t K_ptrs, const uint16_t nRB, const uint8_t k_RE_ref) +{ + const uint16_t nRB_Kptrs = nRB % K_ptrs; + const uint16_t k_RB_ref = nRB_Kptrs ? (rnti % nRB_Kptrs) : (rnti % K_ptrs); + return (k_RE_ref + k_RB_ref * NR_NB_SC_PER_RB); +} + /******************************************************************* * * NAME : is_ptrs_subcarrier diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.h b/openair1/PHY/NR_REFSIG/ptrs_nr.h index 2230cc6fab..75f526dad5 100644 --- a/openair1/PHY/NR_REFSIG/ptrs_nr.h +++ b/openair1/PHY/NR_REFSIG/ptrs_nr.h @@ -53,6 +53,8 @@ void set_ptrs_symb_idx(uint16_t *ptrs_symbols, uint8_t L_ptrs, uint16_t dmrs_symb_pos); +unsigned int get_first_ptrs_re(const rnti_t rnti, const uint8_t K_ptrs, const uint16_t nRB, const uint8_t k_RE_ref); + uint8_t is_ptrs_subcarrier(uint16_t k, uint16_t n_rnti, uint8_t K_ptrs, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index c47d0da92c..b8c9b57410 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -85,6 +85,424 @@ void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t size, uint32_t Nid, uint nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out); } +/* +The function pointers are set once before calling the mapping funcion for +all symbols based on different parameters. Then the mapping is done for +each symbol by calling the function pointers. +*/ +static void (*map_dmrs_ptr)(const unsigned int, const c16_t *, c16_t *); +static void (*map_data_dmrs_ptr)(const c16_t *, c16_t *); + +/* +The following set of functions map dmrs and/or data REs in one RB based on +configuration of DMRS type, number of CDM groups with no data and delta. +For all other combinations of the parameters not present below is not +applicable. +*/ + +/* +DMRS mapping in a RB for Type 1. +*/ +static void map_dmrs_type1_cdm1_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out) +{ + *(out + delta) = *dmrs++; + *(out + delta + 2) = *dmrs++; + *(out + delta + 4) = *dmrs++; + *(out + delta + 6) = *dmrs++; + *(out + delta + 8) = *dmrs++; + *(out + delta + 10) = *dmrs++; +} + +/* +Data in DMRS symbol for Type 1, NumCDMGroupNoData = 1 and delta 0 (antenna port 0 and 1). +There is no data in DMRS symbol for other scenarios in type 1. +*/ +static void map_data_dmrs_type1_cdm1_rb(const c16_t *data, c16_t *out) +{ + *(out + 1) = *data++; + *(out + 3) = *data++; + *(out + 5) = *data++; + *(out + 7) = *data++; + *(out + 9) = *data++; + *(out + 11) = *data++; +} + +#define NR_DMRS_TYPE2_CDM_GRP_SIZE 2 +#define NR_DMRS_TYPE2_NUM_CDM_GRP 3 + +/* +Map DMRS for type 2 +*/ + +static void map_dmrs_type2_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out) +{ + memcpy(out + delta, dmrs, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); + out += (NR_DMRS_TYPE2_CDM_GRP_SIZE * NR_DMRS_TYPE2_NUM_CDM_GRP); + dmrs += NR_DMRS_TYPE2_CDM_GRP_SIZE; + memcpy(out + delta, dmrs, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); +} + +/* +Map data if type 2, delta 0 NumCDMGrpNoData 1. +*/ +static void map_data_dmrs_type2_rb_f1(const c16_t *data, c16_t *out) +{ + memcpy(out + NR_DMRS_TYPE2_CDM_GRP_SIZE, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE * 2); + out += NR_DMRS_TYPE2_CDM_GRP_SIZE * 4; + data += NR_DMRS_TYPE2_CDM_GRP_SIZE * 2; + memcpy(out, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE * 2); +} + +/* +Map data if type 2, delta (0, 2) NumCDMGrpNoData 2, or delta 2 NumCDMGrpNoData 1. +*/ +static void map_data_dmrs_type2_rb_f2(const c16_t *data, c16_t *out) +{ + memcpy(out + NR_DMRS_TYPE2_CDM_GRP_SIZE * 2, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); + out += NR_DMRS_TYPE2_CDM_GRP_SIZE * 5; + data += NR_DMRS_TYPE2_CDM_GRP_SIZE; + memcpy(out, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); +} + +/* +Map data if type 2, delta 4 NumCDMGrpNoData 1. +*/ +static void map_data_dmrs_type2_rb_f3(const c16_t *data, c16_t *out) +{ + memcpy(out + NR_DMRS_TYPE2_CDM_GRP_SIZE, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); + out += NR_DMRS_TYPE2_CDM_GRP_SIZE * 4; + data += NR_DMRS_TYPE2_CDM_GRP_SIZE; + memcpy(out, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); +} + +/* +Map data and PTRS in RB +*/ +static void map_data_ptrs(const unsigned int ptrsIdx, const c16_t *data, const c16_t *ptrs, c16_t *out) +{ + memcpy(out, data, sizeof(c16_t) * ptrsIdx); + data += ptrsIdx; + *(out + ptrsIdx) = *ptrs; + memcpy(out + ptrsIdx + 1, data, sizeof(c16_t) * NR_NB_SC_PER_RB - ptrsIdx - 1); +} + +/* +Map data only in RB +*/ +static void map_data_rb(const c16_t *data, c16_t *out) +{ + memcpy(out, data, sizeof(c16_t) * NR_NB_SC_PER_RB); +} + +/* +This function is used for a PRB which has the DC subcarrier +that is not first subcarrier. +*/ +static void map_over_dc(const unsigned int right_dc, + const unsigned int fft_size, + const unsigned int dmrs_per_rb, + const unsigned int data_per_rb, + const unsigned int delta, + const unsigned int ptrsIdx, + unsigned int *rb, + const c16_t **ptrs, + const c16_t **dmrs, + const c16_t **data, + c16_t **out) +{ + if (right_dc) { + c16_t *out_tmp = *out; + c16_t tmp_out_buf[NR_NB_SC_PER_RB]; + const unsigned int left_dc = NR_NB_SC_PER_RB - right_dc; + /* copy out to temp buffer */ + memcpy(tmp_out_buf, out_tmp, sizeof(c16_t) * left_dc); + out_tmp -= (fft_size - left_dc); + memcpy(tmp_out_buf + left_dc, out_tmp, sizeof(c16_t) * right_dc); + + /* map on to temp buffer */ + if (dmrs && data) { + map_data_dmrs_ptr(*data, tmp_out_buf); + *data += data_per_rb; + } else if (dmrs) { + map_dmrs_ptr(delta, *dmrs, tmp_out_buf); + *dmrs += dmrs_per_rb; + } else if (ptrs) { + map_data_ptrs(ptrsIdx, *data, *ptrs, tmp_out_buf); + *data += (NR_NB_SC_PER_RB - 1); + *ptrs += 1; + } else if (data) { + map_data_rb(*data, tmp_out_buf); + *data += NR_NB_SC_PER_RB; + } else { + DevAssert(false); + } + + /* copy back to out buffer */ + out_tmp = *out; + memcpy(out_tmp, tmp_out_buf, sizeof(c16_t) * left_dc); + out_tmp -= (fft_size - left_dc); + memcpy(out_tmp, tmp_out_buf + left_dc, sizeof(c16_t) * right_dc); + out_tmp += right_dc; + *out = out_tmp; + *rb += 1; + } else { + *out = (*out) - fft_size; + } +} + +/* +Map all REs in one OFDM symbol +*/ +static void map_current_symbol(const rnti_t rnti, + const unsigned int K_ptrs, + const unsigned int k_RE_ref, + const unsigned int nb_rb, + const unsigned int bwp_start, + const unsigned int start_rb, + const unsigned int first_sc_offset, + const pusch_dmrs_type_t dmrs_type, + const unsigned int fft_size, + const bool dmrs_symbol, + const bool ptrs_symbol, + const c16_t *dmrs_seq, + const c16_t *ptrs_seq, + const unsigned int delta, + const c16_t **data, + c16_t *out) +{ + const unsigned int abs_start_rb = bwp_start + start_rb; + const unsigned int start_sc = (first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % fft_size; + const bool cross_dc = start_sc + nb_rb * NR_NB_SC_PER_RB > fft_size; + const unsigned int rb_over_dc = cross_dc ? (fft_size - start_sc) % NR_NB_SC_PER_RB : 0; + const unsigned int stop_rb = cross_dc ? (fft_size - start_sc) / NR_NB_SC_PER_RB : nb_rb; + const c16_t *data_tmp = *data; + if (dmrs_symbol) { + const unsigned int dmrs_per_rb = (dmrs_type == pusch_dmrs_type1) ? 6 : 4; + const unsigned int data_per_rb = NR_NB_SC_PER_RB - dmrs_per_rb; + + const c16_t *p_mod_dmrs = dmrs_seq + abs_start_rb * dmrs_per_rb; + c16_t *out_tmp = out + start_sc; + unsigned int rb = 0; + /* map below/above DC */ + for (; rb < stop_rb; rb++) { + map_dmrs_ptr(delta, p_mod_dmrs, out_tmp); + p_mod_dmrs += dmrs_per_rb; + out_tmp += NR_NB_SC_PER_RB; + } + /* map RB at DC */ + map_over_dc(rb_over_dc, fft_size, dmrs_per_rb, data_per_rb, delta, 0, &rb, NULL, &p_mod_dmrs, NULL, &out_tmp); + /* map above DC */ + for (; rb < nb_rb; rb++) { + map_dmrs_ptr(delta, p_mod_dmrs, out_tmp); + p_mod_dmrs += dmrs_per_rb; + out_tmp += NR_NB_SC_PER_RB; + } + + if (map_data_dmrs_ptr) { + c16_t *out_tmp = out + start_sc; + unsigned int rb = 0; + for (; rb < stop_rb; rb++) { + map_data_dmrs_ptr(data_tmp, out_tmp); + data_tmp += data_per_rb; + out_tmp += NR_NB_SC_PER_RB; + } + map_over_dc(rb_over_dc, fft_size, dmrs_per_rb, data_per_rb, delta, 0, &rb, NULL, &p_mod_dmrs, &data_tmp, &out_tmp); + for (; rb < nb_rb; rb++) { + map_data_dmrs_ptr(data_tmp, out_tmp); + data_tmp += data_per_rb; + out_tmp += NR_NB_SC_PER_RB; + } + } + } else if (ptrs_symbol) { + const unsigned int first_ptrs_re = get_first_ptrs_re(rnti, K_ptrs, nb_rb, k_RE_ref) + start_sc; + const unsigned int ptrs_idx_re = (start_sc - first_ptrs_re) % NR_NB_SC_PER_RB; + unsigned int ptrs_idx_rb = (start_sc - first_ptrs_re) / NR_NB_SC_PER_RB; + unsigned int rb = 0; + c16_t *out_tmp = out + start_sc; + for (; rb < ptrs_idx_rb; rb++) { + map_data_rb(data_tmp, out); + data_tmp += NR_NB_SC_PER_RB; + out_tmp += NR_NB_SC_PER_RB; + } + const c16_t *p_mod_ptrs = ptrs_seq; + ptrs_idx_rb = 0; + for (; rb < stop_rb; rb++) { + if (ptrs_idx_rb % K_ptrs) { + map_data_rb(data_tmp, out_tmp); + data_tmp += NR_NB_SC_PER_RB; + out_tmp += NR_NB_SC_PER_RB; + } else { + map_data_ptrs(ptrs_idx_re, data_tmp, p_mod_ptrs, out_tmp); + p_mod_ptrs++; + data_tmp += (NR_NB_SC_PER_RB - 1); + out_tmp += NR_NB_SC_PER_RB; + } + ptrs_idx_rb++; + } + if (ptrs_idx_rb % K_ptrs) { + map_over_dc(rb_over_dc, fft_size, 0, 0, delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); + } else { + map_over_dc(rb_over_dc, fft_size, 0, 0, delta, ptrs_idx_re, &rb, &p_mod_ptrs, NULL, &data_tmp, &out_tmp); + } + for (; rb < nb_rb; rb++) { + if (ptrs_idx_rb % K_ptrs) { + map_data_rb(data_tmp, out_tmp); + data_tmp += NR_NB_SC_PER_RB; + out_tmp += NR_NB_SC_PER_RB; + } else { + map_data_ptrs(ptrs_idx_re, data_tmp, p_mod_ptrs, out_tmp); + p_mod_ptrs++; + data_tmp += (NR_NB_SC_PER_RB - 1); + out_tmp += NR_NB_SC_PER_RB; + } + ptrs_idx_rb++; + } + } else { + unsigned int rb = 0; + c16_t *out_tmp = out + start_sc; + for (; rb < stop_rb; rb++) { + map_data_rb(data_tmp, out_tmp); + data_tmp += NR_NB_SC_PER_RB; + out_tmp += NR_NB_SC_PER_RB; + } + map_over_dc(rb_over_dc, fft_size, 0, 0, delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); + for (; rb < nb_rb; rb++) { + map_data_rb(data_tmp, out_tmp); + data_tmp += NR_NB_SC_PER_RB; + out_tmp += NR_NB_SC_PER_RB; + } + } + *data = data_tmp; +} + +/* +TS 38.211 table 6.4.1.1.3-1 and 2 +*/ +static void dmrs_amp_mult(const uint32_t dmrs_port, + const int Wt, + const int Wf[2], + const c16_t *mod_dmrs, + c16_t *mod_dmrs_out, + const uint32_t n_dmrs, + const pusch_dmrs_type_t dmrs_type) +{ + /* + A short array that holds amplitude values used for + multiplying with the modulated DMRS vector in 128bit SIMD. + */ + int16_t alpha_dmrs[8] __attribute((aligned(16))); + for (int_fast8_t i = 0; i < sizeofArray(alpha_dmrs) / 2; i++) { + const int16_t a = Wf[i % 2] * Wt * AMP; + alpha_dmrs[2 * i] = a; // multiplier for real part of DMRS symbol + alpha_dmrs[2 * i + 1] = a; // multiplier for img part of DMRS symbol + } + /* multiply mod_dmrs with alpha_dmrs in 4 symbol patches */ + mult_real_vector_single_vector(mod_dmrs, alpha_dmrs, mod_dmrs_out, n_dmrs); +} + +/* +Holds params needed for PUSCH resoruce mapping +*/ +typedef struct { + rnti_t rnti; + unsigned int K_ptrs; + unsigned int k_RE_ref; + unsigned int first_sc_offset; + unsigned int fft_size; + unsigned int num_rb_max; + unsigned int symbols_per_slot; + unsigned int slot; + unsigned int dmrs_scrambling_id; + unsigned int scid; + unsigned int dmrs_port; + int Wt; + int *Wf; + unsigned int dmrs_symb_pos; + unsigned int ptrs_symb_pos; + unsigned int pdu_bit_map; + transformPrecoder_t transform_precoding; + unsigned int bwp_start; + unsigned int start_rb; + unsigned int nb_rb; + unsigned int start_symbol; + unsigned int num_symbols; + pusch_dmrs_type_t dmrs_type; + unsigned int delta; + unsigned int num_cdm_no_data; +} nr_phy_pxsch_params_t; + +/* +Map ULSCH data and DMRS in all of the scheduled symbols and PRBs +*/ +static void map_symbols(const nr_phy_pxsch_params_t p, + const unsigned int slot, + const c16_t *dmrs_seq, + const c16_t *data, + c16_t *out) +{ + // asign the function pointers + if (p.dmrs_type == pusch_dmrs_type1) { + map_dmrs_ptr = map_dmrs_type1_cdm1_rb; + map_data_dmrs_ptr = (p.delta == 0 && p.num_cdm_no_data == 1) ? map_data_dmrs_type1_cdm1_rb : NULL; + } else { + map_dmrs_ptr = map_dmrs_type2_rb; + if (p.delta == 0 && p.num_cdm_no_data == 1) { + map_data_dmrs_ptr = map_data_dmrs_type2_rb_f1; + } else if ((p.delta == 0 && p.num_cdm_no_data == 2) || (p.delta == 2 && p.num_cdm_no_data == 2) + || (p.delta == 2 && p.num_cdm_no_data == 1)) { + map_data_dmrs_ptr = map_data_dmrs_type2_rb_f2; + } else if (p.delta == 4 && p.num_cdm_no_data == 1) { + map_data_dmrs_ptr = map_data_dmrs_type2_rb_f3; + } else { // no data in DMRS symbols for other combinations + map_data_dmrs_ptr = NULL; + } + } + // for all symbols + const unsigned int n_dmrs = (p.bwp_start + p.start_rb + p.nb_rb) * ((p.dmrs_type == pusch_dmrs_type1) ? 6 : 4); + const c16_t *cur_data = data; + for (int l = p.start_symbol; l < p.start_symbol + p.num_symbols; l++) { + const bool dmrs_symbol = is_dmrs_symbol(l, p.dmrs_symb_pos); + const bool ptrs_symbol = is_ptrs_symbol(l, p.ptrs_symb_pos); + c16_t mod_dmrs_amp[ALNARS_16_4(n_dmrs)] __attribute((aligned(16))); + c16_t mod_ptrs_amp[ALNARS_16_4(p.nb_rb)] __attribute((aligned(16))); + const uint32_t *gold = NULL; + if (dmrs_symbol || ptrs_symbol) { + gold = nr_gold_pusch(p.num_rb_max, p.symbols_per_slot, p.dmrs_scrambling_id, p.scid, slot, l); + } + if (dmrs_symbol) { + c16_t mod_dmrs[ALNARS_16_4(n_dmrs)] __attribute((aligned(16))); + if (p.transform_precoding == transformPrecoder_disabled) { + nr_modulation(gold, n_dmrs * 2, DMRS_MOD_ORDER, (int16_t *)mod_dmrs); + dmrs_amp_mult(p.dmrs_port, p.Wt, p.Wf, mod_dmrs, mod_dmrs_amp, n_dmrs, p.dmrs_type); + } else { + dmrs_amp_mult(p.dmrs_port, p.Wt, p.Wf, dmrs_seq, mod_dmrs_amp, n_dmrs, p.dmrs_type); + } + } else if ((p.pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) && ptrs_symbol) { + AssertFatal(p.transform_precoding == transformPrecoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); + c16_t mod_ptrs[ALNARS_16_4(p.nb_rb)] __attribute((aligned(16))); + nr_modulation(gold, p.nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs); + const unsigned int beta_ptrs = 1; // temp value until power control is implemented + multadd_complex_vector_real_scalar((int16_t *)mod_ptrs, beta_ptrs * AMP, (int16_t *)mod_ptrs_amp, 1, p.nb_rb); + } + map_current_symbol(p.rnti, + p.K_ptrs, + p.k_RE_ref, + p.nb_rb, + p.bwp_start, + p.start_rb, + p.first_sc_offset, + p.dmrs_type, + p.fft_size, + dmrs_symbol, + ptrs_symbol, + mod_dmrs_amp, + mod_ptrs_amp, + p.delta, + &cur_data, // increments every symbol + out + l * p.fft_size); + } +} + void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const unsigned char harq_pid, const uint32_t frame, @@ -95,11 +513,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, { LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot); - int Wf[2], Wt[2]; - int l_prime[2], delta; + int l_prime[2]; uint8_t nb_dmrs_re_per_rb; - int i; - int sample_offsetF, N_RE_prime; NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; @@ -143,17 +558,18 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, LOG_D(PHY,"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n", rnti,start_rb,nb_rb,mod_order,Nl,pusch_pdu->Tpmi,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb); // TbD num_of_mod_symbols is set but never used - N_RE_prime = NR_NB_SC_PER_RB*number_of_symbols - nb_dmrs_re_per_rb*number_dmrs_symbols - N_PRB_oh; + const uint32_t N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh; harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb; /////////////////////////PTRS parameters' initialization///////////////////////// /////////// - uint8_t L_ptrs, K_ptrs = 0; + unsigned int K_ptrs = 0, k_RE_ref = 0; uint32_t unav_res = 0; if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { K_ptrs = pusch_pdu->pusch_ptrs.ptrs_freq_density; - L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density; + k_RE_ref = pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; + uint8_t L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density; ulsch_ue->ptrs_symbols = 0; @@ -239,9 +655,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////ULSCH layer mapping///////////////////////// /////////// const int sz = available_bits / mod_order / Nl; - c16_t tx_layers[Nl][sz]; + c16_t ulsch_mod[Nl][sz]; - nr_ue_layer_mapping(d_mod, Nl, sz, tx_layers); + nr_ue_layer_mapping(d_mod, Nl, sz, ulsch_mod); /////////// //////////////////////////////////////////////////////////////////////// @@ -255,8 +671,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint8_t u = 0, v = 0; c16_t *dmrs_seq = NULL; /// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4) - c16_t y[max_num_re] __attribute__((aligned(16))); - memset(y, 0, sizeof(y)); + c16_t ulsch_mod_tp[max_num_re] __attribute__((aligned(16))); + memset(ulsch_mod_tp, 0, sizeof(ulsch_mod_tp)); if (pusch_pdu->transform_precoding == transformPrecoder_enabled) { @@ -281,7 +697,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /* In the symbol with DMRS no data would be transmitted CDM groups is 2*/ continue; - nr_dft(&y[y_offset], &tx_layers[0][y_offset], nb_re_pusch); + nr_dft(&ulsch_mod_tp[y_offset], &ulsch_mod[0][y_offset], nb_re_pusch); y_offset = y_offset + nb_re_pusch; @@ -299,7 +715,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits,mod_order); for (int ll = 0; ll < (available_bits/mod_order); ll++) { - debug_symbols[ll] = ulsch_ue->y[ll]; + debug_symbols[ll] = ulsch_ue->ulsch_mod_tp[ll]; } printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols); @@ -307,8 +723,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, nr_idft(&debug_symbols[offset], nb_re_pusch); offset = offset + nb_re_pusch; } - LOG_M("preDFT_all_symbols.m","UE_preDFT", tx_layers[0],number_of_symbols*nb_re_pusch,1,1); - LOG_M("postDFT_all_symbols.m","UE_postDFT", y,number_of_symbols*nb_re_pusch,1,1); + LOG_M("preDFT_all_symbols.m", "UE_preDFT", ulsch_mod[0], number_of_symbols * nb_re_pusch, 1, 1); + LOG_M("postDFT_all_symbols.m", "UE_postDFT", ulsch_mod_tp, number_of_symbols * nb_re_pusch, 1, 1); LOG_M("DEBUG_IDFT_SYMBOLS.m","UE_Debug_IDFT", debug_symbols,number_of_symbols*nb_re_pusch,1,1); LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1); #endif @@ -323,167 +739,57 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////ULSCH RE mapping///////////////////////// /////////// - const int encoded_length = frame_parms->N_RB_UL * 14 * NR_NB_SC_PER_RB * mod_order * Nl; - c16_t tx_precoding[Nl][encoded_length]; + const int slot_sz = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot; + c16_t tx_precoding[Nl][slot_sz]; memset(tx_precoding, 0, sizeof(tx_precoding)); - for (int nl=0; nl < Nl; nl++) { - uint8_t k_prime = 0; - uint16_t m = 0; - + for (int nl = 0; nl < Nl; nl++) { #ifdef DEBUG_PUSCH_MAPPING printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u); #endif - int dmrs_port = get_dmrs_port(nl,pusch_pdu->dmrs_ports); - // DMRS params for this dmrs port + const uint8_t dmrs_port = get_dmrs_port(nl, pusch_pdu->dmrs_ports); + const uint8_t delta = get_delta(dmrs_port, dmrs_type); + int Wt[2]; + int Wf[2]; get_Wt(Wt, dmrs_port, dmrs_type); get_Wf(Wf, dmrs_port, dmrs_type); - delta = get_delta(dmrs_port, dmrs_type); - for (int l=start_symbol; ltransform_precoding == transformPrecoder_enabled) ? ulsch_mod_tp : ulsch_mod[nl]; - uint16_t k = start_sc; - uint16_t n = 0; - uint8_t is_dmrs_sym = 0; - uint8_t is_ptrs_sym = 0; - uint16_t dmrs_idx = 0, ptrs_idx = 0; + nr_phy_pxsch_params_t params = {.rnti = rnti, + .K_ptrs = K_ptrs, + .k_RE_ref = k_RE_ref, + .first_sc_offset = frame_parms->first_carrier_offset, + .fft_size = frame_parms->ofdm_symbol_size, + .num_rb_max = frame_parms->N_RB_UL, + .symbols_per_slot = frame_parms->symbols_per_slot, + .dmrs_scrambling_id = pusch_pdu->ul_dmrs_scrambling_id, + .scid = pusch_pdu->scid, + .dmrs_port = dmrs_port, + .Wt = Wt[l_prime[0]], + .Wf = Wf, + .dmrs_symb_pos = ul_dmrs_symb_pos, + .ptrs_symb_pos = ulsch_ue->ptrs_symbols, + .pdu_bit_map = pusch_pdu->pdu_bit_map, + .transform_precoding = pusch_pdu->transform_precoding, + .bwp_start = pusch_pdu->bwp_start, + .start_rb = start_rb, + .nb_rb = nb_rb, + .start_symbol = start_symbol, + .num_symbols = number_of_symbols, + .dmrs_type = dmrs_type, + .delta = delta, + .num_cdm_no_data = cdm_grps_no_data}; - uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb) * ((dmrs_type == pusch_dmrs_type1) ? 6 : 4); - c16_t mod_dmrs[n_dmrs] __attribute((aligned(16))); - c16_t mod_dmrs_amp[n_dmrs] __attribute((aligned(16))); + map_symbols(params, slot, dmrs_seq, data, tx_precoding[nl]); - c16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation - c16_t mod_ptrs_amp[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation - - if ((ul_dmrs_symb_pos >> l) & 0x01) { - is_dmrs_sym = 1; - - if (pusch_pdu->transform_precoding == transformPrecoder_disabled){ - - if (dmrs_type == pusch_dmrs_type1) - dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6; - else - dmrs_idx = (pusch_pdu->bwp_start + start_rb)*4; - - // TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part - // Perform this on gold sequence, not required when SC FDMA operation is done, - LOG_D(PHY,"DMRS in symbol %d\n",l); - const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL, - frame_parms->symbols_per_slot, - pusch_pdu->ul_dmrs_scrambling_id, - pusch_pdu->scid, - slot, - l); - nr_modulation(gold, - n_dmrs * 2, - DMRS_MOD_ORDER, - (int16_t *)mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated - - const int tmp = Wt[l_prime[0]] * Wf[k_prime] * AMP; - //todo: mult only needed - multadd_complex_vector_real_scalar((int16_t*)mod_dmrs,tmp,(int16_t*)mod_dmrs_amp,1,n_dmrs*2); - } else { - dmrs_idx = 0; - } - } else if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - - AssertFatal(pusch_pdu->transform_precoding == transformPrecoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); - - if(is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) { - is_ptrs_sym = 1; - const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL, - frame_parms->symbols_per_slot, - pusch_pdu->ul_dmrs_scrambling_id, - pusch_pdu->scid, - slot, - l); - nr_modulation(gold, nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs); - const uint16_t beta_ptrs = 1; // temp value until power control is implemented - multadd_complex_vector_real_scalar((int16_t*)mod_ptrs,beta_ptrs*AMP,(int16_t*)mod_ptrs_amp,1,nb_rb); - } - } - - for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) { - uint8_t is_dmrs = 0; - uint8_t is_ptrs = 0; - - sample_offsetF = l*frame_parms->ofdm_symbol_size + k; - - if (is_dmrs_sym) { - if (k == ((start_sc+get_dmrs_freq_idx_ul(n, k_prime, delta, dmrs_type))%frame_parms->ofdm_symbol_size)) - is_dmrs = 1; - } else if (is_ptrs_sym) { - is_ptrs = is_ptrs_subcarrier(k, - rnti, - K_ptrs, - nb_rb, - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset, - start_sc, - frame_parms->ofdm_symbol_size); - } - - if (is_dmrs == 1) { - // if transform precoding is enabled - const int tmp = Wt[l_prime[0]] * Wf[k_prime] * AMP; - if (pusch_pdu->transform_precoding == transformPrecoder_enabled) - tx_precoding[nl][sample_offsetF] = c16mulRealShift(dmrs_seq[dmrs_idx], tmp, 15); - else - tx_precoding[nl][sample_offsetF] = mod_dmrs_amp[dmrs_idx]; - -#ifdef DEBUG_PUSCH_MAPPING - printf("DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n", - nl, - dmrs_idx, - l, - k, - k_prime, - n, - tx_precoding[nl][sample_offsetF].r, - tx_precoding[nl][sample_offsetF].i); -#endif - - dmrs_idx++; - k_prime++; - k_prime &= 1; - n += (k_prime) ? 0 : 1; - - } else if (is_ptrs == 1) { - tx_precoding[nl][sample_offsetF] = mod_ptrs_amp[ptrs_idx]; - ptrs_idx++; - } else if (!is_dmrs_sym - || allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) { - if (pusch_pdu->transform_precoding == transformPrecoder_disabled) - tx_precoding[nl][sample_offsetF] = tx_layers[nl][m]; - else - tx_precoding[nl][sample_offsetF] = y[m]; - -#ifdef DEBUG_PUSCH_MAPPING - printf("DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n", - nl, - m, - l, - k, - tx_precoding[nl][sample_offsetF].r, - tx_precoding[nl][sample_offsetF].i); -#endif - - m++; - - } else { - tx_precoding[nl][sample_offsetF] = (c16_t){0}; - } - - if (++k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; - } // for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) - } // for (l=start_symbol; lofdm_symbol_size + k; - txdataF[ap][re_offset] = nr_layer_precoder(encoded_length, tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset); + txdataF[ap][re_offset] = nr_layer_precoder(slot_sz, tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset); if (++k >= frame_parms->ofdm_symbol_size) { k -= frame_parms->ofdm_symbol_size; } diff --git a/openair1/PHY/TOOLS/cmult_sv.c b/openair1/PHY/TOOLS/cmult_sv.c index b1c9de34ba..27aaf92c14 100644 --- a/openair1/PHY/TOOLS/cmult_sv.c +++ b/openair1/PHY/TOOLS/cmult_sv.c @@ -24,6 +24,18 @@ #include #include +void mult_real_vector_single_vector(const c16_t *x, const int16_t *alpha, c16_t *y, const unsigned int N) +{ + const simd_q15_t *alpha_128 = (const simd_q15_t *)alpha; + const simd_q15_t *x_128 = (const simd_q15_t *)x; + simd_q15_t *y_128 = (simd_q15_t *)y; + const unsigned int num_adds = (N + 3) / 4; // ceil(N/4) + + for (uint_fast32_t n = 0; n < num_adds; n++) { + y_128[n] = mulhi_int16(x_128[n], *alpha_128); + } +} + void multadd_complex_vector_real_scalar(int16_t *x, int16_t alpha, int16_t *y, @@ -35,19 +47,20 @@ void multadd_complex_vector_real_scalar(int16_t *x, int n; alpha_128 = set1_int16(alpha); + const uint32_t num_adds = (N + 3) / 4; // ceil(N/4) - if (zero_flag == 1) - for (n=0; n>2; n++) { - // print_shorts("x_128[n]=", &x_128[n]); - // print_shorts("alpha_128", &alpha_128); + if (zero_flag == 1) { + for (n = 0; n < num_adds; n++) { + // print_shorts("x_128[n]=", &x_128[n]); + // print_shorts("alpha_128", &alpha_128); y_128[n] = mulhi_int16(x_128[n],alpha_128); // print_shorts("y_128[n]=", &y_128[n]); } - - else - for (n=0; n>2; n++) { + } else { + for (n = 0; n < num_adds; n++) { y_128[n] = adds_int16(y_128[n],mulhi_int16(x_128[n],alpha_128)); } + } simde_mm_empty(); simde_m_empty(); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index aa57627362..dc4c34b181 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -52,6 +52,9 @@ extern "C" { #endif +#define ALIGNARRAYSIZE(a, b) (((a + b - 1) / b) * b) +#define ALNARS_16_4(a) ALIGNARRAYSIZE(a, 4) + typedef struct complexd { double r; double i; @@ -821,6 +824,8 @@ double interp(double x, double *xs, double *ys, int count); void simde_mm128_separate_real_imag_parts(simde__m128i *out_re, simde__m128i *out_im, simde__m128i in0, simde__m128i in1); void simde_mm256_separate_real_imag_parts(simde__m256i *out_re, simde__m256i *out_im, simde__m256i in0, simde__m256i in1); +void mult_real_vector_single_vector(const c16_t *x, const int16_t *alpha, c16_t *y, const unsigned int N); + #ifdef __cplusplus } #endif diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 5403bedbf7..6720f5ab14 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1421,17 +1421,6 @@ int main(int argc, char *argv[]) errors_decoding++; } } - if (n_trials == 1) { - for (int r = 0; r < UE->ul_harq_processes[harq_pid].C; r++) - for (int i = 0; i < UE->ul_harq_processes[harq_pid].K >> 3; i++) { - if ((UE->ul_harq_processes[harq_pid].c[r][i] ^ ulsch_gNB->harq_process->c[r][i]) != 0) - printf("************"); - /*printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r, - i,UE->ul_harq_processes[harq_pid].c[r][i], - i,ulsch_gNB->harq_process->c[r][i], - UE->ul_harq_processes[harq_pid].c[r][i]^ulsch_gNB->harq_process->c[r][i]);*/ - } - } if (errors_decoding > 0 && error_flag == 0) { n_false_positive++; if (n_trials==1) From 26b3fcca3b25ea05e4d2bf12386432b17a328375 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 29 Aug 2024 11:13:33 -0400 Subject: [PATCH 05/10] Remove SIMD operation for DMRS amplitude scaling There was concern that someone in the future might call the function with the wrong inputs. So, based on the discussion on the MR below https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/2916#note_132506 the SIMD for multiplying DMRS vector with amplitude is removed and is now done with plain C (no SIMD). The execution time for the function dmrs_amp_mult() in this commit is 10x higher that the previous commit. --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 21 ++++++++++----------- openair1/PHY/TOOLS/cmult_sv.c | 12 ------------ openair1/PHY/TOOLS/tools_defs.h | 2 -- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index b8c9b57410..5eb4d4b2e8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -386,18 +386,17 @@ static void dmrs_amp_mult(const uint32_t dmrs_port, const uint32_t n_dmrs, const pusch_dmrs_type_t dmrs_type) { - /* - A short array that holds amplitude values used for - multiplying with the modulated DMRS vector in 128bit SIMD. - */ - int16_t alpha_dmrs[8] __attribute((aligned(16))); - for (int_fast8_t i = 0; i < sizeofArray(alpha_dmrs) / 2; i++) { - const int16_t a = Wf[i % 2] * Wt * AMP; - alpha_dmrs[2 * i] = a; // multiplier for real part of DMRS symbol - alpha_dmrs[2 * i + 1] = a; // multiplier for img part of DMRS symbol + /* short array that hold amplitude for k_prime = 0 and k_prime = 1 */ + int32_t alpha_dmrs[2] __attribute((aligned(16))); + for (int_fast8_t i = 0; i < sizeofArray(alpha_dmrs); i++) { + const int32_t a = Wf[i] * Wt * AMP; + alpha_dmrs[i] = a; + } + + /* multiply amplitude with complex DMRS vector */ + for (int_fast16_t i = 0; i < n_dmrs; i++) { + mod_dmrs_out[i] = c16mulRealShift(mod_dmrs[i], alpha_dmrs[i % 2], 15); } - /* multiply mod_dmrs with alpha_dmrs in 4 symbol patches */ - mult_real_vector_single_vector(mod_dmrs, alpha_dmrs, mod_dmrs_out, n_dmrs); } /* diff --git a/openair1/PHY/TOOLS/cmult_sv.c b/openair1/PHY/TOOLS/cmult_sv.c index 27aaf92c14..ea567b0de1 100644 --- a/openair1/PHY/TOOLS/cmult_sv.c +++ b/openair1/PHY/TOOLS/cmult_sv.c @@ -24,18 +24,6 @@ #include #include -void mult_real_vector_single_vector(const c16_t *x, const int16_t *alpha, c16_t *y, const unsigned int N) -{ - const simd_q15_t *alpha_128 = (const simd_q15_t *)alpha; - const simd_q15_t *x_128 = (const simd_q15_t *)x; - simd_q15_t *y_128 = (simd_q15_t *)y; - const unsigned int num_adds = (N + 3) / 4; // ceil(N/4) - - for (uint_fast32_t n = 0; n < num_adds; n++) { - y_128[n] = mulhi_int16(x_128[n], *alpha_128); - } -} - void multadd_complex_vector_real_scalar(int16_t *x, int16_t alpha, int16_t *y, diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index dc4c34b181..d219760586 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -824,8 +824,6 @@ double interp(double x, double *xs, double *ys, int count); void simde_mm128_separate_real_imag_parts(simde__m128i *out_re, simde__m128i *out_im, simde__m128i in0, simde__m128i in1); void simde_mm256_separate_real_imag_parts(simde__m256i *out_re, simde__m256i *out_im, simde__m256i in0, simde__m256i in1); -void mult_real_vector_single_vector(const c16_t *x, const int16_t *alpha, c16_t *y, const unsigned int N); - #ifdef __cplusplus } #endif From f5d22ab85ac80ba5feaf75a935d3392f2159fd14 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 20 Aug 2024 11:56:53 -0400 Subject: [PATCH 06/10] Gracefully exit PUSCH proc if encoding fails --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 5eb4d4b2e8..0a420526de 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -612,8 +612,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, .oob_event_value = 0}; trace_pdu(&tmp); - if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1) + if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1) { + NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid]; + harq_process_ulsch->ULstatus = SCH_IDLE; return; + } /////////// //////////////////////////////////////////////////////////////////// From 28b2de5ac99c76e09821699250e4f5710f62a70d Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 29 Aug 2024 15:20:06 -0400 Subject: [PATCH 07/10] Add comments to the new RE mapping functions Use the new struct as function argument instead of individual parameters --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 170 +++++++++++---------- 1 file changed, 89 insertions(+), 81 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 0a420526de..6a2ce2ea48 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -195,8 +195,9 @@ static void map_data_rb(const c16_t *data, c16_t *out) } /* -This function is used for a PRB which has the DC subcarrier -that is not first subcarrier. +This function is used when a PRB is on both sides of DC. +The destination buffer in this case in not contiguous so REs are mapped on to a temporary buffer +so that we can reuse the existing functions. Then it is copied to the destination buffer. */ static void map_over_dc(const unsigned int right_dc, const unsigned int fft_size, @@ -214,7 +215,7 @@ static void map_over_dc(const unsigned int right_dc, c16_t *out_tmp = *out; c16_t tmp_out_buf[NR_NB_SC_PER_RB]; const unsigned int left_dc = NR_NB_SC_PER_RB - right_dc; - /* copy out to temp buffer */ + /* copy out to temp buffer. incase we want to preserve the REs in the out buffer. */ memcpy(tmp_out_buf, out_tmp, sizeof(c16_t) * left_dc); out_tmp -= (fft_size - left_dc); memcpy(tmp_out_buf + left_dc, out_tmp, sizeof(c16_t) * right_dc); @@ -251,33 +252,63 @@ static void map_over_dc(const unsigned int right_dc, } /* -Map all REs in one OFDM symbol +Holds params needed for PUSCH resoruce mapping */ -static void map_current_symbol(const rnti_t rnti, - const unsigned int K_ptrs, - const unsigned int k_RE_ref, - const unsigned int nb_rb, - const unsigned int bwp_start, - const unsigned int start_rb, - const unsigned int first_sc_offset, - const pusch_dmrs_type_t dmrs_type, - const unsigned int fft_size, +typedef struct { + rnti_t rnti; + unsigned int K_ptrs; + unsigned int k_RE_ref; + unsigned int first_sc_offset; + unsigned int fft_size; + unsigned int num_rb_max; + unsigned int symbols_per_slot; + unsigned int slot; + unsigned int dmrs_scrambling_id; + unsigned int scid; + unsigned int dmrs_port; + int Wt; + int *Wf; + unsigned int dmrs_symb_pos; + unsigned int ptrs_symb_pos; + unsigned int pdu_bit_map; + transformPrecoder_t transform_precoding; + unsigned int bwp_start; + unsigned int start_rb; + unsigned int nb_rb; + unsigned int start_symbol; + unsigned int num_symbols; + pusch_dmrs_type_t dmrs_type; + unsigned int delta; + unsigned int num_cdm_no_data; +} nr_phy_pxsch_params_t; + +/* +Map all REs in one OFDM symbol +This function operation is as follows: +> Computes the number of RB (stop_rb) below DC. (necessarily not below DC as the start_rb can be above DC) +> Maps REs in the RBs below DC. +> We call map_over_dc which + > maps the REs if a RB sits on both sides of DC & increments pointers else, + > it just increments the pointer +> If there are more RBs to map (nb_rb != stop_rb) i.e, RB above DC then those are mapped +*/ +static void map_current_symbol(const nr_phy_pxsch_params_t p, const bool dmrs_symbol, const bool ptrs_symbol, const c16_t *dmrs_seq, const c16_t *ptrs_seq, - const unsigned int delta, const c16_t **data, c16_t *out) { - const unsigned int abs_start_rb = bwp_start + start_rb; - const unsigned int start_sc = (first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % fft_size; - const bool cross_dc = start_sc + nb_rb * NR_NB_SC_PER_RB > fft_size; - const unsigned int rb_over_dc = cross_dc ? (fft_size - start_sc) % NR_NB_SC_PER_RB : 0; - const unsigned int stop_rb = cross_dc ? (fft_size - start_sc) / NR_NB_SC_PER_RB : nb_rb; + const unsigned int abs_start_rb = p.bwp_start + p.start_rb; + const unsigned int start_sc = (p.first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % p.fft_size; + const bool cross_dc = start_sc + p.nb_rb * NR_NB_SC_PER_RB > p.fft_size; + const unsigned int rb_over_dc = cross_dc ? (p.fft_size - start_sc) % NR_NB_SC_PER_RB : 0; + const unsigned int stop_rb = cross_dc ? (p.fft_size - start_sc) / NR_NB_SC_PER_RB : p.nb_rb; const c16_t *data_tmp = *data; + /* If current symbol is DMRS symbol */ if (dmrs_symbol) { - const unsigned int dmrs_per_rb = (dmrs_type == pusch_dmrs_type1) ? 6 : 4; + const unsigned int dmrs_per_rb = (p.dmrs_type == pusch_dmrs_type1) ? 6 : 4; const unsigned int data_per_rb = NR_NB_SC_PER_RB - dmrs_per_rb; const c16_t *p_mod_dmrs = dmrs_seq + abs_start_rb * dmrs_per_rb; @@ -285,19 +316,29 @@ static void map_current_symbol(const rnti_t rnti, unsigned int rb = 0; /* map below/above DC */ for (; rb < stop_rb; rb++) { - map_dmrs_ptr(delta, p_mod_dmrs, out_tmp); + map_dmrs_ptr(p.delta, p_mod_dmrs, out_tmp); p_mod_dmrs += dmrs_per_rb; out_tmp += NR_NB_SC_PER_RB; } + /* if start_rb is above DC or if stop_rb == nb_rb, + every RB is mapped at this point and the following code does nothing + */ + /* map RB at DC */ - map_over_dc(rb_over_dc, fft_size, dmrs_per_rb, data_per_rb, delta, 0, &rb, NULL, &p_mod_dmrs, NULL, &out_tmp); + /* if a RB is on both sides of DC, the following function handles it. + if not, then it just increaments the pointer incase there are more RBs above DC. + */ + map_over_dc(rb_over_dc, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, &rb, NULL, &p_mod_dmrs, NULL, &out_tmp); + /* map above DC */ - for (; rb < nb_rb; rb++) { - map_dmrs_ptr(delta, p_mod_dmrs, out_tmp); + /* if there are more RBs, they are mapped in the following part */ + for (; rb < p.nb_rb; rb++) { + map_dmrs_ptr(p.delta, p_mod_dmrs, out_tmp); p_mod_dmrs += dmrs_per_rb; out_tmp += NR_NB_SC_PER_RB; } + /* if there is data in current DMRS symbol, we map it here. */ if (map_data_dmrs_ptr) { c16_t *out_tmp = out + start_sc; unsigned int rb = 0; @@ -306,46 +347,52 @@ static void map_current_symbol(const rnti_t rnti, data_tmp += data_per_rb; out_tmp += NR_NB_SC_PER_RB; } - map_over_dc(rb_over_dc, fft_size, dmrs_per_rb, data_per_rb, delta, 0, &rb, NULL, &p_mod_dmrs, &data_tmp, &out_tmp); - for (; rb < nb_rb; rb++) { + map_over_dc(rb_over_dc, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, &rb, NULL, &p_mod_dmrs, &data_tmp, &out_tmp); + for (; rb < p.nb_rb; rb++) { map_data_dmrs_ptr(data_tmp, out_tmp); data_tmp += data_per_rb; out_tmp += NR_NB_SC_PER_RB; } } + /* If current symbol is a PTRS symbol */ } else if (ptrs_symbol) { - const unsigned int first_ptrs_re = get_first_ptrs_re(rnti, K_ptrs, nb_rb, k_RE_ref) + start_sc; - const unsigned int ptrs_idx_re = (start_sc - first_ptrs_re) % NR_NB_SC_PER_RB; - unsigned int ptrs_idx_rb = (start_sc - first_ptrs_re) / NR_NB_SC_PER_RB; + const unsigned int first_ptrs_re = get_first_ptrs_re(p.rnti, p.K_ptrs, p.nb_rb, p.k_RE_ref) + start_sc; + const unsigned int ptrs_idx_re = (start_sc - first_ptrs_re) % NR_NB_SC_PER_RB; // PTRS RE index within RB + unsigned int ptrs_idx_rb = (start_sc - first_ptrs_re) / NR_NB_SC_PER_RB; // number of RBs before the first PTRS RB unsigned int rb = 0; c16_t *out_tmp = out + start_sc; + /* map data to RBs before the first PTRS RB */ for (; rb < ptrs_idx_rb; rb++) { map_data_rb(data_tmp, out); data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; } const c16_t *p_mod_ptrs = ptrs_seq; - ptrs_idx_rb = 0; + ptrs_idx_rb = 0; // RB count to check for PTRS RB + /* we start to map remaining RB here */ for (; rb < stop_rb; rb++) { - if (ptrs_idx_rb % K_ptrs) { + if (ptrs_idx_rb % p.K_ptrs) { // if current RB does not contain PTRS map_data_rb(data_tmp, out_tmp); data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; - } else { + } else { // if current RB contains PTRS map_data_ptrs(ptrs_idx_re, data_tmp, p_mod_ptrs, out_tmp); - p_mod_ptrs++; + p_mod_ptrs++; // increament once as only one PTRS RE per RB data_tmp += (NR_NB_SC_PER_RB - 1); out_tmp += NR_NB_SC_PER_RB; } ptrs_idx_rb++; } - if (ptrs_idx_rb % K_ptrs) { - map_over_dc(rb_over_dc, fft_size, 0, 0, delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); + if (ptrs_idx_rb % p.K_ptrs) { + /* if not a PTRS RB set mod_ptrs to NULL in function arg */ + map_over_dc(rb_over_dc, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); } else { - map_over_dc(rb_over_dc, fft_size, 0, 0, delta, ptrs_idx_re, &rb, &p_mod_ptrs, NULL, &data_tmp, &out_tmp); + /* if a PTRS RB set valid mod_ptrs pointer */ + map_over_dc(rb_over_dc, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &rb, &p_mod_ptrs, NULL, &data_tmp, &out_tmp); } - for (; rb < nb_rb; rb++) { - if (ptrs_idx_rb % K_ptrs) { + /* map remaining RBs above DC */ + for (; rb < p.nb_rb; rb++) { + if (ptrs_idx_rb % p.K_ptrs) { map_data_rb(data_tmp, out_tmp); data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; @@ -358,6 +405,7 @@ static void map_current_symbol(const rnti_t rnti, ptrs_idx_rb++; } } else { + /* only data in this symbol */ unsigned int rb = 0; c16_t *out_tmp = out + start_sc; for (; rb < stop_rb; rb++) { @@ -365,8 +413,8 @@ static void map_current_symbol(const rnti_t rnti, data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; } - map_over_dc(rb_over_dc, fft_size, 0, 0, delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); - for (; rb < nb_rb; rb++) { + map_over_dc(rb_over_dc, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); + for (; rb < p.nb_rb; rb++) { map_data_rb(data_tmp, out_tmp); data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; @@ -399,37 +447,6 @@ static void dmrs_amp_mult(const uint32_t dmrs_port, } } -/* -Holds params needed for PUSCH resoruce mapping -*/ -typedef struct { - rnti_t rnti; - unsigned int K_ptrs; - unsigned int k_RE_ref; - unsigned int first_sc_offset; - unsigned int fft_size; - unsigned int num_rb_max; - unsigned int symbols_per_slot; - unsigned int slot; - unsigned int dmrs_scrambling_id; - unsigned int scid; - unsigned int dmrs_port; - int Wt; - int *Wf; - unsigned int dmrs_symb_pos; - unsigned int ptrs_symb_pos; - unsigned int pdu_bit_map; - transformPrecoder_t transform_precoding; - unsigned int bwp_start; - unsigned int start_rb; - unsigned int nb_rb; - unsigned int start_symbol; - unsigned int num_symbols; - pusch_dmrs_type_t dmrs_type; - unsigned int delta; - unsigned int num_cdm_no_data; -} nr_phy_pxsch_params_t; - /* Map ULSCH data and DMRS in all of the scheduled symbols and PRBs */ @@ -483,20 +500,11 @@ static void map_symbols(const nr_phy_pxsch_params_t p, const unsigned int beta_ptrs = 1; // temp value until power control is implemented multadd_complex_vector_real_scalar((int16_t *)mod_ptrs, beta_ptrs * AMP, (int16_t *)mod_ptrs_amp, 1, p.nb_rb); } - map_current_symbol(p.rnti, - p.K_ptrs, - p.k_RE_ref, - p.nb_rb, - p.bwp_start, - p.start_rb, - p.first_sc_offset, - p.dmrs_type, - p.fft_size, + map_current_symbol(p, dmrs_symbol, ptrs_symbol, mod_dmrs_amp, mod_ptrs_amp, - p.delta, &cur_data, // increments every symbol out + l * p.fft_size); } From e4c37fb3b2a16897d1bcbc173e1bc631b1f6cfd3 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 12 Sep 2024 11:27:50 -0400 Subject: [PATCH 08/10] Simplify data in DMRS symbol function Mapping of data REs in DMRS symbol depends only on number of CDM group no data. So the special case function that depended on delta is removed and a single function is used. --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 103 +++++++++++---------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 6a2ce2ea48..82d3321e3f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -91,7 +91,7 @@ all symbols based on different parameters. Then the mapping is done for each symbol by calling the function pointers. */ static void (*map_dmrs_ptr)(const unsigned int, const c16_t *, c16_t *); -static void (*map_data_dmrs_ptr)(const c16_t *, c16_t *); +static void (*map_data_dmrs_ptr)(const unsigned int num_cdm_no_data, const c16_t *, c16_t *); /* The following set of functions map dmrs and/or data REs in one RB based on @@ -117,7 +117,7 @@ static void map_dmrs_type1_cdm1_rb(const unsigned int delta, const c16_t *dmrs, Data in DMRS symbol for Type 1, NumCDMGroupNoData = 1 and delta 0 (antenna port 0 and 1). There is no data in DMRS symbol for other scenarios in type 1. */ -static void map_data_dmrs_type1_cdm1_rb(const c16_t *data, c16_t *out) +static void map_data_dmrs_type1_cdm1_rb(const unsigned int num_cdm_no_data, const c16_t *data, c16_t *out) { *(out + 1) = *data++; *(out + 3) = *data++; @@ -143,36 +143,16 @@ static void map_dmrs_type2_rb(const unsigned int delta, const c16_t *dmrs, c16_t } /* -Map data if type 2, delta 0 NumCDMGrpNoData 1. +Map data for type 2 DMRS */ -static void map_data_dmrs_type2_rb_f1(const c16_t *data, c16_t *out) +static void map_data_dmrs_type2_rb(const unsigned int num_cdm_no_data, const c16_t *data, c16_t *out) { - memcpy(out + NR_DMRS_TYPE2_CDM_GRP_SIZE, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE * 2); - out += NR_DMRS_TYPE2_CDM_GRP_SIZE * 4; - data += NR_DMRS_TYPE2_CDM_GRP_SIZE * 2; - memcpy(out, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE * 2); -} - -/* -Map data if type 2, delta (0, 2) NumCDMGrpNoData 2, or delta 2 NumCDMGrpNoData 1. -*/ -static void map_data_dmrs_type2_rb_f2(const c16_t *data, c16_t *out) -{ - memcpy(out + NR_DMRS_TYPE2_CDM_GRP_SIZE * 2, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); - out += NR_DMRS_TYPE2_CDM_GRP_SIZE * 5; - data += NR_DMRS_TYPE2_CDM_GRP_SIZE; - memcpy(out, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); -} - -/* -Map data if type 2, delta 4 NumCDMGrpNoData 1. -*/ -static void map_data_dmrs_type2_rb_f3(const c16_t *data, c16_t *out) -{ - memcpy(out + NR_DMRS_TYPE2_CDM_GRP_SIZE, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); - out += NR_DMRS_TYPE2_CDM_GRP_SIZE * 4; - data += NR_DMRS_TYPE2_CDM_GRP_SIZE; - memcpy(out, data, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); + unsigned int offset = num_cdm_no_data * NR_DMRS_TYPE2_CDM_GRP_SIZE; + const unsigned int size = (NR_DMRS_TYPE2_NUM_CDM_GRP - num_cdm_no_data) * NR_DMRS_TYPE2_CDM_GRP_SIZE; + memcpy(out + offset, data, sizeof(c16_t) * size); + offset += NR_DMRS_TYPE2_CDM_GRP_SIZE * NR_DMRS_TYPE2_NUM_CDM_GRP; + data += size; + memcpy(out + offset, data, sizeof(c16_t) * size); } /* @@ -200,6 +180,7 @@ The destination buffer in this case in not contiguous so REs are mapped on to a so that we can reuse the existing functions. Then it is copied to the destination buffer. */ static void map_over_dc(const unsigned int right_dc, + const unsigned int num_cdm_no_data, const unsigned int fft_size, const unsigned int dmrs_per_rb, const unsigned int data_per_rb, @@ -222,7 +203,7 @@ static void map_over_dc(const unsigned int right_dc, /* map on to temp buffer */ if (dmrs && data) { - map_data_dmrs_ptr(*data, tmp_out_buf); + map_data_dmrs_ptr(num_cdm_no_data, *data, tmp_out_buf); *data += data_per_rb; } else if (dmrs) { map_dmrs_ptr(delta, *dmrs, tmp_out_buf); @@ -328,7 +309,18 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, /* if a RB is on both sides of DC, the following function handles it. if not, then it just increaments the pointer incase there are more RBs above DC. */ - map_over_dc(rb_over_dc, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, &rb, NULL, &p_mod_dmrs, NULL, &out_tmp); + map_over_dc(rb_over_dc, + p.num_cdm_no_data, + p.fft_size, + dmrs_per_rb, + data_per_rb, + p.delta, + 0, + &rb, + NULL, + &p_mod_dmrs, + NULL, + &out_tmp); /* map above DC */ /* if there are more RBs, they are mapped in the following part */ @@ -343,13 +335,24 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, c16_t *out_tmp = out + start_sc; unsigned int rb = 0; for (; rb < stop_rb; rb++) { - map_data_dmrs_ptr(data_tmp, out_tmp); + map_data_dmrs_ptr(p.num_cdm_no_data, data_tmp, out_tmp); data_tmp += data_per_rb; out_tmp += NR_NB_SC_PER_RB; } - map_over_dc(rb_over_dc, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, &rb, NULL, &p_mod_dmrs, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, + p.num_cdm_no_data, + p.fft_size, + dmrs_per_rb, + data_per_rb, + p.delta, + 0, + &rb, + NULL, + &p_mod_dmrs, + &data_tmp, + &out_tmp); for (; rb < p.nb_rb; rb++) { - map_data_dmrs_ptr(data_tmp, out_tmp); + map_data_dmrs_ptr(p.num_cdm_no_data, data_tmp, out_tmp); data_tmp += data_per_rb; out_tmp += NR_NB_SC_PER_RB; } @@ -385,10 +388,21 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, } if (ptrs_idx_rb % p.K_ptrs) { /* if not a PTRS RB set mod_ptrs to NULL in function arg */ - map_over_dc(rb_over_dc, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, p.num_cdm_no_data, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); } else { /* if a PTRS RB set valid mod_ptrs pointer */ - map_over_dc(rb_over_dc, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &rb, &p_mod_ptrs, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, + p.num_cdm_no_data, + p.fft_size, + 0, + 0, + p.delta, + ptrs_idx_re, + &rb, + &p_mod_ptrs, + NULL, + &data_tmp, + &out_tmp); } /* map remaining RBs above DC */ for (; rb < p.nb_rb; rb++) { @@ -413,7 +427,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; } - map_over_dc(rb_over_dc, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, p.num_cdm_no_data, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); for (; rb < p.nb_rb; rb++) { map_data_rb(data_tmp, out_tmp); data_tmp += NR_NB_SC_PER_RB; @@ -459,19 +473,10 @@ static void map_symbols(const nr_phy_pxsch_params_t p, // asign the function pointers if (p.dmrs_type == pusch_dmrs_type1) { map_dmrs_ptr = map_dmrs_type1_cdm1_rb; - map_data_dmrs_ptr = (p.delta == 0 && p.num_cdm_no_data == 1) ? map_data_dmrs_type1_cdm1_rb : NULL; + map_data_dmrs_ptr = (p.num_cdm_no_data == 1) ? map_data_dmrs_type1_cdm1_rb : NULL; } else { map_dmrs_ptr = map_dmrs_type2_rb; - if (p.delta == 0 && p.num_cdm_no_data == 1) { - map_data_dmrs_ptr = map_data_dmrs_type2_rb_f1; - } else if ((p.delta == 0 && p.num_cdm_no_data == 2) || (p.delta == 2 && p.num_cdm_no_data == 2) - || (p.delta == 2 && p.num_cdm_no_data == 1)) { - map_data_dmrs_ptr = map_data_dmrs_type2_rb_f2; - } else if (p.delta == 4 && p.num_cdm_no_data == 1) { - map_data_dmrs_ptr = map_data_dmrs_type2_rb_f3; - } else { // no data in DMRS symbols for other combinations - map_data_dmrs_ptr = NULL; - } + map_data_dmrs_ptr = (p.num_cdm_no_data < 3) ? map_data_dmrs_type2_rb : NULL; } // for all symbols const unsigned int n_dmrs = (p.bwp_start + p.start_rb + p.nb_rb) * ((p.dmrs_type == pusch_dmrs_type1) ? 6 : 4); From a50cb354f47d2664738bd5faaf74ab4996467e81 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 12 Sep 2024 12:57:54 -0400 Subject: [PATCH 09/10] Simplify map_current_symbol() function --- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 244 ++++++++------------- 1 file changed, 95 insertions(+), 149 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 82d3321e3f..bef7724e5d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -102,6 +102,7 @@ applicable. /* DMRS mapping in a RB for Type 1. +Mapping as in TS 38.211 6.4.1.1.3 k = 4n + 2k^prime + delta */ static void map_dmrs_type1_cdm1_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out) { @@ -132,8 +133,8 @@ static void map_data_dmrs_type1_cdm1_rb(const unsigned int num_cdm_no_data, cons /* Map DMRS for type 2 +Mapping as in TS 38.211 6.4.1.1.3 k = 6n + k^prime + delta */ - static void map_dmrs_type2_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out) { memcpy(out + delta, dmrs, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE); @@ -186,50 +187,50 @@ static void map_over_dc(const unsigned int right_dc, const unsigned int data_per_rb, const unsigned int delta, const unsigned int ptrsIdx, - unsigned int *rb, const c16_t **ptrs, const c16_t **dmrs, const c16_t **data, c16_t **out) { - if (right_dc) { - c16_t *out_tmp = *out; - c16_t tmp_out_buf[NR_NB_SC_PER_RB]; - const unsigned int left_dc = NR_NB_SC_PER_RB - right_dc; - /* copy out to temp buffer. incase we want to preserve the REs in the out buffer. */ - memcpy(tmp_out_buf, out_tmp, sizeof(c16_t) * left_dc); - out_tmp -= (fft_size - left_dc); - memcpy(tmp_out_buf + left_dc, out_tmp, sizeof(c16_t) * right_dc); + // if first RE is DC no need to map in this function + if (right_dc == 0) + return; - /* map on to temp buffer */ - if (dmrs && data) { - map_data_dmrs_ptr(num_cdm_no_data, *data, tmp_out_buf); - *data += data_per_rb; - } else if (dmrs) { - map_dmrs_ptr(delta, *dmrs, tmp_out_buf); - *dmrs += dmrs_per_rb; - } else if (ptrs) { - map_data_ptrs(ptrsIdx, *data, *ptrs, tmp_out_buf); - *data += (NR_NB_SC_PER_RB - 1); - *ptrs += 1; - } else if (data) { - map_data_rb(*data, tmp_out_buf); - *data += NR_NB_SC_PER_RB; - } else { - DevAssert(false); - } + c16_t *out_tmp = *out; + c16_t tmp_out_buf[NR_NB_SC_PER_RB]; + const unsigned int left_dc = NR_NB_SC_PER_RB - right_dc; + /* copy out to temp buffer. incase we want to preserve the REs in the out buffer + as we call mapping of data in DMRS symbol after mapping DMRS REs + */ + memcpy(tmp_out_buf, out_tmp, sizeof(c16_t) * left_dc); + out_tmp -= (fft_size - left_dc); + memcpy(tmp_out_buf + left_dc, out_tmp, sizeof(c16_t) * right_dc); - /* copy back to out buffer */ - out_tmp = *out; - memcpy(out_tmp, tmp_out_buf, sizeof(c16_t) * left_dc); - out_tmp -= (fft_size - left_dc); - memcpy(out_tmp, tmp_out_buf + left_dc, sizeof(c16_t) * right_dc); - out_tmp += right_dc; - *out = out_tmp; - *rb += 1; + /* map on to temp buffer */ + if (dmrs && data) { + map_data_dmrs_ptr(num_cdm_no_data, *data, tmp_out_buf); + *data += data_per_rb; + } else if (dmrs) { + map_dmrs_ptr(delta, *dmrs, tmp_out_buf); + *dmrs += dmrs_per_rb; + } else if (ptrs) { + map_data_ptrs(ptrsIdx, *data, *ptrs, tmp_out_buf); + *data += (NR_NB_SC_PER_RB - 1); + *ptrs += 1; + } else if (data) { + map_data_rb(*data, tmp_out_buf); + *data += NR_NB_SC_PER_RB; } else { - *out = (*out) - fft_size; + DevAssert(false); } + + /* copy back to out buffer */ + out_tmp = *out; + memcpy(out_tmp, tmp_out_buf, sizeof(c16_t) * left_dc); + out_tmp -= (fft_size - left_dc); + memcpy(out_tmp, tmp_out_buf + left_dc, sizeof(c16_t) * right_dc); + out_tmp += right_dc; + *out = out_tmp; } /* @@ -266,12 +267,8 @@ typedef struct { /* Map all REs in one OFDM symbol This function operation is as follows: -> Computes the number of RB (stop_rb) below DC. (necessarily not below DC as the start_rb can be above DC) -> Maps REs in the RBs below DC. -> We call map_over_dc which - > maps the REs if a RB sits on both sides of DC & increments pointers else, - > it just increments the pointer -> If there are more RBs to map (nb_rb != stop_rb) i.e, RB above DC then those are mapped +mapping is done on RB basis. if RB contains DC and if DC is in middle +of the RB, then the mapping is done via map_over_dc(). */ static void map_current_symbol(const nr_phy_pxsch_params_t p, const bool dmrs_symbol, @@ -283,9 +280,9 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, { const unsigned int abs_start_rb = p.bwp_start + p.start_rb; const unsigned int start_sc = (p.first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % p.fft_size; - const bool cross_dc = start_sc + p.nb_rb * NR_NB_SC_PER_RB > p.fft_size; - const unsigned int rb_over_dc = cross_dc ? (p.fft_size - start_sc) % NR_NB_SC_PER_RB : 0; - const unsigned int stop_rb = cross_dc ? (p.fft_size - start_sc) / NR_NB_SC_PER_RB : p.nb_rb; + const unsigned int dc_rb = (p.fft_size - start_sc) / NR_NB_SC_PER_RB; + const unsigned int rb_over_dc = (p.fft_size - start_sc) % NR_NB_SC_PER_RB; + const unsigned int n_cdm = p.num_cdm_no_data; const c16_t *data_tmp = *data; /* If current symbol is DMRS symbol */ if (dmrs_symbol) { @@ -294,37 +291,18 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, const c16_t *p_mod_dmrs = dmrs_seq + abs_start_rb * dmrs_per_rb; c16_t *out_tmp = out + start_sc; - unsigned int rb = 0; - /* map below/above DC */ - for (; rb < stop_rb; rb++) { - map_dmrs_ptr(p.delta, p_mod_dmrs, out_tmp); - p_mod_dmrs += dmrs_per_rb; - out_tmp += NR_NB_SC_PER_RB; - } - /* if start_rb is above DC or if stop_rb == nb_rb, - every RB is mapped at this point and the following code does nothing - */ - - /* map RB at DC */ - /* if a RB is on both sides of DC, the following function handles it. - if not, then it just increaments the pointer incase there are more RBs above DC. - */ - map_over_dc(rb_over_dc, - p.num_cdm_no_data, - p.fft_size, - dmrs_per_rb, - data_per_rb, - p.delta, - 0, - &rb, - NULL, - &p_mod_dmrs, - NULL, - &out_tmp); - - /* map above DC */ - /* if there are more RBs, they are mapped in the following part */ - for (; rb < p.nb_rb; rb++) { + for (unsigned int rb = 0; rb < p.nb_rb; rb++) { + if (rb == dc_rb) { + // map RB at DC + if (rb_over_dc) { + // if DC is in middle of RB, the following function handles it. + map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, NULL, &out_tmp); + continue; + } else { + // else just move the pointer and following function will map the rb + out_tmp -= p.fft_size; + } + } map_dmrs_ptr(p.delta, p_mod_dmrs, out_tmp); p_mod_dmrs += dmrs_per_rb; out_tmp += NR_NB_SC_PER_RB; @@ -333,26 +311,16 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, /* if there is data in current DMRS symbol, we map it here. */ if (map_data_dmrs_ptr) { c16_t *out_tmp = out + start_sc; - unsigned int rb = 0; - for (; rb < stop_rb; rb++) { - map_data_dmrs_ptr(p.num_cdm_no_data, data_tmp, out_tmp); - data_tmp += data_per_rb; - out_tmp += NR_NB_SC_PER_RB; - } - map_over_dc(rb_over_dc, - p.num_cdm_no_data, - p.fft_size, - dmrs_per_rb, - data_per_rb, - p.delta, - 0, - &rb, - NULL, - &p_mod_dmrs, - &data_tmp, - &out_tmp); - for (; rb < p.nb_rb; rb++) { - map_data_dmrs_ptr(p.num_cdm_no_data, data_tmp, out_tmp); + for (unsigned int rb = 0; rb < p.nb_rb; rb++) { + if (rb == dc_rb) { + if (rb_over_dc) { + map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, &data_tmp, &out_tmp); + continue; + } else { + out_tmp -= p.fft_size; + } + } + map_data_dmrs_ptr(n_cdm, data_tmp, out_tmp); data_tmp += data_per_rb; out_tmp += NR_NB_SC_PER_RB; } @@ -361,24 +329,33 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, } else if (ptrs_symbol) { const unsigned int first_ptrs_re = get_first_ptrs_re(p.rnti, p.K_ptrs, p.nb_rb, p.k_RE_ref) + start_sc; const unsigned int ptrs_idx_re = (start_sc - first_ptrs_re) % NR_NB_SC_PER_RB; // PTRS RE index within RB - unsigned int ptrs_idx_rb = (start_sc - first_ptrs_re) / NR_NB_SC_PER_RB; // number of RBs before the first PTRS RB - unsigned int rb = 0; + unsigned int non_ptrs_rb = (start_sc - first_ptrs_re) / NR_NB_SC_PER_RB; // number of RBs before the first PTRS RB + int ptrs_idx_rb = -non_ptrs_rb; // RB count to check for PTRS RB c16_t *out_tmp = out + start_sc; - /* map data to RBs before the first PTRS RB */ - for (; rb < ptrs_idx_rb; rb++) { - map_data_rb(data_tmp, out); - data_tmp += NR_NB_SC_PER_RB; - out_tmp += NR_NB_SC_PER_RB; - } const c16_t *p_mod_ptrs = ptrs_seq; - ptrs_idx_rb = 0; // RB count to check for PTRS RB - /* we start to map remaining RB here */ - for (; rb < stop_rb; rb++) { - if (ptrs_idx_rb % p.K_ptrs) { // if current RB does not contain PTRS + /* map data to RBs before the first PTRS RB or if current RB has no PTRS */ + for (unsigned int rb = 0; rb < p.nb_rb; rb++) { + if (rb < non_ptrs_rb || ptrs_idx_rb % p.K_ptrs) { + if (rb == dc_rb) { + if (rb_over_dc) { + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp); + continue; + } else { + out_tmp -= p.fft_size; + } + } map_data_rb(data_tmp, out_tmp); data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; - } else { // if current RB contains PTRS + } else { + if (rb == dc_rb) { + if (rb_over_dc) { + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &p_mod_ptrs, NULL, &data_tmp, &out_tmp); + continue; + } else { + out_tmp -= p.fft_size; + } + } map_data_ptrs(ptrs_idx_re, data_tmp, p_mod_ptrs, out_tmp); p_mod_ptrs++; // increament once as only one PTRS RE per RB data_tmp += (NR_NB_SC_PER_RB - 1); @@ -386,49 +363,18 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, } ptrs_idx_rb++; } - if (ptrs_idx_rb % p.K_ptrs) { - /* if not a PTRS RB set mod_ptrs to NULL in function arg */ - map_over_dc(rb_over_dc, p.num_cdm_no_data, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); - } else { - /* if a PTRS RB set valid mod_ptrs pointer */ - map_over_dc(rb_over_dc, - p.num_cdm_no_data, - p.fft_size, - 0, - 0, - p.delta, - ptrs_idx_re, - &rb, - &p_mod_ptrs, - NULL, - &data_tmp, - &out_tmp); - } - /* map remaining RBs above DC */ - for (; rb < p.nb_rb; rb++) { - if (ptrs_idx_rb % p.K_ptrs) { - map_data_rb(data_tmp, out_tmp); - data_tmp += NR_NB_SC_PER_RB; - out_tmp += NR_NB_SC_PER_RB; - } else { - map_data_ptrs(ptrs_idx_re, data_tmp, p_mod_ptrs, out_tmp); - p_mod_ptrs++; - data_tmp += (NR_NB_SC_PER_RB - 1); - out_tmp += NR_NB_SC_PER_RB; - } - ptrs_idx_rb++; - } } else { /* only data in this symbol */ - unsigned int rb = 0; c16_t *out_tmp = out + start_sc; - for (; rb < stop_rb; rb++) { - map_data_rb(data_tmp, out_tmp); - data_tmp += NR_NB_SC_PER_RB; - out_tmp += NR_NB_SC_PER_RB; - } - map_over_dc(rb_over_dc, p.num_cdm_no_data, p.fft_size, 0, 0, p.delta, 0, &rb, NULL, NULL, &data_tmp, &out_tmp); - for (; rb < p.nb_rb; rb++) { + for (unsigned int rb = 0; rb < p.nb_rb; rb++) { + if (rb == dc_rb) { + if (rb_over_dc) { + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp); + continue; + } else { + out_tmp -= p.fft_size; + } + } map_data_rb(data_tmp, out_tmp); data_tmp += NR_NB_SC_PER_RB; out_tmp += NR_NB_SC_PER_RB; From 321a20ea787fccd15e18929a04e0e57a9394af05 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 19 Sep 2024 09:54:53 -0400 Subject: [PATCH 10/10] Fix vector mult function for out of bound access --- openair1/PHY/TOOLS/cmult_sv.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/TOOLS/cmult_sv.c b/openair1/PHY/TOOLS/cmult_sv.c index ea567b0de1..c20bd24f71 100644 --- a/openair1/PHY/TOOLS/cmult_sv.c +++ b/openair1/PHY/TOOLS/cmult_sv.c @@ -30,28 +30,30 @@ void multadd_complex_vector_real_scalar(int16_t *x, uint8_t zero_flag, uint32_t N) { - simd_q15_t alpha_128,*x_128=(simd_q15_t *)x,*y_128=(simd_q15_t*)y; int n; alpha_128 = set1_int16(alpha); - const uint32_t num_adds = (N + 3) / 4; // ceil(N/4) + const uint32_t num_simd_adds = N / 4; + const uint32_t num_adds = N % 4; if (zero_flag == 1) { - for (n = 0; n < num_adds; n++) { - // print_shorts("x_128[n]=", &x_128[n]); - // print_shorts("alpha_128", &alpha_128); + for (n = 0; n < num_simd_adds; n++) { y_128[n] = mulhi_int16(x_128[n],alpha_128); - // print_shorts("y_128[n]=", &y_128[n]); + } + for (n = 0; n < num_adds; n++) { + const uint32_t offset = num_simd_adds * 4; + y[offset + n] = (x[offset + n] * alpha) >> 16; } } else { - for (n = 0; n < num_adds; n++) { + for (n = 0; n < num_simd_adds; n++) { y_128[n] = adds_int16(y_128[n],mulhi_int16(x_128[n],alpha_128)); } + for (n = 0; n < num_adds; n++) { + const uint32_t offset = num_simd_adds * 4; + y[offset + n] += (x[offset + n] * alpha) >> 16; + } } - - simde_mm_empty(); - simde_m_empty(); } void multadd_real_vector_complex_scalar(const int16_t *x, const int16_t *alpha, int16_t *y, uint32_t N)