Merge remote-tracking branch 'origin/ue-symbol-based-receiver' into integration_2025_w43 (!3603)
UE symbol based PDCCH receiver This is a partial rebase/rewrite of !2895 The goal of this MR is to check how we can merge this. The eventual result is stated in !2895. The way forward is to modify UE RX procedures to work symbol by symbol by extracting the symbol loop out of RX procedures. After all channels are modified this way, the main thread can be modified to work symbol by symbol. At this point only PDCCH was modified.
This commit is contained in:
@@ -196,14 +196,14 @@ static void rx_func(processingData_L1_t *info)
|
||||
int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size;
|
||||
for (int bb = 0; bb < gNB->common_vars.num_beams_period; bb++) {
|
||||
for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
|
||||
apply_nr_rotation_RX(&gNB->frame_parms,
|
||||
gNB->common_vars.rxdataF[bb][aa],
|
||||
gNB->frame_parms.symbol_rotation[1],
|
||||
slot_rx,
|
||||
gNB->frame_parms.N_RB_UL,
|
||||
soffset,
|
||||
0,
|
||||
gNB->frame_parms.Ncp == EXTENDED ? 12 : 14);
|
||||
const uint max_symb = (gNB->frame_parms.Ncp == EXTENDED) ? 12 : 14;
|
||||
for (int sym = 0; sym < max_symb; sym++)
|
||||
apply_nr_rotation_symbol_RX(&gNB->frame_parms,
|
||||
gNB->common_vars.rxdataF[bb][aa] + soffset + sym * gNB->frame_parms.ofdm_symbol_size,
|
||||
gNB->frame_parms.symbol_rotation[1],
|
||||
gNB->frame_parms.N_RB_UL,
|
||||
slot_rx,
|
||||
sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -564,7 +564,8 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
|
||||
UE->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
|
||||
sampleShift = pbch_pdcch_processing(UE, proc, phy_data);
|
||||
sampleShift = pbch_processing(UE, proc, phy_data);
|
||||
pdcch_processing(UE, proc, phy_data);
|
||||
if (phy_data->dlsch[0].active
|
||||
&& (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) {
|
||||
// indicate to tx thread to wait for DLSCH decoding
|
||||
|
||||
@@ -73,6 +73,7 @@ typedef struct {
|
||||
/// frequency_domain_resource;
|
||||
uint8_t frequency_domain_resource[6];
|
||||
uint8_t StartSymbolIndex;
|
||||
uint16_t StartSymbolBitmap;
|
||||
uint8_t duration;
|
||||
uint8_t CceRegMappingType; // interleaved or noninterleaved
|
||||
uint8_t RegBundleSize; // valid if CCE to REG mapping type is interleaved type
|
||||
|
||||
@@ -117,14 +117,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
const c16_t *rot,
|
||||
int slot,
|
||||
int nb_rb,
|
||||
int soffset,
|
||||
int first_symbol,
|
||||
int nsymb);
|
||||
void apply_nr_rotation_symbol_RX(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
const c16_t *rot,
|
||||
int nb_rb,
|
||||
int slot,
|
||||
int symbol);
|
||||
|
||||
/*! \brief Perform NR precoding. TS 38.211 V15.4.0 subclause 6.3.1.5
|
||||
@param[in] datatx_F_precoding, Pointer to n_layers*re data array
|
||||
|
||||
@@ -28,6 +28,36 @@
|
||||
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
|
||||
#include <common/utils/LOG/log.h>
|
||||
|
||||
/* rxdataF should be 16 bytes aligned */
|
||||
void nr_symbol_fep(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
const int slot,
|
||||
const unsigned char symbol,
|
||||
const int link_type,
|
||||
c16_t *rxdata[frame_parms->nb_antennas_rx],
|
||||
c16_t *rxdataF[frame_parms->nb_antennas_rx],
|
||||
time_stats_t* dft_stats)
|
||||
{
|
||||
AssertFatal(symbol < frame_parms->symbols_per_slot,
|
||||
"slot_fep: symbol must be between 0 and %d\n",
|
||||
frame_parms->symbols_per_slot - 1);
|
||||
AssertFatal(slot < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame - 1);
|
||||
|
||||
dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size);
|
||||
for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
|
||||
if (dft_stats) start_meas(dft_stats);
|
||||
dft(dftsize, (int16_t *)rxdata[aa], (int16_t *)rxdataF[aa], 1);
|
||||
if (dft_stats) stop_meas(dft_stats);
|
||||
|
||||
const bool is_sl = (link_type == link_type_sl);
|
||||
apply_nr_rotation_symbol_RX(frame_parms,
|
||||
rxdataF[aa],
|
||||
frame_parms->symbol_rotation[link_type],
|
||||
is_sl ? frame_parms->N_RB_SL : frame_parms->N_RB_DL,
|
||||
slot,
|
||||
symbol);
|
||||
}
|
||||
}
|
||||
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
const NR_DL_FRAME_PARMS *frame_parms,
|
||||
unsigned int slot,
|
||||
@@ -37,35 +67,23 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
uint32_t sample_offset,
|
||||
c16_t **rxdata)
|
||||
{
|
||||
AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1);
|
||||
AssertFatal(symbol < frame_parms->symbols_per_slot,
|
||||
"slot_fep: symbol must be between 0 and %d\n",
|
||||
frame_parms->symbols_per_slot - 1);
|
||||
AssertFatal(slot < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame - 1);
|
||||
|
||||
bool is_sl = (linktype == link_type_sl) ? true : false;
|
||||
bool is_sl = (linktype == link_type_sl);
|
||||
bool is_synchronized = (ue) ? ue->is_synchronized : false;
|
||||
unsigned int nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0;
|
||||
unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
unsigned int nb_prefix_samples0 = (is_synchronized || is_sl) ? frame_parms->nb_prefix_samples0 : nb_prefix_samples;
|
||||
|
||||
// For Sidelink 16 frames worth of samples is processed to find SSB, for 5G-NR 2.
|
||||
unsigned int total_samples = (is_sl) ? 16 * frame_parms->samples_per_frame : 2 * frame_parms->samples_per_frame;
|
||||
|
||||
int N_RB = (is_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_DL;
|
||||
|
||||
if (is_synchronized || is_sl) {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
||||
} else {
|
||||
nb_prefix_samples = frame_parms->nb_prefix_samples;
|
||||
nb_prefix_samples0 = frame_parms->nb_prefix_samples;
|
||||
AssertFatal(slot == 0, "Slot should be 0\n");
|
||||
}
|
||||
|
||||
dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size);
|
||||
// This is for misalignment issues
|
||||
c16_t tmp_dft_in[frame_parms->ofdm_symbol_size] __attribute__ ((aligned (32)));
|
||||
const unsigned int total_samples = (is_sl) ? 16 * frame_parms->samples_per_frame : 2 * frame_parms->samples_per_frame;
|
||||
|
||||
unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0);
|
||||
unsigned int abs_symbol = slot * frame_parms->symbols_per_slot + symbol;
|
||||
const unsigned int abs_symbol = slot * frame_parms->symbols_per_slot + symbol;
|
||||
for (int idx_symb = slot * frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
|
||||
rx_offset += (idx_symb%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
rx_offset += (idx_symb % (0x7 << frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
|
||||
rx_offset += frame_parms->ofdm_symbol_size * symbol;
|
||||
|
||||
rx_offset += sample_offset;
|
||||
@@ -73,48 +91,47 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
// use OFDM symbol from within 1/8th of the CP to avoid ISI
|
||||
rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor);
|
||||
|
||||
rx_offset %= total_samples;
|
||||
|
||||
for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
c16_t *rxdata_ptr = &rxdata[aa][rx_offset];
|
||||
LOG_D(PHY,
|
||||
"slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n",
|
||||
slot,
|
||||
symbol,
|
||||
nb_prefix_samples,
|
||||
nb_prefix_samples0,
|
||||
rx_offset,
|
||||
dB_fixed(signal_energy((int32_t *)&rxdata[0][rx_offset], frame_parms->ofdm_symbol_size)));
|
||||
|
||||
c16_t tmp_dft_in[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
c16_t *rxdata_symb_ptr[frame_parms->nb_antennas_rx];
|
||||
c16_t *rxdataF_symb_ptr[frame_parms->nb_antennas_rx];
|
||||
for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
|
||||
rxdataF_symb_ptr[aa] = &rxdataF[aa][frame_parms->ofdm_symbol_size * symbol];
|
||||
// This happens only during initial sync
|
||||
if (rx_offset + frame_parms->ofdm_symbol_size > total_samples) {
|
||||
// rxdata is 2 frames len
|
||||
// we have to wrap on the end
|
||||
|
||||
memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], (total_samples - rx_offset) * sizeof(int32_t));
|
||||
memcpy((void *)&tmp_dft_in[total_samples - rx_offset],
|
||||
(void *)&rxdata[aa][0],
|
||||
memcpy(&tmp_dft_in[aa][0], &rxdata[aa][rx_offset], (total_samples - rx_offset) * sizeof(int32_t));
|
||||
memcpy(&tmp_dft_in[aa][total_samples - rx_offset],
|
||||
&rxdata[aa][0],
|
||||
(frame_parms->ofdm_symbol_size - (total_samples - rx_offset)) * sizeof(int32_t));
|
||||
rxdata_ptr = tmp_dft_in;
|
||||
|
||||
} else if ((rx_offset & 7) != 0) { // if input to dft is not 256-bit aligned
|
||||
memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], frame_parms->ofdm_symbol_size * sizeof(int32_t));
|
||||
rxdata_ptr = tmp_dft_in;
|
||||
rxdata_symb_ptr[aa] = tmp_dft_in[aa];
|
||||
} else {
|
||||
rxdata_symb_ptr[aa] = &rxdata[aa][rx_offset];
|
||||
}
|
||||
|
||||
if (ue && ue->cont_fo_comp) {
|
||||
start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
|
||||
nr_fo_compensation(ue->freq_offset, frame_parms->samples_per_subframe, rx_offset, rxdata_ptr, tmp_dft_in, frame_parms->ofdm_symbol_size);
|
||||
rxdata_ptr = tmp_dft_in;
|
||||
nr_fo_compensation(ue->freq_offset,
|
||||
frame_parms->samples_per_subframe,
|
||||
rx_offset,
|
||||
rxdata_symb_ptr[aa],
|
||||
tmp_dft_in[aa],
|
||||
frame_parms->ofdm_symbol_size);
|
||||
stop_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
|
||||
rxdata_symb_ptr[aa] = tmp_dft_in[aa];
|
||||
}
|
||||
|
||||
if (ue)
|
||||
start_meas_nr_ue_phy(ue, RX_DFT_STATS);
|
||||
|
||||
dft(dftsize,
|
||||
(int16_t *)rxdata_ptr,
|
||||
(int16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
|
||||
1);
|
||||
|
||||
if (ue)
|
||||
stop_meas_nr_ue_phy(ue, RX_DFT_STATS);
|
||||
|
||||
apply_nr_rotation_RX(frame_parms, rxdataF[aa], frame_parms->symbol_rotation[linktype], slot, N_RB, 0, symbol, 1);
|
||||
}
|
||||
|
||||
time_stats_t* dft_stats = NULL;
|
||||
if (ue) dft_stats = &ue->phy_cpu_stats.cpu_time_stats[RX_DFT_STATS];
|
||||
nr_symbol_fep(frame_parms, slot, symbol, linktype, rxdata_symb_ptr, rxdataF_symb_ptr, dft_stats);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -177,54 +194,46 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
const c16_t *rot,
|
||||
int slot,
|
||||
int nb_rb,
|
||||
int soffset,
|
||||
int first_symbol,
|
||||
int nsymb)
|
||||
void apply_nr_rotation_symbol_RX(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF,
|
||||
const c16_t *rot,
|
||||
int nb_rb,
|
||||
int slot,
|
||||
int symbol)
|
||||
{
|
||||
AssertFatal(first_symbol + nsymb <= NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
"First symbol %d and number of symbol %d not compatible with number of symbols in a slot %d\n",
|
||||
first_symbol, nsymb, NR_NUMBER_OF_SYMBOLS_PER_SLOT);
|
||||
int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot;
|
||||
const int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot;
|
||||
|
||||
for (int symbol = first_symbol; symbol < first_symbol + nsymb; symbol++) {
|
||||
|
||||
c16_t rot2 = rot[symbol + symb_offset];
|
||||
rot2.i = -rot2.i;
|
||||
LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i);
|
||||
const c16_t *shift_rot = frame_parms->timeshift_symbol_rotation;
|
||||
c16_t *this_symbol = &rxdataF[soffset + (frame_parms->ofdm_symbol_size * symbol)];
|
||||
c16_t rot2 = rot[symbol + symb_offset];
|
||||
rot2.i = -rot2.i;
|
||||
LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i);
|
||||
const c16_t *shift_rot = frame_parms->timeshift_symbol_rotation;
|
||||
c16_t *this_symbol = rxdataF;
|
||||
|
||||
if (nb_rb & 1) {
|
||||
rotate_cpx_vector(this_symbol, &rot2, this_symbol,
|
||||
(nb_rb + 1) * 6, 15);
|
||||
rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6,
|
||||
&rot2,
|
||||
this_symbol + frame_parms->first_carrier_offset - 6,
|
||||
(nb_rb + 1) * 6, 15);
|
||||
mult_cpx_vector(this_symbol, shift_rot, this_symbol, (nb_rb + 1) * 6, 15);
|
||||
mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6,
|
||||
shift_rot + frame_parms->first_carrier_offset - 6,
|
||||
if (nb_rb & 1) {
|
||||
rotate_cpx_vector(this_symbol, &rot2, this_symbol, (nb_rb + 1) * 6, 15);
|
||||
rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6,
|
||||
&rot2,
|
||||
this_symbol + frame_parms->first_carrier_offset - 6,
|
||||
(nb_rb + 1) * 6,
|
||||
15);
|
||||
} else {
|
||||
rotate_cpx_vector(this_symbol, &rot2, this_symbol,
|
||||
nb_rb * 6, 15);
|
||||
rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset,
|
||||
&rot2,
|
||||
this_symbol + frame_parms->first_carrier_offset,
|
||||
nb_rb * 6, 15);
|
||||
mult_cpx_vector(this_symbol, shift_rot, this_symbol, nb_rb * 6, 15);
|
||||
mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset,
|
||||
shift_rot + frame_parms->first_carrier_offset,
|
||||
mult_cpx_vector(this_symbol, shift_rot, this_symbol, (nb_rb + 1) * 6, 15);
|
||||
mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6,
|
||||
shift_rot + frame_parms->first_carrier_offset - 6,
|
||||
this_symbol + frame_parms->first_carrier_offset - 6,
|
||||
(nb_rb + 1) * 6,
|
||||
15);
|
||||
} else {
|
||||
rotate_cpx_vector(this_symbol, &rot2, this_symbol, nb_rb * 6, 15);
|
||||
rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset,
|
||||
&rot2,
|
||||
this_symbol + frame_parms->first_carrier_offset,
|
||||
nb_rb * 6,
|
||||
15);
|
||||
}
|
||||
mult_cpx_vector(this_symbol, shift_rot, this_symbol, nb_rb * 6, 15);
|
||||
mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset,
|
||||
shift_rot + frame_parms->first_carrier_offset,
|
||||
this_symbol + frame_parms->first_carrier_offset,
|
||||
nb_rb * 6,
|
||||
15);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,9 +150,7 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue,
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_pdcch_dmrs_rx(const PHY_VARS_NR_UE *ue,
|
||||
unsigned int Ns,
|
||||
const unsigned int *nr_gold_pdcch,
|
||||
int nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch,
|
||||
c16_t *output,
|
||||
unsigned short p,
|
||||
unsigned short nb_rb_coreset)
|
||||
|
||||
@@ -35,9 +35,7 @@ void nr_pbch_dmrs_rx(int dmrss, const unsigned int *nr_gold_pbch, c16_t *output,
|
||||
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS.
|
||||
@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
|
||||
*/
|
||||
int nr_pdcch_dmrs_rx(const PHY_VARS_NR_UE *ue,
|
||||
unsigned int Ns,
|
||||
const unsigned int *nr_gold_pdcch,
|
||||
int nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch,
|
||||
c16_t *output,
|
||||
unsigned short p,
|
||||
unsigned short nb_rb_corset);
|
||||
|
||||
@@ -805,17 +805,12 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
uint16_t BWPStart,
|
||||
int32_t pdcch_est_size,
|
||||
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size])
|
||||
{
|
||||
int slot = proc->nr_slot_rx;
|
||||
unsigned char aarx;
|
||||
unsigned short k;
|
||||
unsigned int pilot_cnt;
|
||||
int ch_offset,symbol_offset;
|
||||
|
||||
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
|
||||
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
|
||||
int nb_rb_coreset=0;
|
||||
int coreset_start_rb=0;
|
||||
@@ -830,8 +825,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12;
|
||||
|
||||
#ifdef DEBUG_PDCCH
|
||||
printf("PDCCH Channel Estimation : ch_offset %d, OFDM size %d, Ncp=%d, slot=%d, symbol %d\n",
|
||||
ch_offset,
|
||||
printf("PDCCH Channel Estimation : OFDM size %d, Ncp=%d, slot=%d, symbol %d\n",
|
||||
ue->frame_parms.ofdm_symbol_size,
|
||||
ue->frame_parms.Ncp,
|
||||
slot,
|
||||
@@ -852,14 +846,14 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16)));
|
||||
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
|
||||
const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol);
|
||||
nr_pdcch_dmrs_rx(ue, slot, gold, pilot, 2000, (nb_rb_coreset + dmrs_ref));
|
||||
nr_pdcch_dmrs_rx(gold, pilot, 2000, (nb_rb_coreset + dmrs_ref));
|
||||
|
||||
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
k = coreset_start_subcarrier;
|
||||
c16_t *pil = &pilot[dmrs_ref * 3];
|
||||
c16_t *rxF = &rxdataF[aarx][symbol_offset + k + 1];
|
||||
c16_t *dl_ch = &pdcch_dl_ch_estimates[aarx][ch_offset];
|
||||
c16_t *rxF = &rxdataF[aarx][k + 1];
|
||||
c16_t *dl_ch = &pdcch_dl_ch_estimates[aarx][0];
|
||||
|
||||
memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size);
|
||||
|
||||
@@ -879,29 +873,29 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
if (k >= ue->frame_parms.ofdm_symbol_size) {
|
||||
k -= ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = &rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
rxF = &rxdataF[aarx][k + 1];
|
||||
}
|
||||
multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
|
||||
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
rxF = (c16_t *)&rxdataF[aarx][k + 1)];
|
||||
|
||||
multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
|
||||
dl_ch += 12;
|
||||
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
rxF = (c16_t *)&rxdataF[aarx][k + 1];
|
||||
|
||||
for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) {
|
||||
multadd_real_vector_complex_scalar(fl, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
|
||||
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
rxF = (c16_t *)&rxdataF[aarx][k + 1];
|
||||
|
||||
multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
|
||||
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
rxF = (c16_t *)&rxdataF[aarx][k + 1];
|
||||
multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
|
||||
dl_ch += 12;
|
||||
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
rxF = (c16_t *)&rxdataF[aarx][k + 1];
|
||||
}
|
||||
#else //ELSE CH_INTERP
|
||||
c32_t ch_sum = {0, 0};
|
||||
@@ -915,7 +909,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
ch_sum.r += ch.r;
|
||||
ch_sum.i += ch.i;
|
||||
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
|
||||
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
|
||||
rxF = (c16_t *)&rxdataF[aarx][k + 1];
|
||||
|
||||
if (pilot_cnt % 3 == 2) {
|
||||
ch.r = ch_sum.r / 3;
|
||||
|
||||
@@ -52,7 +52,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
uint16_t BWPStart,
|
||||
int32_t pdcch_est_size,
|
||||
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]);
|
||||
|
||||
c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
|
||||
#include "assertions.h"
|
||||
#include "T.h"
|
||||
@@ -72,10 +73,10 @@
|
||||
#define RE_PER_RB_OUT_DMRS 9
|
||||
|
||||
static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb,
|
||||
c16_t llr[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS],
|
||||
c16_t *llr,
|
||||
c16_t *e_rx,
|
||||
uint8_t coreset_time_dur,
|
||||
uint8_t reg_bundle_size_L,
|
||||
uint8_t reg_bundle_size_L_in,
|
||||
uint8_t coreset_interleaver_size_R,
|
||||
uint8_t n_shift,
|
||||
uint8_t number_of_candidates,
|
||||
@@ -118,17 +119,11 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb,
|
||||
| REG 0 (bundle 0) bundle 0 bundle 0
|
||||
|
||||
*/
|
||||
|
||||
uint32_t coreset_C = 0;
|
||||
int coreset_interleaved = 0;
|
||||
const int N_regs = coreset_nbr_rb * coreset_time_dur;
|
||||
|
||||
if (reg_bundle_size_L != 0) { // interleaving will be done only if reg_bundle_size_L != 0
|
||||
coreset_interleaved = 1;
|
||||
coreset_C = (uint32_t)(N_regs / (coreset_interleaver_size_R * reg_bundle_size_L));
|
||||
} else {
|
||||
reg_bundle_size_L = 6;
|
||||
}
|
||||
/* interleaving will be done only if reg_bundle_size_L != 0 */
|
||||
const int coreset_C = (reg_bundle_size_L_in != 0) ? (uint32_t)(N_regs / (coreset_interleaver_size_R * reg_bundle_size_L_in)) : 0;
|
||||
const int coreset_interleaved = (reg_bundle_size_L_in != 0) ? 1 : 0;
|
||||
const int reg_bundle_size_L = (reg_bundle_size_L_in != 0) ? reg_bundle_size_L_in : 6;
|
||||
|
||||
int B_rb = reg_bundle_size_L / coreset_time_dur; // nb of RBs occupied by each REG bundle
|
||||
int num_bundles_per_cce = 6 / reg_bundle_size_L;
|
||||
@@ -173,7 +168,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb,
|
||||
for (int cce_count = 0; cce_count < L[c_id]; cce_count++) {
|
||||
for (int k = 0; k < NR_NB_REG_PER_CCE / reg_bundle_size_L; k++) { // loop over REG bundles
|
||||
int f = f_bundle_j_list_ord[c_id][k + NR_NB_REG_PER_CCE * cce_count / reg_bundle_size_L];
|
||||
c16_t *in = llr[symbol_idx] + f * B_rb * RE_PER_RB_OUT_DMRS;
|
||||
c16_t *in = llr + (f * B_rb + symbol_idx * coreset_nbr_rb) * RE_PER_RB_OUT_DMRS;
|
||||
// loop over the RBs of the bundle
|
||||
memcpy(e_rx + RE_PER_RB_OUT_DMRS * rb_count, in, B_rb * RE_PER_RB_OUT_DMRS * sizeof(*e_rx));
|
||||
rb_count += B_rb;
|
||||
@@ -200,16 +195,15 @@ static void nr_pdcch_llr(uint32_t sz, c16_t *rxF, c16_t *llr)
|
||||
|
||||
// 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,
|
||||
c16_t rxdataF[][rxdataF_sz],
|
||||
int32_t est_size,
|
||||
c16_t dl_ch_estimates[][est_size],
|
||||
int arraySz,
|
||||
c16_t rxdataF_ext[][arraySz],
|
||||
c16_t dl_ch_estimates_ext[][arraySz],
|
||||
int symbol,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t *coreset_freq_dom,
|
||||
uint32_t coreset_nbr_rb,
|
||||
uint32_t n_BWP_start)
|
||||
{
|
||||
/*
|
||||
@@ -224,8 +218,8 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
|
||||
*/
|
||||
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
const c16_t *dl_ch0 = dl_ch_estimates[aarx] + frame_parms->ofdm_symbol_size * symbol;
|
||||
c16_t *rxFbase = rxdataF[aarx] + frame_parms->ofdm_symbol_size * symbol;
|
||||
c16_t *dl_ch0 = dl_ch_estimates[aarx];
|
||||
c16_t *rxFbase = rxdataF[aarx];
|
||||
LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n", aarx);
|
||||
|
||||
c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx];
|
||||
@@ -249,44 +243,52 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
|
||||
* the position 0+c_rb-N_RB_DL/2 in rxdataF and we have to point the pointer at (1+c_rb-N_RB_DL/2) in rxdataF
|
||||
*/
|
||||
|
||||
int c_rb = 0;
|
||||
for (int rb = 0; rb < coreset_nbr_rb; rb++, c_rb++) {
|
||||
int c_rb_by6 = c_rb / 6;
|
||||
c16_t middle_prb_buffer[RE_PER_RB];
|
||||
for (int rb_group = 0; rb_group < coreset_nbr_rb / 6; rb_group++) {
|
||||
if ((coreset_freq_dom[rb_group / 8] & (1 << (7 - (rb_group & 7)))) == 0) {
|
||||
continue;
|
||||
}
|
||||
for (int rb = 0; rb < 6; rb++) {
|
||||
int c_rb = rb_group * 6 + rb;
|
||||
c16_t *rxF = NULL;
|
||||
if ((frame_parms->N_RB_DL & 1) == 0) {
|
||||
if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2)
|
||||
// if RB to be treated is lower than middle system bandwidth then rxdataF pointed
|
||||
// at (offset + c_br + symbol * ofdm_symbol_size): even case
|
||||
rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start);
|
||||
else
|
||||
// number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC)
|
||||
// if these conditions are true the pointer has to be situated at the 1st part of the rxdataF
|
||||
// we point at the 1st part of the rxdataF in symbol
|
||||
rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2);
|
||||
} else {
|
||||
if ((c_rb + n_BWP_start) <= frame_parms->N_RB_DL / 2)
|
||||
// if RB to be treated is lower than middle system bandwidth then rxdataF pointed
|
||||
// at (offset + c_br + symbol * ofdm_symbol_size): odd case
|
||||
// Reassemble the middle PRB
|
||||
if (c_rb + n_BWP_start == frame_parms->N_RB_DL / 2) {
|
||||
memcpy(middle_prb_buffer, rxFbase + frame_parms->ofdm_symbol_size - RE_PER_RB / 2, sizeof(c16_t) * RE_PER_RB / 2);
|
||||
memcpy(middle_prb_buffer + RE_PER_RB / 2, rxFbase, sizeof(c16_t) * RE_PER_RB / 2);
|
||||
rxF = middle_prb_buffer;
|
||||
} else {
|
||||
rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start);
|
||||
}
|
||||
|
||||
// skip zeros in frequency domain bitmap
|
||||
while ((coreset_freq_dom[c_rb_by6 / 8] & (1 << (7 - (c_rb_by6 & 7)))) == 0) {
|
||||
c_rb += 6;
|
||||
c_rb_by6 = c_rb / 6;
|
||||
else
|
||||
// number of RBs is odd and c_rb is higher than half system bandwidth + 1
|
||||
// if these conditions are true the pointer has to be situated at the 1st part of
|
||||
// the rxdataF just after the first IQ symbols of the RB containing DC
|
||||
// we point at the 1st part of the rxdataF in symbol
|
||||
rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6;
|
||||
}
|
||||
|
||||
const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11};
|
||||
for (int i = 0; i < sizeofArray(valid_re); i++) {
|
||||
*rxF_ext++ = rxF[valid_re[i]];
|
||||
*dl_ch0_ext++ = dl_ch0[valid_re[i]];
|
||||
}
|
||||
dl_ch0 += RE_PER_RB;
|
||||
}
|
||||
c16_t *rxF = NULL;
|
||||
if ((frame_parms->N_RB_DL & 1) == 0) {
|
||||
if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2)
|
||||
// if RB to be treated is lower than middle system bandwidth then rxdataF pointed
|
||||
// at (offset + c_br + symbol * ofdm_symbol_size): even case
|
||||
rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start);
|
||||
else
|
||||
// number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC)
|
||||
// if these conditions are true the pointer has to be situated at the 1st part of the rxdataF
|
||||
// we point at the 1st part of the rxdataF in symbol
|
||||
rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2);
|
||||
} else {
|
||||
if ((c_rb + n_BWP_start) <= frame_parms->N_RB_DL / 2)
|
||||
// if RB to be treated is lower than middle system bandwidth then rxdataF pointed
|
||||
// at (offset + c_br + symbol * ofdm_symbol_size): odd case
|
||||
rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start);
|
||||
else
|
||||
// number of RBs is odd and c_rb is higher than half system bandwidth + 1
|
||||
// if these conditions are true the pointer has to be situated at the 1st part of
|
||||
// the rxdataF just after the first IQ symbols of the RB containing DC
|
||||
// we point at the 1st part of the rxdataF in symbol
|
||||
rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6;
|
||||
}
|
||||
const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11};
|
||||
for (int i = 0; i < sizeofArray(valid_re); i++) {
|
||||
*rxF_ext++ = rxF[valid_re[i]];
|
||||
*dl_ch0_ext++ = dl_ch0[valid_re[i]];
|
||||
}
|
||||
dl_ch0 += RE_PER_RB;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,99 +320,222 @@ static void nr_pdcch_detection_mrc(int sz, c16_t rxdataF_comp[][sz])
|
||||
}
|
||||
}
|
||||
|
||||
void nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pdcch_est_size,
|
||||
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
c16_t *pdcch_e_rx,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
/* Produce LLRs from received PDCCH signal */
|
||||
static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int symbol,
|
||||
int rel_symb_monOcc,
|
||||
int ss_idx,
|
||||
nr_phy_data_t *phy_data,
|
||||
int llr_size_symbol,
|
||||
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size],
|
||||
c16_t llr[llr_size_symbol])
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset;
|
||||
int32_t pdcch_est_size = ((((fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH) + 15) / 16) * 16);
|
||||
__attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size];
|
||||
|
||||
int n_rb,rb_offset;
|
||||
get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset);
|
||||
const int antRx = frame_parms->nb_antennas_rx;
|
||||
nr_pdcch_channel_estimation(ue,
|
||||
proc,
|
||||
symbol,
|
||||
coreset,
|
||||
fp->first_carrier_offset,
|
||||
phy_pdcch_config->pdcch_config[ss_idx].BWPStart,
|
||||
pdcch_est_size,
|
||||
pdcch_dl_ch_estimates,
|
||||
rxdataF);
|
||||
|
||||
// Pointer to llrs
|
||||
const int symb_size = n_rb * RE_PER_RB_OUT_DMRS;
|
||||
c16_t llr[rel15->coreset.duration][symb_size];
|
||||
const int32_t rx_size = ((4 * fp->N_RB_DL * 12 + 31) >> 5) << 5;
|
||||
__attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size];
|
||||
__attribute__((aligned(32))) c16_t rxdataF_comp[fp->nb_antennas_rx][rx_size];
|
||||
__attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size];
|
||||
memset(rxdataF_comp, 0, sizeof(rxdataF_comp));
|
||||
|
||||
LOG_D(NR_PHY_DCI,
|
||||
"pdcch coreset: freq %x, n_rb %d, rb_offset %d\n",
|
||||
rel15->coreset.frequency_domain_resource[0],
|
||||
n_rb,
|
||||
rb_offset);
|
||||
for (int s = 0; s < rel15->coreset.duration; s++) {
|
||||
LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
|
||||
const int arraySz = ceil_mod(symb_size, 32);
|
||||
__attribute__((aligned(32))) c16_t rxdataF_ext[antRx][arraySz];
|
||||
__attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][arraySz];
|
||||
nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP,
|
||||
n_rb,
|
||||
rxdataF,
|
||||
pdcch_est_size,
|
||||
pdcch_dl_ch_estimates,
|
||||
arraySz,
|
||||
int n_rb;
|
||||
int rb_offset;
|
||||
get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset);
|
||||
|
||||
nr_pdcch_extract_rbs_single(ue->frame_parms.ofdm_symbol_size,
|
||||
rxdataF,
|
||||
pdcch_est_size,
|
||||
pdcch_dl_ch_estimates,
|
||||
rx_size,
|
||||
rxdataF_ext,
|
||||
pdcch_dl_ch_estimates_ext,
|
||||
fp,
|
||||
coreset->frequency_domain_resource,
|
||||
n_rb,
|
||||
phy_pdcch_config->pdcch_config[ss_idx].BWPStart);
|
||||
|
||||
LOG_D(NR_PHY_DCI, "in channel level function (dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
|
||||
int avg[fp->nb_antennas_rx];
|
||||
nr_channel_level(0, rx_size, pdcch_dl_ch_estimates_ext, fp->nb_antennas_rx, 1, avg, n_rb * RE_PER_RB_OUT_DMRS);
|
||||
int avgs = avg[0];
|
||||
for (int i = 1; i < fp->nb_antennas_rx; i++)
|
||||
avgs = cmax(avgs, avg[i]);
|
||||
const int log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx;
|
||||
|
||||
nr_pdcch_channel_compensation(rx_size,
|
||||
rxdataF_ext,
|
||||
pdcch_dl_ch_estimates_ext,
|
||||
rel15->coreset.StartSymbolIndex + s,
|
||||
frame_parms,
|
||||
rel15->coreset.frequency_domain_resource,
|
||||
rel15->BWPStart);
|
||||
rxdataF_comp,
|
||||
fp->nb_antennas_rx,
|
||||
log2_maxh); // log2_maxh+I0_shift
|
||||
|
||||
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
|
||||
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;
|
||||
UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), fp->nb_antennas_rx, rx_size, 0);
|
||||
|
||||
#ifdef UE_DEBUG_TRACE
|
||||
LOG_D(NR_PHY_DCI, "slot %d: pdcch log2_maxh = %d (%d,%d)\n", proc->nr_slot_rx, log2_maxh, avgP[0], avgs);
|
||||
#endif
|
||||
#if T_TRACER
|
||||
T(T_UE_PHY_PDCCH_ENERGY,
|
||||
T_INT(0),
|
||||
T_INT(proc->frame_rx % 1024),
|
||||
T_INT(proc->nr_slot_rx),
|
||||
T_INT(avg[0]),
|
||||
T_INT(antRx > 1 ? avg[1] : 0),
|
||||
T_INT(antRx > 2 ? avg[2] : 0),
|
||||
T_INT(antRx > 3 ? avg[3] : 0));
|
||||
#endif
|
||||
LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh);
|
||||
LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n");
|
||||
// compute LLRs for ofdm symbol 0 only
|
||||
__attribute__((aligned(32))) c16_t rxdataF_comp[antRx][arraySz];
|
||||
nr_pdcch_channel_compensation(arraySz,
|
||||
rxdataF_ext,
|
||||
pdcch_dl_ch_estimates_ext,
|
||||
rxdataF_comp,
|
||||
antRx,
|
||||
log2_maxh); // log2_maxh+I0_shift
|
||||
|
||||
UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, symb_size, 0);
|
||||
|
||||
if (antRx > 1)
|
||||
nr_pdcch_detection_mrc(arraySz, rxdataF_comp);
|
||||
|
||||
nr_pdcch_llr(symb_size, rxdataF_comp[0], llr[s]);
|
||||
if (fp->nb_antennas_rx > 1) {
|
||||
nr_pdcch_detection_mrc(rx_size, rxdataF_comp);
|
||||
}
|
||||
UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, rel15->coreset.duration * symb_size, 0);
|
||||
|
||||
nr_pdcch_demapping_deinterleaving(n_rb,
|
||||
llr,
|
||||
pdcch_e_rx,
|
||||
rel15->coreset.duration,
|
||||
rel15->coreset.RegBundleSize,
|
||||
rel15->coreset.InterleaverSize,
|
||||
rel15->coreset.ShiftIndex,
|
||||
rel15->number_of_candidates,
|
||||
rel15->CCE,
|
||||
rel15->L);
|
||||
nr_pdcch_llr(llr_size_symbol, rxdataF_comp[0], llr);
|
||||
}
|
||||
|
||||
bool is_start_symbol_in_ss(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, const int symbol)
|
||||
{
|
||||
return ((ss->coreset.StartSymbolBitmap >> (NR_SYMBOLS_PER_SLOT - 1 - symbol)) & 1);
|
||||
}
|
||||
|
||||
int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT])
|
||||
{
|
||||
int sum = 0;
|
||||
for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) {
|
||||
if (is_start_symbol_in_ss(ss, s)) {
|
||||
if (start_symb != NULL)
|
||||
start_symb[sum] = s;
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config)
|
||||
{
|
||||
int monOcc = 0;
|
||||
for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) {
|
||||
monOcc = max(monOcc, get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss], NULL));
|
||||
}
|
||||
return monOcc;
|
||||
}
|
||||
|
||||
static void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
c16_t *pdcch_e_rx,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
fapi_nr_dci_indication_t *dci_ind);
|
||||
|
||||
void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb)
|
||||
{
|
||||
*first_symb = NR_SYMBOLS_PER_SLOT; // max first pdcch symbol
|
||||
*last_symb = 0; // min last pdcch symbol
|
||||
for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) {
|
||||
for (int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) {
|
||||
if (is_start_symbol_in_ss(&phy_pdcch_config->pdcch_config[ss], symb)) {
|
||||
const int duration = phy_pdcch_config->pdcch_config[ss].coreset.duration;
|
||||
*first_symb = min(*first_symb, symb);
|
||||
*last_symb = max(*last_symb, symb + duration - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates PDCCH LLRs from received symbol for each Search-Space */
|
||||
void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int symbol,
|
||||
nr_phy_data_t *phy_data,
|
||||
int llr_size_symbol,
|
||||
int num_monitoring_occ,
|
||||
int max_symb,
|
||||
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size],
|
||||
c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol])
|
||||
{
|
||||
const NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
|
||||
// Loop over search spaces
|
||||
for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) {
|
||||
uint8_t start_symb[NR_SYMBOLS_PER_SLOT] = {0};
|
||||
const int num_monOcc = get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss_idx], start_symb);
|
||||
// Loop over monitoring occations within the slot in this ss
|
||||
for (int occ = 0; occ < num_monOcc; occ++) {
|
||||
const int first_symb = start_symb[occ];
|
||||
const int last_symb = first_symb + phy_pdcch_config->pdcch_config[ss_idx].coreset.duration;
|
||||
// Decode PDCCH and generate LLR for each ss in this OFDM symbol
|
||||
if ((symbol >= first_symb) && (symbol < last_symb)) {
|
||||
const int rel_symb_monOcc = symbol - first_symb;
|
||||
nr_rx_pdcch_symbol(ue,
|
||||
proc,
|
||||
symbol,
|
||||
rel_symb_monOcc,
|
||||
ss_idx,
|
||||
phy_data,
|
||||
llr_size_symbol,
|
||||
rxdataF,
|
||||
&pdcch_llr[ss_idx][occ][rel_symb_monOcc * llr_size_symbol]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode DCI from LLRs for each Search-Space and send to MAC */
|
||||
void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
|
||||
int llr_size,
|
||||
int max_monOcc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size])
|
||||
{
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_dci_indication_t dci_ind = {.SFN = proc->frame_rx, .slot = proc->nr_slot_rx};
|
||||
|
||||
for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) {
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[ss_idx];
|
||||
uint8_t unused_start_symb[NR_SYMBOLS_PER_SLOT] = {0};
|
||||
const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, unused_start_symb);
|
||||
|
||||
int n_rb;
|
||||
int rb_offset;
|
||||
get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
|
||||
|
||||
for (int m = 0; m < num_monitoring_occ; m++) {
|
||||
/// PDCCH/DCI e-sequence (input to rate matching).
|
||||
c16_t pdcch_e_rx[NR_MAX_PDCCH_SIZE];
|
||||
|
||||
nr_pdcch_demapping_deinterleaving(n_rb,
|
||||
llr[ss_idx][m],
|
||||
pdcch_e_rx,
|
||||
rel15->coreset.duration,
|
||||
rel15->coreset.RegBundleSize,
|
||||
rel15->coreset.InterleaverSize,
|
||||
rel15->coreset.ShiftIndex,
|
||||
rel15->number_of_candidates,
|
||||
rel15->CCE,
|
||||
rel15->L);
|
||||
|
||||
nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, rel15, &dci_ind);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < dci_ind.number_of_dcis; i++) {
|
||||
LOG_D(PHY,
|
||||
"Frame.slot: %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
i + 1,
|
||||
dci_ind.number_of_dcis,
|
||||
dci_ind.dci_list[i].rnti,
|
||||
dci_ind.dci_list[i].dci_format);
|
||||
}
|
||||
|
||||
/* Send to MAC */
|
||||
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
phy_pdcch_config->nb_search_space = 0;
|
||||
}
|
||||
|
||||
static void nr_pdcch_unscrambling(c16_t *e_rx,
|
||||
@@ -432,14 +557,13 @@ static void nr_pdcch_unscrambling(c16_t *e_rx,
|
||||
}
|
||||
}
|
||||
|
||||
void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
c16_t *pdcch_e_rx,
|
||||
fapi_nr_dci_indication_t *dci_ind,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15)
|
||||
static void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
c16_t *pdcch_e_rx,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
fapi_nr_dci_indication_t *dci_ind)
|
||||
{
|
||||
int e_rx_cand_idx = 0;
|
||||
*dci_ind = (fapi_nr_dci_indication_t){.SFN = proc->frame_rx, .slot = proc->nr_slot_rx};
|
||||
// if DCI for SIB we don't break after finding 1st DCI with that RNTI
|
||||
// there might be SIB1 and otherSIB in the same slot with the same length
|
||||
bool is_SI = rel15->rnti == SI_RNTI;
|
||||
|
||||
@@ -69,6 +69,12 @@ 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_conjch0_mult_ch1(c16_t *ch0, c16_t *ch1, c16_t *ch0conj_ch1, unsigned short nb_rb, unsigned char output_shift0);
|
||||
|
||||
void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb);
|
||||
|
||||
int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]);
|
||||
|
||||
int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config);
|
||||
|
||||
/** \brief This is the alternative top-level entry point for DLSCH decoding in UE.
|
||||
It handles all the HARQ processes in only one call. The routine first
|
||||
computes the segmentation information and then call LDPC decoder on the
|
||||
@@ -180,14 +186,6 @@ void nr_dlsch_unscrambling(int16_t* llr,
|
||||
uint32_t Nid,
|
||||
uint32_t n_RNTI);
|
||||
|
||||
void nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pdcch_est_size,
|
||||
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
c16_t *pdcch_e_rx,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
/*! \brief Performs detection of SSS to find cell ID and other framing parameters (FDD/TDD, normal/extended prefix)
|
||||
@param phy_vars_ue Pointer to UE variables
|
||||
@param tot_metric Pointer to variable containing maximum metric under framing hypothesis (to be compared to other hypotheses
|
||||
@@ -279,12 +277,6 @@ void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue,
|
||||
openair0_config_t *openair0_cfg,
|
||||
int freq_offset);
|
||||
|
||||
void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
c16_t *pdcch_e_rx,
|
||||
fapi_nr_dci_indication_t *dci_ind,
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15);
|
||||
|
||||
/** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel
|
||||
estimation. It performs
|
||||
- RB extraction (signal and channel estimates)
|
||||
|
||||
@@ -92,7 +92,8 @@
|
||||
*/
|
||||
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp);
|
||||
|
||||
int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
|
||||
void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data);
|
||||
|
||||
@@ -137,13 +138,22 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
void *typeSpecific,
|
||||
uint8_t *b);
|
||||
|
||||
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pdcch_est_size,
|
||||
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
int symbol,
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
int llr_size_symbol,
|
||||
int num_monitoring_occ,
|
||||
int max_symb,
|
||||
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size],
|
||||
c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol]);
|
||||
|
||||
void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
|
||||
int llr_size,
|
||||
int max_monOcc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size]);
|
||||
|
||||
void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
@@ -530,53 +530,6 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pdcch_est_size,
|
||||
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[n_ss];
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
|
||||
|
||||
/// PDCCH/DCI e-sequence (input to rate matching).
|
||||
int32_t pdcch_e_rx_size = NR_MAX_PDCCH_SIZE;
|
||||
c16_t pdcch_e_rx[pdcch_e_rx_size];
|
||||
|
||||
nr_rx_pdcch(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF);
|
||||
|
||||
fapi_nr_dci_indication_t dci_ind;
|
||||
nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, &dci_ind, rel15);
|
||||
|
||||
for (int i = 0; i < dci_ind.number_of_dcis; i++) {
|
||||
LOG_D(PHY,
|
||||
"[UE %d] AbsSubFrame %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
|
||||
ue->Mod_id,
|
||||
frame_rx % 1024,
|
||||
nr_slot_rx,
|
||||
i + 1,
|
||||
dci_ind.number_of_dcis,
|
||||
dci_ind.dci_list[i].rnti,
|
||||
dci_ind.dci_list[i].dci_format);
|
||||
}
|
||||
|
||||
nr_downlink_indication_t dl_indication;
|
||||
// fill dl_indication message
|
||||
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
|
||||
// send to mac
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT);
|
||||
return (dci_ind.number_of_dcis);
|
||||
}
|
||||
|
||||
static 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 = {
|
||||
@@ -1030,14 +983,80 @@ static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index)
|
||||
return ue->frame_parms.ssb_index == index;
|
||||
}
|
||||
|
||||
int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
|
||||
static int get_pdcch_max_rbs(NR_UE_PDCCH_CONFIG *phy_pdcch_config)
|
||||
{
|
||||
int nb_rb = 0;
|
||||
int rb_offset = 0;
|
||||
for (int i = 0; i < phy_pdcch_config->nb_search_space; i++) {
|
||||
int tmp = 0;
|
||||
get_coreset_rballoc(phy_pdcch_config->pdcch_config[i].coreset.frequency_domain_resource, &tmp, &rb_offset);
|
||||
if (tmp > nb_rb)
|
||||
nb_rb = tmp;
|
||||
}
|
||||
return nb_rb;
|
||||
}
|
||||
|
||||
static int get_max_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config)
|
||||
{
|
||||
int max_pdcch_symb = 0;
|
||||
for (int i = 0; i < phy_pdcch_config->nb_search_space; i++)
|
||||
if (phy_pdcch_config->pdcch_config[i].coreset.duration > max_pdcch_symb)
|
||||
max_pdcch_symb = phy_pdcch_config->pdcch_config[i].coreset.duration;
|
||||
|
||||
return max_pdcch_symb;
|
||||
}
|
||||
|
||||
void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
|
||||
{
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
if (phy_pdcch_config->nb_search_space == 0)
|
||||
return;
|
||||
|
||||
TracyCZone(ctx, true);
|
||||
/* process PDCCH */
|
||||
LOG_D(PHY, " ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", proc->frame_rx % 1024, proc->nr_slot_rx);
|
||||
start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
|
||||
int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config);
|
||||
int max_nb_symb_pdcch = get_max_pdcch_symb(phy_pdcch_config);
|
||||
int llr_size_symbol = get_pdcch_max_rbs(phy_pdcch_config) * 9;
|
||||
c16_t pdcch_llr[phy_pdcch_config->nb_search_space][num_monitoring_occ][max_nb_symb_pdcch * llr_size_symbol];
|
||||
|
||||
int start_symb_pdcch, last_symb_pdcch;
|
||||
set_first_last_pdcch_symb(phy_pdcch_config, &start_symb_pdcch, &last_symb_pdcch);
|
||||
|
||||
/* Temporarily loop over symbols in the slot, perform OFDM demod and process PDCCH.
|
||||
When symbol based proc design is fully merged, this function will be called to process only one symbol
|
||||
and OFDM demod will be removed from here. */
|
||||
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
|
||||
__attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
|
||||
for (int symbol = start_symb_pdcch; symbol <= last_symb_pdcch; symbol++) {
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
nr_slot_fep(ue, fp, proc->nr_slot_rx, symbol, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
|
||||
__attribute__((aligned(32))) c16_t rxdataF_symb[fp->nb_antennas_rx][((fp->ofdm_symbol_size + 7) / 8) * 8];
|
||||
|
||||
for (int ant = 0; ant < fp->nb_antennas_rx; ant++)
|
||||
memcpy(rxdataF_symb[ant], &rxdataF[ant][symbol * fp->ofdm_symbol_size], sizeof(c16_t) * fp->ofdm_symbol_size);
|
||||
|
||||
nr_pdcch_generate_llr(ue, proc, symbol, phy_data, llr_size_symbol, num_monitoring_occ, max_nb_symb_pdcch, rxdataF_symb, pdcch_llr);
|
||||
if (symbol == last_symb_pdcch) {
|
||||
nr_pdcch_dci_indication(proc, llr_size_symbol * max_nb_symb_pdcch, num_monitoring_occ, ue, phy_data, pdcch_llr);
|
||||
UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr), 0);
|
||||
}
|
||||
}
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
|
||||
TracyCZoneEnd(ctx);
|
||||
if (ue->phy_sim_rxdataF)
|
||||
memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * max_nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size);
|
||||
}
|
||||
|
||||
int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
|
||||
{
|
||||
TracyCZone(ctx, true);
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
int gNB_id = proc->gNB_id;
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
|
||||
int sampleShift = INT_MAX;
|
||||
nr_ue_dlsch_init(phy_data->dlsch, NR_MAX_NB_LAYERS>4 ? 2:1, ue->max_ldpc_iterations);
|
||||
|
||||
@@ -1169,43 +1188,7 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_
|
||||
} // for i
|
||||
} // for rsc_id
|
||||
} // for gNB_id
|
||||
|
||||
LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_IN);
|
||||
|
||||
uint8_t nb_symb_pdcch = phy_pdcch_config->nb_search_space > 0 ? phy_pdcch_config->pdcch_config[0].coreset.duration : 0;
|
||||
int first_symb_pdcch = phy_pdcch_config->nb_search_space > 0 ? phy_pdcch_config->pdcch_config[0].coreset.StartSymbolIndex : 0;
|
||||
int last_symb_pdcch = first_symb_pdcch + nb_symb_pdcch;
|
||||
for (int l = first_symb_pdcch; l < last_symb_pdcch; l++) {
|
||||
nr_slot_fep(ue, fp, proc->nr_slot_rx, l, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
|
||||
}
|
||||
|
||||
// Hold the channel estimates in frequency domain.
|
||||
int32_t pdcch_est_size = ((((fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH))+15)/16)*16);
|
||||
__attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[4 * fp->nb_antennas_rx][pdcch_est_size];
|
||||
|
||||
uint8_t dci_cnt = 0;
|
||||
for(int n_ss = 0; n_ss<phy_pdcch_config->nb_search_space; n_ss++) {
|
||||
for (int l = first_symb_pdcch; l < last_symb_pdcch; l++) {
|
||||
// note: this only works if RBs for PDCCH are contigous!
|
||||
nr_pdcch_channel_estimation(ue,
|
||||
proc,
|
||||
l,
|
||||
&phy_pdcch_config->pdcch_config[n_ss].coreset,
|
||||
fp->first_carrier_offset,
|
||||
phy_pdcch_config->pdcch_config[n_ss].BWPStart,
|
||||
pdcch_est_size,
|
||||
pdcch_dl_ch_estimates,
|
||||
rxdataF);
|
||||
}
|
||||
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF);
|
||||
}
|
||||
LOG_D(PHY, "[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt);
|
||||
phy_pdcch_config->nb_search_space = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT);
|
||||
TracyCZoneEnd(ctx);
|
||||
if (ue->phy_sim_rxdataF)
|
||||
memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size);
|
||||
return sampleShift;
|
||||
}
|
||||
|
||||
|
||||
@@ -1216,9 +1216,8 @@ int main(int argc, char **argv)
|
||||
ue_dci_configuration(UE_mac, &dl_config, frame, slot);
|
||||
nr_ue_scheduled_response(&scheduled_response);
|
||||
|
||||
pbch_pdcch_processing(UE,
|
||||
&UE_proc,
|
||||
&phy_data);
|
||||
pbch_processing(UE, &UE_proc, &phy_data);
|
||||
pdcch_processing(UE, &UE_proc, &phy_data);
|
||||
pdsch_processing(UE,
|
||||
&UE_proc,
|
||||
&phy_data);
|
||||
|
||||
@@ -110,17 +110,6 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
{
|
||||
}
|
||||
|
||||
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int32_t pdcch_est_size,
|
||||
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
|
||||
nr_phy_data_t *phy_data,
|
||||
int n_ss,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
configmodule_interface_t *uniqCfg = NULL;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
@@ -1468,14 +1468,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
int offset = (slot & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size;
|
||||
for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
|
||||
apply_nr_rotation_RX(&gNB->frame_parms,
|
||||
gNB->common_vars.rxdataF[0][aa],
|
||||
gNB->frame_parms.symbol_rotation[1],
|
||||
slot,
|
||||
gNB->frame_parms.N_RB_UL,
|
||||
offset,
|
||||
0,
|
||||
gNB->frame_parms.Ncp == EXTENDED ? 12 : 14);
|
||||
const unsigned int max_symb = (gNB->frame_parms.Ncp == EXTENDED) ? 12 : 14;
|
||||
for (int sym = 0; sym < max_symb; sym++)
|
||||
apply_nr_rotation_symbol_RX(&gNB->frame_parms,
|
||||
gNB->common_vars.rxdataF[0][aa] + offset + sym * gNB->frame_parms.ofdm_symbol_size,
|
||||
gNB->frame_parms.symbol_rotation[1],
|
||||
gNB->frame_parms.N_RB_UL,
|
||||
slot,
|
||||
sym);
|
||||
}
|
||||
|
||||
ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot, &UL_INFO);
|
||||
|
||||
@@ -307,12 +307,7 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac,
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sps; i++) {
|
||||
if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) {
|
||||
rel15->coreset.StartSymbolIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rel15->coreset.StartSymbolBitmap = monitoringSymbolsWithinSlot;
|
||||
uint32_t Y = 0;
|
||||
if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific)
|
||||
Y = get_Y(ss, slot, rel15->rnti);
|
||||
|
||||
Reference in New Issue
Block a user