Commit fa237ffa authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/oai_ue_perf_opt' into integration_2026_w24

UE DL Channel compensation and LLR optimization (#142)

- Common channel compensation: Extracted nr_channel_compensation() as a
  shared function (AVX2/MRC inline) used by both gNB and UE PDSCH/PUSCH
  paths, eliminating duplicated compensation logic.
- Common ML/MMSE 2-layer MIMO: Created shared ML LLR and MMSE routines
  for 2-layer spatial multiplexing, shared between gNB and UE
  demodulation.
- File segregation: Moved common LLR and channel compensation functions
  into dedicated source files for better modularity and reuse.
- nr_dlsim -E flag: Added a command-line argument to enable/disable
  ML/MMSE equalization at runtime (MMSE default), enabling side-by-side
  performance comparison without recompilation.
- Persistent UE buffer allocation: pdsch_dl_ch_estimates, rxdataF_comp,
  dl_ch_mag,dl_ch_magb,dl_ch_magr and rho_dl are now allocated once in
  PHY_VARS_NR_UE on first use, resize automatically when dimensions
  change (resizeAllowed=true), and are freed at UE teardown in
  term_nr_ue_signal. Eliminates per-slot heap allocation/free overhead.
- PTRS restricted to one antenna port: PTRS phase tracking is only valid
  for a single port; processing now correctly restricted to avoid
  unnecessary computation.
- Reduce rxdataF_comp buffer size: MRC combines all Rx antenna
  contributions into a per-layer output, so the first dimension was
  reduced from Nl * nb_antennas_rx to Nl, reducing buffer footprint
  proportionally.
- 256QAM segfault fix: nr_256qam_llr() on gNB side used a VLA for LLRs
  without alignment, causing AVX2 load faults. Fixed with
  attribute((aligned(32))).
Reviewed-by: default avatarSakthivel Velumani <s.velumani@northeastern.edu>
parents 8c255558 460cbf95
...@@ -924,7 +924,6 @@ set(PHY_SRC_UE ...@@ -924,7 +924,6 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c
......
...@@ -176,14 +176,14 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) ...@@ -176,14 +176,14 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id]; NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
pusch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); pusch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); pusch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *));
pusch->rxdataF_comp = (c16_t **)malloc16(n_buf * sizeof(*pusch->rxdataF_comp));
for (int i = 0; i < n_buf; i++) { for (int i = 0; i < n_buf; i++) {
pusch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size * fp->symbols_per_slot); pusch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size * fp->symbols_per_slot);
pusch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->symbols_per_slot); // symbols per slot pusch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->symbols_per_slot); // symbols per slot
pusch->rxdataF_comp[i] = (c16_t *)malloc16_clear(sizeof(**pusch->rxdataF_comp) * nb_re_pusch2 * fp->symbols_per_slot);
} }
pusch->rxdataF_comp = (c16_t **)malloc16(max_ul_mimo_layers * sizeof(*pusch->rxdataF_comp));
for (int i = 0; i < max_ul_mimo_layers; i++) { for (int i = 0; i < max_ul_mimo_layers; i++) {
pusch->rxdataF_comp[i] = (c16_t *)malloc16_clear(sizeof(**pusch->rxdataF_comp) * nb_re_pusch2 * fp->symbols_per_slot);
} }
pusch->llr = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12)) pusch->llr = (int16_t *)malloc16_clear((8 * ((3 * 8 * 6144) + 12))
* sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear * sizeof(int16_t)); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
...@@ -232,8 +232,10 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) ...@@ -232,8 +232,10 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
for (int i = 0; i < n_buf; i++) { for (int i = 0; i < n_buf; i++) {
free_and_zero(pusch_vars->ul_ch_estimates[i]); free_and_zero(pusch_vars->ul_ch_estimates[i]);
free_and_zero(pusch_vars->ptrs_phase_per_slot[i]); free_and_zero(pusch_vars->ptrs_phase_per_slot[i]);
free_and_zero(pusch_vars->rxdataF_comp[i]);
} }
for (int i = 0; i < max_ul_mimo_layers; i++)
free_and_zero(pusch_vars->rxdataF_comp[i]);
free_and_zero(pusch_vars->ul_ch_estimates); free_and_zero(pusch_vars->ul_ch_estimates);
free_and_zero(pusch_vars->ptrs_phase_per_slot); free_and_zero(pusch_vars->ptrs_phase_per_slot);
free_and_zero(pusch_vars->ul_valid_re_per_slot); free_and_zero(pusch_vars->ul_valid_re_per_slot);
......
...@@ -106,62 +106,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, ...@@ -106,62 +106,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
*/ */
void nr_idft(int32_t *z, uint32_t Msc_PUSCH); void nr_idft(int32_t *z, uint32_t Msc_PUSCH);
void nr_ulsch_qpsk_qpsk(c16_t *stream0_in,
c16_t *stream1_in,
c16_t *stream0_out,
c16_t *rho01,
uint32_t length);
void nr_ulsch_qam16_qam16(c16_t *stream0_in,
c16_t *stream1_in,
c16_t *ch_mag,
c16_t *ch_mag_i,
c16_t *stream0_out,
c16_t *rho01,
uint32_t length);
void nr_ulsch_qam64_qam64(c16_t *stream0_in,
c16_t *stream1_in,
c16_t *ch_mag,
c16_t *ch_mag_i,
c16_t *stream0_out,
c16_t *rho01,
uint32_t length);
/** \brief This function computes the log-likelihood ratios for 4, 16, and 64 QAM
@param rxdataF_comp Compensated channel output
@param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64
@param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 64
@param ulsch_llr llr output
@param nb_re number of REs for this allocation
@param symbol OFDM symbol index in sub-frame
@param mod_order modulation order
*/
void nr_ulsch_compute_llr(c16_t *rxdataF_comp,
c16_t *ul_ch_mag,
c16_t *ul_ch_magb,
c16_t *ul_ch_magc,
int16_t *ulsch_llr,
uint32_t nb_re,
uint8_t symbol,
uint8_t mod_order);
void reset_active_stats(PHY_VARS_gNB *gNB, int frame); void reset_active_stats(PHY_VARS_gNB *gNB, int frame);
void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame);
void nr_ulsch_compute_ML_llr(c16_t *rxdataF_comp0,
c16_t *rxdataF_comp1,
c16_t *ul_ch_mag0,
c16_t *ul_ch_mag1,
int16_t *llr_layers0,
int16_t *llr_layers1,
c16_t *rho0,
c16_t *rho1,
uint32_t nb_re,
uint8_t mod_order);
void nr_ulsch_shift_llr(int16_t **llr_layers, uint32_t nb_re, uint32_t rxdataF_ext_offset, uint8_t mod_order, int shift);
void nr_fill_ulsch(PHY_VARS_gNB *gNB, void nr_fill_ulsch(PHY_VARS_gNB *gNB,
int frame, int frame,
int slot, int slot,
......
...@@ -1345,7 +1345,7 @@ void nr_pdsch_ptrs_processing(int nbRx, ...@@ -1345,7 +1345,7 @@ void nr_pdsch_ptrs_processing(int nbRx,
int32_t ptrs_re_per_slot[][14], int32_t ptrs_re_per_slot[][14],
uint32_t rx_size_symbol, uint32_t rx_size_symbol,
int nl, int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol], c16_t rxdataF_comp[][nl][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
uint8_t nr_slot_rx, uint8_t nr_slot_rx,
...@@ -1369,7 +1369,7 @@ void nr_pdsch_ptrs_processing(int nbRx, ...@@ -1369,7 +1369,7 @@ void nr_pdsch_ptrs_processing(int nbRx,
int nscid = dlsch_config->nscid; int nscid = dlsch_config->nscid;
/* loop over antennas */ /* loop over antennas */
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < nbRx; aarx++) {
c16_t *phase_per_symbol = (c16_t*)ptrs_phase_per_slot[aarx]; c16_t *phase_per_symbol = (c16_t*)ptrs_phase_per_slot[aarx];
ptrs_re_symbol = (int32_t*)ptrs_re_per_slot[aarx]; ptrs_re_symbol = (int32_t*)ptrs_re_per_slot[aarx];
ptrs_re_symbol[symbol] = 0; ptrs_re_symbol[symbol] = 0;
...@@ -1404,7 +1404,7 @@ void nr_pdsch_ptrs_processing(int nbRx, ...@@ -1404,7 +1404,7 @@ void nr_pdsch_ptrs_processing(int nbRx,
nb_rb, nb_rb,
rnti, rnti,
frame_parms->ofdm_symbol_size, frame_parms->ofdm_symbol_size,
rxdataF_comp[symbol][0][aarx], rxdataF_comp[symbol][aarx],
gold, gold,
(int16_t *)&phase_per_symbol[symbol], (int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]); &ptrs_re_symbol[symbol]);
...@@ -1436,9 +1436,9 @@ void nr_pdsch_ptrs_processing(int nbRx, ...@@ -1436,9 +1436,9 @@ void nr_pdsch_ptrs_processing(int nbRx,
#ifdef DEBUG_DL_PTRS #ifdef DEBUG_DL_PTRS
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i); printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i);
#endif #endif
rotate_cpx_vector(rxdataF_comp[i][0][aarx], &phase_per_symbol[i], rxdataF_comp[i][0][aarx], nb_rb * NR_NB_SC_PER_RB, 15); rotate_cpx_vector(rxdataF_comp[i][aarx], &phase_per_symbol[i], rxdataF_comp[i][aarx], nb_rb * NR_NB_SC_PER_RB, 15);
}// if not DMRS Symbol }// if not DMRS Symbol
}// symbol loop }// symbol loop
}// last symbol check }// last symbol check
}//Antenna loop } // Antenna loop
}//main function }//main function
...@@ -119,7 +119,7 @@ void nr_pdsch_ptrs_processing(int nbRx, ...@@ -119,7 +119,7 @@ void nr_pdsch_ptrs_processing(int nbRx,
int32_t ptrs_re_per_slot[][14], int32_t ptrs_re_per_slot[][14],
uint32_t rx_size_symbol, uint32_t rx_size_symbol,
int nl, int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol], c16_t rxdataF_comp[][nl][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
uint8_t nr_slot_rx, uint8_t nr_slot_rx,
......
...@@ -277,14 +277,15 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, ...@@ -277,14 +277,15 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
int32_t *log2_maxh, int32_t *log2_maxh,
int rx_size_symbol, int rx_size_symbol,
int nbRx, int nbRx,
c16_t rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], c16_t rxdataF_comp[][dlsch->cw_info.Nl][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], c16_t dl_ch_mag[][dlsch->cw_info.Nl][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], c16_t dl_ch_magb[][dlsch->cw_info.Nl][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->cw_info.Nl][nbRx][rx_size_symbol], c16_t dl_ch_magr[][dlsch->cw_info.Nl][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT], c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT], int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
uint32_t nvar, uint32_t nvar,
pdsch_scope_req_t *scope_req); pdsch_scope_req_t *scope_req,
c16_t rho_dl[][dlsch->cw_info.Nl * dlsch->cw_info.Nl][rx_size_symbol]);
int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t slot, c16_t **txData); int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t slot, c16_t **txData);
void apply_ntn_config(PHY_VARS_NR_UE *UE, void apply_ntn_config(PHY_VARS_NR_UE *UE,
......
...@@ -412,6 +412,10 @@ typedef struct PHY_VARS_NR_UE_s { ...@@ -412,6 +412,10 @@ typedef struct PHY_VARS_NR_UE_s {
/// Phase precompensation flag /// Phase precompensation flag
bool no_phase_pre_comp; bool no_phase_pre_comp;
/// Enable ML-based LLR computation for 2-layer MIMO (QPSK/16QAM/64QAM).
/// When false (default), MMSE equalization is used for all configurations.
bool do_ml;
void* scopeData; void* scopeData;
// Pointers to hold PDSCH data only for phy simulators // Pointers to hold PDSCH data only for phy simulators
void *phy_sim_rxdataF; void *phy_sim_rxdataF;
......
# SPDX-License-Identifier: LicenseRef-CSSL-1.0 # SPDX-License-Identifier: LicenseRef-CSSL-1.0
add_library(nr_phy_common src/nr_phy_common.c) add_library(nr_phy_common src/nr_phy_common.c
src/nr_channel_compensation.c
src/nr_compute_llr.c)
target_link_libraries(nr_phy_common PRIVATE UTIL PHY_COMMON) target_link_libraries(nr_phy_common PRIVATE UTIL PHY_COMMON)
target_include_directories(nr_phy_common PUBLIC inc/) target_include_directories(nr_phy_common PUBLIC inc/)
......
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#ifndef __NR_CHANNEL_COMPENSATION__H__
#define __NR_CHANNEL_COMPENSATION__H__
#include "PHY/impl_defs_top.h"
/**
* @brief Common channel compensation function shared by DL (PDSCH) and UL (PUSCH) paths.
*
* Computes matched-filter output (rxComp) and channel magnitude arrays used for LLR
* computation. MRC across Rx antennas is performed inline: for each layer, contributions
* from all Rx antennas are accumulated into rxComp[layer * nb_rx_ant][symbol * buffer_length].
* Uses AVX2 (256-bit SIMD) for throughput.
*
* @param buffer_length Number of complex samples per symbol (must be a multiple of 8)
* @param nb_rx_ant Number of Rx antennas
* @param nb_layers Number of spatial layers
* @param rxFext Extracted received signal [nb_rx_ant][buffer_length]
* @param chFext Extracted channel estimates [nb_layers][nb_rx_ant][buffer_length]
* @param ch_maga Output magnitude array for threshold 'a' [nb_layers][buffer_length]
* @param ch_magb Output magnitude array for threshold 'b' [nb_layers][buffer_length]
* @param ch_magc Output magnitude array for threshold 'c' [nb_layers][buffer_length]
* @param rxComp Output compensated signal; row [l * nb_rx_ant] holds the MRC result
* for layer l at offset [symbol * buffer_length]
* @param rho Tx-correlation matrix [nb_layers][nb_layers][buffer_length], or NULL
* @param mod_order Modulation order (2=QPSK, 4=16QAM, 6=64QAM, 8=256QAM)
* @param symbol OFDM symbol index (used to compute offset into rxComp rows)
* @param output_shift Right-shift applied after each complex multiply
*/
void nr_channel_compensation(uint32_t buffer_length,
int nb_rx_ant,
int nb_layers,
c16_t rxFext[nb_rx_ant][buffer_length],
c16_t chFext[nb_layers][nb_rx_ant][buffer_length],
c16_t ch_maga[nb_layers][buffer_length],
c16_t ch_magb[nb_layers][buffer_length],
c16_t ch_magc[nb_layers][buffer_length],
c16_t **rxComp,
c16_t (*rho)[nb_layers][buffer_length],
int mod_order,
uint32_t symbol,
uint32_t output_shift);
#endif /* __NR_CHANNEL_COMPENSATION__H__ */
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#ifndef __NR_COMPUTE_LLR__H__
#define __NR_COMPUTE_LLR__H__
#include "PHY/impl_defs_top.h"
void nr_compute_llr(c16_t *rxdataF_comp,
c16_t *ch_mag,
c16_t *ch_magb,
c16_t *ch_magc,
int16_t *llr,
uint32_t nb_re,
uint8_t symbol,
uint8_t mod_order);
void nr_qpsk_llr_2layer(c16_t *stream0_in, c16_t *stream1_in, int16_t *stream0_out, c16_t *rho01, uint32_t length);
void nr_qam16_llr_2layer(c16_t *stream0_in,
c16_t *stream1_in,
c16_t *ch_mag,
c16_t *ch_mag_i,
int16_t *stream0_out,
c16_t *rho01,
uint32_t length);
void nr_qam64_llr_2layer(c16_t *stream0_in,
c16_t *stream1_in,
c16_t *ch_mag,
c16_t *ch_mag_i,
int16_t *stream0_out,
c16_t *rho01,
uint32_t length);
void nr_compute_ML_llr(c16_t *rxdataF_comp0,
c16_t *rxdataF_comp1,
c16_t *ch_mag0,
c16_t *ch_mag1,
int16_t *llr_layers0,
int16_t *llr_layers1,
c16_t *rho0,
c16_t *rho1,
uint32_t nb_re,
uint8_t mod_order);
uint8_t nr_mmse_2layers(c16_t **rxdataF_comp,
uint32_t buffer_length,
int nb_rx_ant,
int nb_layers,
c16_t ch_mag[nb_layers][buffer_length],
c16_t ch_magb[nb_layers][buffer_length],
c16_t ch_magc[nb_layers][buffer_length],
c16_t ch_estimates_ext[][nb_rx_ant][buffer_length],
unsigned short nb_rb,
unsigned char mod_order,
int shift,
unsigned char symbol,
int length,
uint32_t noise_var);
#endif /* __NR_COMPUTE_LLR__H__ */
...@@ -376,4 +376,7 @@ int nr_get_ssb_start_sc(int scs, ...@@ -376,4 +376,7 @@ int nr_get_ssb_start_sc(int scs,
int ssb_offset_point_a, int ssb_offset_point_a,
int ssb_sco, int ssb_sco,
frequency_range_t freq_range); frequency_range_t freq_range);
#include "nr_channel_compensation.h"
#include "nr_compute_llr.h"
#endif #endif
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#include "nr_channel_compensation.h"
#include "bits.h"
#include <complex.h>
#include "PHY/sse_intrin.h"
#include "PHY/impl_defs_top.h"
#ifdef __aarch64__
#define USE_128BIT
#endif
void nr_channel_compensation(uint32_t buffer_length,
int nb_rx_ant,
int nb_layers,
c16_t rxFext[nb_rx_ant][buffer_length],
c16_t chFext[nb_layers][nb_rx_ant][buffer_length],
c16_t ch_maga[nb_layers][buffer_length],
c16_t ch_magb[nb_layers][buffer_length],
c16_t ch_magc[nb_layers][buffer_length],
c16_t **rxComp,
c16_t (*rho)[nb_layers][buffer_length],
int mod_order,
uint32_t symbol,
uint32_t output_shift)
{
simde__m256i QAM_ampa_256 = simde_mm256_setzero_si256();
simde__m256i QAM_ampb_256 = simde_mm256_setzero_si256();
simde__m256i QAM_ampc_256 = simde_mm256_setzero_si256();
if (mod_order == 4) {
QAM_ampa_256 = simde_mm256_set1_epi16(QAM16_n1);
} else if (mod_order == 6) {
QAM_ampa_256 = simde_mm256_set1_epi16(QAM64_n1);
QAM_ampb_256 = simde_mm256_set1_epi16(QAM64_n2);
} else if (mod_order == 8) {
QAM_ampa_256 = simde_mm256_set1_epi16(QAM256_n1);
QAM_ampb_256 = simde_mm256_set1_epi16(QAM256_n2);
QAM_ampc_256 = simde_mm256_set1_epi16(QAM256_n3);
}
for (int aatx = 0; aatx < nb_layers; aatx++) {
simde__m256i *rxComp_256 = (simde__m256i *)&rxComp[aatx][symbol * buffer_length];
simde__m256i *ch_maga_256 = (simde__m256i *)ch_maga[aatx];
simde__m256i *ch_magb_256 = (simde__m256i *)ch_magb[aatx];
simde__m256i *ch_magc_256 = (simde__m256i *)ch_magc[aatx];
// First Rx antenna: direct store — eliminates need to pre memset the output buffers
{
simde__m256i *rxF_256 = (simde__m256i *)rxFext[0];
simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][0];
for (uint32_t i = 0; i < buffer_length >> 3; i++) {
rxComp_256[i] = oai_mm256_cpx_mult_conj(chF_256[i], rxF_256[i], output_shift);
if (mod_order > 2) {
simde__m256i mag = oai_mm256_smadd(chF_256[i], chF_256[i], output_shift);
mag = simde_mm256_packs_epi32(mag, mag);
mag = simde_mm256_unpacklo_epi16(mag, mag);
ch_maga_256[i] = simde_mm256_mulhrs_epi16(mag, QAM_ampa_256);
if (mod_order > 4)
ch_magb_256[i] = simde_mm256_mulhrs_epi16(mag, QAM_ampb_256);
if (mod_order > 6)
ch_magc_256[i] = simde_mm256_mulhrs_epi16(mag, QAM_ampc_256);
}
}
if (rho) {
for (int atx = 0; atx < nb_layers; atx++) {
simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx];
simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][0];
for (uint32_t i = 0; i < buffer_length >> 3; i++)
rho_256[i] = oai_mm256_cpx_mult_conj(chF_256[i], chF2_256[i], output_shift);
}
}
}
// Remaining Rx antennas: accumulate (MRC)
for (int aarx = 1; aarx < nb_rx_ant; aarx++) {
simde__m256i *rxF_256 = (simde__m256i *)rxFext[aarx];
simde__m256i *chF_256 = (simde__m256i *)chFext[aatx][aarx];
for (uint32_t i = 0; i < buffer_length >> 3; i++) {
simde__m256i comp = oai_mm256_cpx_mult_conj(chF_256[i], rxF_256[i], output_shift);
rxComp_256[i] = simde_mm256_add_epi16(rxComp_256[i], comp);
if (mod_order > 2) {
simde__m256i mag = oai_mm256_smadd(chF_256[i], chF_256[i], output_shift);
mag = simde_mm256_packs_epi32(mag, mag);
mag = simde_mm256_unpacklo_epi16(mag, mag);
ch_maga_256[i] = simde_mm256_add_epi16(ch_maga_256[i], simde_mm256_mulhrs_epi16(mag, QAM_ampa_256));
if (mod_order > 4)
ch_magb_256[i] = simde_mm256_add_epi16(ch_magb_256[i], simde_mm256_mulhrs_epi16(mag, QAM_ampb_256));
if (mod_order > 6)
ch_magc_256[i] = simde_mm256_add_epi16(ch_magc_256[i], simde_mm256_mulhrs_epi16(mag, QAM_ampc_256));
}
}
if (rho) {
for (int atx = 0; atx < nb_layers; atx++) {
simde__m256i *rho_256 = (simde__m256i *)rho[aatx][atx];
simde__m256i *chF2_256 = (simde__m256i *)chFext[atx][aarx];
for (uint32_t i = 0; i < buffer_length >> 3; i++)
rho_256[i] = simde_mm256_adds_epi16(rho_256[i], oai_mm256_cpx_mult_conj(chF_256[i], chF2_256[i], output_shift));
}
}
}
}
}
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include "nr_phy_common.h" #include "nr_phy_common.h"
#include "bits.h" #include "bits.h"
#include <complex.h> #include <complex.h>
#include "PHY/sse_intrin.h"
#include "PHY/impl_defs_top.h"
#ifdef __aarch64__ #ifdef __aarch64__
#define USE_128BIT #define USE_128BIT
#endif #endif
...@@ -486,5 +488,4 @@ int nr_get_ssb_start_sc(int scs, int ssb_offset_point_a, int ssb_sco, frequency_ ...@@ -486,5 +488,4 @@ int nr_get_ssb_start_sc(int scs, int ssb_offset_point_a, int ssb_sco, frequency_
prb_offset, ssb_sco, scs, freq_range, ssb_start_subcarrier); prb_offset, ssb_sco, scs, freq_range, ssb_start_subcarrier);
return ssb_start_subcarrier; return ssb_start_subcarrier;
} }
...@@ -475,14 +475,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -475,14 +475,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
const uint32_t rx_size_symbol = (freq_alloc->num_rbs * NR_NB_SC_PER_RB + 15) & ~15; const uint32_t rx_size_symbol = (freq_alloc->num_rbs * NR_NB_SC_PER_RB + 15) & ~15;
fourDimArray_t *toFree2 = NULL; fourDimArray_t *toFree2 = NULL;
allocCast4D(rxdataF_comp, allocCast3D(rxdataF_comp, c16_t, toFree2, ue->frame_parms.symbols_per_slot, dlsch->cw_info.Nl, rx_size_symbol, false);
c16_t,
toFree2,
ue->frame_parms.symbols_per_slot,
dlsch->cw_info.Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol,
false);
uint32_t nvar = 0; uint32_t nvar = 0;
...@@ -566,32 +559,19 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -566,32 +559,19 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
&mt); &mt);
} }
fourDimArray_t *toFree3 = NULL; fourDimArray_t *toFree3 = NULL;
allocCast4D(dl_ch_mag, allocCast3D(dl_ch_mag, c16_t, toFree3, NR_SYMBOLS_PER_SLOT, dlsch->cw_info.Nl, rx_size_symbol, false);
c16_t,
toFree3,
NR_SYMBOLS_PER_SLOT,
dlsch->cw_info.Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol,
false);
fourDimArray_t *toFree4 = NULL; fourDimArray_t *toFree4 = NULL;
allocCast4D(dl_ch_magb, allocCast3D(dl_ch_magb, c16_t, toFree4, NR_SYMBOLS_PER_SLOT, dlsch->cw_info.Nl, rx_size_symbol, false);
c16_t,
toFree4,
NR_SYMBOLS_PER_SLOT,
dlsch->cw_info.Nl,
ue->frame_parms.nb_antennas_rx,
rx_size_symbol,
false);
fourDimArray_t *toFree5 = NULL; fourDimArray_t *toFree5 = NULL;
allocCast4D(dl_ch_magr, allocCast3D(dl_ch_magr, c16_t, toFree5, NR_SYMBOLS_PER_SLOT, dlsch->cw_info.Nl, rx_size_symbol, false);
c16_t, fourDimArray_t *toFreeRho = NULL;
toFree5, const bool need_rho = ue->do_ml && dlsch->cw_info.Nl == 2 && dlsch->cw_info.qamModOrder <= 6;
NR_SYMBOLS_PER_SLOT, c16_t(*rho_dl)[dlsch->cw_info.Nl * dlsch->cw_info.Nl][rx_size_symbol] = NULL;
dlsch->cw_info.Nl, if (need_rho) {
ue->frame_parms.nb_antennas_rx, allocCast3D(rho_dl_buf, c16_t, toFreeRho, NR_SYMBOLS_PER_SLOT, dlsch->cw_info.Nl * dlsch->cw_info.Nl, rx_size_symbol, false);
rx_size_symbol, rho_dl = rho_dl_buf;
false); }
for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) { for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) {
bool first_symbol_flag = false; bool first_symbol_flag = false;
if (m == first_symbol_with_data) if (m == first_symbol_with_data)
...@@ -623,7 +603,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -623,7 +603,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
ptrs_phase_per_slot, ptrs_phase_per_slot,
ptrs_re_per_slot, ptrs_re_per_slot,
nvar, nvar,
&scope_req) &scope_req,
rho_dl)
< 0) { < 0) {
if (scope_req.copy_chanest_to_scope) { if (scope_req.copy_chanest_to_scope) {
UEunlockScopeData(ue, pdschChanEstimates); UEunlockScopeData(ue, pdschChanEstimates);
...@@ -646,6 +627,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -646,6 +627,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
free(toFree3); free(toFree3);
free(toFree4); free(toFree4);
free(toFree5); free(toFree5);
free(toFreeRho);
return 0; return 0;
} }
......
...@@ -409,6 +409,7 @@ int main(int argc, char **argv) ...@@ -409,6 +409,7 @@ int main(int argc, char **argv)
randominit(); randominit();
int print_perf = 0; int print_perf = 0;
bool do_ml = false;
int use_cuda = 0; int use_cuda = 0;
...@@ -421,7 +422,7 @@ int main(int argc, char **argv) ...@@ -421,7 +422,7 @@ int main(int argc, char **argv)
void *d_channel_coeffs_gpu = NULL; void *d_channel_coeffs_gpu = NULL;
#endif #endif
while ((c = getopt(argc, argv, "--:O:f:hA:p:f:g:i:n:s:S:t:v:x:y:z:o:H:M:N:F:GR:d:PI:L:a:b:e:m:w:T:U:q:X:Y:Z:Q:")) != -1) { while ((c = getopt(argc, argv, "--:O:f:hA:p:f:g:i:n:s:S:t:v:x:y:z:o:H:M:N:F:GR:d:PI:L:a:b:e:m:w:T:U:q:X:Y:Z:Q:E")) != -1) {
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */ /* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */ /* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
if (c == 1 || c == '-' || c == 'O') if (c == 1 || c == '-' || c == 'O')
...@@ -539,6 +540,10 @@ int main(int argc, char **argv) ...@@ -539,6 +540,10 @@ int main(int argc, char **argv)
break; break;
case 'E':
do_ml = true;
break;
case 'P': case 'P':
print_perf=1; print_perf=1;
cpu_meas_enabled = 1; cpu_meas_enabled = 1;
...@@ -654,6 +659,7 @@ int main(int argc, char **argv) ...@@ -654,6 +659,7 @@ int main(int argc, char **argv)
printf("-b Number of PRB for PDSCH\n"); printf("-b Number of PRB for PDSCH\n");
printf("-d number of dlsch threads, 0: no dlsch parallelization\n"); printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
printf("-e MSC index\n"); printf("-e MSC index\n");
printf("-E Enable ML-based LLR for 2-layer MIMO (QPSK/16QAM/64QAM). Default: MMSE equalization\n");
printf("-f <flag> Enable optional feature flag. Available flags:\n"); printf("-f <flag> Enable optional feature flag. Available flags:\n");
#ifdef CHANNEL_SIM_CUDA #ifdef CHANNEL_SIM_CUDA
printf(" cuda Enable CUDA channel simulation\n"); printf(" cuda Enable CUDA channel simulation\n");
...@@ -935,6 +941,7 @@ int main(int argc, char **argv) ...@@ -935,6 +941,7 @@ int main(int argc, char **argv)
UE->frame_parms.nb_antenna_ports_gNB = n_tx; UE->frame_parms.nb_antenna_ports_gNB = n_tx;
UE->nrLDPC_coding_interface = gNB->nrLDPC_coding_interface; UE->nrLDPC_coding_interface = gNB->nrLDPC_coding_interface;
UE->max_ldpc_iterations = max_ldpc_iterations; UE->max_ldpc_iterations = max_ldpc_iterations;
UE->do_ml = do_ml;
init_nr_ue_phy_cpu_stats(&UE->phy_cpu_stats); init_nr_ue_phy_cpu_stats(&UE->phy_cpu_stats);
UE->is_synchronized = 1; UE->is_synchronized = 1;
......
...@@ -1639,9 +1639,9 @@ int main(int argc, char *argv[]) ...@@ -1639,9 +1639,9 @@ int main(int argc, char *argv[])
1, 1,
1 | log_format); 1 | log_format);
LOG_M("rxsigF2_comp.m", LOG_M("rxsigF1_comp.m",
"rxsF2_comp", "rxsF1_comp",
&pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], &pusch_vars->rxdataF_comp[1][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1, 1,
1 | log_format); 1 | log_format);
...@@ -1667,21 +1667,15 @@ int main(int argc, char *argv[]) ...@@ -1667,21 +1667,15 @@ int main(int argc, char *argv[])
1, 1,
1 | log_format); 1 | log_format);
LOG_M("rxsigF4_comp.m", LOG_M("rxsigF2_comp.m",
"rxsF4_comp", "rxsF2_comp",
&pusch_vars->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], &pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1 | log_format);
LOG_M("rxsigF8_comp.m",
"rxsF8_comp",
&pusch_vars->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1, 1,
1 | log_format); 1 | log_format);
LOG_M("rxsigF12_comp.m", LOG_M("rxsigF3_comp.m",
"rxsF12_comp", "rxsF3_comp",
&pusch_vars->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], &pusch_vars->rxdataF_comp[3][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1, 1,
1 | log_format); 1 | log_format);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment