Merge remote-tracking branch 'origin/NR_common_L1' into integration_2025_w34 (!3035)

NR L1 common channel level functions

Common L1 functions shared between gNB and UE for DLSCH/ULSCH/PDCCH/PBCH
channel level
This commit is contained in:
Robert Schmidt
2025-08-21 09:34:31 +02:00
8 changed files with 69 additions and 197 deletions
@@ -7,6 +7,7 @@
#include "PHY/NR_REFSIG/ptrs_nr.h"
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
#include "PHY/defs_nr_common.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
#include "common/utils/nr/nr_common.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
#include "PHY/sse_intrin.h"
@@ -210,31 +211,6 @@ static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t
} else return(rel15_ul->rb_size * NR_NB_SC_PER_RB);
}
// compute average channel_level on each (TX,RX) antenna pair
static void nr_ulsch_channel_level(int size_est,
int ul_ch_estimates_ext[][size_est],
NR_DL_FRAME_PARMS *frame_parms,
int32_t *avg,
uint8_t symbol,
uint32_t len,
uint8_t nrOfLayers)
{
int16_t x = factor2(len);
int16_t y = (len)>>x;
for (int aatx = 0; aatx < nrOfLayers; aatx++) {
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * len];
//compute average level
avg[aatx * frame_parms->nb_antennas_rx + aarx] = simde_mm_average(ul_ch128, len, x, y);
//LOG_D(PHY, "Channel level: %d\n", avg[aatx * frame_parms->nb_antennas_rx + aarx]);
}
}
}
static void nr_ulsch_channel_compensation(uint32_t buffer_length,
int nb_rx_ant,
c16_t rxFext[][buffer_length],
@@ -1394,8 +1370,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
rel15_ul,
frame_parms);
int avgs = 0;
int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers];
uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0;
//----------------------------------------------------------
@@ -1410,15 +1384,17 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
rel15_ul->nrOfLayers,
rel15_ul->rb_size,
shift_ch_ext);
nr_ulsch_channel_level(size_est,
ul_ch_estimates_ext,
frame_parms,
avg,
meas_symbol, // index of the start symbol
nb_re_pusch, // number of the re in pusch
rel15_ul->nrOfLayers);
int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers];
nr_channel_level(meas_symbol,
size_est,
(c16_t (*)[size_est])ul_ch_estimates_ext,
frame_parms->nb_antennas_rx,
rel15_ul->nrOfLayers,
avg,
nb_re_pusch);
int avgs = 0;
for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++)
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++)
avgs = cmax(avgs, avg[nl * frame_parms->nb_antennas_rx + aarx]);
+7 -16
View File
@@ -36,6 +36,7 @@
#include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h"
#include "PHY/phy_extern.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
#include "PHY/sse_intrin.h"
#include "common/utils/nr/nr_common.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
@@ -197,20 +198,6 @@ static void nr_pdcch_llr(uint32_t sz, c16_t *rxF, c16_t *llr)
}
}
//compute average channel_level on each (TX,RX) antenna pair
static int32_t nr_pdcch_channel_level(int nb_re, int arraySz, c16_t dl_ch_estimates_ext[][arraySz], int nb_antennas_rx)
{
int32_t avgs = 0;
for (int aarx = 0; aarx < nb_antennas_rx; aarx++) {
simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx];
// compute average level
// if nb_re is not %4, some samples are missed inside simde_mm_average, so let's discard it
int32_t tmp = simde_mm_average(dl_ch128, nb_re & ~3, 0, nb_re & ~3);
avgs = cmax(avgs, tmp);
}
return avgs;
}
// This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources)
static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
uint32_t coreset_nbr_rb,
@@ -372,9 +359,13 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue,
rel15->coreset.frequency_domain_resource,
rel15->BWPStart);
LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
LOG_D(NR_PHY_DCI, "in channel level function (dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
// compute channel level based on ofdm symbol 0
int32_t avgs = nr_pdcch_channel_level(n_rb, arraySz, pdcch_dl_ch_estimates_ext, antRx);
int avg[antRx];
nr_channel_level(0, arraySz, pdcch_dl_ch_estimates_ext, antRx, 1, avg, n_rb);
int avgs = avg[0];
for (int i = 1; i < antRx; i++)
avgs = cmax(avgs, avg[i]);
uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx;
#ifdef UE_DEBUG_TRACE
@@ -193,20 +193,6 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol,
unsigned char output_shift,
PHY_NR_MEASUREMENTS *measurements);
/** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal
@param dl_ch_estimates_ext Channel estimates in allocated RBs
@param frame_parms Pointer to frame descriptor
@param avg Pointer to average signal strength
@param pilots_flag Flag to indicate pilots in symbol
@param nb_rb Number of allocated RBs
*/
static void nr_dlsch_channel_level(uint32_t rx_size_symbol,
int32_t dl_ch_estimates_ext[][rx_size_symbol],
uint8_t n_rx,
uint8_t n_tx,
int32_t avg[MAX_ANT][MAX_ANT],
uint32_t len);
void nr_dlsch_scale_channel(uint32_t rx_size_symbol,
int32_t dl_ch_estimates_ext[][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms,
@@ -538,25 +524,25 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
//----------------------------------------------------------
start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_LEVEL_STATS);
if (first_symbol_flag) {
int32_t avg[MAX_ANT][MAX_ANT] = {};
int32_t avg[nl * n_rx];
if (nb_re_pdsch)
nr_dlsch_channel_level(rx_size_symbol, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, nl, avg, nb_re_pdsch);
nr_channel_level(0, rx_size_symbol, (c16_t (*)[rx_size_symbol])dl_ch_estimates_ext, n_rx, nl, avg, nb_re_pdsch);
else
LOG_E(NR_PHY, "Average channel level is 0: nb_rb_pdsch = %d, nb_re_pdsch = %d\n", nb_rb_pdsch, nb_re_pdsch);
int avgs = 0;
int32_t median[MAX_ANT][MAX_ANT];
for (int aatx = 0; aatx < nl; aatx++)
for (int l = 0; l < nl; l++)
for (int aarx = 0; aarx < n_rx; aarx++) {
avgs = cmax(avgs, avg[aatx][aarx]);
LOG_D(PHY, "nb_rb %d avg_%d_%d Power per SC is %d\n", nb_rb_pdsch, aarx, aatx, avg[aatx][aarx]);
avgs = cmax(avgs, avg[l * n_rx + aarx]);
LOG_D(PHY, "nb_rb %d avg_%d_%d Power per SC is %d\n", nb_rb_pdsch, aarx, l, avg[l * n_rx + aarx]);
LOG_D(PHY, "avgs Power per SC is %d\n", avgs);
median[aatx][aarx] = avg[aatx][aarx];
median[l][aarx] = avg[l * n_rx + aarx];
}
if (nl > 1) {
nr_dlsch_channel_level_median(rx_size_symbol, dl_ch_estimates_ext, median, nl, n_rx, nb_re_pdsch);
for (int aatx = 0; aatx < nl; aatx++) {
for (int l = 0; l < nl; l++) {
for (int aarx = 0; aarx < n_rx; aarx++) {
avgs = cmax(avgs, median[aatx][aarx]);
avgs = cmax(avgs, median[l][aarx]);
}
}
}
@@ -795,53 +781,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
return (0);
}
void nr_dlsch_deinterleaving(uint8_t symbol,
uint8_t start_symbol,
uint16_t L,
uint16_t *llr,
uint16_t *llr_deint,
uint16_t nb_rb_pdsch)
{
uint32_t bundle_idx, N_bundle, R, C, r,c;
int32_t m,k;
uint8_t nb_re;
R=2;
N_bundle = nb_rb_pdsch/L;
C=N_bundle/R;
uint32_t bundle_deint[N_bundle];
memset(bundle_deint, 0 , sizeof(bundle_deint));
printf("N_bundle %u L %d nb_rb_pdsch %d\n",N_bundle, L,nb_rb_pdsch);
if (symbol==start_symbol)
nb_re = 6;
else
nb_re = 12;
AssertFatal(llr!=NULL,"nr_dlsch_deinterleaving: FATAL llr is Null\n");
for (c =0; c< C; c++){
for (r=0; r<R;r++){
bundle_idx = r*C+c;
bundle_deint[bundle_idx] = c*R+r;
//printf("c %u r %u bundle_idx %u bundle_deinter %u\n", c, r, bundle_idx, bundle_deint[bundle_idx]);
}
}
for (k=0; k<N_bundle;k++)
{
for (m=0; m<nb_re*L;m++){
llr_deint[bundle_deint[k]*nb_re*L+m]= llr[k*nb_re*L+m];
//printf("k %d m %d bundle_deint %d llr_deint %d\n", k, m, bundle_deint[k], llr_deint[bundle_deint[k]*nb_re*L+m]);
}
}
}
//==============================================================================================
// Pre-processing for LLR computation
//==============================================================================================
@@ -1032,41 +971,6 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol,
}
}
/** @brief This function computes the average channel level over all allocated RBs
* and antennas (TX/RX) in order to compute output shift for compensated signal
@param rx_size_symbol
@param dl_ch_estimates_ext Channel estimates in allocated RBs
@param n_rx number of antennas in RX
@param n_tx number of antennas in TX
@param avg Pointer to average signal strength
@param len Number of allocated PDSCH REs
*/
void nr_dlsch_channel_level(uint32_t rx_size_symbol,
int32_t dl_ch_estimates_ext[][rx_size_symbol],
uint8_t n_rx,
uint8_t n_tx,
int32_t avg[MAX_ANT][MAX_ANT],
uint32_t len)
{
int16_t x = factor2(len);
int16_t y = (len) >> x;
uint32_t nb_rb_0 = len / NR_NB_SC_PER_RB + ((len % NR_NB_SC_PER_RB) ? 1 : 0);
LOG_D(NR_PHY, "nb_rb_0 %d len %d = %d * 2^(%d)\n", nb_rb_0, len, y, x);
for (int aatx = 0; aatx < n_tx; aatx++) {
for (int aarx = 0; aarx < n_rx; aarx++) {
simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(aatx * n_rx) + aarx];
//compute average level
avg[aatx][aarx] = simde_mm_average(dl_ch128, nb_rb_0 * 12, x, y);
//LOG_D(PHY, "Channel level: %d\n", avg[aatx][aarx]);
}
}
}
static void nr_dlsch_channel_level_median(uint32_t rx_size_symbol,
int32_t dl_ch_estimates_ext[][rx_size_symbol],
int32_t median[MAX_ANT][MAX_ANT],
+8 -30
View File
@@ -38,6 +38,7 @@
#include <openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h>
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
#include "instrumentation.h"
//#define DEBUG_PBCH
//#define DEBUG_PBCH_ENCODING
@@ -201,31 +202,6 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz,
return(0);
}
//__m128i avg128;
//compute average channel_level on each (TX,RX) antenna pair
int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
const NR_DL_FRAME_PARMS *frame_parms,
int nb_re)
{
int32_t avg2 = 0;
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[aarx];
//compute average level
int32_t avg1 = simde_mm_average(dl_ch128, nb_re, 0, nb_re);
if (avg1>avg2)
avg2 = avg1;
//LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2);
}
return(avg2);
}
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
int nb_re,
@@ -346,7 +322,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
const struct complex16 rxdataF[][rxdataFSize])
{
TracyCZone(ctx, true);
int max_h=0;
int symbol;
uint8_t Lmax=frame_parms->Lmax;
int M = NR_POLAR_PBCH_E;
@@ -390,11 +365,14 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
LOG_I(PHY,"[PHY] PBCH starting channel_level\n");
#endif
int max_h = 0;
if (symbol == 1) {
max_h = nr_pbch_channel_level(dl_ch_estimates_ext,
frame_parms,
nb_re);
log2_maxh = 3+(log2_approx(max_h)/2);
int avg[frame_parms->nb_antennas_rx];
nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re);
max_h = avg[0];
for (int i = 1; i < frame_parms->nb_antennas_rx; i++)
max_h = cmax(avg[i], max_h);
log2_maxh = 3 + (log2_approx(max_h) / 2);
}
#ifdef DEBUG_PBCH
+6 -2
View File
@@ -25,6 +25,7 @@
#include "common/utils/LOG/log.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/TOOLS/phy_scope_interface.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
// #define DEBUG_PSBCH
@@ -158,8 +159,11 @@ int nr_rx_psbch(PHY_VARS_NR_UE *ue,
int max_h = 0;
if (symbol == 0) {
max_h = nr_pbch_channel_level(dl_ch_estimates_ext, frame_parms, nb_re);
// log2_maxh = 3+(log2_approx(max_h)/2);
int avg[frame_parms->nb_antennas_rx];
nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re);
max_h = avg[0];
for (int i = 1; i < frame_parms->nb_antennas_rx; i++)
max_h = cmax(avg[i], max_h);
log2_maxh = 5 + (log2_approx(max_h) / 2); // LLR32 crc error. LLR 16 CRC works
}
#ifdef DEBUG_PSBCH
@@ -59,13 +59,6 @@ typedef struct pdsch_scope_req_s {
*/
void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations);
void nr_dlsch_deinterleaving(uint8_t symbol,
uint8_t start_symbol,
uint16_t L,
uint16_t *llr,
uint16_t *llr_deint,
uint16_t nb_rb_pdsch);
void nr_conjch0_mult_ch1(c16_t *ch0, c16_t *ch1, c16_t *ch0conj_ch1, unsigned short nb_rb, unsigned char output_shift0);
/** \brief This is the alternative top-level entry point for DLSCH decoding in UE.
@@ -346,9 +339,6 @@ void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx, sl_nr_
nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames);
// Reuse already existing PBCH functions
int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
const NR_DL_FRAME_PARMS *frame_parms,
int nb_re);
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
int nb_re,
@@ -47,6 +47,13 @@ void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_si
void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay);
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb);
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);
void nr_channel_level(const int symbol,
const int size_est,
const c16_t ch_estimates_ext[][size_est],
const int nb_rx,
const int Nl,
int32_t avg[nb_rx * Nl],
const uint32_t len);
void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms,
const csi_mapping_parms_t *phy_csi_parms,
const int16_t amp,
@@ -404,6 +404,28 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, in
return (0);
}
// compute average channel_level on each antenna
void nr_channel_level(const int symbol,
const int size_est,
const c16_t ch_estimates_ext[][size_est],
const int nb_rx,
const int Nl,
int32_t avg[nb_rx * Nl],
const uint32_t len)
{
int16_t x = factor2(len);
int16_t y = len >> x;
for (int aarx = 0; aarx < nb_rx; aarx++) {
for (int l = 0; l < Nl; l++) {
simde__m128i *ch128 = (simde__m128i *)&ch_estimates_ext[l * nb_rx + aarx][symbol * len];
//compute average level
avg[l * nb_rx + aarx] = simde_mm_average(ch128, len, x, y);
LOG_D(PHY, "Channel level: %d\n", avg[l * nb_rx + aarx]);
}
}
}
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)
{
const double phase_inc = -fo_Hz / (samples_per_ms * 1000);