diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 21b564d3c2..1092545705 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -103,7 +103,8 @@ void nr_phy_init_RU(RU_t *ru) ru->common.txdataF_BF = (int32_t **)malloc16(nb_tx_streams * sizeof(int32_t*)); LOG_D(PHY, "[INIT] common.txdata_BF= %p (%lu bytes)\n", ru->common.txdataF_BF, nb_tx_streams * sizeof(int32_t *)); for (int i = 0; i < nb_tx_streams; i++) { - ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP * sizeof(int32_t)); + ru->common.txdataF_BF[i] = + (int32_t *)malloc16_clear(fp->samples_per_slot_wCP * sizeof(int32_t)); LOG_D(PHY, "txdataF_BF[%d] %p for RU %d\n", i, ru->common.txdataF_BF[i], ru->idx); } // allocate FFT output buffers (RX) diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 9e8ac3ba3c..fda32fa86f 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -105,6 +105,7 @@ void nr_beam_precoding(c16_t **txdataF, void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, c16_t *txdataF, + bool is_flat_buff, const c16_t *symbol_rotation, int slot, int nb_rb, @@ -161,4 +162,12 @@ void nr_layer_precoder_simd(const int n_layers, const int sc_offset, const int re_cnt, c16_t *txdataF_precoded); + +void fft_shift(const c16_t *in, + uint32_t in_symb_sz, + uint16_t num_prb, + c16_t *out, + uint16_t fft_size_out, + uint16_t start_symb, + uint16_t num_symb); #endif diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index c3311fb78a..8a31648605 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -288,6 +288,7 @@ void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_s void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, c16_t *txdataF, + bool is_flat_buff, const c16_t *symbol_rotation, int slot, int nb_rb, @@ -309,20 +310,39 @@ void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, this_rotation->r, this_rotation->i); - if (nb_rb & 1) { - rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - (nb_rb + 1) * 6, 15); - rotate_cpx_vector(this_symbol + fp->first_carrier_offset - 6, - this_rotation, - this_symbol + fp->first_carrier_offset - 6, - (nb_rb + 1) * 6, 15); - } else { - rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - nb_rb * 6, 15); - rotate_cpx_vector(this_symbol + fp->first_carrier_offset, - this_rotation, - this_symbol + fp->first_carrier_offset, - nb_rb * 6, 15); + if (is_flat_buff) + rotate_cpx_vector(this_symbol, this_rotation, this_symbol, nb_rb * NR_NB_SC_PER_RB, 15); + else { + c16_t *this_symbol_neg = this_symbol + fp->first_carrier_offset; + if (nb_rb & 1) { + this_symbol_neg -= 6; + nb_rb += 1; + } + rotate_cpx_vector(this_symbol, this_rotation, this_symbol, nb_rb * 6, 15); + rotate_cpx_vector(this_symbol_neg, this_rotation, this_symbol_neg, nb_rb * 6, 15); } } } + +/* Do FFT-shift for symbols in the provided in buffer and writes to out buffer. */ +void fft_shift(const c16_t *in, + uint32_t in_symb_sz, + uint16_t num_prb, + c16_t *out, + uint16_t fft_size_out, + uint16_t start_symb, + uint16_t num_symb) +{ + const int num_samp_half = num_prb * NR_NB_SC_PER_RB / 2; + const int first_carrier_offset = fft_size_out - num_samp_half; + for (int s = start_symb; s < start_symb + num_symb; s++) { + // Copy negative freq component + uint16_t out_offset = s * fft_size_out + first_carrier_offset; + uint16_t in_offset = s * in_symb_sz; + memcpy(out + out_offset, in + in_offset, num_samp_half * sizeof(int32_t)); + // Copy positive freq component + out_offset = s * fft_size_out; + in_offset = s * in_symb_sz + num_samp_half; + memcpy(out + out_offset, in + in_offset, num_samp_half * sizeof(int32_t)); + } +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index edb296e8a4..a4f5c80989 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -67,7 +67,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, if (pdcch_pdu_rel15->CoreSetType == 1) additional_offset = (pdcch_pdu_rel15->BWPStart + 5) / 6 * 6 - pdcch_pdu_rel15->BWPStart; int rb_offset = cset_start + additional_offset; - uint16_t cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; + uint16_t cset_start_sc = (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; int idx1 = pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols; int idx2 = (((n_rb + rb_offset + pdcch_pdu_rel15->BWPStart) * 3) + 15) & ~15; c16_t mod_dmrs[idx1][idx2] __attribute__((aligned(16))); @@ -179,8 +179,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, /// Resource mapping uint16_t amp = gNB->TX_AMP; c16_t *txdataF = gNB->common_vars.txdataF[beam_nb][0]; - if (cset_start_sc >= frame_parms->ofdm_symbol_size) - cset_start_sc -= frame_parms->ofdm_symbol_size; int num_regs = dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols; /*Mapping the encoded DCI along with the DMRS */ @@ -189,8 +187,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, for (int reg_count = 0; reg_count < num_regs; reg_count++) { int k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB; LOG_D(NR_PHY_DCI, "REG %d k %d\n", reg_list[d][reg_count], k); - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; int l = cset_start_symb + symbol_idx; @@ -226,9 +222,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, } k++; - - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; } // m } // reg_count } // symbol_idx diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index b09f816c7d..1edb590a58 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -86,8 +86,7 @@ static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, printf("k %d \t txdataF: %d %d\n", k, txF[k].r, txF[k].i); #endif } - if (++k >= symbol_sz) - k -= symbol_sz; + k++; } return in - tx_layer; } @@ -294,7 +293,7 @@ static inline int dmrs_case00(c16_t *output, else { output[k] = (c16_t){0}; } - k = (k + 1) % symbol_sz; + k++; } // RE loop return in - txl; } @@ -355,12 +354,6 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, { c16_t *txl = txl_start; const uint sz = rel15->rbSize * NR_NB_SC_PER_RB; - int upper_limit = sz; - int remaining_re = 0; - if (start_sc + upper_limit > symbol_sz) { - upper_limit = symbol_sz - start_sc; - remaining_re = sz - upper_limit; - } /* calculate if current symbol is PTRS symbols */ int ptrs_symbol = 0; @@ -385,47 +378,39 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, if (rel15->numDmrsCdmGrpsNoData == 2) { switch (dmrs_port & 3) { case 0: - txl += interleave_with_0_signal_first(output + start_sc, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_with_0_signal_first(output, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_signal_first(output + start_sc, dmrs_start, amp_dmrs, sz); break; case 1: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_with_0_signal_first(output + start_sc, dmrs, amp_dmrs, upper_limit); - txl += interleave_with_0_signal_first(output, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_signal_first(output + start_sc, dmrs, amp_dmrs, sz); } break; case 2: - txl += interleave_with_0_start_with_0(output + start_sc, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_with_0_start_with_0(output, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_start_with_0(output + start_sc, dmrs_start, amp_dmrs, sz); break; case 3: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_with_0_start_with_0(output + start_sc, dmrs, amp_dmrs, upper_limit); - txl += interleave_with_0_start_with_0(output, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_start_with_0(output + start_sc, dmrs, amp_dmrs, sz); } break; } } else if (rel15->numDmrsCdmGrpsNoData == 1) { switch (dmrs_port & 3) { case 0: - txl += interleave_signals(output + start_sc, txl, amp, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_signals(output, txl, amp, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_signals(output + start_sc, txl, amp, dmrs_start, amp_dmrs, sz); break; case 1: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_signals(output + start_sc, txl, amp, dmrs, amp_dmrs, upper_limit); - txl += interleave_signals(output, txl, amp, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_signals(output + start_sc, txl, amp, dmrs, amp_dmrs, sz); } break; case 2: - txl += interleave_signals(output + start_sc, dmrs_start, amp_dmrs, txl, amp, upper_limit); - txl += interleave_signals(output, dmrs_start + upper_limit / 2, amp_dmrs, txl, amp, remaining_re); + txl += interleave_signals(output + start_sc, dmrs_start, amp_dmrs, txl, amp, sz); break; case 3: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_signals(output + start_sc, dmrs, amp_dmrs, txl, amp, upper_limit); - txl += interleave_signals(output, dmrs + upper_limit / 2, amp_dmrs, txl, amp, remaining_re); + txl += interleave_signals(output + start_sc, dmrs, amp_dmrs, txl, amp, sz); } break; } } else @@ -445,8 +430,7 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, rel15->numDmrsCdmGrpsNoData); } // generic DMRS case } else { // no PTRS or DMRS in this symbol - txl += no_ptrs_dmrs_case(output + start_sc, txl, amp, upper_limit); - txl += no_ptrs_dmrs_case(output, txl, amp, remaining_re); + txl += no_ptrs_dmrs_case(output + start_sc, txl, amp, sz); } // no DMRS/PTRS in symbol return txl - txl_start; } @@ -477,30 +461,13 @@ static inline void do_txdataF(c16_t **txdataF, const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0; const int re_cnt = NR_NB_SC_PER_RB * rb_step; if (pmi == 0) { // unitary Precoding - if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC - if (ant < rel15->nrOfLayers) - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - re_cnt * sizeof(**txdataF)); - else - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); - } else { // RB does cross DC - const int neg_length = symbol_sz - subCarrier; - const int pos_length = re_cnt - neg_length; - if (ant < rel15->nrOfLayers) { - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - neg_length * sizeof(**txdataF)); - memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant], pos_length * sizeof(**txdataF)); - } else { - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF)); - memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF)); - } - } + if (ant < rel15->nrOfLayers) + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[ant][subCarrier], + re_cnt * sizeof(**txdataF)); + else + memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); subCarrier += re_cnt; - if (subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } } else { // non-unitary Precoding AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n"); // get the precoding matrix weights: @@ -514,38 +481,21 @@ static inline void do_txdataF(c16_t **txdataF, "Number of layers %d doesn't match to the one in precoding matrix %d\n", rel15->nrOfLayers, pmi_pdu->numLayers); - if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe - nr_layer_precoder_simd(rel15->nrOfLayers, - symbol_sz, - txdataF_precoding, - ant, - pmi_pdu, - subCarrier, - re_cnt, - &txdataF[ant][txdataF_offset_per_symbol]); - subCarrier += re_cnt; - } else { // crossing ofdm_symbol_size, use simple arithmetic operations - for (int i = 0; i < re_cnt; i++) { - txdataF[ant][txdataF_offset_per_symbol + subCarrier] = - nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier); -#ifdef DEBUG_DLSCH_MAPPING - printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", - ant, - l_symbol, - subCarrier, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i); -#endif - if (++subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } - } - } // else{ // crossing ofdm_symbol_size, use simple arithmetic operations + nr_layer_precoder_simd(rel15->nrOfLayers, + symbol_sz, + txdataF_precoding, + ant, + pmi_pdu, + subCarrier, + re_cnt, + &txdataF[ant][txdataF_offset_per_symbol]); + subCarrier += re_cnt; } // else { // non-unitary Precoding rb += rb_step; } // RB loop: while(rb < rel15->rbSize) } + static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot) { const int16_t amp = gNB->TX_AMP; @@ -641,9 +591,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC start_meas(&gNB->dlsch_pdsch_generation_stats); /// Resource mapping // Non interleaved VRB to PRB mapping - uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB; - if (start_sc >= symbol_sz) - start_sc -= symbol_sz; + uint16_t start_sc = (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB; #ifdef DEBUG_DLSCH_MAPPING printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 159e040d11..4acda03b91 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -71,7 +71,7 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, /// Resource mapping // PBCH DMRS are mapped within the SSB block on every fourth subcarrier starting from nushift of symbols 1, 2, 3 ///symbol 1 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l = ssb_start_symbol + 1; for (int m = 0; m < 60; m++) { @@ -80,13 +80,10 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #endif txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 2 [0+u:4:44+nushift ; 192+nu:4:236+nushift] -- 24 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l++; for (int m = 60; m < 84; m++) { @@ -100,13 +97,10 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif k+=(m==71)?148:4; // Jump from 44+nu to 192+nu - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 3 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l++; for (int m = 84; m < NR_PBCH_DMRS_LENGTH; m++) { @@ -115,9 +109,6 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #endif txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef DEBUG_PBCH_DMRS @@ -334,7 +325,7 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, nushift = config->cell_config.phy_cell_id.value &3; // PBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PBCH DMRS ///symbol 1 [0:239] -- 180 mod symbols - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + int k = frame_parms->ssb_start_subcarrier; int l = ssb_start_symbol + 1; int m = 0; int16_t amp = gNB->TX_AMP; @@ -351,13 +342,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 2 [0:47 ; 192:239] -- 72 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + k = frame_parms->ssb_start_subcarrier; l++; m=180; @@ -373,16 +361,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } k += 144; - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - m=216; for (int ssb_sc_idx = 192; ssb_sc_idx < 240; ssb_sc_idx++) { @@ -397,13 +379,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 3 [0:239] -- 180 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + k = frame_parms->ssb_start_subcarrier; l++; m=252; @@ -419,9 +398,5 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prs.c b/openair1/PHY/NR_TRANSPORT/nr_prs.c index 207a94447d..87edffdc7d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prs.c @@ -51,9 +51,9 @@ int nr_generate_prs(int slot, c16_t *txdataF, int16_t amp, prs_config_t *prs_cfg else if (prs_cfg->CombSize == 12){ k_prime = k_prime_table[3][symInd]; } - - k = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset*12 + frame_parms->first_carrier_offset; - + + k = (prs_cfg->REOffset + k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset * 12; + // QPSK modulation uint32_t *gold = nr_gold_prs(prs_cfg->NPRSID, slot, l); for (int m = 0; m < (12/prs_cfg->CombSize) * prs_cfg->NumRB; m++) { @@ -66,10 +66,7 @@ int nr_generate_prs(int slot, c16_t *txdataF, int16_t amp, prs_config_t *prs_cfg txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_prs[m], amp, 15); k = k + prs_cfg->CombSize; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - } + } } #ifdef DEBUG_PRS_MAP LOG_M("nr_prs.m", "prs",(int16_t *)&txdataF[prs_cfg->SymbolStart*frame_parms->ofdm_symbol_size],prs_cfg->NumPRSSymbols*frame_parms->ofdm_symbol_size, 1, 1); diff --git a/openair1/PHY/NR_TRANSPORT/nr_pss.c b/openair1/PHY/NR_TRANSPORT/nr_pss.c index 965ac51c21..6b219dba90 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pss.c @@ -49,8 +49,7 @@ int nr_generate_pss( c16_t *txdataF, /// Resource mapping // PSS occupies a predefined position (subcarriers 56-182, symbol 0) within the SSB block starting from - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and - if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; + int k = frame_parms->ssb_start_subcarrier + 56; int l = ssb_start_symbol; @@ -61,9 +60,6 @@ int nr_generate_pss( c16_t *txdataF, // printf("pss: writing position k %d / %d\n",k,frame_parms->ofdm_symbol_size); ((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_pss) >> 15; k++; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef NR_PSS_DEBUG diff --git a/openair1/PHY/NR_TRANSPORT/nr_sss.c b/openair1/PHY/NR_TRANSPORT/nr_sss.c index 45835f8206..71bae9a065 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sss.c @@ -59,16 +59,13 @@ int nr_generate_sss( c16_t *txdataF, /// Resource mapping // SSS occupies a predefined position (subcarriers 56-182, symbol 2) within the SSB block starting from - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and + int k = frame_parms->ssb_start_subcarrier + 56; int l = ssb_start_symbol + 2; for (int i = 0; i < NR_SSS_LENGTH; i++) { int16_t d_sss = (1 - 2*x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2*x1[(i + m1) % NR_SSS_LENGTH] ) * 23170; ((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_sss) >> 15; k++; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef NR_SSS_DEBUG // write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 881ce016bc..e24166a5b6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1619,7 +1619,14 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, if (was_symbol_used[i] == false) continue; for (int ap = 0; ap < n_antenna_ports; ap++) { - apply_nr_rotation_TX(frame_parms, txdataF[ap], frame_parms->symbol_rotation[linktype], slot, N_RB, i, 1); + apply_nr_rotation_TX(frame_parms, + txdataF[ap], + false, + frame_parms->symbol_rotation[linktype], + slot, + N_RB, + i, + 1); } } } diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c index 7cc14b385f..a0db67e50d 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c @@ -25,7 +25,6 @@ static void csi_rs_resource_mapping(c16_t **dataF, int csi_rs_length, int16_t mod_csi[][csi_rs_length >> 1], int ofdm_symbol_size, - int start_sc, const csi_mapping_parms_t *mapping_parms, int start_rb, int nb_rbs, @@ -43,7 +42,7 @@ static void csi_rs_resource_mapping(c16_t **dataF, int p = s + mapping_parms->j[ji] * gs; // port index for (int kp = 0; kp <= mapping_parms->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) + mapping_parms->koverline[ji] + kp) % (ofdm_symbol_size); + int k = ((n * NR_NB_SC_PER_RB) + mapping_parms->koverline[ji] + kp); // wf 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; @@ -625,7 +624,6 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, frame_parms->N_RB_DL << 4, mod_csi, frame_parms->ofdm_symbol_size, - frame_parms->first_carrier_offset, phy_csi_parms, start_rb, nr_of_rbs, diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 01b6fe7389..20ca99f0c4 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -217,8 +217,6 @@ void nr_feptx(void *arg) int startSymbol = feptx->startSymbol; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; int numSymbols = feptx->numSymbols; - int numSamples = feptx->numSymbols * fp->ofdm_symbol_size; - int txdataF_offset = startSymbol * fp->ofdm_symbol_size; int tx_idx = aa + bb * ru->nb_tx; @@ -232,11 +230,17 @@ void nr_feptx(void *arg) } // If there is no digital beamforming we just need to copy the data to RU - if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) - memcpy((void *)&ru->common.txdataF_BF[tx_idx][txdataF_offset], - (void *)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset], - numSamples * sizeof(int32_t)); - else { + if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) { + // FFT shift + const NR_DL_FRAME_PARMS *fp = &ru->gNB_list[0]->frame_parms; + fft_shift(ru->gNB_list[0]->common_vars.txdataF[bb][aa], + fp->ofdm_symbol_size, + fp->N_RB_DL, + (c16_t *)ru->common.txdataF_BF[tx_idx], + fp->ofdm_symbol_size, + startSymbol, + numSymbols); + } else { AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n"); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 80f96e1f43..629d9cc406 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -320,6 +320,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, if (gNB->phase_comp) { apply_nr_rotation_TX(fp, gNB->common_vars.txdataF[i][aa], + true, fp->symbol_rotation[0], slot, fp->N_RB_DL, diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index aa9ebccde8..2cdaa4143e 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1141,9 +1141,17 @@ int main(int argc, char **argv) //TODO: loop over slots for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - + c16_t fft_in_buff[frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot] __attribute__((aligned(64))); + memset(fft_in_buff, 0, sizeof(fft_in_buff)); if (cyclic_prefix_type == 1) { - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 12); + PHY_ofdm_mod((int *)fft_in_buff, (int *)&txdata[aa][slot_offset], frame_parms->ofdm_symbol_size, 12, @@ -1154,7 +1162,14 @@ int main(int argc, char **argv) for (int i = 0; i < 14; i++) { was_symbol_used[i] = true; } - nr_normal_prefix_mod(gNB->common_vars.txdataF[0][aa], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 14); + nr_normal_prefix_mod(fft_in_buff, &txdata[aa][slot_offset], 14, frame_parms, diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index cad3012400..a828db184d 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -525,17 +525,28 @@ int main(int argc, char **argv) nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]); int samp = get_samples_slot_timestamp(frame_parms, slot); - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + for (aa = 0; aa < gNB->frame_parms.nb_antennas_tx; aa++) { + c16_t fft_in_buff[frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot] __attribute__((aligned(64))); + memset(fft_in_buff, 0, sizeof(fft_in_buff)); if (cyclic_prefix_type == 1) { apply_nr_rotation_TX(frame_parms, gNB->common_vars.txdataF[0][aa], + true, frame_parms->symbol_rotation[0], slot, frame_parms->N_RB_DL, 0, 12); - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 12); + + PHY_ofdm_mod((int *)fft_in_buff, (int *)&txdata[aa][samp], frame_parms->ofdm_symbol_size, 12, @@ -544,21 +555,30 @@ int main(int argc, char **argv) } else { apply_nr_rotation_TX(frame_parms, gNB->common_vars.txdataF[0][aa], + true, frame_parms->symbol_rotation[0], slot, frame_parms->N_RB_DL, 0, 14); - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], - (int*)&txdata[aa][samp], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 14); + + PHY_ofdm_mod((int *)fft_in_buff, + (int *)&txdata[aa][samp], frame_parms->ofdm_symbol_size, 1, frame_parms->nb_prefix_samples0, CYCLIC_PREFIX); - PHY_ofdm_mod((int *)&gNB->common_vars.txdataF[0][aa][frame_parms->ofdm_symbol_size], - (int*)&txdata[aa][samp + frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size], + PHY_ofdm_mod((int *)fft_in_buff + frame_parms->ofdm_symbol_size, + (int *)&txdata[aa][samp + frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 13, frame_parms->nb_prefix_samples, diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 7f858219ac..d7b39b307b 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -612,21 +612,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int num_totalRB = p_prbMapElm->nRBSize; int start_totalRB = p_prbMapElm->nRBStart; - int pos_len = 0; - int neg_len = 0; - - if (start_totalRB < (num_totalRB >> 1)) // there are PRBs left of DC - neg_len = min((num_totalRB * 6) - (start_totalRB * 12), num_totalRB * N_SC_PER_PRB); - pos_len = (num_totalRB * N_SC_PER_PRB) - neg_len; - // Calculation of the pointer for the section in the buffer. - // start of positive frequency component - uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((start_totalRB * N_SC_PER_PRB) - (num_totalRB * 6)) : 0]; - // start of negative frequency component - uint16_t *src2 = (uint16_t *)&pos[(start_totalRB * N_SC_PER_PRB) + fftsize - (num_totalRB * 6)]; - - uint32_t local_src[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); - memcpy((void *)local_src, (void *)src2, neg_len * 4); - memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); if (ptr && pos) { u8dptr = (uint8_t *)ptr; int16_t payload_len = 0; @@ -662,26 +647,33 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) } uint16_t *dst16 = (uint16_t *)dst; + // Start of this section + int32_t *pos_start = pos + (start_totalRB + startRB) * N_SC_PER_PRB; + if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { payload_len = numRB * N_SC_PER_PRB * 4L; /* convert to Network order */ // NOTE: ggc 11 knows how to generate AVX2 for this! for (idx = 0; idx < (numRB * N_SC_PER_PRB) * 2; idx++) - ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx + startRB * N_SC_PER_PRB * 2]); + ((uint16_t *)dst16)[idx] = htons(((uint16_t *)pos_start)[idx]); } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { payload_len = (3 * p_prbMapElm->iqWidth + 1) * numRB; + /* Although arm intrinsics natively handle unaligned memory + access, we use a 64 byte aligned input here for maximum + performance. So the src_compr buffer is used for both x86 and arm. + */ + uint32_t src_compr[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); + + /* Copy from txdataF with current symbol's PRB start (nRBStart) + + current section's PRB start (UP_nPRBStart) */ + memcpy(src_compr, pos_start, (numRB * N_SC_PER_PRB) * sizeof(*pos_start)); + #if defined(__i386__) || defined(__x86_64__) struct xranlib_compress_request bfp_com_req = {}; struct xranlib_compress_response bfp_com_rsp = {}; - uint32_t src_compr[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); - if (numRB == num_totalRB) { - bfp_com_req.data_in = (int16_t *)local_src; - } else { - memcpy(src_compr, local_src + (startRB * N_SC_PER_PRB), (numRB * N_SC_PER_PRB) * sizeof(*local_src)); - bfp_com_req.data_in = (int16_t *)src_compr; - } + bfp_com_req.data_in = (int16_t *)src_compr; bfp_com_req.numRBs = numRB; bfp_com_req.len = payload_len; @@ -693,7 +685,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); #elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)(local_src + startRB * N_SC_PER_PRB), (int8_t *)dst); + armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)src_compr, (int8_t *)dst); #else AssertFatal(1 == 0, "BFP compression not supported on this architecture"); #endif @@ -950,7 +942,6 @@ int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t t const struct xran_fh_init *fh_init = get_xran_fh_init(); const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int nPRBs = fh_cfg->nDLRBs; int fftsize = 1 << fh_cfg->nDLFftSize; int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; @@ -1105,36 +1096,32 @@ int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t t } uint16_t *dst16 = (uint16_t *)dst; - int pos_len = 0; - int neg_len = 0; - - if (p_prbMapElm->UP_nRBStart < (nPRBs >> 1)) // there are PRBs left of DC - neg_len = min((nPRBs * 6) - (p_prbMapElm->UP_nRBStart * 12), p_prbMapElm->UP_nRBSize * N_SC_PER_PRB); - pos_len = (p_prbMapElm->UP_nRBSize * N_SC_PER_PRB) - neg_len; - // Calculation of the pointer for the section in the buffer. - // start of positive frequency component - uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0]; - // start of negative frequency component - uint16_t *src2 = (uint16_t *)&pos[(p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6)]; - - uint32_t local_src[p_prbMapElm->UP_nRBSize * N_SC_PER_PRB] __attribute__((aligned(64))); - memcpy((void *)local_src, (void *)src2, neg_len * 4); - memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); + int32_t *pos_start = pos + p_prbMapElm->UP_nRBStart * N_SC_PER_PRB; + uint32_t numPrb = p_prbMapElm->UP_nRBSize; if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { - payload_len = p_prbMapElm->UP_nRBSize * N_SC_PER_PRB * 4L; + payload_len = numPrb * N_SC_PER_PRB * 4L; /* convert to Network order */ // NOTE: ggc 11 knows how to generate AVX2 for this! - for (idx = 0; idx < (pos_len + neg_len) * 2; idx++) - ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx]); + for (idx = 0; idx < numPrb * N_SC_PER_PRB * 2; idx++) + ((uint16_t *)dst16)[idx] = htons(((uint16_t *)pos_start)[idx]); } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { - payload_len = (3 * p_prbMapElm->iqWidth + 1) * p_prbMapElm->UP_nRBSize; + payload_len = (3 * p_prbMapElm->iqWidth + 1) * numPrb; + /* Although arm intrinsics natively handle unaligned memory + access, we use a 64 byte aligned input here for maximum + performance. So the src_compr buffer is used for both x86 and arm. + */ + uint32_t src_compr[numPrb * N_SC_PER_PRB] __attribute__((aligned(64))); + + /* Copy from txdataF with current symbol's PRB start (nRBStart) + + current section's PRB start (UP_nPRBStart) */ + memcpy(src_compr, pos_start, (numPrb * N_SC_PER_PRB) * sizeof(*pos_start)); #if defined(__i386__) || defined(__x86_64__) struct xranlib_compress_request bfp_com_req = {}; struct xranlib_compress_response bfp_com_rsp = {}; - bfp_com_req.data_in = (int16_t *)local_src; - bfp_com_req.numRBs = p_prbMapElm->UP_nRBSize; + bfp_com_req.data_in = (int16_t *)src_compr; + bfp_com_req.numRBs = numPrb; bfp_com_req.len = payload_len; bfp_com_req.compMethod = p_prbMapElm->compMethod; bfp_com_req.iqWidth = p_prbMapElm->iqWidth; @@ -1144,7 +1131,7 @@ int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t t xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); #elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, p_prbMapElm->UP_nRBSize, (int16_t *)local_src, (int8_t *)dst); + armral_bfp_compression(p_prbMapElm->iqWidth, numPrb, (int16_t *)src_compr, (int8_t *)dst); #else AssertFatal(1 == 0, "BFP compression not supported on this architecture"); #endif