diff --git a/common/utils/bits.h b/common/utils/bits.h index 4d266ec53a..88ca05edd2 100644 --- a/common/utils/bits.h +++ b/common/utils/bits.h @@ -7,17 +7,59 @@ #include #include +#include #include "assertions.h" uint64_t reverse_bits(uint64_t in, int n_bits); void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out); -static inline int count_bits(uint8_t *arr, int sz) +static inline int get_last_bit_index(const uint32_t *arr, int sz) +{ + AssertFatal(sz > 0, "Invalid size %d to get the first bit of array\n", sz); + for (int i = sz - 1; i >= 0; i--) { + if (arr[i] != 0) { + // 31 - clz gives the index of the highest bit (0-31) + return (i * 32) + (31 - __builtin_clz(arr[i])); + } + } + return -1; +} + +static uint32_t bit_mask(int from_bit, int num_bits) +{ + int total = from_bit + num_bits; + uint32_t right_mask = total < 32 ? (0xFFFFFFFF >> (32 - total)) : 0xFFFFFFFF; + return (0xFFFFFFFF << from_bit) & right_mask; +} + +static inline int get_first_bit_index_mask(const uint32_t *arr, int sz, int from_bit, int num_bits) +{ + // start i from first_bit + int i = from_bit / 32; + from_bit %= 32; + for (; i < sz && num_bits > 0; i++) { + uint32_t a = arr[i] & bit_mask(from_bit, num_bits); + if (a != 0) { + // Find the first set bit in this 32-bit word + return (i * 32) + __builtin_ctz(a); + } + num_bits -= 32 - from_bit; + from_bit = 0; + } + return -1; +} + +static inline int get_first_bit_index(const uint32_t *arr, int sz) +{ + return get_first_bit_index_mask(arr, sz, 0, sz * 32); +} + +static inline int count_bits(const uint32_t *arr, int sz) { - AssertFatal(sz % sizeof(int) == 0, "to implement if needed\n"); int ret = 0; - for (uint *ptr = (uint *)arr; (uint8_t *)ptr < arr + sz; ptr++) - ret += __builtin_popcount(*ptr); + // sz is the number of uint32_t elements + for (int i = 0; i < sz; i++) + ret += __builtin_popcount(arr[i]); return ret; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index e7478ffac8..7edf19dec5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -25,9 +25,13 @@ static void nr_pdsch_codeword_scrambling(uint8_t *in, uint32_t size, uint8_t q, nr_codeword_scrambling(in, size, q, Nid, n_RNTI, out); } +static uint32_t get_block_start_sc(int block_start, int bwp_start, int symbol_sz) +{ + return (block_start + bwp_start) * NR_NB_SC_PER_RB; +} + static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, const freq_alloc_bitmap_t *freq_alloc, - int start_sc, int symbol_sz, c16_t *txF, c16_t *tx_layer, @@ -35,10 +39,11 @@ static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, c16_t *mod_ptrs) { int ptrs_idx = 0; - int k = start_sc; c16_t *in = tx_layer; - int last_rb = freq_alloc->end[freq_alloc->num_blocks - 1]; - int first_rb = freq_alloc->start[0]; + int last_rb = freq_alloc->last_rb; + int first_rb = freq_alloc->first_rb; + uint32_t start_sc = get_block_start_sc(freq_alloc->first_rb, rel15->BWPStart, symbol_sz); + int k = start_sc; for (int j = first_rb; j <= last_rb; j++) { if (check_rb_in_bitmap(freq_alloc, j)) { for (int i = 0; i < NR_NB_SC_PER_RB; i++) { @@ -222,12 +227,11 @@ static inline int dmrs_case00(c16_t *output, const freq_alloc_bitmap_t *freq_alloc, const int16_t amp_dmrs, const int amp, - int start_sc, int dmrs_port, const int dmrs_Type, int symbol_sz, int l_prime, - uint8_t numDmrsCdmGrpsNoData) + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15) { // DMRS params for this dmrs port int Wt[2], Wf[2]; @@ -235,30 +239,37 @@ static inline int dmrs_case00(c16_t *output, get_Wf(Wf, dmrs_port, dmrs_Type); const int8_t delta = get_delta(dmrs_port, dmrs_Type); int dmrs_idx = 0; + uint32_t start_sc = get_block_start_sc(freq_alloc->first_rb, rel15->BWPStart, symbol_sz); int k = start_sc; c16_t *in = txl; uint8_t k_prime = 0; uint16_t n = 0; - int rb_span = freq_alloc->end[freq_alloc->num_blocks - 1] - freq_alloc->start[0] + 1; - int sz = rb_span * NR_NB_SC_PER_RB; - for (int i = 0; i < sz; i++) { - int rb = freq_alloc->start[0] + (i / NR_NB_SC_PER_RB); - if (check_rb_in_bitmap(freq_alloc, rb)) { - if (k == ((start_sc + get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type)) % (symbol_sz))) { - output[k] = c16mulRealShift(mod_dmrs[dmrs_idx], Wt[l_prime] * Wf[k_prime] * amp_dmrs, 15); - dmrs_idx++; - k_prime = (k_prime + 1) & 1; - n += (k_prime ? 0 : 1); - } else if (allowed_xlsch_re_in_dmrs_symbol(k, start_sc, symbol_sz, numDmrsCdmGrpsNoData, dmrs_Type)) { - /* Map PTRS Symbol */ - /* Map DATA Symbol */ - output[k] = c16mulRealShift(*in++, amp, 15); - } else { - /* mute RE */ - output[k] = (c16_t){0}; + int pos = freq_alloc->first_rb; + int last_processed_rb = freq_alloc->first_rb; + int block_start, block_end; + while (find_next_rb_block(freq_alloc->bitmap, rel15->BWPSize, &pos, &block_start, &block_end)) { + // Mute skipped RBs + int skipped_sc = (block_start - last_processed_rb) * NR_NB_SC_PER_RB; + memset(output + k, 0, skipped_sc * sizeof(c16_t)); + k += skipped_sc; + for (int j = block_start; j <= block_end; j++) { + for (int i = 0; i < NR_NB_SC_PER_RB; i++) { + if (k == ((start_sc + get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type)) % (symbol_sz))) { + output[k] = c16mulRealShift(mod_dmrs[dmrs_idx], Wt[l_prime] * Wf[k_prime] * amp_dmrs, 15); + dmrs_idx++; + k_prime = (k_prime + 1) & 1; + n += (k_prime ? 0 : 1); + } else if (allowed_xlsch_re_in_dmrs_symbol(k, start_sc, symbol_sz, rel15->numDmrsCdmGrpsNoData, dmrs_Type)) { + /* Map PTRS Symbol */ + /* Map DATA Symbol */ + output[k] = c16mulRealShift(*in++, amp, 15); + } else { + output[k] = (c16_t){0}; + } + k++; } } - k++; + last_processed_rb = block_end + 1; } // RE loop return in - txl; } @@ -300,11 +311,6 @@ static inline void neg_dmrs(c16_t *in, c16_t *out, int sz) *out++ = i % 2 ? (c16_t){-in[i].r, -in[i].i} : in[i]; } -static uint32_t get_block_start_sc(int block_start, int bwp_start, int symbol_sz) -{ - return (block_start + bwp_start) * NR_NB_SC_PER_RB; -} - static inline void do_onelayer(NR_DL_FRAME_PARMS *frame_parms, int slot, const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, @@ -323,7 +329,6 @@ static inline void do_onelayer(NR_DL_FRAME_PARMS *frame_parms, c16_t *dmrs_start) { c16_t *txl = txl_start; - uint32_t start_sc = get_block_start_sc(freq_alloc->start[0], rel15->BWPStart, symbol_sz); /* calculate if current symbol is PTRS symbols */ int ptrs_symbol = 0; @@ -339,17 +344,19 @@ static inline void do_onelayer(NR_DL_FRAME_PARMS *frame_parms, const uint32_t *gold = nr_gold_pdsch(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, rel15->dlDmrsScramblingId, rel15->SCID, slot, l_symbol); nr_modulation(gold, n_ptrs * DMRS_MOD_ORDER, DMRS_MOD_ORDER, (int16_t *)mod_ptrs); - txl += do_ptrs_symbol(rel15, freq_alloc, start_sc, symbol_sz, output, txl, amp, mod_ptrs); + txl += do_ptrs_symbol(rel15, freq_alloc, symbol_sz, output, txl, amp, mod_ptrs); } else if (rel15->dlDmrsSymbPos & (1 << l_symbol)) { /* Map DMRS Symbol */ int dmrs_port = get_dmrs_port(layer, rel15->dmrsPorts); if (l_prime == 0 && dmrs_Type == NFAPI_NR_DMRS_TYPE1) { - for (int i = 0; i < freq_alloc->num_blocks; i++) { - if (i != 0) - start_sc = get_block_start_sc(freq_alloc->start[i], rel15->BWPStart, symbol_sz); - const int rb_span = freq_alloc->end[i] - freq_alloc->start[i] + 1; - const int sz = rb_span * NR_NB_SC_PER_RB; + int pos = 0; + int block_start, block_end; + while (find_next_rb_block(freq_alloc->bitmap, rel15->BWPSize, &pos, &block_start, &block_end)) { + int start_rb = block_start; + int nb_rb = block_end - block_start + 1; + int start_sc = get_block_start_sc(start_rb, rel15->BWPStart, symbol_sz); + const int sz = nb_rb * NR_NB_SC_PER_RB; if (rel15->numDmrsCdmGrpsNoData == 2) { switch (dmrs_port & 3) { case 0: @@ -398,19 +405,20 @@ static inline void do_onelayer(NR_DL_FRAME_PARMS *frame_parms, freq_alloc, amp_dmrs, amp, - start_sc, dmrs_port, dmrs_Type, symbol_sz, l_prime, - rel15->numDmrsCdmGrpsNoData); + rel15); } // generic DMRS case } else { // no PTRS or DMRS in this symbol - for (int i = 0; i < freq_alloc->num_blocks; i++) { - if (i != 0) - start_sc = get_block_start_sc(freq_alloc->start[i], rel15->BWPStart, symbol_sz); - const int rb_span = freq_alloc->end[i] - freq_alloc->start[i] + 1; - const int sz = rb_span * NR_NB_SC_PER_RB; + int pos = 0; + int block_start, block_end; + while (find_next_rb_block(freq_alloc->bitmap, rel15->BWPSize, &pos, &block_start, &block_end)) { + int start_rb = block_start; + int nb_rb = block_end - block_start + 1; + int start_sc = get_block_start_sc(start_rb, rel15->BWPStart, symbol_sz); + const int sz = nb_rb * NR_NB_SC_PER_RB; txl += no_ptrs_dmrs_case(output + start_sc, txl, amp, sz); } } // no DMRS/PTRS in symbol @@ -511,7 +519,7 @@ static void nr_pdsch_symbol_processing(void *arg) tx_layers[l] = rdata->tx_layers[l]; freq_alloc_bitmap_t *freq_alloc = rdata->freq_alloc; const int nb_re_dmrs = rel15->numDmrsCdmGrpsNoData * (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); - const int n_dmrs = (rel15->BWPStart + freq_alloc->end[freq_alloc->num_blocks - 1] + 1) * nb_re_dmrs; + const int n_dmrs = (rel15->BWPStart + freq_alloc->last_rb + 1) * nb_re_dmrs; // Loop Over OFDM symbols: c16_t mod_dmrs[(n_dmrs + 63) & ~63] __attribute__((aligned(64))); const int symbol_sz = frame_parms->ofdm_symbol_size; @@ -544,7 +552,7 @@ static void nr_pdsch_symbol_processing(void *arg) nr_modulation(gold, n_dmrs * DMRS_MOD_ORDER, DMRS_MOD_ORDER, (int16_t *)mod_dmrs); } - uint32_t dmrs_idx = freq_alloc->start[0]; + uint32_t dmrs_idx = freq_alloc->first_rb; if (rel15->refPoint == 0) dmrs_idx += rel15->BWPStart; dmrs_idx *= rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; @@ -572,17 +580,19 @@ static void nr_pdsch_symbol_processing(void *arg) start_meas(&rdata->dlsch_precoding_stats); const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz; for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) { - for (int b = 0; b < freq_alloc->num_blocks; b++) { - int nb_rb_block = freq_alloc->end[b] - freq_alloc->start[b] + 1; + int pos = 0; + int block_start, block_end; + while (find_next_rb_block(freq_alloc->bitmap, rel15->BWPSize, &pos, &block_start, &block_end)) { do_txdataF(txdataF, symbol_sz, txdataF_precoding, gNB, rel15, ant, - freq_alloc->start[b], - nb_rb_block, + block_start, + block_end - block_start + 1, txdataF_offset_per_symbol); + } } stop_meas(&rdata->dlsch_precoding_stats); @@ -802,8 +812,8 @@ void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_arr "pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbEnd %d rbsize %d\n", rel15->BWPStart, rel15->BWPSize, - dlsch->freq_alloc.start[0], - dlsch->freq_alloc.end[dlsch->freq_alloc.num_blocks - 1], + dlsch->freq_alloc.first_rb, + dlsch->freq_alloc.last_rb, dlsch->freq_alloc.num_rbs); const int Qm = rel15->qamModOrder[0]; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index b9fba62a27..239268b6a6 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -900,25 +900,30 @@ void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, } } -void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, - c16_t *rxF, - c16_t *pil, - c16_t *dl_ch, - unsigned short bwp_start_subcarrier, - int rb_offset, - int nb_rb_pdsch, - const uint8_t bitmap[36], - delay_t *delay, - uint32_t *nvar) +static void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, + c16_t *rxF, + c16_t *pil, + c16_t *dl_ch, + unsigned short bwp_start_subcarrier, + const freq_alloc_bitmap_t *freq_alloc, + int nb_rb_pdsch, + int bwpsize, + delay_t *delay, + uint32_t *nvar) { c16_t *dl_ch0 = dl_ch; int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size; c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); int idx = 0; - for (int rb = rb_offset; rb < rb_offset + nb_rb_pdsch; rb++) { - bool allocated_rb = (bitmap[rb / 8] >> (rb % 8)) & 0x01; - if (allocated_rb) { + int pos = freq_alloc->first_rb; + int last_processed_rb = freq_alloc->first_rb; + int block_start, block_end; + while (find_next_rb_block(freq_alloc->bitmap, bwpsize, &pos, &block_start, &block_end)) { + int skipped_rbs = block_start - last_processed_rb; + pil += skipped_rbs * 6; + re_offset = (re_offset + skipped_rbs * 12) % frame_parms->ofdm_symbol_size; + for (int rb = block_start; rb <= block_end; rb++) { for (int pilot_cnt = 0; pilot_cnt < 6; pilot_cnt += 2) { c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); #ifdef DEBUG_PDSCH @@ -938,10 +943,8 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, idx++; } } - } else { - pil += 6; - re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size; } + last_processed_rb = block_end + 1; } c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); nr_est_delay(frame_parms->ofdm_symbol_size, dl_ls_est, ch_estimates_time, delay); @@ -1071,9 +1074,9 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t *pil, c16_t *dl_ch, unsigned short bwp_start_subcarrier, - int rb_offset, + const freq_alloc_bitmap_t *freq_alloc, int nb_rb_pdsch, - const uint8_t bitmap[36], + int bwpsize, delay_t *delay, uint32_t *nvar) { @@ -1082,9 +1085,14 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); int idx = 0; - for (int rb = rb_offset; rb < rb_offset + nb_rb_pdsch; rb++) { - bool allocated_rb = (bitmap[rb / 8] >> (rb % 8)) & 0x01; - if (allocated_rb) { + int pos = freq_alloc->first_rb; + int last_processed_rb = freq_alloc->first_rb; + int block_start, block_end; + while (find_next_rb_block(freq_alloc->bitmap, bwpsize, &pos, &block_start, &block_end)) { + int skipped_rbs = block_start - last_processed_rb; + pil += skipped_rbs * 4; + re_offset = (re_offset + skipped_rbs * 12) % frame_parms->ofdm_symbol_size; + for (int rb = block_start; rb <= block_end; rb++) { for (int pilot_cnt = 0; pilot_cnt < 4; pilot_cnt += 2) { c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); #ifdef DEBUG_PDSCH @@ -1104,10 +1112,8 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, idx++; } } - } else { - pil += 4; - re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size; } + last_processed_rb = block_end + 1; } c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); @@ -1251,7 +1257,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *fp = &ue->frame_parms; const int ch_offset = fp->ofdm_symbol_size * symbol; const int symbol_offset = fp->ofdm_symbol_size * symbol; - int bwp_start_subcarrier = fp->first_carrier_offset + (dlsch->BWPStart + freq_alloc->start[0]) * 12; + int bwp_start_subcarrier = fp->first_carrier_offset + (dlsch->BWPStart + freq_alloc->first_rb) * 12; #ifdef DEBUG_PDSCH printf( @@ -1268,8 +1274,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, // generate pilot for gNB port number 1000+p int config_type = dlsch->dmrsConfigType; - int rb_offset = freq_alloc->start[0] + (dlsch->refPoint ? 0 : dlsch->BWPStart); - int nb_rb_pdsch = freq_alloc->end[freq_alloc->num_blocks - 1] - freq_alloc->start[0] + 1; + int rb_offset = freq_alloc->first_rb + (dlsch->refPoint ? 0 : dlsch->BWPStart); + int nb_rb_pdsch = freq_alloc->last_rb - freq_alloc->first_rb + 1; int8_t delta = get_delta(p, config_type); c16_t pilot[3280] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS @@ -1297,9 +1303,9 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, &pilot[6 * rb_offset], dl_ch, bwp_start_subcarrier, - freq_alloc->start[0], + freq_alloc, nb_rb_pdsch, - freq_alloc->bitmap, + dlsch->BWPSize, &delay, nvar); @@ -1309,9 +1315,9 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, &pilot[4 * rb_offset], dl_ch, bwp_start_subcarrier, - freq_alloc->start[0], + freq_alloc, nb_rb_pdsch, - freq_alloc->bitmap, + dlsch->BWPSize, &delay, nvar); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 53a6cbc19f..8e8162034f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -12,6 +12,7 @@ #include "nr_transport_proto_ue.h" #include "PHY/sse_intrin.h" #include "T.h" +#include "bits.h" #include "openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/NR_REFSIG/nr_refsig.h" #include "PHY/NR_REFSIG/dmrs_nr.h" @@ -276,21 +277,26 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, int32_t dl_ch_estimates_ext[][rx_size_symbol], unsigned char symbol, uint8_t pilots, - uint8_t config_type, - int startBWP, + const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, const freq_alloc_bitmap_t *freq_alloc, - uint8_t n_dmrs_cdm_groups, uint8_t Nl, NR_DL_FRAME_PARMS *fp, - uint16_t dlDmrsSymbPos, uint32_t csi_res_bitmap, int chest_time_type) { + int config_type = dlsch_config->dmrsConfigType; + int n_dmrs_cdm_groups = dlsch_config->n_dmrs_cdm_groups; if (config_type == NFAPI_NR_DMRS_TYPE1) - AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2, "n_dmrs_cdm_groups %d is illegal\n", n_dmrs_cdm_groups); + AssertFatal(n_dmrs_cdm_groups == 1 + || n_dmrs_cdm_groups == 2, + "n_dmrs_cdm_groups %d is illegal\n", + n_dmrs_cdm_groups); else - AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2 || n_dmrs_cdm_groups == 3, - "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); + AssertFatal(n_dmrs_cdm_groups == 1 + || n_dmrs_cdm_groups == 2 + || n_dmrs_cdm_groups == 3, + "n_dmrs_cdm_groups %d is illegal\n", + n_dmrs_cdm_groups); uint32_t dmrs_rb_bitmap = 0; if (pilots) { @@ -312,13 +318,15 @@ static void nr_dlsch_extract_rbs(uint32_t rxdataF_sz, uint32_t dmrs_csi_overlap_odd = csi_res_odd + dmrs_rb_bitmap; int8_t validDmrsEst; if (chest_time_type == 0) - validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlDmrsSymbPos, symbol); + validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlsch_config->dlDmrsSymbPos, symbol); else - validDmrsEst = get_next_dmrs_symbol_in_slot(dlDmrsSymbPos, 0, 14); // get first dmrs symbol index + validDmrsEst = get_next_dmrs_symbol_in_slot(dlsch_config->dlDmrsSymbPos, 0, 14); // get first dmrs symbol index - for (int b = 0; b < freq_alloc->num_blocks; b++) { - int start_rb = freq_alloc->start[b] + startBWP; - int nb_rb = freq_alloc->end[b] - freq_alloc->start[b] + 1; + int pos = 0; + int block_start, block_end; + while (find_next_rb_block(freq_alloc->bitmap, dlsch_config->BWPSize, &pos, &block_start, &block_end)) { + int start_rb = block_start + dlsch_config->BWPStart; + int nb_rb = block_end - block_start + 1; const int start_re = (fp->first_carrier_offset + start_rb * NR_NB_SC_PER_RB) % fp->ofdm_symbol_size; for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) { c16_t *rxF_ext = rxdataF_ext[aarx]; @@ -1076,13 +1084,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dl_ch_estimates_ext, symbol, pilots, - config_type, - dlsch_config->BWPStart, + dlsch_config, freq_alloc, - dlsch_config->n_dmrs_cdm_groups, nl, fp, - dlsch_config->dlDmrsSymbPos, csi_res_bitmap, ue->chest_time); stop_meas_nr_ue_phy(ue, DLSCH_EXTRACT_RBS_STATS); @@ -1112,13 +1117,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, uint32_t csi_re_count = 0; uint32_t csi_res_even = csi_res_bitmap & 0xfff; uint32_t csi_res_odd = (csi_res_bitmap >> 16) & 0xfff; - int start = freq_alloc->start[0] + dlsch_config->BWPStart; - int end = freq_alloc->end[freq_alloc->num_blocks - 1] + 1; + uint32_t count_even = count_bits(&csi_res_even, 1); + uint32_t count_odd = count_bits(&csi_res_odd, 1); + int start = freq_alloc->first_rb + dlsch_config->BWPStart; + int end = freq_alloc->last_rb + 1; for (int rb = start; rb < end; rb++) { - if ((freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01) { - uint32_t rb_csi_pattern = (rb % 2 == 0) ? csi_res_even : csi_res_odd; - csi_re_count += __builtin_popcount(rb_csi_pattern); - } + if ((freq_alloc->bitmap[rb / 32] >> (rb % 32)) & 0x01) + csi_re_count += (rb % 2 == 0) ? count_even : count_odd; } nb_re_pdsch = (nb_re_pdsch > csi_re_count) ? (nb_re_pdsch - csi_re_count) : 0; if (csi_re_count > 0) { diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index cc0f43ccf0..74beb9e02b 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -377,13 +377,12 @@ int nr_get_ssb_start_sc(int scs, int ssb_sco, frequency_range_t freq_range); -#define MAX_FA_BLOCKS 10 +bool find_next_rb_block(const uint32_t *bitmap, int size, int *pos, int *start, int *end); typedef struct { - int start[MAX_FA_BLOCKS]; - int end[MAX_FA_BLOCKS]; + int first_rb; + int last_rb; int num_rbs; - int num_blocks; - uint8_t bitmap[36]; + uint32_t bitmap[9]; } freq_alloc_bitmap_t; bool check_rb_in_bitmap(const freq_alloc_bitmap_t *alloc, int rb); freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, const uint8_t bitmap[alloc_size]); diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index 3fb1d53bdf..5239aa2c00 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -430,32 +430,17 @@ void nr_scale_channel(int size, int ch_estimates_ext[][size], int symb, uint32_t freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, const uint8_t bitmap[alloc_size]) { - freq_alloc_bitmap_t alloc = { - .num_rbs = 0, - .num_blocks = 0 - }; - - bool pos_bit = false; - for (int i = 0; i < size; i++) { - if ((bitmap[i / 8] >> i % 8) & 0x1) { - if (!pos_bit) { - pos_bit = true; - alloc.start[alloc.num_blocks] = i; - AssertFatal(alloc.num_blocks < MAX_FA_BLOCKS, "Number of type0 PDSCH RBG exceeting %d\n", MAX_FA_BLOCKS); - alloc.num_blocks++; - } - alloc.num_rbs++; - } else { - if (pos_bit) { - pos_bit = false; - alloc.end[alloc.num_blocks - 1] = i - 1; - } - } - } - if (pos_bit) - alloc.end[alloc.num_blocks - 1] = size - 1; - AssertFatal(alloc.num_blocks > 0, "Frequency allocation bitmap empty\n"); - memcpy(alloc.bitmap, bitmap, alloc_size * sizeof(uint8_t)); + freq_alloc_bitmap_t alloc = {0}; + int num_words = (size + 31) / 32; + AssertFatal(num_words <= sizeofArray(alloc.bitmap), + "freq_alloc_bitmap.bitmap %lu words < %d\n", + sizeofArray(alloc.bitmap), + num_words); + memcpy(alloc.bitmap, bitmap, alloc_size); + alloc.num_rbs = count_bits(alloc.bitmap, num_words); + alloc.first_rb = get_first_bit_index(alloc.bitmap, num_words); + alloc.last_rb = get_last_bit_index(alloc.bitmap, num_words); + AssertFatal(alloc.first_rb >= 0 && alloc.last_rb >=0 , "No valid RB set, no bit set in bitmap\n"); return alloc; } @@ -463,19 +448,57 @@ freq_alloc_bitmap_t set_bitmap_from_start_size(int start, int size) { freq_alloc_bitmap_t alloc = { .num_rbs = size, - .num_blocks = 1, - .start[0] = start, - .end[0] = start + size - 1 + .first_rb = start, + .last_rb = start + size - 1 }; - memset(alloc.bitmap, 0, 36 * sizeof(uint8_t)); + memset(alloc.bitmap, 0, sizeof(alloc.bitmap)); for (int i = start; i < size + start; i++) - alloc.bitmap[i / 8] += 1 << (i % 8); + alloc.bitmap[i / 32] |= (1U << (i % 32)); return alloc; } bool check_rb_in_bitmap(const freq_alloc_bitmap_t *alloc, int rb) { - return (alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01; + return (alloc->bitmap[rb / 32] >> (rb % 32)) & 0x01; +} + +/** + * Finds the next contiguous block of set bits. + * @param bitmap The bit buffer + * @param size Total bits in the buffer + * @param pos Pointer to current bit index (updated by function) + * @param start Output: Start index of the found block + * @param end Output: End index of the found block + * @return true if a block was found, false if no more bits are set + */ +bool find_next_rb_block(const uint32_t *bitmap, int size, int *pos, int *start, int *end) +{ + AssertFatal(*pos >= 0 && *pos <= size, "Invalid combination of bit index %d and size %d\n", *pos, size); + const int words = (size + 31) / 32; + + // Find start of next block + int idx = get_first_bit_index_mask(bitmap, words, *pos, size - *pos); + if (idx < 0) + return false; + *start = idx; + + // Find end of block: first zero bit after idx + // Reuse get_first_bit_index_from on the inverted bitmap + idx++; + int word_idx = idx / 32; + int n = words - word_idx; + uint32_t inv[n]; + for (int i = 0; i < n; i++) + inv[i] = ~bitmap[word_idx + i]; + if (size % 32 != 0) + inv[n - 1] &= (1u << (size % 32)) - 1; + + int end_off = get_first_bit_index_mask(inv, n, idx - word_idx * 32, size - idx); + idx = (end_off < 0) ? size : word_idx * 32 + end_off; + + *end = (idx > size) ? size - 1 : idx - 1; + *pos = idx; // Update position for the next call + return true; } void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, const c16_t *rxdata_in, c16_t *rxdata_out, int size) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b24ba81168..89d222048e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -524,8 +524,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, harq_pid, dlsch0_harq->status, dlschCfg->BWPStart, - freq_alloc.start[0], - freq_alloc.end[freq_alloc.num_blocks - 1], + freq_alloc.first_rb, + freq_alloc.last_rb, dlschCfg->start_symbol, dlschCfg->number_symbols, dlschCfg->dlDmrsSymbPos, diff --git a/openair2/RRC/NR_UE/verify_RRC.c b/openair2/RRC/NR_UE/verify_RRC.c index 60bdee462e..07017639c5 100644 --- a/openair2/RRC/NR_UE/verify_RRC.c +++ b/openair2/RRC/NR_UE/verify_RRC.c @@ -120,8 +120,9 @@ static bool check_csi_resourceMapping_consistency(NR_CSI_RS_ResourceMapping_t re valid = false; break; case NR_CSI_RS_ResourceMapping__nrofPorts_p8: { - uint8_t freq = BIT_STRING_to_uint8(&resourceMapping.frequencyDomainAllocation.choice.other); - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2 || count_bits(&freq, 1) != 4) { + uint32_t freq32 = 0; + freq32 = (uint32_t)BIT_STRING_to_uint8(&resourceMapping.frequencyDomainAllocation.choice.other); + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2 || count_bits(&freq32, 1) != 4) { // row 7 and 8 -> l0+1 if (resourceMapping.firstOFDMSymbolInTimeDomain == 13) valid = false;