reworking the handling of freq_alloc_bitmap_t to make it more efficient

Co-Authored-By: @schmidtr
Assisted-by: Gemini:3 Flash
This commit is contained in:
francescomani
2026-04-20 19:15:27 +02:00
co-authored by @schmidtr
parent 0dd1243e6e
commit 29457abe71
8 changed files with 235 additions and 149 deletions
+46 -4
View File
@@ -7,17 +7,59 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#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;
}
+61 -51
View File
@@ -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];
@@ -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);
@@ -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) {
@@ -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]);
+55 -32
View File
@@ -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)
+2 -2
View File
@@ -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,
+3 -2
View File
@@ -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;