Merge remote-tracking branch 'origin/l1-rx-use-queues' into integration_2026_w16 (!3991)

L1 RX: use queues instead of arrays and linear search for PUCCH, PUSCH, SRS, PRACH

This MR is an attempt to reduce the time L1 RX searches in array for the
next job to process, and instead use a queue. This queue is a FIFO,
because the various jobs (FAPI messages) to process come in order, and
need to be processed in order. The MR (hopefully, to be measured)
reduces the amount of time spent searching for the next UE (because the
next job is always at the beginning of the queue), and should scale
better for many UEs.

It does the following:

- introduce two helper libraries for (1) Frame.Slot calculation (sfn_t),
  already introduced in !3521 (merged) commit 3102068e, and (2) a ring
  buffer with fixed size
- use sfn_t and ring buffer (gNB->pucch_queue) to remove the linear
  array for PUCCH (gNB->pucch)
- use sfn_t and ring buffer (gNB->pusch_queue) for some PUSCH lookups.
  Because we need to still store PUSCH contexts, gNB->pusch is still
  there
- use sfn_t and ring buffer (gNB->srs_queue) to remove the linear array
  for SRS (gNB->srs)
- use sfn_t and ring buffers (gNB->prach_ru_queue and
  gNB->prach_l1rx_queue) to remove the linear array for PRACH
  (gNB->prach_list)
- some minor cleanups, e.g., additional loops over the PUSCH array,
  using const, using pointers instead of indices, etc
This commit is contained in:
Robert Schmidt
2026-04-16 13:50:53 +02:00
49 changed files with 1356 additions and 1247 deletions
@@ -56,40 +56,6 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot)
UNUSED(slot);
}
int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(pPackedBuf);
UNUSED(packedBufLen);
return 0;
}
int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
return 0;
}
int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(pPackedBuf);
UNUSED(packedBufLen);
return 0;
}
int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf,
uint32_t messageBufLen,
void *pUnpackedBuf,
uint32_t unpackedBufLen)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
return 0;
}
void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port)
{
UNUSED(vnf_ip_addr);
@@ -102,37 +68,3 @@ void configure_nr_nfapi_vnf(eth_params_t params)
{
UNUSED(params);
}
int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config)
{
UNUSED(pMessageBuf);
UNUSED(pPackedBuf);
UNUSED(packedBufLen);
UNUSED(config);
return 0;
}
bool nfapi_nr_p7_message_unpack(void *pMessageBuf,
uint32_t messageBufLen,
void *pUnpackedBuf,
uint32_t unpackedBufLen,
nfapi_p7_codec_config_t *config)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
UNUSED(config);
return false;
}
int nfapi_p7_message_header_unpack(void *pMessageBuf,
uint32_t messageBufLen,
void *pUnpackedBuf,
uint32_t unpackedBufLen,
nfapi_p7_codec_config_t *config)
{
UNUSED(pMessageBuf);
UNUSED(messageBufLen);
UNUSED(pUnpackedBuf);
UNUSED(unpackedBufLen);
UNUSED(config);
return 0;
}
+8 -11
View File
@@ -547,12 +547,10 @@ int main(int argc, char **argv){
phy_init_nr_gNB(gNB);
nr_phy_init_RU(ru);
prach_item_t *prach_data = calloc(1,sizeof(prach_item_t));
gNB->prach_list.list[0] = prach_data;
nfapi_nr_prach_pdu_t *prach_pdu = &prach_data->pdu;
prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig);
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs));
prach_pdu->prach_format = prach_format;
nfapi_nr_prach_pdu_t prach_pdu = {0};
prach_pdu.num_cs = get_NCS(NCS_config, format0, restrictedSetConfig);
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu.num_cs));
prach_pdu.prach_format = prach_format;
// Configure UE
UE = malloc(sizeof(PHY_VARS_NR_UE));
@@ -749,14 +747,14 @@ int main(int argc, char **argv){
}
nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra];
prach_pdu->num_prach_ocas=1;
nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu.num_ra];
prach_pdu.num_prach_ocas=1;
prach_item_t *in = malloc(sizeof(prach_item_t)
+ sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value
* NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L);
*in = (prach_item_t){.frame = frame,
.slot = slot,
.pdu = *prach_pdu,
.pdu = prach_pdu,
.rootSequenceIndex = occ->prach_root_sequence_index.value,
.numrootSequenceIndex = occ->num_root_sequences.value,
.msg1_frequencystart = occ->k1.value,
@@ -772,7 +770,7 @@ int main(int argc, char **argv){
if (n_frames == 1)
LOG_I(PHY,
"ncs %d,num_seq %d\n",
prach_pdu->num_cs,
prach_pdu.num_cs,
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value);
rx_prach_out_t out = rx_nr_prach(in, prachOccasion);
@@ -823,7 +821,6 @@ int main(int argc, char **argv){
nr_phy_free_RU(ru);
free(RC.ru[0]);
free(RC.ru);
free(prach_data);
phy_free_nr_gNB(gNB);
// allocated in set_tdd_config_nr()
int nb_slots_to_set = (1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
+4 -7
View File
@@ -630,27 +630,24 @@ int main(int argc, char **argv)
rxlev_pucch += signal_energy((int32_t *)&rxdataF[aarx][startingSymbolIndex * frame_parms->ofdm_symbol_size], 12);
// set UL mask for pucch allocation
uint32_t rb_mask_ul[14][9] = {0};
uint32_t rb_mask_ul[14][MAX_BWP_SIZE] = {0};
if (format == 1) {
for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2))
for (int rb = 0; rb < N_RB; rb++) {
int rb2 = rb + startingPRB;
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
rb_mask_ul[s][rb + startingPRB] = 1;
}
else if (s >= (startingSymbolIndex + nrofSymbols / 2) && s < startingSymbolIndex + nrofSymbols)
for (int rb = 0; rb < N_RB; rb++) {
int rb2 = rb + startingPRB_intraSlotHopping;
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
rb_mask_ul[s][rb + startingPRB_intraSlotHopping] = 1;
}
}
} else {
for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols))
for (int rb = 0; rb < N_RB; rb++) {
int rb2 = rb + startingPRB;
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
rb_mask_ul[s][rb + startingPRB] = 1;
}
}
}
+9 -21
View File
@@ -435,11 +435,7 @@ int main(int argc, char *argv[])
.beamforming.num_prgs = m_SRS[srs_pdu.config_index],
.beamforming.prg_size = 1};
gNB->srs->srs_pdu = srs_pdu;
gNB->srs->active = true;
gNB->srs->beam_nb = 0;
gNB->srs->frame = frame;
gNB->srs->slot = slot;
NR_gNB_SRS_job_t srs_job = {.frame = frame, .slot = slot, .srs_pdu = srs_pdu};
// Configure SRS parameters at UE
fapi_nr_ul_config_srs_pdu srs_config_pdu = {.rnti = srs_pdu.rnti,
@@ -467,11 +463,6 @@ int main(int argc, char *argv[])
.beamforming.num_prgs = srs_pdu.beamforming.num_prgs,
.beamforming.prg_size = srs_pdu.beamforming.prg_size};
nr_phy_data_tx_t phy_data = {0};
phy_data.srs_vars.active = true;
phy_data.srs_vars.srs_config_pdu = srs_config_pdu;
UE->nr_srs_info = malloc16_clear(sizeof(nr_srs_info_t));
//----------- UE TX SRS procedures ---------------------
UE_nr_rxtx_proc_t proc;
@@ -492,7 +483,7 @@ int main(int argc, char *argv[])
for (i = 0; i < n_tx; i++)
txd[i] = txdata[i] + slot_offset;
ue_srs_procedures_nr(UE, &proc, (c16_t **)txF, &phy_data, was_symbol_used);
ue_srs_procedures_nr(UE, &proc, (c16_t **)txF, &srs_config_pdu, was_symbol_used);
//------------ TX rotation and OFDM Modulation --------------------------
nr_tx_rotation_and_ofdm_mod(slot, fp, n_tx, txF, txd, link_type_ul, was_symbol_used, false);
@@ -564,16 +555,15 @@ int main(int argc, char *argv[])
//----------- UE RX SRS procedures ---------------------
start_meas(&gNB->rx_srs_stats);
NR_gNB_SRS_t *srs = &gNB->srs[0];
uint8_t N_symb_SRS = 1 << srs->srs_pdu.num_symbols;
uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports;
int16_t snr_per_rb[srs->srs_pdu.bwp_size];
uint8_t N_symb_SRS = 1 << srs_pdu.num_symbols;
uint8_t N_ap = 1 << srs_pdu.num_ant_ports;
int16_t snr_per_rb[srs_pdu.bwp_size];
uint16_t timing_advance_offset;
int16_t timing_advance_offset_nsec[n_rx];
int srs_est;
c16_t srs_estimated_channel_freq[n_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
c16_t srs_estimated_channel_time[n_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size] __attribute__((aligned(32)));
int8_t snr;
nr_srs_rx_procedures(gNB,
frame,
slot,
@@ -581,16 +571,15 @@ int main(int argc, char *argv[])
N_ap,
N_symb_SRS,
ofdm_symbol_size,
srs,
gNB->nr_srs_info[0],
&srs_job,
&srs_est,
&snr,
srs_estimated_channel_freq,
srs_estimated_channel_time,
snr_per_rb,
&timing_advance_offset,
timing_advance_offset_nsec);
sum_srs_snr += pow(10, (double)gNB->srs->snr / 10.0);
sum_srs_snr += pow(10, (double)snr / 10.0);
int16_t delay_ns = delay * 1e9 / (fp->samples_per_frame * 100);
for (int ant_idx = 0; ant_idx < n_rx; ant_idx++) {
@@ -666,7 +655,6 @@ int main(int argc, char *argv[])
phy_free_nr_gNB(gNB);
free_channel_desc_scm(UE2gNB);
free_and_zero(UE->nr_srs_info);
free(gNB->RU_list[0]);
free(UE);
+9 -7
View File
@@ -414,12 +414,12 @@ int main(int argc, char **argv)
unsigned int TBS = 8424;
unsigned int available_bits;
uint8_t nb_re_dmrs = 6;
uint8_t length_dmrs = 1;
uint8_t length_dmrs = 2;
uint8_t N_PRB_oh;
uint16_t N_RE_prime,code_rate;
unsigned char mod_order;
uint8_t rvidx = 0;
uint8_t UE_id = 0;
int UE_id = 0;
NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id];
NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_process;
@@ -429,9 +429,6 @@ int main(int argc, char **argv)
nr_phy_data_tx_t phy_data = {0};
NR_UE_ULSCH_t *ulsch_ue = &phy_data.ulsch;
if ((Nl==4)||(Nl==3))
nb_re_dmrs = nb_re_dmrs*2;
mod_order = nr_get_Qm_ul(Imcs, mcs_table);
code_rate = nr_get_code_rate_ul(Imcs, mcs_table);
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, 0, mod_order, Nl);
@@ -445,10 +442,15 @@ int main(int argc, char **argv)
rel15_ul->qam_mod_order = mod_order;
rel15_ul->mcs_index = Imcs;
rel15_ul->pusch_data.rv_index = rvidx;
rel15_ul->ul_dmrs_symb_pos = nb_re_dmrs;
rel15_ul->dmrs_config_type = pusch_dmrs_type1;
rel15_ul->num_dmrs_cdm_grps_no_data = 1;
rel15_ul->nrOfLayers = Nl;
rel15_ul->target_code_rate = code_rate;
rel15_ul->pusch_data.tb_size = TBS>>3;
rel15_ul->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, code_rate);
int bits = count_bits64_with_mask(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols);
AssertFatal(length_dmrs == bits, "length_dmrs %d bits %d\n", length_dmrs, bits);
///////////////////////////////////////////////////
double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc
@@ -558,9 +560,9 @@ int main(int argc, char **argv)
printf("\n");
exit(-1);
#endif
nr_ulsch_decoding(gNB, frame_parms, frame, subframe, &G, &UE_id, 1);
nr_ulsch_decoding(gNB, frame_parms, frame, subframe, &UE_id, 1);
if (harq_process_gNB->processedSegments == harq_process_gNB->C) {
bool crc_valid = check_crc(harq_process_gNB->b, lenWithCrc(1, (harq_process_gNB->TBS) << 3), crcType(1, (harq_process_gNB->TBS) << 3));
bool crc_valid = check_crc(harq_process_gNB->b, lenWithCrc(1, TBS << 3), crcType(1, TBS << 3));
if (!crc_valid) {
n_false_positive++;
}
+13 -6
View File
@@ -1208,6 +1208,7 @@ int main(int argc, char *argv[])
uint8_t round = 0;
crc_status = 1;
errors_decoding = 0;
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id];
while (round < max_rounds && crc_status && !stop) {
@@ -1307,7 +1308,7 @@ int main(int argc, char *argv[])
srs_pdu->resource_type = NR_SRS_Resource__resourceType_PR_periodic;
srs_pdu->t_srs = 1;
srs_pdu->srs_parameters_v4.srs_bandwidth_size = m_SRS[srs_pdu->config_index];
srs_pdu->srs_parameters_v4.usage = 1 << NR_SRS_ResourceSet__usage_codebook;
srs_pdu->srs_parameters_v4.usage = 1 << NFAPI_NR_SRS_BEAMMANAGEMENT; // to get SNR
srs_pdu->srs_parameters_v4.report_type[0] = 1;
srs_pdu->srs_parameters_v4.iq_representation = 1;
srs_pdu->srs_parameters_v4.prg_size = 1;
@@ -1594,7 +1595,6 @@ int main(int argc, char *argv[])
}
}
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id];
if (n_trials == 1 && round == 0) {
__attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0;
@@ -1742,13 +1742,20 @@ int main(int argc, char *argv[])
if (!crc_status)
effRate += ((double)TBS) / (double)round;
sum_pusch_delay += ulsch_gNB->delay.est_delay;
min_pusch_delay = min(ulsch_gNB->delay.est_delay, min_pusch_delay);
max_pusch_delay = max(ulsch_gNB->delay.est_delay, max_pusch_delay);
sum_pusch_delay += pusch_vars->delay.est_delay;
min_pusch_delay = min(pusch_vars->delay.est_delay, min_pusch_delay);
max_pusch_delay = max(pusch_vars->delay.est_delay, max_pusch_delay);
delay_pusch_est_count++;
if (do_SRS == 1) {
sum_srs_snr += gNB->srs->snr;
DevAssert(UL_INFO.srs_ind.number_of_pdus == 1); // there must be SRS indication
const nfapi_nr_srs_indication_pdu_t *srs_ind = &UL_INFO.srs_ind.pdu_list[0];
DevAssert(srs_ind->srs_usage == NFAPI_NR_SRS_BEAMMANAGEMENT);
nfapi_nr_srs_beamforming_report_t bf_rep;
unpack_nr_srs_beamforming_report((void *)srs_ind->report_tlv.value, srs_ind->report_tlv.length, &bf_rep, sizeof(bf_rep));
DevAssert(bf_rep.wide_band_snr != 0xff);
int8_t snr = (bf_rep.wide_band_snr >> 1) - 64;
sum_srs_snr += snr;
srs_snr_count++;
}
} // trial loop