Commit 06ef3119 authored by Sakthivel Velumani's avatar Sakthivel Velumani

Moved PDSCH, rxdataF to stack

--Removed NR_UE_PDSCH global structure
--Changed UE scope to accomodate local PDSCH data
--Removed common_vars.rxdataF from global structure
parent cfe698eb
......@@ -865,6 +865,7 @@ void *UE_thread(void *arg) {
bool syncRunning=false;
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
UE->phy_sim_mode = false;
while (!oai_exit) {
if (UE->lost_sync) {
......
......@@ -39,104 +39,6 @@
extern uint16_t beta_cqi[16];
/*! \brief Helper function to allocate memory for DLSCH data structures.
* \param[out] pdsch Pointer to the LTE_UE_PDSCH structure to initialize.
* \param[in] frame_parms LTE_DL_FRAME_PARMS structure.
* \note This function is optimistic in that it expects malloc() to succeed.
*/
void phy_init_nr_ue_PDSCH(NR_UE_PDSCH *const pdsch,
const NR_DL_FRAME_PARMS *const fp) {
AssertFatal( pdsch, "pdsch==0" );
pdsch->llr128 = (int16_t **)malloc16_clear( sizeof(int16_t *) );
// FIXME! no further allocation for (int16_t*)pdsch->llr128 !!! expect SIGSEGV
// FK, 11-3-2015: this is only as a temporary pointer, no memory is stored there
pdsch->rxdataF_ext = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->rxdataF_uespec_pilots = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->rxdataF_comp0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->rho = (int32_t ***)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t **) );
pdsch->dl_ch_estimates = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->dl_ch_estimates_ext = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->dl_bf_ch_estimates = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->dl_bf_ch_estimates_ext = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->dl_ch_mag0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->dl_ch_magb0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->dl_ch_magr0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->ptrs_phase_per_slot = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) );
pdsch->ptrs_re_per_slot = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) );
// the allocated memory size is fixed:
AssertFatal( fp->nb_antennas_rx <= 4, "nb_antennas_rx > 4" );//Extend the max number of UE Rx antennas to 4
const size_t num = 7*2*fp->N_RB_DL*12;
for (int i=0; i<fp->nb_antennas_rx; i++) {
pdsch->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
pdsch->rxdataF_uespec_pilots[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * fp->N_RB_DL*12);
pdsch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * 14 );
pdsch->ptrs_re_per_slot[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * 14);
pdsch->rho[i] = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*NR_MAX_NB_LAYERS*sizeof(int32_t *) );
for (int j=0; j<NR_MAX_NB_LAYERS; j++) {
const int idx = (j*fp->nb_antennas_rx)+i;
for (int k=0; k<NR_MAX_NB_LAYERS; k++) {
pdsch->rho[i][j*NR_MAX_NB_LAYERS+k] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
}
pdsch->rxdataF_comp0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * fp->ofdm_symbol_size*7*2);
pdsch->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_bf_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * fp->ofdm_symbol_size*7*2);
pdsch->dl_bf_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_ch_mag0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_ch_magb0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_ch_magr0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
}
}
}
void phy_term_nr_ue__PDSCH(NR_UE_PDSCH* pdsch, const NR_DL_FRAME_PARMS *const fp)
{
for (int i = 0; i < fp->nb_antennas_rx; i++) {
for (int j = 0; j < NR_MAX_NB_LAYERS; j++) {
const int idx = j * fp->nb_antennas_rx + i;
for (int k = 0; k < NR_MAX_NB_LAYERS; k++)
free_and_zero(pdsch->rho[i][j*NR_MAX_NB_LAYERS+k]);
free_and_zero(pdsch->rxdataF_comp0[idx]);
free_and_zero(pdsch->dl_ch_estimates[idx]);
free_and_zero(pdsch->dl_ch_estimates_ext[idx]);
free_and_zero(pdsch->dl_bf_ch_estimates[idx]);
free_and_zero(pdsch->dl_bf_ch_estimates_ext[idx]);
free_and_zero(pdsch->dl_ch_mag0[idx]);
free_and_zero(pdsch->dl_ch_magb0[idx]);
free_and_zero(pdsch->dl_ch_magr0[idx]);
}
free_and_zero(pdsch->rxdataF_ext[i]);
free_and_zero(pdsch->rxdataF_uespec_pilots[i]);
free_and_zero(pdsch->ptrs_phase_per_slot[i]);
free_and_zero(pdsch->ptrs_re_per_slot[i]);
free_and_zero(pdsch->rho[i]);
}
free_and_zero(pdsch->pmi_ext);
int nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1;
for (int i=0; i<nb_codewords; i++)
free_and_zero(pdsch->llr[i]);
for (int i=0; i<NR_MAX_NB_LAYERS; i++)
free_and_zero(pdsch->layer_llr[i]);
free_and_zero(pdsch->llr128);
free_and_zero(pdsch->rxdataF_ext);
free_and_zero(pdsch->rxdataF_uespec_pilots);
free_and_zero(pdsch->rxdataF_comp0);
free_and_zero(pdsch->rho);
free_and_zero(pdsch->dl_ch_estimates);
free_and_zero(pdsch->dl_ch_estimates_ext);
free_and_zero(pdsch->dl_bf_ch_estimates);
free_and_zero(pdsch->dl_bf_ch_estimates_ext);
free_and_zero(pdsch->dl_ch_mag0);
free_and_zero(pdsch->dl_ch_magb0);
free_and_zero(pdsch->dl_ch_magr0);
free_and_zero(pdsch->ptrs_phase_per_slot);
free_and_zero(pdsch->ptrs_re_per_slot);
}
void RCconfig_nrUE_prs(void *cfg)
{
int j = 0, k = 0, gNB_id = 0;
......@@ -406,11 +308,9 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
// init RX buffers
common_vars->rxdata = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
common_vars->rxdataF = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
for (i=0; i<fp->nb_antennas_rx; i++) {
common_vars->rxdata[i] = (int32_t *) malloc16_clear( (2*(fp->samples_per_frame)+fp->ofdm_symbol_size)*sizeof(int32_t) );
common_vars->rxdataF[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(fp->samples_per_slot_wCP) );
}
// ceil(((NB_RB<<1)*3)/32) // 3 RE *2(QPSK)
......@@ -453,19 +353,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
}
// DLSCH
for (gNB_id = 0; gNB_id < ue->n_connected_gNB+1; gNB_id++) {
ue->pdsch_vars[gNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH));
phy_init_nr_ue_PDSCH( ue->pdsch_vars[gNB_id], fp );
int nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1;
for (i=0; i<nb_codewords; i++) {
ue->pdsch_vars[gNB_id]->llr[i] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) );//Q_m = 8 bits/Sym, Code_Rate=3, Number of Segments =8, Circular Buffer K_cb = 8448
}
for (i=0; i<NR_MAX_NB_LAYERS; i++) {
ue->pdsch_vars[gNB_id]->layer_llr[i] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) );//Q_m = 8 bits/Sym, Code_Rate=3, Number of Segments =8, Circular Buffer K_cb = 8448
}
}
for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
prach_vars[gNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH));
pbch_vars[gNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH));
......@@ -539,9 +426,7 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
for (int i = 0; i < fp->nb_antennas_rx; i++) {
free_and_zero(common_vars->rxdata[i]);
free_and_zero(common_vars->rxdataF[i]);
}
free_and_zero(common_vars->rxdataF);
free_and_zero(common_vars->rxdata);
for (int slot = 0; slot < fp->slots_per_frame; slot++) {
......@@ -564,10 +449,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
for (int gNB_id = 0; gNB_id < ue->n_connected_gNB+1; gNB_id++) {
// PDSCH
free_and_zero(ue->pdsch_vars[gNB_id]->llr_shifts);
free_and_zero(ue->pdsch_vars[gNB_id]->llr128_2ndstream);
phy_term_nr_ue__PDSCH(ue->pdsch_vars[gNB_id], fp);
free_and_zero(ue->pdsch_vars[gNB_id]);
}
for (int gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
......@@ -628,7 +509,7 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
}
}
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t* harq_list, int number_of_processes, int num_rb) {
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb) {
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS;
if (num_rb != 273) {
......@@ -636,19 +517,21 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t* harq_list, int number_of_processes, int
a_segments = (a_segments/273)+1;
}
for (int j=0; j < 2; j++) {
for (int i=0; i<number_of_processes; i++) {
free_and_zero(harq_list[i].b);
free_and_zero(harq_list[j][i].b);
for (int r=0; r<a_segments; r++) {
free_and_zero(harq_list[i].c[r]);
free_and_zero(harq_list[i].d[r]);
free_and_zero(harq_list[j][i].c[r]);
free_and_zero(harq_list[j][i].d[r]);
}
free_and_zero(harq_list[j][i].c);
free_and_zero(harq_list[j][i].d);
}
free_and_zero(harq_list[i].c);
free_and_zero(harq_list[i].d);
}
}
void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t *harq_list, int number_of_processes, int num_rb, int num_ant_tx) {
void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES], int number_of_processes, int num_rb, int num_ant_tx) {
int max_layers = (num_ant_tx < NR_MAX_NB_LAYERS) ? num_ant_tx : NR_MAX_NB_LAYERS;
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*max_layers; //number of segments to be allocated
......@@ -676,14 +559,11 @@ void term_nr_ue_transport(PHY_VARS_NR_UE *ue)
{
const int N_RB_DL = ue->frame_parms.N_RB_DL;
const int N_RB_UL = ue->frame_parms.N_RB_UL;
int num_cw = NR_MAX_NB_LAYERS > 4? 2:1;
for (int j = 0; j < num_cw; j++) {
free_nr_ue_dl_harq(ue->dl_harq_processes[j], NR_MAX_DLSCH_HARQ_PROCESSES, N_RB_DL);
}
free_nr_ue_dl_harq(ue->dl_harq_processes, NR_MAX_DLSCH_HARQ_PROCESSES, N_RB_DL);
free_nr_ue_ul_harq(ue->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, N_RB_UL, ue->frame_parms.nb_antennas_tx);
}
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t* harq_list, int number_of_processes, int num_rb) {
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb) {
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated
if (num_rb != 273) {
......@@ -693,35 +573,39 @@ void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t* harq_list, int number_of_process
uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
for (int j=0; j<2; j++) {
for (int i=0; i<number_of_processes; i++) {
memset(harq_list + i, 0, sizeof(NR_DL_UE_HARQ_t));
init_downlink_harq_status(harq_list + i);
harq_list[i].b = malloc16(dlsch_bytes);
memset(harq_list[j] + i, 0, sizeof(NR_DL_UE_HARQ_t));
init_downlink_harq_status(harq_list[j] + i);
harq_list[j][i].b = malloc16(dlsch_bytes);
if (harq_list[i].b)
memset(harq_list[i].b, 0, dlsch_bytes);
if (harq_list[j][i].b)
memset(harq_list[j][i].b, 0, dlsch_bytes);
else
AssertFatal(true, "Unable to reset harq memory \"b\"\n");
harq_list[i].c = malloc16(a_segments*sizeof(uint8_t *));
harq_list[i].d = malloc16(a_segments*sizeof(int16_t *));
harq_list[j][i].c = malloc16(a_segments*sizeof(uint8_t *));
harq_list[j][i].d = malloc16(a_segments*sizeof(int16_t *));
for (int r=0; r<a_segments; r++) {
harq_list[i].c[r] = malloc16(1056);
harq_list[i].d[r] = malloc16(5*8448*sizeof(int16_t));
if (harq_list[i].c[r])
memset(harq_list[i].c[r],0,1056);
harq_list[j][i].c[r] = malloc16(1056);
harq_list[j][i].d[r] = malloc16(5*8448*sizeof(int16_t));
if (harq_list[j][i].c[r])
memset(harq_list[j][i].c[r],0,1056);
else
AssertFatal(true, "Unable to reset harq memory \"c\"\n");
if (harq_list[i].d[r])
memset(harq_list[i].d[r],0,5*8448);
if (harq_list[j][i].d[r])
memset(harq_list[j][i].d[r],0,5*8448);
else
AssertFatal(true, "Unable to reset harq memory \"d\"\n");
}
harq_list[j][i].status = 0;
harq_list[j][i].DLround = 0;
}
}
}
void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t *harq_list, int number_of_processes, int num_rb, int num_ant_tx) {
void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES], int number_of_processes, int num_rb, int num_ant_tx) {
int max_layers = (num_ant_tx < NR_MAX_NB_LAYERS) ? num_ant_tx : NR_MAX_NB_LAYERS;
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*max_layers; //number of segments to be allocated
......@@ -772,11 +656,7 @@ void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t *harq_list, int number_of_process
void init_nr_ue_transport(PHY_VARS_NR_UE *ue) {
int num_codeword = NR_MAX_NB_LAYERS > 4? 2:1;
for (int j=0; j<num_codeword; j++) {
nr_init_dl_harq_processes(ue->dl_harq_processes[j], NR_MAX_DLSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_DL);
}
nr_init_dl_harq_processes(ue->dl_harq_processes, NR_MAX_DLSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_DL);
nr_init_ul_harq_processes(ue->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, ue->frame_parms.N_RB_UL, ue->frame_parms.nb_antennas_tx);
for(int i=0; i<5; i++)
......
......@@ -418,10 +418,10 @@ void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg);
void RCconfig_nrUE_prs(void *cfg);
void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue);
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t* harq_list, int number_of_processes, int num_rb);
void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t *harq_list, int number_of_processes, int num_rb, int num_ant_tx);
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t* harq_list, int number_of_processes, int num_rb);
void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t *harq_list, int number_of_processes, int num_rb, int num_ant_tx);
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb);
void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES], int number_of_processes, int num_rb, int num_ant_tx);
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb);
void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES], int number_of_processes, int num_rb, int num_ant_tx);
/** @} */
#endif
......
......@@ -51,14 +51,16 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
int nr_slot_fep(PHY_VARS_NR_UE *phy_vars_ue,
UE_nr_rxtx_proc_t *proc,
unsigned char l,
unsigned char Ns);
unsigned char Ns,
int32_t rxdataF[][phy_vars_ue->frame_parms.samples_per_slot_wCP]);
int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
unsigned char Ns,
int sample_offset,
bool pbch_decoded);
bool pbch_decoded,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue,
unsigned char l,
......
......@@ -37,7 +37,8 @@
int nr_slot_fep(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
unsigned char Ns)
unsigned char Ns,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
NR_UE_COMMON *common_vars = &ue->common_vars;
......@@ -75,7 +76,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
//#endif
for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
memset(&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
memset(&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
......@@ -92,7 +93,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
dft(dftsize,
rxdata_ptr,
(int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
(int16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
1);
stop_meas(&ue->rx_dft_stats);
......@@ -108,7 +109,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
#endif
c16_t *shift_rot = frame_parms->timeshift_symbol_rotation;
c16_t *this_symbol = (c16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol];
c16_t *this_symbol = (c16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol];
if (frame_parms->N_RB_DL & 1) {
rotate_cpx_vector(this_symbol, &rot2, this_symbol,
......@@ -151,7 +152,8 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
unsigned char symbol,
unsigned char Ns,
int sample_offset,
bool pbch_decoded)
bool pbch_decoded,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
NR_UE_COMMON *common_vars = &ue->common_vars;
......@@ -189,7 +191,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
#endif
for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
memset(&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
memset(&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
int16_t *rxdata_ptr;
rx_offset%=frame_length_samples*2;
......@@ -225,7 +227,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
dft(dftsize,
rxdata_ptr,
(int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
(int16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
1);
stop_meas(&ue->rx_dft_stats);
......@@ -240,7 +242,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
symbol+symb_offset,rot2.r,rot2.i);
#endif
c16_t *this_symbol = (c16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol];
c16_t *this_symbol = (c16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol];
rotate_cpx_vector(this_symbol, &rot2, this_symbol, frame_parms->ofdm_symbol_size, 15);
}
......
......@@ -341,7 +341,7 @@ int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t count
/* perform averaging of channel estimates and store result in first symbol buffer */
void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
int **ch_est,
int32_t **ch_estimates,
uint8_t num_symbols,
uint8_t start_symbol,
uint16_t dmrs_bitmap,
......@@ -356,9 +356,9 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
AssertFatal(first_dmrs_symb > -1, "No DMRS symbol present in this slot\n");
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
for (int symb = first_dmrs_symb+1; symb < total_symbols; symb++) {
ul_ch128_0 = (__m128i *)&ch_est[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
ul_ch128_0 = (__m128i *)&ch_estimates[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
if ((dmrs_bitmap >> symb) & 0x01) {
ul_ch128_1 = (__m128i *)&ch_est[aarx][symb*frame_parms->ofdm_symbol_size];
ul_ch128_1 = (__m128i *)&ch_estimates[aarx][symb*frame_parms->ofdm_symbol_size];
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = _mm_adds_epi16(ul_ch128_0[0], ul_ch128_1[0]);
ul_ch128_0[1] = _mm_adds_epi16(ul_ch128_0[1], ul_ch128_1[1]);
......@@ -368,7 +368,7 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
}
}
}
ul_ch128_0 = (__m128i *)&ch_est[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
ul_ch128_0 = (__m128i *)&ch_estimates[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
if (num_dmrs_symb == 2) {
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = _mm_srai_epi16(ul_ch128_0[0], 1);
......@@ -384,7 +384,7 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
ul_ch128_0 += 3;
}
} else if (num_dmrs_symb == 3) {
ul_ch16_0 = (int16_t *)&ch_est[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
ul_ch16_0 = (int16_t *)&ch_estimates[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch16_0[0] /= 3;
ul_ch16_0[1] /= 3;
......
......@@ -66,7 +66,7 @@ int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter,
uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb);
int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter);
void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
int **ch_est,
int32_t **ch_estimates,
uint8_t num_symbols,
uint8_t start_symbol,
uint16_t dmrs_bitmap,
......
......@@ -96,7 +96,7 @@ int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR]);
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss);
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
#undef INIT_VARIABLES_SSS_NR_H
#undef EXTERN
......
......@@ -66,10 +66,10 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
uint8_t rep_num,
PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
NR_DL_FRAME_PARMS *frame_params)
NR_DL_FRAME_PARMS *frame_params,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
uint8_t rxAnt = 0, idx = 0;
int32_t **rxdataF = ue->common_vars.rxdataF;
prs_config_t *prs_cfg = &ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg;
prs_meas_t **prs_meas = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_meas;
c16_t ch_tmp_buf[ ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
......@@ -571,7 +571,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
unsigned char Ns,
unsigned char symbol,
int dmrss,
NR_UE_SSB *current_ssb)
NR_UE_SSB *current_ssb,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
int pilot[200] __attribute__((aligned(16)));
unsigned short k;
......@@ -583,7 +584,6 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
uint8_t nushift;
uint8_t ssb_index=current_ssb->i_ssb;
uint8_t n_hf=current_ssb->n_hf;
int **rxdataF=ue->common_vars.rxdataF;
nushift = ue->frame_parms.Nid_cell%4;
ue->frame_parms.nushift = nushift;
......@@ -735,7 +735,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
unsigned char symbol,
int dmrss,
uint8_t ssb_index,
uint8_t n_hf)
uint8_t n_hf,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
int pilot[200] __attribute__((aligned(16)));
unsigned short k;
......@@ -745,8 +746,6 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
//int slot_pbch;
uint8_t nushift;
int **rxdataF=ue->common_vars.rxdataF;
nushift = ue->frame_parms.Nid_cell%4;
ue->frame_parms.nushift = nushift;
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
......@@ -1001,7 +1000,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
uint16_t first_carrier_offset,
uint16_t BWPStart,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size])
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
unsigned char aarx;
......@@ -1010,8 +1010,6 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
int16_t ch[2],*pil,*rxF,*dl_ch;
int ch_offset,symbol_offset;
int **rxdataF=ue->common_vars.rxdataF;
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
......@@ -1249,7 +1247,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
unsigned short BWPStart,
uint8_t config_type,
unsigned short bwp_start_subcarrier,
unsigned short nb_rb_pdsch)
unsigned short nb_rb_pdsch,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
int pilot[3280] __attribute__((aligned(16)));
unsigned char aarx;
......@@ -1260,9 +1261,6 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
int ch_offset,symbol_offset;
uint8_t nushift;
int **dl_ch_estimates = ue->pdsch_vars[gNB_id]->dl_ch_estimates;
int **rxdataF=ue->common_vars.rxdataF;
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
......@@ -2030,7 +2028,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
* NAME : nr_pdsch_ptrs_processing
*
* PARAMETERS : PHY_VARS_NR_UE : ue data structure
* NR_UE_PDSCH : pdsch_vars pointer
* c16_t : ptrs_phase_per_slot array
* int32_t : ptrs_re_per_slot array
* uint32_t : rx_size,
* int32_t : rxdataF_comp, array
* NR_DL_FRAME_PARMS : frame_parms pointer
* NR_DL_UE_HARQ_t : dlsch0_harq pointer
* NR_DL_UE_HARQ_t : dlsch1_harq pointer
......@@ -2049,7 +2050,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
* 3) Compensate signal with PTRS estimation for slot
*********************************************************************/
void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
NR_UE_PDSCH **pdsch_vars,
c16_t ptrs_phase_per_slot[][14],
int32_t ptrs_re_per_slot[][14],
uint32_t rx_size,
int32_t rxdataF_comp[][rx_size],
NR_DL_FRAME_PARMS *frame_parms,
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
......@@ -2104,8 +2108,8 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
}
/* loop over antennas */
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
c16_t *phase_per_symbol = (c16_t*)pdsch_vars[gNB_id]->ptrs_phase_per_slot[aarx];
ptrs_re_symbol = (int32_t*)pdsch_vars[gNB_id]->ptrs_re_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[symbol] = 0;
phase_per_symbol[symbol].i = 0; // Imag
/* set DMRS estimates to 0 angle with magnitude 1 */
......@@ -2141,7 +2145,7 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
rnti,
nr_slot_rx,
symbol,frame_parms->ofdm_symbol_size,
(int16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(symbol * nb_re_pdsch)],
(int16_t*)&rxdataF_comp[aarx][(symbol * nb_re_pdsch)],
ue->nr_gold_pdsch[gNB_id][nr_slot_rx][symbol][0],
(int16_t*)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]);
......@@ -2161,9 +2165,9 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
}
}
#ifdef DEBUG_DL_PTRS
LOG_M("ptrsEst.m","est",pdsch_vars[gNB_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
LOG_M("ptrsEst.m","est",ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp",
&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb) ],
&rxdataF_comp[aarx][(*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb) ],
(*nb_rb) * NR_NB_SC_PER_RB * (*nbSymb),1,1);
#endif
/*------------------------------------------------------------------------------------------------------- */
......@@ -2176,9 +2180,9 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
#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);
#endif
rotate_cpx_vector((c16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
rotate_cpx_vector((c16_t*)&rxdataF_comp[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
&phase_per_symbol[i],
(c16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
(c16_t*)&rxdataF_comp[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
((*nb_rb) * NR_NB_SC_PER_RB), 15);
}// if not DMRS Symbol
}// symbol loop
......
......@@ -38,7 +38,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
uint8_t rep_num,
PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
NR_DL_FRAME_PARMS *frame_params);
NR_DL_FRAME_PARMS *frame_params,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
/* Generic function to find the peak of channel estimation buffer */
void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val);
......@@ -59,7 +60,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
uint16_t first_carrier_offset,
uint16_t BWPStart,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size]);
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
......@@ -67,7 +69,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
unsigned char Ns,
unsigned char symbol,
int dmrss,
NR_UE_SSB *current_ssb);
NR_UE_SSB *current_ssb,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
int estimateSz,
......@@ -79,7 +82,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
unsigned char symbol,
int dmrss,
uint8_t ssb_index,
uint8_t n_hf);
uint8_t n_hf,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
......@@ -93,7 +97,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
unsigned short BWPStart,
uint8_t config_type,
unsigned short bwp_start_subcarrier,
unsigned short nb_rb_pdsch);
unsigned short nb_rb_pdsch,
uint32_t pdsch_est_size,
int32_t pdsch_dl_ch_estimates[][pdsch_est_size],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
PHY_VARS_NR_UE *ue,
......@@ -107,24 +114,30 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
void nr_ue_measurements(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
uint8_t slot,
NR_UE_DLSCH_t *dlsch);
NR_UE_DLSCH_t *dlsch,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size]);
void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
uint8_t gNB_index,
UE_nr_rxtx_proc_t *proc,
uint8_t slot);
uint8_t slot,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
uint8_t slot);
uint8_t slot,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue,
uint32_t rx_power_fil_dB,
uint8_t gNB_id);
void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
NR_UE_PDSCH **pdsch_vars,
c16_t ptrs_phase_per_slot[][14],
int32_t ptrs_re_per_slot[][14],
uint32_t rx_size,
int32_t rxdataF_comp[][rx_size],
NR_DL_FRAME_PARMS *frame_parms,
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
......
......@@ -76,9 +76,11 @@ float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index)
void nr_ue_measurements(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
uint8_t slot,
NR_UE_DLSCH_t *dlsch)
NR_UE_DLSCH_t *dlsch,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size])
{
int slot = proc->nr_slot_rx;
int aarx, aatx, gNB_id = 0;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
int ch_offset = frame_parms->ofdm_symbol_size*2;
......@@ -97,7 +99,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue,
for (aatx = 0; aatx < frame_parms->nb_antenna_ports_gNB; aatx++){
ue->measurements.rx_spatial_power[gNB_id][aatx][aarx] = (signal_energy_nodc(&ue->pdsch_vars[0]->dl_ch_estimates[gNB_id][ch_offset], N_RB_DL*NR_NB_SC_PER_RB));
ue->measurements.rx_spatial_power[gNB_id][aatx][aarx] = (signal_energy_nodc(&dl_ch_estimates[gNB_id][ch_offset], N_RB_DL*NR_NB_SC_PER_RB));
if (ue->measurements.rx_spatial_power[gNB_id][aatx][aarx]<0)
ue->measurements.rx_spatial_power[gNB_id][aatx][aarx] = 0;
......@@ -170,7 +172,8 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue,
void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
int ssb_index,
UE_nr_rxtx_proc_t *proc,
uint8_t slot) {
uint8_t slot,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
int k_start = 56;
int k_end = 183;
......@@ -192,7 +195,7 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
int16_t *rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(l_sss*ue->frame_parms.ofdm_symbol_size) + ssb_offset];
int16_t *rxF_sss = (int16_t *)&rxdataF[aarx][(l_sss*ue->frame_parms.ofdm_symbol_size) + ssb_offset];
for(int k = k_start; k < k_end; k++){
......@@ -225,7 +228,8 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
// - psd_awgn (AWGN power spectral density): dBm/Hz
void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
uint8_t slot){
uint8_t slot,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]){
uint8_t k;
int aarx, nb_nulls;
......@@ -246,7 +250,7 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
nb_nulls = 0;
ue->measurements.n0_power[aarx] = 0;
rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(l_sss*ue->frame_parms.ofdm_symbol_size) + ssb_offset];
rxF_sss = (int16_t *)&rxdataF[aarx][(l_sss*ue->frame_parms.ofdm_symbol_size) + ssb_offset];
//-ve spectrum from SSS
for(k = k_left; k < k_left + k_length; k++){
......
......@@ -190,9 +190,9 @@ int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue,
const uint8_t *l_overline,
int32_t csi_rs_received_signal[][ue->frame_parms.samples_per_slot_wCP],
uint32_t *rsrp,
int *rsrp_dBm) {
int *rsrp_dBm,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
int32_t **rxdataF = ue->common_vars.rxdataF;
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
uint16_t meas_count = 0;
uint32_t rsrp_sum = 0;
......@@ -729,9 +729,9 @@ int nr_csi_rs_cqi_estimation(const uint32_t precoded_sinr,
int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
const fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu,
uint32_t *interference_plus_noise_power) {
uint32_t *interference_plus_noise_power,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
int32_t **rxdataF = ue->common_vars.rxdataF;
const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
const uint16_t end_rb = csiim_config_pdu->start_rb + csiim_config_pdu->nr_of_rbs > csiim_config_pdu->bwp_size ?
......@@ -800,7 +800,7 @@ int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue,
return 0;
}
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) {
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
if(!ue->csiim_vars[gNB_id]->active) {
return -1;
......@@ -818,13 +818,13 @@ int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
LOG_I(NR_PHY, "csiim_config_pdu->l_csiim = %i.%i.%i.%i\n", csiim_config_pdu->l_csiim[0], csiim_config_pdu->l_csiim[1], csiim_config_pdu->l_csiim[2], csiim_config_pdu->l_csiim[3]);
#endif
nr_csi_im_power_estimation(ue, proc, csiim_config_pdu, &ue->nr_csi_info->interference_plus_noise_power);
nr_csi_im_power_estimation(ue, proc, csiim_config_pdu, &ue->nr_csi_info->interference_plus_noise_power, rxdataF);
ue->nr_csi_info->csi_im_meas_computed = true;
return 0;
}
int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) {
int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
if(!ue->csirs_vars[gNB_id]->active) {
return -1;
......@@ -901,7 +901,8 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
l_overline,
csi_rs_received_signal,
&rsrp,
&rsrp_dBm);
&rsrp_dBm,
rxdataF);
nr_csi_rs_channel_estimation(ue,
proc,
......
......@@ -340,7 +340,8 @@ void nr_pdcch_channel_level(int32_t rx_size,
// This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources)
void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
int32_t rxdataF[][rxdataF_sz],
int32_t est_size,
int32_t dl_ch_estimates[][est_size],
int32_t rx_size,
......@@ -671,11 +672,11 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
int16_t *pdcch_e_rx,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) {
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
uint32_t frame = proc->frame_rx;
uint32_t slot = proc->nr_slot_rx;
NR_UE_COMMON *common_vars = &ue->common_vars;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
uint8_t log2_maxh, aarx;
......@@ -703,7 +704,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) {
LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
nr_pdcch_extract_rbs_single(common_vars->rxdataF,
nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP,
rxdataF,
pdcch_est_size,
pdcch_dl_ch_estimates,
rx_size,
......
......@@ -81,11 +81,12 @@ unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{
#define print_shorts(s,x) printf("%s = [%d+j*%d, %d+j*%d, %d+j*%d, %d+j*%d]\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7])
/* compute H_h_H matrix inversion up to 4x4 matrices */
uint8_t nr_zero_forcing_rx(int **rxdataF_comp,
int **dl_ch_mag,
int **dl_ch_magb,
int **dl_ch_magr,
int **dl_ch_estimates_ext,
uint8_t nr_zero_forcing_rx(uint32_t rx_size,
int32_t rxdataF_comp[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
int32_t dl_ch_estimates_ext[][rx_size],
unsigned short nb_rb,
unsigned char n_rx,
unsigned char n_tx,//number of layer
......@@ -95,19 +96,22 @@ uint8_t nr_zero_forcing_rx(int **rxdataF_comp,
int length);
/* Apply layer demapping */
static void nr_dlsch_layer_demapping(int16_t **llr_cw,
static void nr_dlsch_layer_demapping(int16_t *llr_cw[2],
uint8_t Nl,
uint8_t mod_order,
uint32_t length,
int32_t codeword_TB0,
int32_t codeword_TB1,
int16_t **llr_layers);
int16_t *llr_layers[NR_MAX_NB_LAYERS]);
/* compute LLR */
static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
static int nr_dlsch_llr(uint32_t rx_size,
int16_t *layer_llr[NR_MAX_NB_LAYERS],
NR_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp_ptr,
int32_t **dl_ch_mag_ptr,
int32_t rxdataF_comp[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
unsigned char harq_pid,
......@@ -120,24 +124,40 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
int32_t codeword_TB1,
uint32_t len,
uint8_t nr_slot_rx,
NR_UE_DLSCH_t *dlsch);
NR_UE_DLSCH_t dlsch[2],
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT]);
/* Main Function */
int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch,
NR_UE_DLSCH_t dlsch[2],
unsigned char gNB_id,
unsigned char gNB_id_i,
uint32_t frame,
uint8_t nr_slot_rx,
unsigned char symbol,
unsigned char first_symbol_flag,
unsigned char harq_pid)
unsigned char harq_pid,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size],
int16_t *llr[2],
int16_t *layer_llr[NR_MAX_NB_LAYERS],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
uint32_t rx_size,
int32_t dl_ch_estimates_ext[][rx_size],
int32_t rxdataF_ext[][rx_size],
int32_t rxdataF_comp[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT],
int32_t *log2_maxh)
{
NR_UE_COMMON *common_vars = &ue->common_vars;
NR_UE_PDSCH **pdsch_vars;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
PHY_NR_MEASUREMENTS *measurements = &ue->measurements;
......@@ -152,8 +172,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
int avgs = 0;// rb;
NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL;
int32_t **rxdataF_comp_ptr;
int32_t **dl_ch_mag_ptr;
int32_t codeword_TB0 = -1;
int32_t codeword_TB1 = -1;
......@@ -169,7 +187,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
uint16_t nbSymb=0;
uint16_t pduBitmap=0x0;
pdsch_vars = ue->pdsch_vars;
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
if (NR_MAX_NB_LAYERS>4)
dlsch1_harq = &ue->dl_harq_processes[1][harq_pid];
......@@ -251,11 +268,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
return(-1);
}
if (!pdsch_vars) {
LOG_W(PHY,"dlsch_demodulation.c: Null pdsch_vars pointer\n");
return(-1);
}
if (!frame_parms) {
LOG_W(PHY,"dlsch_demodulation.c: Null frame_parms\n");
return(-1);
......@@ -272,10 +284,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
//--------------------- RBs extraction ---------------------
//----------------------------------------------------------
start_meas(&ue->generic_stat_bis[slot]);
nr_dlsch_extract_rbs(common_vars->rxdataF,
pdsch_vars[gNB_id]->dl_ch_estimates,
pdsch_vars[gNB_id]->rxdataF_ext,
pdsch_vars[gNB_id]->dl_ch_estimates_ext,
nr_dlsch_extract_rbs(ue->frame_parms.samples_per_slot_wCP,
rxdataF,
rx_size,
dl_ch_estimates,
rxdataF_ext,
dl_ch_estimates_ext,
symbol,
pilots,
config_type,
......@@ -298,7 +312,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
//--------------------- Channel Scaling --------------------
//----------------------------------------------------------
start_meas(&ue->generic_stat_bis[slot]);
nr_dlsch_scale_channel(pdsch_vars[gNB_id]->dl_ch_estimates_ext,
nr_dlsch_scale_channel(rx_size,
dl_ch_estimates_ext,
frame_parms,
nl,
n_rx,
......@@ -317,7 +332,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
//----------------------------------------------------------
start_meas(&ue->generic_stat_bis[slot]);
if (first_symbol_flag==1) {
nr_dlsch_channel_level(pdsch_vars[gNB_id]->dl_ch_estimates_ext,
nr_dlsch_channel_level(rx_size,
dl_ch_estimates_ext,
frame_parms,
nl,
avg,
......@@ -333,7 +349,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
median[(aatx*n_rx)+aarx] = avg[(aatx*n_rx)+aarx];
}
if (dlsch[0].Nl > 1) {
nr_dlsch_channel_level_median(pdsch_vars[gNB_id]->dl_ch_estimates_ext,
nr_dlsch_channel_level_median(rx_size,
dl_ch_estimates_ext,
median,
nl,
n_rx,
......@@ -345,14 +362,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
}
}
}
pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1;
//LOG_I(PHY, "avgs Power per SC is %d lg2_maxh %d\n", avgs, pdsch_vars[gNB_id]->log2_maxh);
LOG_D(PHY,"[DLSCH] AbsSubframe %d.%d log2_maxh = %d [log2_maxh0 %d log2_maxh1 %d] (%d,%d)\n",
*log2_maxh = (log2_approx(avgs)/2) + 1;
//LOG_I(PHY, "avgs Power per SC is %d lg2_maxh %d\n", avgs, log2_maxh);
LOG_D(PHY,"[DLSCH] AbsSubframe %d.%d log2_maxh = %d (%d,%d)\n",
frame%1024,
nr_slot_rx,
pdsch_vars[gNB_id]->log2_maxh,
pdsch_vars[gNB_id]->log2_maxh0,
pdsch_vars[gNB_id]->log2_maxh1,
*log2_maxh,
avg[0],
avgs);
}
......@@ -373,13 +388,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
//----------------------------------------------------------
// Disable correlation measurement for optimizing UE
start_meas(&ue->generic_stat_bis[slot]);
nr_dlsch_channel_compensation(pdsch_vars[gNB_id]->rxdataF_ext,
pdsch_vars[gNB_id]->dl_ch_estimates_ext,
pdsch_vars[gNB_id]->dl_ch_mag0,
pdsch_vars[gNB_id]->dl_ch_magb0,
pdsch_vars[gNB_id]->dl_ch_magr0,
pdsch_vars[gNB_id]->rxdataF_comp0,
NULL,//NULL:disable meas. pdsch_vars[gNB_id]->rho:enable meas.
nr_dlsch_channel_compensation(rx_size,
rxdataF_ext,
dl_ch_estimates_ext,
dl_ch_mag,
dl_ch_magb,
dl_ch_magr,
rxdataF_comp,
NULL,
frame_parms,
nl,
symbol,
......@@ -387,67 +403,63 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
first_symbol_flag,
dlsch[0].dlsch_config.qamModOrder,
nb_rb_pdsch,
pdsch_vars[gNB_id]->log2_maxh,
*log2_maxh,
measurements); // log2_maxh+I0_shift
stop_meas(&ue->generic_stat_bis[slot]);
if (cpumeas(CPUMEAS_GETSTATE))
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[slot].p_time/(cpuf*1000.0));
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, *log2_maxh, proc->channel_level, ue->generic_stat_bis[slot].p_time/(cpuf*1000.0));
start_meas(&ue->generic_stat_bis[slot]);
if (n_rx > 1) {
nr_dlsch_detection_mrc(pdsch_vars[gNB_id]->rxdataF_comp0,
(nl>1)? pdsch_vars[gNB_id]->rho : NULL,
pdsch_vars[gNB_id]->dl_ch_mag0,
pdsch_vars[gNB_id]->dl_ch_magb0,
pdsch_vars[gNB_id]->dl_ch_magr0,
nr_dlsch_detection_mrc(rx_size,
rxdataF_comp,
NULL,
dl_ch_mag,
dl_ch_magb,
dl_ch_magr,
nl,
n_rx,
symbol,
nb_rb_pdsch,
nb_re_pdsch);
if (nl >= 2)//Apply zero forcing for 2, 3, and 4 Tx layers
nr_zero_forcing_rx(pdsch_vars[gNB_id]->rxdataF_comp0,
pdsch_vars[gNB_id]->dl_ch_mag0,
pdsch_vars[gNB_id]->dl_ch_magb0,
pdsch_vars[gNB_id]->dl_ch_magr0,
pdsch_vars[gNB_id]->dl_ch_estimates_ext,
nr_zero_forcing_rx(rx_size,
rxdataF_comp,
dl_ch_mag,
dl_ch_magb,
dl_ch_magr,
dl_ch_estimates_ext,
nb_rb_pdsch,
n_rx,
nl,
dlsch[0].dlsch_config.qamModOrder,
pdsch_vars[gNB_id]->log2_maxh,
*log2_maxh,
symbol,
nb_re_pdsch);
}
stop_meas(&ue->generic_stat_bis[slot]);
//printf("start compute LLR\n");
rxdataF_comp_ptr = pdsch_vars[gNB_id_i]->rxdataF_comp0;
dl_ch_mag_ptr = pdsch_vars[gNB_id_i]->dl_ch_mag0;
if (cpumeas(CPUMEAS_GETSTATE))
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine and zero forcing %5.2f \n", frame, nr_slot_rx, slot, symbol, ue->generic_stat_bis[slot].p_time / (cpuf * 1000.0));
start_meas(&ue->generic_stat_bis[slot]);
/* Store the valid DL RE's */
pdsch_vars[gNB_id]->dl_valid_re[symbol-1] = nb_re_pdsch;
dl_valid_re[symbol-1] = nb_re_pdsch;
if(dlsch0_harq->status == ACTIVE) {
startSymbIdx = dlsch[0].dlsch_config.start_symbol;
nbSymb = dlsch[0].dlsch_config.number_symbols;
pduBitmap = dlsch[0].dlsch_config.pduBitmap;
}
if(dlsch1_harq) {
startSymbIdx = dlsch[1].dlsch_config.start_symbol;
nbSymb = dlsch[1].dlsch_config.number_symbols;
pduBitmap = dlsch[1].dlsch_config.pduBitmap;
}
/* Check for PTRS bitmap and process it respectively */
if((pduBitmap & 0x1) && (dlsch[0].rnti_type == _C_RNTI_)) {
nr_pdsch_ptrs_processing(ue,
pdsch_vars,
ptrs_phase_per_slot,
ptrs_re_per_slot,
rx_size,
rxdataF_comp,
frame_parms,
dlsch0_harq,
dlsch1_harq,
......@@ -456,7 +468,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
symbol,
(nb_rb_pdsch*12),
dlsch[0].rnti,dlsch);
pdsch_vars[gNB_id]->dl_valid_re[symbol-1] -= pdsch_vars[gNB_id]->ptrs_re_per_slot[0][symbol];
dl_valid_re[symbol-1] -= ptrs_re_per_slot[0][symbol];
}
/* at last symbol in a slot calculate LLR's for whole slot */
......@@ -470,16 +482,27 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
first_symbol_flag=0;
}
/* Calculate LLR's for each symbol */
nr_dlsch_llr(pdsch_vars, frame_parms,
rxdataF_comp_ptr, dl_ch_mag_ptr,
dlsch0_harq, dlsch1_harq,
nr_dlsch_llr(rx_size,
layer_llr,
frame_parms,
rxdataF_comp,
dl_ch_mag,
dl_ch_magb,
dl_ch_magr,
dlsch0_harq,
dlsch1_harq,
harq_pid,
gNB_id, gNB_id_i,
gNB_id,
gNB_id_i,
first_symbol_flag,
i, nb_rb_pdsch,
codeword_TB0, codeword_TB1,
pdsch_vars[gNB_id]->dl_valid_re[i-1],
nr_slot_rx, dlsch);
i,
nb_rb_pdsch,
codeword_TB0,
codeword_TB1,
dl_valid_re[i-1],
nr_slot_rx,
dlsch,
llr_offset);
}
int dmrs_type = dlsch[0].dlsch_config.dmrsConfigType;
......@@ -498,18 +521,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
dlsch[0].dlsch_config.qamModOrder,
dlsch[0].Nl);
nr_dlsch_layer_demapping(pdsch_vars[gNB_id]->llr,
nr_dlsch_layer_demapping(llr,
dlsch[0].Nl,
dlsch[0].dlsch_config.qamModOrder,
dlsch0_harq->G,
codeword_TB0,
codeword_TB1,
pdsch_vars[gNB_id]->layer_llr);
}
stop_meas(&ue->generic_stat_bis[slot]);
if (cpumeas(CPUMEAS_GETSTATE))
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n", frame, nr_slot_rx, slot, symbol, ue->generic_stat_bis[slot].p_time / (cpuf * 1000.0));
layer_llr);
// Please keep it: useful for debugging
#ifdef DEBUG_PDSCH_RX
......@@ -517,32 +535,37 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
uint8_t aa = 0;
snprintf(filename, 50, "rxdataF0_symb_%d_nr_slot_rx_%d.m", symbol, nr_slot_rx);
write_output(filename, "rxdataF0", &common_vars->rxdataF[0][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1);
write_output(filename, "rxdataF0", &rxdataF[0][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1);
snprintf(filename, 50, "dl_ch_estimates0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx);
write_output(filename, "dl_ch_estimates", &pdsch_vars[gNB_id]->dl_ch_estimates[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1);
write_output(filename, "dl_ch_estimates", &dl_ch_estimates[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1);
snprintf(filename, 50, "rxdataF_ext0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx);
write_output(filename, "rxdataF_ext", &pdsch_vars[gNB_id]->rxdataF_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1);
write_output(filename, "rxdataF_ext", &rxdataF_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1);
snprintf(filename, 50, "dl_ch_estimates_ext0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx);
write_output(filename, "dl_ch_estimates_ext00", &pdsch_vars[gNB_id]->dl_ch_estimates_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1);
write_output(filename, "dl_ch_estimates_ext00", &dl_ch_estimates_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1);
snprintf(filename, 50, "rxdataF_comp0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx);
write_output(filename, "rxdataF_comp00", &pdsch_vars[gNB_id]->rxdataF_comp0[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1);
/*
write_output(filename, "rxdataF_comp00", &rxdataF_comp[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1);
/*
for (int i=0; i < 2; i++){
snprintf(filename, 50, "llr%d_symb_%d_nr_slot_rx_%d.m", i, symbol, nr_slot_rx);
write_output(filename,"llr", &pdsch_vars[gNB_id]->llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb_pdsch*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb_pdsch*4*dlsch1_harq->Qm), 1, 0);
write_output(filename,"llr", &llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb_pdsch*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb_pdsch*4*dlsch1_harq->Qm), 1, 0);
}
*/
*/
#endif
}
stop_meas(&ue->generic_stat_bis[slot]);
if (cpumeas(CPUMEAS_GETSTATE))
LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n", frame, nr_slot_rx, slot, symbol, ue->generic_stat_bis[slot].p_time / (cpuf * 1000.0));
#if T_TRACER
T(T_UE_PHY_PDSCH_IQ, T_INT(gNB_id), T_INT(ue->Mod_id), T_INT(frame%1024),
T_INT(nr_slot_rx), T_INT(nb_rb_pdsch),
T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_slot),
T_BUFFER(&pdsch_vars[gNB_id]->rxdataF_comp0[gNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_slot*2));
T_BUFFER(&rxdataF_comp[gNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_slot*2));
#endif
return(0);
......@@ -599,12 +622,13 @@ void nr_dlsch_deinterleaving(uint8_t symbol,
// Pre-processing for LLR computation
//==============================================================================================
void nr_dlsch_channel_compensation(int **rxdataF_ext,
int **dl_ch_estimates_ext,
int **dl_ch_mag,
int **dl_ch_magb,
int **dl_ch_magr,
int **rxdataF_comp,
void nr_dlsch_channel_compensation(uint32_t rx_size,
int32_t rxdataF_ext[][rx_size],
int32_t dl_ch_estimates_ext[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
int32_t rxdataF_comp[][rx_size],
int ***rho,
NR_DL_FRAME_PARMS *frame_parms,
uint8_t nb_aatx,
......@@ -1304,7 +1328,8 @@ void nr_dlsch_channel_compensation_core(int **rxdataF_ext,
}
void nr_dlsch_scale_channel(int **dl_ch_estimates_ext,
void nr_dlsch_scale_channel(uint32_t rx_size,
int32_t dl_ch_estimates_ext[][rx_size],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t n_tx,
uint8_t n_rx,
......@@ -1359,7 +1384,8 @@ void nr_dlsch_scale_channel(int **dl_ch_estimates_ext,
//compute average channel_level on each (TX,RX) antenna pair
void nr_dlsch_channel_level(int **dl_ch_estimates_ext,
void nr_dlsch_channel_level(uint32_t rx_size,
int32_t dl_ch_estimates_ext[][rx_size],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t n_tx,
int32_t *avg,
......@@ -1466,7 +1492,8 @@ void nr_dlsch_channel_level(int **dl_ch_estimates_ext,
#endif
}
void nr_dlsch_channel_level_median(int **dl_ch_estimates_ext,
void nr_dlsch_channel_level_median(uint32_t rx_size,
int32_t dl_ch_estimates_ext[][rx_size],
int32_t *median,
int n_tx,
int n_rx,
......@@ -1563,10 +1590,12 @@ void nr_dlsch_channel_level_median(int **dl_ch_estimates_ext,
// Extraction functions
//==============================================================================================
void nr_dlsch_extract_rbs(int **rxdataF,
int **dl_ch_estimates,
int **rxdataF_ext,
int **dl_ch_estimates_ext,
void nr_dlsch_extract_rbs(uint32_t rxdataF_sz,
int32_t rxdataF[][rxdataF_sz],
uint32_t rx_size,
int32_t dl_ch_estimates[][rx_size],
int32_t rxdataF_ext[][rx_size],
int32_t dl_ch_estimates_ext[][rx_size],
unsigned char symbol,
uint8_t pilots,
uint8_t config_type,
......@@ -1682,11 +1711,12 @@ void nr_dlsch_extract_rbs(int **rxdataF,
}
}
void nr_dlsch_detection_mrc(int **rxdataF_comp,
void nr_dlsch_detection_mrc(uint32_t rx_size,
int32_t rxdataF_comp[][rx_size],
int ***rho,
int **dl_ch_mag,
int **dl_ch_magb,
int **dl_ch_magr,
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
short n_tx,
short n_rx,
unsigned char symbol,
......@@ -2144,11 +2174,12 @@ void nr_conjch0_mult_ch1(int *ch0,
*
*
* */
uint8_t nr_zero_forcing_rx(int **rxdataF_comp,
int **dl_ch_mag,
int **dl_ch_magb,
int **dl_ch_magr,
int **dl_ch_estimates_ext,
uint8_t nr_zero_forcing_rx(uint32_t rx_size,
int32_t rxdataF_comp[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
int32_t dl_ch_estimates_ext[][rx_size],
unsigned short nb_rb,
unsigned char n_rx,
unsigned char n_tx,//number of layer
......@@ -2305,13 +2336,13 @@ uint8_t nr_zero_forcing_rx(int **rxdataF_comp,
return(0);
}
static void nr_dlsch_layer_demapping(int16_t **llr_cw,
static void nr_dlsch_layer_demapping(int16_t *llr_cw[2],
uint8_t Nl,
uint8_t mod_order,
uint32_t length,
int32_t codeword_TB0,
int32_t codeword_TB1,
int16_t **llr_layers) {
int16_t *llr_layers[NR_MAX_NB_LAYERS]) {
switch (Nl) {
case 1:
......@@ -2343,10 +2374,13 @@ static void nr_dlsch_layer_demapping(int16_t **llr_cw,
}
}
static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
static int nr_dlsch_llr(uint32_t rx_size,
int16_t *layer_llr[NR_MAX_NB_LAYERS],
NR_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp_ptr,
int32_t **dl_ch_mag_ptr,
int32_t rxdataF_comp[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
unsigned char harq_pid,
......@@ -2359,22 +2393,23 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
int32_t codeword_TB1,
uint32_t len,
uint8_t nr_slot_rx,
NR_UE_DLSCH_t *dlsch)
NR_UE_DLSCH_t dlsch[2],
uint32_t llr_offset[14])
{
uint32_t llr_offset_symbol;
if (first_symbol_flag==1)
pdsch_vars[gNB_id]->llr_offset[symbol-1] = 0;
llr_offset_symbol = pdsch_vars[gNB_id]->llr_offset[symbol-1];
llr_offset[symbol-1] = 0;
llr_offset_symbol = llr_offset[symbol-1];
pdsch_vars[gNB_id]->llr_offset[symbol] = len*dlsch->dlsch_config.qamModOrder + llr_offset_symbol;
llr_offset[symbol] = len*dlsch[0].dlsch_config.qamModOrder + llr_offset_symbol;
switch (dlsch[0].dlsch_config.qamModOrder) {
case 2 :
for(int l=0; l < dlsch[0].Nl; l++)
nr_dlsch_qpsk_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx],
pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol,
rxdataF_comp[l*frame_parms->nb_antennas_rx],
layer_llr[l]+llr_offset_symbol,
symbol,
len,
first_symbol_flag,
......@@ -2384,9 +2419,9 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
case 4 :
for(int l=0; l < dlsch[0].Nl; l++)
nr_dlsch_16qam_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx],
pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol,
pdsch_vars[gNB_id]->dl_ch_mag0[0],
rxdataF_comp[l*frame_parms->nb_antennas_rx],
layer_llr[l]+llr_offset_symbol,
dl_ch_mag[0],
symbol,
len,
first_symbol_flag,
......@@ -2396,10 +2431,10 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
case 6 :
for(int l=0; l < dlsch[0].Nl; l++)
nr_dlsch_64qam_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx],
pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol,
pdsch_vars[gNB_id]->dl_ch_mag0[0],
pdsch_vars[gNB_id]->dl_ch_magb0[0],
rxdataF_comp[l*frame_parms->nb_antennas_rx],
layer_llr[l]+llr_offset_symbol,
dl_ch_mag[0],
dl_ch_magb[0],
symbol,
len,
first_symbol_flag,
......@@ -2409,11 +2444,11 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
case 8:
for(int l=0; l < dlsch[0].Nl; l++)
nr_dlsch_256qam_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx],
pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol,
pdsch_vars[gNB_id]->dl_ch_mag0[0],
pdsch_vars[gNB_id]->dl_ch_magb0[0],
pdsch_vars[gNB_id]->dl_ch_magr0[0],
rxdataF_comp[l*frame_parms->nb_antennas_rx],
layer_llr[l]+llr_offset_symbol,
dl_ch_mag[0],
dl_ch_magb[0],
dl_ch_magr[0],
symbol,
len,
first_symbol_flag,
......@@ -2426,12 +2461,13 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
break;
}
//TODO: Revisited for Nl>4
if (dlsch1_harq) {
switch (dlsch[1].dlsch_config.qamModOrder) {
case 2 :
nr_dlsch_qpsk_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[0],
pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol,
rxdataF_comp[0],
layer_llr[0]+llr_offset_symbol,
symbol,
len,
first_symbol_flag,
......@@ -2440,9 +2476,9 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
case 4:
nr_dlsch_16qam_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[0],
pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol,
pdsch_vars[gNB_id]->dl_ch_mag0[0],
rxdataF_comp[0],
layer_llr[0]+llr_offset_symbol,
dl_ch_mag[0],
symbol,
len,
first_symbol_flag,
......@@ -2451,10 +2487,10 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
case 6 :
nr_dlsch_64qam_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[0],
pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol,
pdsch_vars[gNB_id]->dl_ch_mag0[0],
pdsch_vars[gNB_id]->dl_ch_magb0[0],
rxdataF_comp[0],
layer_llr[0]+llr_offset_symbol,
dl_ch_mag[0],
dl_ch_magb[0],
symbol,
len,
first_symbol_flag,
......@@ -2463,11 +2499,11 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
case 8 :
nr_dlsch_256qam_llr(frame_parms,
pdsch_vars[gNB_id]->rxdataF_comp0[0],
pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol,
pdsch_vars[gNB_id]->dl_ch_mag0[0],
pdsch_vars[gNB_id]->dl_ch_magb0[0],
pdsch_vars[gNB_id]->dl_ch_magr0[0],
rxdataF_comp[0],
layer_llr[0]+llr_offset_symbol,
dl_ch_mag[0],
dl_ch_magb[0],
dl_ch_magr[0],
symbol,
len,
first_symbol_flag,
......
......@@ -101,7 +101,7 @@ void free_list(NR_UE_SSB *node) {
}
int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_initial_symbol, nr_phy_data_t *phy_data)
int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_initial_symbol, nr_phy_data_t *phy_data, int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
int ret =-1;
......@@ -127,7 +127,7 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
start_meas(&ue->dlsch_channel_estimation_stats);
// computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
nr_pbch_dmrs_correlation(ue,proc,0,0,i,i-pbch_initial_symbol,current_ssb);
nr_pbch_dmrs_correlation(ue,proc,0,0,i,i-pbch_initial_symbol,current_ssb,rxdataF);
stop_meas(&ue->dlsch_channel_estimation_stats);
current_ssb->metric = current_ssb->c_re*current_ssb->c_re + current_ssb->c_im*current_ssb->c_im;
......@@ -152,7 +152,7 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
nr_pbch_channel_estimation(ue,estimateSz, dl_ch_estimates, dl_ch_estimates_time,
proc,0,0,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf);
proc,0,0,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF);
stop_meas(&ue->dlsch_channel_estimation_stats);
fapiPbch_t result;
......@@ -166,7 +166,8 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
temp_ptr->i_ssb,
SISO,
phy_data,
&result);
&result,
rxdataF);
if (DUMP_PBCH_CH_ESTIMATES && (ret == 0)) {
write_output("pbch_ch_estimates.m", "pbch_ch_estimates", dl_ch_estimates, frame_parms->nb_antennas_rx*estimateSz, 1, 1);
......@@ -242,6 +243,8 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
* sync_pos SS/PBCH block
*/
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
__attribute__ ((aligned(32))) int32_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
cnt++;
if (1){ // (cnt>100)
cnt =0;
......@@ -304,14 +307,15 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
i,
0,
is*fp->samples_per_frame+ue->ssb_offset,
false);
false,
rxdataF);
#ifdef DEBUG_INITIAL_SYNCH
LOG_I(PHY,"Calling sss detection (normal CP)\n");
#endif
int freq_offset_sss = 0;
ret = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss);
ret = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss, rxdataF);
// digital compensation of FFO for SSB symbols
if (ue->UE_fo_compensation){
......@@ -341,7 +345,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
if (ret==0) { //we got sss channel
nr_gold_pbch(ue);
ret = nr_pbch_detection(proc, ue, 1, &phy_data); // start pbch detection at first symbol after pss
ret = nr_pbch_detection(proc, ue, 1, &phy_data, rxdataF); // start pbch detection at first symbol after pss
}
if (ret == 0) {
......@@ -541,7 +545,8 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
l, // the UE PHY has no notion of the symbols to be monitored in the search space
phy_pdcch_config->slot,
is*fp->samples_per_frame+phy_pdcch_config->sfn*fp->samples_per_frame+ue->rx_offset,
true);
true,
rxdataF);
nr_pdcch_channel_estimation(ue,
proc,
......@@ -552,10 +557,11 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
fp->first_carrier_offset,
phy_pdcch_config->pdcch_config[n_ss].BWPStart,
pdcch_est_size,
pdcch_dl_ch_estimates);
pdcch_dl_ch_estimates,
rxdataF);
}
int dci_cnt = nr_ue_pdcch_procedures(gnb_id, ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, &phy_data, n_ss);
int dci_cnt = nr_ue_pdcch_procedures(gnb_id, ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, &phy_data, n_ss, rxdataF);
if (dci_cnt>0){
NR_UE_DLSCH_t *dlsch = phy_data.dlsch;
if (dlsch[0].active == 1) {
......@@ -568,22 +574,51 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
m,
phy_pdcch_config->slot, // same slot and offset as pdcch
is*fp->samples_per_frame+phy_pdcch_config->sfn*fp->samples_per_frame+ue->rx_offset,
true);
true,
rxdataF);
}
uint8_t nb_re_dmrs;
if (dlsch[0].dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1) {
nb_re_dmrs = 6*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
}
else {
nb_re_dmrs = 4*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
}
uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos);
const uint32_t rx_llr_size = nr_get_G(dlsch[0].dlsch_config.number_rbs,
dlsch[0].dlsch_config.number_symbols,
nb_re_dmrs,
dmrs_len,
dlsch[0].dlsch_config.qamModOrder,
dlsch[0].Nl);
const uint32_t rx_llr_layer_size = (rx_llr_size + dlsch[0].Nl - 1) / dlsch[0].Nl;
int16_t* llr[2];
int16_t* layer_llr[NR_MAX_NB_LAYERS];
llr[0] = (int16_t *)malloc16_clear(rx_llr_size*sizeof(int16_t));
for (int i=0; i<NR_MAX_NB_LAYERS; i++)
layer_llr[i] = (int16_t *)malloc16_clear(rx_llr_layer_size*sizeof(int16_t));
int ret = nr_ue_pdsch_procedures(ue,
proc,
gnb_id,
dlsch);
phy_data.dlsch,
llr,
layer_llr,
rxdataF);
if (ret >= 0)
dec = nr_ue_dlsch_procedures(ue,
proc,
gnb_id,
dlsch,
NULL);
phy_data.dlsch,
llr);
// deactivate dlsch once dlsch proc is done
dlsch->active = 0;
dlsch[0].active = 0;
free(llr[0]);
for (int i=0; i<NR_MAX_NB_LAYERS; i++)
free(layer_llr[i]);
}
}
}
......
......@@ -49,7 +49,8 @@
#define PBCH_MAX_RE (PBCH_MAX_RE_PER_SYMBOL*4)
#define print_shorts(s,x) printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s,((int16_t*)x)[0],((int16_t*)x)[1],((int16_t*)x)[2],((int16_t*)x)[3],((int16_t*)x)[4],((int16_t*)x)[5],((int16_t*)x)[6],((int16_t*)x)[7])
static uint16_t nr_pbch_extract(int **rxdataF,
static uint16_t nr_pbch_extract(uint32_t rxdataF_sz,
int32_t rxdataF[][rxdataF_sz],
const int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
......@@ -392,9 +393,9 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
uint8_t i_ssb,
MIMO_mode_t mimo_mode,
nr_phy_data_t *phy_data,
fapiPbch_t *result) {
fapiPbch_t *result,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars;
int max_h=0;
int symbol;
//uint8_t pbch_a[64];
......@@ -424,7 +425,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
#ifdef DEBUG_PBCH
//printf("address dataf %p",nr_ue_common_vars->rxdataF);
write_output("rxdataF0_pbch.m","rxF0pbch",
&nr_ue_common_vars->rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1);
&rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1);
#endif
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
double log2_maxh = 0;
......@@ -434,7 +435,8 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
__attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
nr_pbch_extract(nr_ue_common_vars->rxdataF,
nr_pbch_extract(ue->frame_parms.samples_per_slot_wCP,
rxdataF,
estimateSz,
dl_ch_estimates,
rxdataF_ext,
......
......@@ -543,10 +543,12 @@ void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms,
@param n_dmrs_cdm_groups
@param frame_parms Pointer to frame descriptor
*/
void nr_dlsch_extract_rbs(int **rxdataF,
int **dl_ch_estimates,
int **rxdataF_ext,
int **dl_ch_estimates_ext,
void nr_dlsch_extract_rbs(uint32_t rxdataF_sz,
int rxdataF[][rxdataF_sz],
uint32_t rx_size,
int32_t dl_ch_estimates[][rx_size],
int32_t rxdataF_ext[][rx_size],
int32_t dl_ch_estimates_ext[][rx_size],
unsigned char symbol,
uint8_t pilots,
uint8_t config_type,
......@@ -558,7 +560,6 @@ void nr_dlsch_extract_rbs(int **rxdataF,
uint16_t dlDmrsSymbPos,
int chest_time_type);
/** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation. In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation)
@param rxdataF_ext Frequency-domain received signal in RBs to be demodulated
@param dl_ch_estimates_ext Frequency-domain channel estimates in RBs to be demodulated
......@@ -574,22 +575,23 @@ void nr_dlsch_extract_rbs(int **rxdataF,
@param output_shift Rescaling for compensated output (should be energy-normalizing)
@param phy_measurements Pointer to UE PHY measurements
*/
void nr_dlsch_channel_compensation(int32_t **rxdataF_ext,
int32_t **dl_ch_estimates_ext,
int32_t **dl_ch_mag,
int32_t **dl_ch_magb,
int32_t **dl_ch_magr,
int32_t **rxdataF_comp,
int32_t ***rho,
void nr_dlsch_channel_compensation(uint32_t rx_size,
int32_t rxdataF_ext[][rx_size],
int32_t dl_ch_estimates_ext[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
int32_t rxdataF_comp[][rx_size],
int ***rho,
NR_DL_FRAME_PARMS *frame_parms,
uint8_t nb_aatx,
uint8_t symbol,
unsigned char symbol,
int length,
uint8_t first_symbol_flag,
uint8_t mod_order,
uint16_t nb_rb,
uint8_t output_shift,
PHY_NR_MEASUREMENTS *phy_measurements);
unsigned char mod_order,
unsigned short nb_rb,
unsigned char output_shift,
PHY_NR_MEASUREMENTS *measurements);
void nr_dlsch_channel_compensation_core(int **rxdataF_ext,
int **dl_ch_estimates_ext,
......@@ -611,18 +613,20 @@ void nr_dlsch_deinterleaving(uint8_t symbol,
uint16_t *llr_deint,
uint16_t nb_rb_pdsch);
void nr_dlsch_channel_level_median(int **dl_ch_estimates_ext,
void nr_dlsch_channel_level_median(uint32_t rx_size,
int32_t dl_ch_estimates[][rx_size],
int32_t *median,
int n_tx,
int n_rx,
int length,
int start_point);
void nr_dlsch_detection_mrc(int **rxdataF_comp,
void nr_dlsch_detection_mrc(uint32_t rx_size,
int32_t rxdataF_comp[][rx_size],
int ***rho,
int **dl_ch_mag,
int **dl_ch_magb,
int **dl_ch_magr,
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
short n_tx,
short n_rx,
unsigned char symbol,
......@@ -647,7 +651,8 @@ void nr_a_sum_b(__m128i *input_x,
@param pilots_flag Flag to indicate pilots in symbol
@param nb_rb Number of allocated RBs
*/
void nr_dlsch_channel_level(int **dl_ch_estimates_ext,
void nr_dlsch_channel_level(uint32_t rx_size,
int32_t dl_ch_estimates[][rx_size],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t n_tx,
int32_t *avg,
......@@ -655,15 +660,15 @@ void nr_dlsch_channel_level(int **dl_ch_estimates_ext,
uint32_t len,
unsigned short nb_rb);
void nr_dlsch_scale_channel(int32_t **dl_ch_estimates_ext,
void nr_dlsch_scale_channel(uint32_t rx_size,
int32_t dl_ch_estimates[][rx_size],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t n_tx,
uint8_t n_rx,
uint8_t symbol,
uint8_t start_symbol,
uint8_t pilots,
uint32_t len,
uint16_t nb_rb);
unsigned short nb_rb);
/** \brief This is the top-level entry point for DLSCH decoding in UE. It should be replicated on several
threads (on multi-core machines) corresponding to different HARQ processes. The routine first
......@@ -751,7 +756,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
int16_t *pdcch_e_rx,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15);
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
int32_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)
......@@ -777,12 +783,14 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
uint8_t i_ssb,
MIMO_mode_t mimo_mode,
nr_phy_data_t *phy_data,
fapiPbch_t* result);
fapiPbch_t* result,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_pbch_detection(UE_nr_rxtx_proc_t *proc,
PHY_VARS_NR_UE *ue,
int pbch_initial_symbol,
nr_phy_data_t *phy_data);
nr_phy_data_t *phy_data,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
#ifndef modOrder
......@@ -862,14 +870,31 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
*/
int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch,
NR_UE_DLSCH_t dlsch[2],
unsigned char gNB_id,
unsigned char gNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference
unsigned char gNB_id_i,
uint32_t frame,
uint8_t nr_slot_rx,
unsigned char symbol,
unsigned char first_symbol_flag,
unsigned char harq_pid);
unsigned char harq_pid,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size],
int16_t *llr[2],
int16_t *layer_llr[NR_MAX_NB_LAYERS],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
uint32_t rx_size,
int32_t dl_ch_estimates_ext[][rx_size],
int32_t rxdataF_ext[][rx_size],
int32_t rxdataF_comp[][rx_size],
int32_t dl_ch_mag[][rx_size],
int32_t dl_ch_magb[][rx_size],
int32_t dl_ch_magr[][rx_size],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT],
int32_t *log2_maxh);
int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t slot);
......
......@@ -318,13 +318,13 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue,
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
uint8_t doPss, uint8_t doSss,
uint8_t subframe) // add flag to indicate extracting only PSS, only SSS, or both
uint8_t subframe,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both
{
uint8_t aarx;
int32_t *pss_rxF,*pss_rxF_ext;
int32_t *sss_rxF,*sss_rxF_ext;
uint8_t pss_symbol, sss_symbol;
int32_t **rxdataF;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
......@@ -332,8 +332,6 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue,
pss_symbol = 0;
sss_symbol = SSS_SYMBOL_NB-PSS_SYMBOL_NB;
rxdataF = ue->common_vars.rxdataF;
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
pss_rxF = &rxdataF[aarx][pss_symbol*ofdm_symbol_size];
......@@ -402,9 +400,10 @@ int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
UE_nr_rxtx_proc_t *proc,
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
uint8_t subframe)
uint8_t subframe,
int32_t rxdataF[][phy_vars_ue->frame_parms.samples_per_slot_wCP])
{
return do_pss_sss_extract_nr(phy_vars_ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe);
return do_pss_sss_extract_nr(phy_vars_ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe, rxdataF);
}
/*******************************************************************
......@@ -420,7 +419,7 @@ int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
*
*********************************************************************/
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss)
int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
uint8_t i;
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
......@@ -439,7 +438,8 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric,
proc,
pss_ext,
sss_ext,
0); /* subframe */
0,
rxdataF); /* subframe */
#ifdef DEBUG_PLOT_SSS
......
......@@ -788,13 +788,19 @@ static void ueChannelResponse (scopeGraphData_t **data, OAIgraph_t *graph, PHY_
}
static void ueFreqWaterFall (scopeGraphData_t **data, OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id ) {
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->frame_parms;
//use 1st antenna
if (!data[commonRxdataF])
return;
const int sz = data[commonRxdataF]->lineSz;
scopeSample_t *rxdataF = (scopeSample_t *)(data[commonRxdataF]+1);
genericWaterFall(graph,
(scopeSample_t *)phy_vars_ue->common_vars.rxdataF[0],
frame_parms->samples_per_slot_wCP,
phy_vars_ue->frame_parms.slots_per_frame,
"X axis: one frame frequency" );
rxdataF,
sz,
1,
"X axis: one slot frequency" );
}
/*
static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
......@@ -925,70 +931,48 @@ static void uePcchIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_U
}
static void uePdschLLR (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
// PDSCH LLRs
if (!phy_vars_ue->pdsch_vars[eNB_id]->llr[0])
if (!data[pdschLlr])
return;
int num_re = 4500;
int Qm = 2;
int coded_bits_per_codeword = num_re*Qm;
int newsz = 0;
const int sz = data[pdschLlr]->lineSz;
float *llr, *bit;
int nx = sz;
int16_t *pdsch_llr = (int16_t *)(data[pdschLlr]+1);
#ifndef WEBSRVSCOPE
oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword*RX_NB_TH_MAX, 0);
#endif
int base=0;
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
int16_t *pdsch_llr = (int16_t *) phy_vars_ue->pdsch_vars[eNB_id]->llr[0]; // stream 0
#ifdef WEBSRVSCOPE
newsz += websrv_cpllrbuff_tomsg(graph, pdsch_llr, coded_bits_per_codeword, 0, thr, RX_NB_TH_MAX);
nx = websrv_cpllrbuff_tomsg(graph, pdsch_llr, sz, UE_id, 0, 0);
#else
for (int i=0; i<coded_bits_per_codeword; i++) {
llr[base+i] = (float) pdsch_llr[i];
bit[base+i] = (float) base+i;
oai_xygraph_getbuff(graph, &bit, &llr, sz, 0);
for (int i=0; i<sz; i++) {
llr[i] = (float) pdsch_llr[i];
}
newsz += coded_bits_per_codeword;
#endif
base+=coded_bits_per_codeword;
}
AssertFatal(base <= coded_bits_per_codeword*RX_NB_TH_MAX, "");
//fl_set_xyplot_xbounds(form->pdsch_llr,0,coded_bits_per_codeword);
oai_xygraph(graph, bit, llr, newsz, 0, 10);
oai_xygraph(graph, bit, llr, nx, 0, 10);
}
static void uePdschIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
// PDSCH I/Q of MF Output
if (!phy_vars_ue->pdsch_vars[eNB_id]->rxdataF_comp0[0])
if (!data[pdschRxdataF_comp])
return;
NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms;
int sz=7*2*frame_parms->N_RB_DL*12; // size of the malloced buffer
int newsz = 0;
const int sz=data[pdschRxdataF_comp]->lineSz;
int nz = sz;
float *I, *Q;
int base=0;
#ifndef WEBSRVSCOPE
oai_xygraph_getbuff(graph, &I, &Q, sz * RX_NB_TH_MAX, 0);
memset(I+base, 0, sz*RX_NB_TH_MAX * sizeof(*I));
memset(Q+base, 0, sz*RX_NB_TH_MAX * sizeof(*Q));
#endif
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
scopeSample_t *pdsch_comp = (scopeSample_t *) phy_vars_ue->pdsch_vars[eNB_id]->rxdataF_comp0[0];
scopeSample_t *pdsch_comp = (scopeSample_t *) (data[pdschRxdataF_comp]+1);
#ifdef WEBSRVSCOPE
newsz += websrv_cpiqbuff_tomsg(graph, pdsch_comp, sz, 0, base);
nz += websrv_cpiqbuff_tomsg(graph, pdsch_comp, sz, 0, 0);
#else
oai_xygraph_getbuff(graph, &I, &Q, sz, 0);
for (int s=0; s<sz; s++) {
I[s+base] += pdsch_comp[s].r;
Q[s+base] += pdsch_comp[s].i;
I[s] = pdsch_comp[s].r;
Q[s] = pdsch_comp[s].i;
}
newsz += sz;
#endif
base+=sz;
}
AssertFatal(base <= sz*RX_NB_TH_MAX, "");
oai_xygraph(graph, I, Q, newsz, 0, 10);
oai_xygraph(graph, I, Q, nz, 0, 10);
}
static void uePdschThroughput (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
/*
......@@ -1153,19 +1137,23 @@ static void *nrUEscopeThread(void *arg) {
}
#endif
pthread_mutex_t UEcopyDataMutex;
void UEcopyData(PHY_VARS_NR_UE *ue, enum UEdataType type, void *dataIn, int elementSz, int colSz, int lineSz) {
// Local static copy of the scope data bufs
// The active data buf is alterned to avoid interference between the Scope thread (display) and the Rx thread (data input)
// Index of "2" could be set to the number of Rx threads + 1
static scopeGraphData_t *copyDataBufs[UEdataTypeNumberOfItems][2] = {0};
static scopeGraphData_t *copyDataBufs[UEdataTypeNumberOfItems][3] = {0};
static int copyDataBufsIdx[UEdataTypeNumberOfItems] = {0};
scopeData_t *tmp=(scopeData_t *)ue->scopeData;
if (tmp) {
// Begin of critical zone between UE Rx threads that might copy new data at the same time: might require a mutex
int newCopyDataIdx = (copyDataBufsIdx[type]==0)?1:0;
// Begin of critical zone between UE Rx threads that might copy new data at the same time:
pthread_mutex_lock(&UEcopyDataMutex);
int newCopyDataIdx = (copyDataBufsIdx[type]<2)?copyDataBufsIdx[type]+1:0;
copyDataBufsIdx[type] = newCopyDataIdx;
pthread_mutex_unlock(&UEcopyDataMutex);
// End of critical zone between UE Rx threads
// New data will be copied in a different buffer than the live one
......@@ -1204,6 +1192,7 @@ STATICFORXSCOPE void nrUEinitScope(PHY_VARS_NR_UE *ue)
pthread_t forms_thread;
threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW);
#endif
pthread_mutex_init(&UEcopyDataMutex, NULL);
}
void nrscope_autoinit(void *dataptr) {
......
......@@ -47,6 +47,9 @@ enum UEdataType {
pbchRxdataF_comp,
pdcchLlr,
pdcchRxdataF_comp,
pdschLlr,
pdschRxdataF_comp,
commonRxdataF,
UEdataTypeNumberOfItems
};
......
......@@ -232,11 +232,6 @@ typedef struct {
/// - second index: sample [0..2*FRAME_LENGTH_COMPLEX_SAMPLES+2048[
int32_t **rxdata;
/// \brief Holds the received data in the frequency domain.
/// - first index: rx antenna [0..nb_antennas_rx[
/// - second index: symbol [0..28*ofdm_symbol_size[
int32_t **rxdataF;
/// holds output of the sync correlator
int32_t *sync_corr;
/// estimated frequency offset (in radians) for all subcarriers
......@@ -245,97 +240,6 @@ typedef struct {
int32_t eNb_id;
} NR_UE_COMMON;
typedef struct {
/// \brief Received frequency-domain signal after extraction.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **rxdataF_ext;
/// \brief Received frequency-domain ue specific pilots.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..12*N_RB_DL[
int32_t **rxdataF_uespec_pilots;
/// \brief Received frequency-domain signal after extraction and channel compensation.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **rxdataF_comp0;
/// \brief Hold the channel estimates in frequency domain.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[
int32_t **dl_ch_estimates;
/// \brief Downlink channel estimates extracted in PRBS.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **dl_ch_estimates_ext;
/// \brief Downlink beamforming channel estimates in frequency domain.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[
int32_t **dl_bf_ch_estimates;
/// \brief Downlink beamforming channel estimates.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **dl_bf_ch_estimates_ext;
/// \brief Downlink PMIs extracted in PRBS and grouped in subbands.
/// - first index: ressource block [0..N_RB_DL[
uint8_t *pmi_ext;
/// \brief Magnitude of Downlink Channel first layer (16QAM level/First 64QAM level).
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **dl_ch_mag0;
/// \brief Magnitude of Downlink Channel, first layer (2nd 64QAM level).
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **dl_ch_magb0;
/// \brief Magnitude of Downlink Channel, first layer (256QAM level).
int32_t **dl_ch_magr0;
/// \brief Cross-correlation Matrix of the gNB Tx channel signals.
/// - first index: aatx*n_rx+aarx for all aatx=[0..n_tx[ and aarx=[0..nb_rx[
/// - second index: symbol [0..]
int32_t ***rho;
/// \brief Pointers to llr vectors (2 TBs).
/// - first index: ? [0..1] (hard coded)
/// - second index: ? [0..1179743] (hard coded)
int16_t *llr[2];
/// Pointers to layer llr vectors (4 layers).
int16_t *layer_llr[4];
/// \f$\log_2(\max|H_i|^2)\f$
int16_t log2_maxh;
/// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer1 channel compensation
int16_t log2_maxh0;
/// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer2 channel commpensation
int16_t log2_maxh1;
/// \brief LLR shifts for subband scaling.
/// - first index: ? [0..168*N_RB_DL[
uint8_t *llr_shifts;
/// \brief Pointer to LLR shifts.
/// - first index: ? [0..168*N_RB_DL[
uint8_t *llr_shifts_p;
/// \brief Pointers to llr vectors (128-bit alignment).
/// - first index: ? [0..0] (hard coded)
/// - second index: ? [0..]
int16_t **llr128;
/// \brief Pointers to llr vectors (128-bit alignment).
/// - first index: ? [0..0] (hard coded)
/// - second index: ? [0..]
int16_t **llr128_2ndstream;
//uint32_t *rb_alloc;
//uint8_t Qm[2];
//MIMO_mode_t mimo_mode;
// llr offset per ofdm symbol
uint32_t llr_offset[14];
// llr length per ofdm symbol
uint32_t llr_length[14];
// llr offset per ofdm symbol
uint32_t dl_valid_re[14];
/// \brief Estimated phase error based upon PTRS on each symbol .
/// - first index: ? [0..7] Number of Antenna
/// - second index: ? [0...14] smybol per slot
int32_t **ptrs_phase_per_slot;
/// \brief Estimated phase error based upon PTRS on each symbol .
/// - first index: ? [0..7] Number of Antenna
/// - second index: ? [0...14] smybol per slot
int32_t **ptrs_re_per_slot;
} NR_UE_PDSCH;
#define NR_PRS_IDFT_OVERSAMP_FACTOR 1 // IDFT oversampling factor for NR PRS channel estimates in time domain, ALLOWED value 16x, and 1x is default(ie. IDFT size is frame_params->ofdm_symbol_size)
typedef struct {
prs_config_t prs_cfg;
......@@ -532,7 +436,6 @@ typedef struct {
fapi_nr_config_request_t nrUE_config;
NR_UE_PDSCH *pdsch_vars[NUMBER_OF_CONNECTED_gNB_MAX+1];
NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_CSI_IM *csiim_vars[NUMBER_OF_CONNECTED_gNB_MAX];
......@@ -540,7 +443,7 @@ typedef struct {
NR_UE_SRS *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE];
uint8_t prs_active_gNBs;
NR_DL_UE_HARQ_t dl_harq_processes[NR_MAX_NB_LAYERS>4 ? 2:1][NR_MAX_DLSCH_HARQ_PROCESSES];
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
NR_UL_UE_HARQ_t ul_harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES];
//Paging parameters
......@@ -750,6 +653,14 @@ typedef struct {
int dl_errors;
int dl_stats[8];
void* scopeData;
// Pointers to hold PDSCH data only for phy simulators
void *phy_sim_rxdataF;
void *phy_sim_pdsch_llr;
void *phy_sim_pdsch_rxdataF_ext;
void *phy_sim_pdsch_rxdataF_comp;
void *phy_sim_pdsch_dl_ch_estimates;
void *phy_sim_pdsch_dl_ch_estimates_ext;
bool phy_sim_mode;
} PHY_VARS_NR_UE;
typedef struct nr_phy_data_tx_s {
......@@ -759,7 +670,7 @@ typedef struct nr_phy_data_tx_s {
typedef struct nr_phy_data_s {
NR_UE_PDCCH_CONFIG phy_pdcch_config;
NR_UE_DLSCH_t dlsch[NR_MAX_NB_LAYERS>4 ? 2:1];
NR_UE_DLSCH_t dlsch[2];
} nr_phy_data_t;
/* this structure is used to pass both UE phy vars and
* proc to the function UE_thread_rxn_txnp4
......
......@@ -175,13 +175,16 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int gNB_id,
NR_UE_DLSCH_t *dlsch0,
NR_UE_DLSCH_t *dlsch1);
NR_UE_DLSCH_t dlsch[2],
int16_t* llr[2]);
int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int gNB_id,
NR_UE_DLSCH_t *dlsch);
NR_UE_DLSCH_t dlsch[2],
int16_t *llr[2],
int16_t *layer_llr[NR_MAX_NB_LAYERS],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_ue_pdcch_procedures(uint8_t gNB_id,
PHY_VARS_NR_UE *ue,
......@@ -189,11 +192,12 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss);
int n_ss,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id);
int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id);
int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
#endif
......@@ -65,6 +65,11 @@
/*************** FUNCTIONS ****************************************/
/** \brief This function update uplink harq context and return transmission type (new transmission or retransmission)
@param ulsch uplink harq context
@param harq process identifier harq_pid
@returns retransmission or new transmission */
harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, NR_UL_UE_HARQ_t harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES], int ndi, uint8_t rnti_type);
/** \brief This function initialises downlink HARQ status
......
......@@ -52,7 +52,8 @@
#include "executables/softmodem-common.h"
#include "executables/nr-uesoftmodem.h"
#include "LAYER2/NR_MAC_UE/mac_proto.h"
#include "openair1/SCHED_NR_UE/pucch_uci_ue_nr.h"
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
//#define DEBUG_PHY_PROC
#define NR_PDCCH_SCHED
......@@ -323,8 +324,9 @@ void nr_ue_measurement_procedures(uint16_t l,
PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
uint8_t gNB_id,
uint16_t slot,
NR_UE_DLSCH_t *dlsch){
NR_UE_DLSCH_t *dlsch,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size]) {
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
int frame_rx = proc->frame_rx;
......@@ -339,10 +341,10 @@ void nr_ue_measurement_procedures(uint16_t l,
nr_slot_rx,
ue->common_vars.rxdata);
nr_ue_measurements(ue, proc, nr_slot_rx, dlsch);
nr_ue_measurements(ue, proc, dlsch, pdsch_est_size, dl_ch_estimates);
#if T_TRACER
if(slot == 0)
if(nr_slot_rx == 0)
T(T_UE_PHY_MEAS, T_INT(gNB_id), T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_slot_rx),
T_INT((int)(10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB)),
T_INT((int)ue->measurements.rx_rssi_dBm[0]),
......@@ -355,7 +357,7 @@ void nr_ue_measurement_procedures(uint16_t l,
}
// accumulate and filter timing offset estimation every subframe (instead of every frame)
if (( slot == 2) && (l==(2-frame_parms->Ncp))) {
if (( nr_slot_rx == 2) && (l==(2-frame_parms->Ncp))) {
// AGC
......@@ -377,7 +379,8 @@ static void nr_ue_pbch_procedures(uint8_t gNB_id,
UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
nr_phy_data_t *phy_data) {
nr_phy_data_t *phy_data,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
int ret = 0;
DevAssert(ue);
......@@ -389,15 +392,18 @@ static void nr_ue_pbch_procedures(uint8_t gNB_id,
LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,nr_slot_rx,ue->frame_parms.Nid_cell,gNB_id);
fapiPbch_t result;
ret = nr_rx_pbch(ue, proc,
estimateSz, dl_ch_estimates,
ret = nr_rx_pbch(ue,
proc,
estimateSz,
dl_ch_estimates,
ue->pbch_vars[gNB_id],
&ue->frame_parms,
gNB_id,
(ue->frame_parms.ssb_index)&7,
SISO,
phy_data,
&result);
&result,
rxdataF);
if (ret==0) {
......@@ -504,7 +510,8 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss)
int n_ss,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
......@@ -522,7 +529,7 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id,
int16_t pdcch_e_rx[pdcch_e_rx_size];
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
nr_rx_pdcch(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15);
nr_rx_pdcch(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT);
......@@ -566,7 +573,13 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id,
}
#endif // NR_PDCCH_SCHED
int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_id, NR_UE_DLSCH_t *dlsch) {
int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int gNB_id,
NR_UE_DLSCH_t dlsch[2],
int16_t *llr[2],
int16_t *layer_llr[NR_MAX_NB_LAYERS],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
......@@ -577,12 +590,8 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
if (!dlsch[0].active)
return 0;
NR_UE_DLSCH_t *dlsch1 = NULL;
if (NR_MAX_NB_LAYERS > 4)
dlsch1 = &dlsch[1];
if (!dlsch1) {
// We handle only one CW now
if (!(NR_MAX_NB_LAYERS>4)) {
NR_UE_DLSCH_t *dlsch0 = &dlsch[0];
int harq_pid = dlsch0->dlsch_config.harq_process_nbr;
NR_DL_UE_HARQ_t *dlsch0_harq = ue->dl_harq_processes[harq_pid];
......@@ -596,6 +605,10 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
LOG_D(PHY,"[UE %d] nr_slot_rx %d, harq_pid %d (%d), rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x, Nl %d\n",
ue->Mod_id,nr_slot_rx,harq_pid,dlsch0_harq->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->dlsch_config.dlDmrsSymbPos, dlsch0->Nl);
const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot*ue->frame_parms.ofdm_symbol_size+15)/16)*16;
__attribute__ ((aligned(32))) int32_t pdsch_dl_ch_estimates[ue->frame_parms.nb_antennas_rx][pdsch_est_size];
memset(pdsch_dl_ch_estimates, 0, sizeof(int32_t)*ue->frame_parms.nb_antennas_rx*pdsch_est_size);
for (m = s0; m < (s0 +s1); m++) {
if (dlsch0->dlsch_config.dlDmrsSymbPos & (1 << m)) {
for (uint8_t aatx=0; aatx<dlsch0->Nl; aatx++) {//for MIMO Config: it shall loop over no_layers
......@@ -612,7 +625,10 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
BWPStart,
dlsch0->dlsch_config.dmrsConfigType,
ue->frame_parms.first_carrier_offset+(BWPStart + pdsch_start_rb)*12,
pdsch_nb_rb);
pdsch_nb_rb,
pdsch_est_size,
pdsch_dl_ch_estimates,
rxdataF);
#if 0
///LOG_M: the channel estimation
int nr_frame_rx = proc->frame_rx;
......@@ -626,10 +642,11 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
}
}
}
nr_ue_measurement_procedures(2, ue, proc, gNB_id, &dlsch[0], pdsch_est_size, pdsch_dl_ch_estimates);
if (ue->chest_time == 1) { // averaging time domain channel estimates
nr_chest_time_domain_avg(&ue->frame_parms,
ue->pdsch_vars[gNB_id]->dl_ch_estimates,
(int32_t **) pdsch_dl_ch_estimates,
dlsch0->dlsch_config.number_symbols,
dlsch0->dlsch_config.start_symbol,
dlsch0->dlsch_config.dlDmrsSymbPos,
......@@ -648,6 +665,37 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
first_symbol_with_data++;
}
c16_t ptrs_phase_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
memset(ptrs_phase_per_slot, 0, ue->frame_parms.nb_antennas_rx*NR_SYMBOLS_PER_SLOT*sizeof(c16_t));
int32_t ptrs_re_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
memset(ptrs_re_per_slot, 0, ue->frame_parms.nb_antennas_rx*NR_SYMBOLS_PER_SLOT*sizeof(c16_t));
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT] = {0};
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT] = {0};
const uint32_t rx_size = NR_SYMBOLS_PER_SLOT*
dlsch[0].dlsch_config.number_rbs*
NR_NB_SC_PER_RB;
__attribute__ ((aligned(32))) int32_t dl_ch_estimates_ext[ue->frame_parms.nb_antennas_rx][rx_size];
memset(dl_ch_estimates_ext, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
__attribute__ ((aligned(32))) int32_t rxdataF_ext[ue->frame_parms.nb_antennas_rx][rx_size];
memset(rxdataF_ext, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
__attribute__ ((aligned(32))) int32_t rxdataF_comp[ue->frame_parms.nb_antennas_rx][rx_size];
memset(rxdataF_comp, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
__attribute__ ((aligned(32))) int32_t dl_ch_mag[ue->frame_parms.nb_antennas_rx][rx_size];
memset(dl_ch_mag, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
__attribute__ ((aligned(32))) int32_t dl_ch_magb[ue->frame_parms.nb_antennas_rx][rx_size];
memset(dl_ch_magb, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
__attribute__ ((aligned(32))) int32_t dl_ch_magr[ue->frame_parms.nb_antennas_rx][rx_size];
memset(dl_ch_magr, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
int32_t log2_maxh = 0;
start_meas(&ue->rx_pdsch_stats);
for (m = s0; m < (s1 + s0); m++) {
......@@ -672,7 +720,24 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
nr_slot_rx,
m,
first_symbol_flag,
harq_pid) < 0)
harq_pid,
pdsch_est_size,
pdsch_dl_ch_estimates,
llr,
layer_llr,
ptrs_phase_per_slot,
ptrs_re_per_slot,
dl_valid_re,
rx_size,
dl_ch_estimates_ext,
rxdataF_ext,
rxdataF_comp,
dl_ch_mag,
dl_ch_magb,
dl_ch_magr,
rxdataF,
llr_offset,
&log2_maxh) < 0)
return -1;
stop_meas(&ue->dlsch_llr_stats_parallelization[slot]);
......@@ -683,6 +748,15 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
}
} // CRNTI active
stop_meas(&ue->rx_pdsch_stats);
UEscopeCopy(ue, pdschRxdataF_comp, rxdataF_comp, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx, rx_size);
if (ue->phy_sim_mode) {
memcpy(ue->phy_sim_pdsch_rxdataF_comp, rxdataF_comp, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
memcpy(ue->phy_sim_pdsch_rxdataF_ext, rxdataF_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext, dl_ch_estimates_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
memcpy(ue->phy_sim_pdsch_dl_ch_estimates, dl_ch_estimates_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
}
}
return 0;
}
......@@ -690,20 +764,22 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int gNB_id,
NR_UE_DLSCH_t *dlsch0,
NR_UE_DLSCH_t *dlsch1) {
NR_UE_DLSCH_t dlsch[2],
int16_t* llr[2]) {
if (dlsch[0].active == false) {
LOG_E(PHY, "DLSCH should be active when calling this function\n");
return 1;
}
if (dlsch0==NULL)
AssertFatal(0,"dlsch0 should be defined at this level \n");
bool dec = false;
int harq_pid = dlsch0->dlsch_config.harq_process_nbr;
int harq_pid = dlsch[0].dlsch_config.harq_process_nbr;
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
uint32_t ret = UINT32_MAX, ret1 = UINT32_MAX;
NR_UE_PDSCH *pdsch_vars;
NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][harq_pid];
NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[NR_MAX_NB_LAYERS>4 ? 1:0][harq_pid];
uint16_t dmrs_len = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos);
NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid];
uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos);
nr_downlink_indication_t dl_indication;
fapi_nr_rx_indication_t *rx_ind = calloc(1, sizeof(*rx_ind));
uint16_t number_pdus = 1;
......@@ -711,45 +787,40 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id];
uint8_t is_cw0_active = dl_harq0->status;
uint16_t nb_symb_sch = dlsch0->dlsch_config.number_symbols;
uint16_t start_symbol = dlsch0->dlsch_config.start_symbol;
uint8_t dmrs_type = dlsch0->dlsch_config.dmrsConfigType;
uint8_t is_cw1_active = dl_harq1->status;
uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols;
uint16_t start_symbol = dlsch[0].dlsch_config.start_symbol;
uint8_t dmrs_type = dlsch[0].dlsch_config.dmrsConfigType;
uint8_t nb_re_dmrs;
if (dmrs_type==NFAPI_NR_DMRS_TYPE1) {
nb_re_dmrs = 6*dlsch0->dlsch_config.n_dmrs_cdm_groups;
nb_re_dmrs = 6*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
}
else {
nb_re_dmrs = 4*dlsch0->dlsch_config.n_dmrs_cdm_groups;
nb_re_dmrs = 4*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
}
uint8_t is_cw1_active = 0;
if(dlsch1)
is_cw1_active = dl_harq1->status;
LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw0_active);
LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw1_active);
pdsch_vars = ue->pdsch_vars[gNB_id];
// exit dlsch procedures as there are no active dlsch
if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE)
return false;
// start ldpc decode for CW 0
dl_harq0->G = nr_get_G(dlsch0->dlsch_config.number_rbs,
dl_harq0->G = nr_get_G(dlsch[0].dlsch_config.number_rbs,
nb_symb_sch,
nb_re_dmrs,
dmrs_len,
dlsch0->dlsch_config.qamModOrder,
dlsch0->Nl);
dlsch[0].dlsch_config.qamModOrder,
dlsch[0].Nl);
start_meas(&ue->dlsch_unscrambling_stats);
nr_dlsch_unscrambling(pdsch_vars->llr[0],
nr_dlsch_unscrambling(llr[0],
dl_harq0->G,
0,
ue->frame_parms.Nid_cell,
dlsch0->rnti);
dlsch[0].rnti);
stop_meas(&ue->dlsch_unscrambling_stats);
......@@ -759,9 +830,9 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
ret = nr_dlsch_decoding(ue,
proc,
gNB_id,
pdsch_vars->llr[0],
llr[0],
&ue->frame_parms,
dlsch0,
&dlsch[0],
dl_harq0,
frame_rx,
nb_symb_sch,
......@@ -775,7 +846,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
dec = true;
int ind_type = -1;
switch(dlsch0->rnti_type) {
switch(dlsch[0].rnti_type) {
case _RA_RNTI_:
ind_type = FAPI_NR_RX_PDU_TYPE_RAR;
break;
......@@ -789,14 +860,14 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
break;
default:
AssertFatal(true, "Invalid DLSCH type %d\n", dlsch0->rnti_type);
AssertFatal(true, "Invalid DLSCH type %d\n", dlsch[0].rnti_type);
break;
}
nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, gNB_id, NULL);
nr_fill_rx_indication(rx_ind, ind_type, gNB_id, ue, dlsch0, NULL, number_pdus, proc, NULL);
nr_fill_rx_indication(rx_ind, ind_type, gNB_id, ue, &dlsch[0], NULL, number_pdus, proc, NULL);
LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->dlsch_config.TBS, dlsch0->dlsch_config.TBS / 8);
LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8);
stop_meas(&ue->dlsch_decoding_stats);
if (cpumeas(CPUMEAS_GETSTATE)) {
......@@ -808,18 +879,18 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
if(is_cw1_active) {
// start ldpc decode for CW 1
dl_harq1->G = nr_get_G(dlsch1->dlsch_config.number_rbs,
dl_harq1->G = nr_get_G(dlsch[1].dlsch_config.number_rbs,
nb_symb_sch,
nb_re_dmrs,
dmrs_len,
dlsch1->dlsch_config.qamModOrder,
dlsch1->Nl);
dlsch[1].dlsch_config.qamModOrder,
dlsch[1].Nl);
start_meas(&ue->dlsch_unscrambling_stats);
nr_dlsch_unscrambling(pdsch_vars->llr[1],
nr_dlsch_unscrambling(llr[1],
dl_harq1->G,
0,
ue->frame_parms.Nid_cell,
dlsch1->rnti);
dlsch[1].rnti);
stop_meas(&ue->dlsch_unscrambling_stats);
start_meas(&ue->dlsch_decoding_stats);
......@@ -827,9 +898,9 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
ret1 = nr_dlsch_decoding(ue,
proc,
gNB_id,
pdsch_vars->llr[1],
llr[1],
&ue->frame_parms,
dlsch1,
&dlsch[1],
dl_harq1,
frame_rx,
nb_symb_sch,
......@@ -844,7 +915,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats.p_time)/(cpuf*1000.0));
}
LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch0->dlsch_config.TBS);
LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS);
}
// send to mac
if (ue->if_inst && ue->if_inst->dl_indication) {
......@@ -1012,6 +1083,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n",
frame_rx%1024, nr_slot_rx);
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
__attribute__ ((aligned(32))) int32_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
// checking if current frame is compatible with SSB periodicity
if (cfg->ssb_table.ssb_period == 0 ||
!(frame_rx%(1<<(cfg->ssb_table.ssb_period-1)))){
......@@ -1039,17 +1112,26 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
nr_slot_fep(ue,
proc,
(ssb_start_symbol+i)%(fp->symbols_per_slot),
nr_slot_rx);
nr_slot_rx,
rxdataF);
start_meas(&ue->dlsch_channel_estimation_stats);
nr_pbch_channel_estimation(ue, estimateSz, dl_ch_estimates,
dl_ch_estimates_time, proc, gNB_id,
nr_slot_rx, (ssb_start_symbol+i)%(fp->symbols_per_slot),
i-1, ssb_index&7, ssb_slot_2 == nr_slot_rx);
nr_pbch_channel_estimation(ue,
estimateSz,
dl_ch_estimates,
dl_ch_estimates_time,
proc,
gNB_id,
nr_slot_rx,
(ssb_start_symbol+i)%(fp->symbols_per_slot),
i-1,
ssb_index&7,
ssb_slot_2 == nr_slot_rx,
rxdataF);
stop_meas(&ue->dlsch_channel_estimation_stats);
}
nr_ue_ssb_rsrp_measurements(ue, ssb_index, proc, nr_slot_rx);
nr_ue_ssb_rsrp_measurements(ue, ssb_index, proc, nr_slot_rx, rxdataF);
// resetting ssb index for PBCH detection if there is a stronger SSB index
if(ue->measurements.ssb_rsrp_dBm[ssb_index] > ue->measurements.ssb_rsrp_dBm[fp->ssb_index])
......@@ -1058,7 +1140,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
if(ssb_index == fp->ssb_index) {
LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx);
nr_ue_pbch_procedures(gNB_id, ue, proc, estimateSz, dl_ch_estimates, phy_data);
nr_ue_pbch_procedures(gNB_id, ue, proc, estimateSz, dl_ch_estimates, phy_data, rxdataF);
if (ue->no_timing_correction==0) {
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
......@@ -1074,7 +1156,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
}
}
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
nr_ue_rrc_measurements(ue, proc, nr_slot_rx);
nr_ue_rrc_measurements(ue, proc, nr_slot_rx, rxdataF);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_OUT);
}
}
......@@ -1096,9 +1178,16 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
nr_slot_fep(ue,
proc,
(j%fp->symbols_per_slot),
nr_slot_rx);
nr_slot_rx,
rxdataF);
}
nr_prs_channel_estimation(gNB_id,rsc_id,i,ue,proc,fp);
nr_prs_channel_estimation(gNB_id,
rsc_id,
i,
ue,
proc,
fp,
rxdataF);
}
} // for i
} // for rsc_id
......@@ -1132,7 +1221,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
nr_slot_fep(ue,
proc,
l,
nr_slot_rx);
nr_slot_rx,
rxdataF);
}
// Hold the channel estimates in frequency domain.
......@@ -1154,12 +1244,13 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
fp->first_carrier_offset,
phy_pdcch_config->pdcch_config[n_ss].BWPStart,
pdcch_est_size,
pdcch_dl_ch_estimates);
pdcch_dl_ch_estimates,
rxdataF);
stop_meas(&ue->ofdm_demod_stats);
}
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(gNB_id, ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss);
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(gNB_id, ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF);
}
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);
......@@ -1181,7 +1272,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
nr_slot_fep(ue,
proc,
m, //to be updated from higher layer
nr_slot_rx);
nr_slot_rx,
rxdataF);
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT);
}
......@@ -1194,27 +1286,53 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
start_meas(&ue->generic_stat);
// do procedures for C-RNTI
int ret_pdsch = 0;
if (dlsch->active) {
if (dlsch[0].active) {
uint8_t nb_re_dmrs;
if (dlsch[0].dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1) {
nb_re_dmrs = 6*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
}
else {
nb_re_dmrs = 4*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
}
uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos);
const uint32_t rx_llr_size = nr_get_G(dlsch[0].dlsch_config.number_rbs,
dlsch[0].dlsch_config.number_symbols,
nb_re_dmrs,
dmrs_len,
dlsch[0].dlsch_config.qamModOrder,
dlsch[0].Nl);
const uint32_t rx_llr_buf_sz = ((rx_llr_size+15)/16)*16;
const uint32_t rx_llr_layer_size = (rx_llr_size + dlsch[0].Nl - 1) / dlsch[0].Nl;
const uint32_t nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1;
int16_t* llr[2];
int16_t* layer_llr[NR_MAX_NB_LAYERS];
for (int i=0; i<nb_codewords; i++)
llr[i] = (int16_t *)malloc16_clear(rx_llr_buf_sz*sizeof(int16_t));
for (int i=0; i<NR_MAX_NB_LAYERS; i++)
layer_llr[i] = (int16_t *)malloc16_clear(rx_llr_layer_size*sizeof(int16_t));
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_IN);
ret_pdsch = nr_ue_pdsch_procedures(ue,
proc,
gNB_id,
dlsch);
dlsch,
llr,
layer_llr,
rxdataF);
nr_ue_measurement_procedures(2, ue, proc, gNB_id, nr_slot_rx, dlsch);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_OUT);
UEscopeCopy(ue, pdschLlr, llr[0], sizeof(int16_t), 1, rx_llr_size);
LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d\n", nr_slot_rx);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
start_meas(&ue->dlsch_procedures_stat);
NR_UE_DLSCH_t *dlsch1 = NULL;
if (NR_MAX_NB_LAYERS>4)
dlsch1 = &phy_data->dlsch[1];
if (ret_pdsch >= 0)
nr_ue_dlsch_procedures(ue, proc, gNB_id, dlsch, dlsch1);
nr_ue_dlsch_procedures(ue, proc, gNB_id, dlsch, llr);
stop_meas(&ue->dlsch_procedures_stat);
if (cpumeas(CPUMEAS_GETSTATE)) {
......@@ -1222,8 +1340,16 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_slot_rx,ue->dlsch_procedures_stat.p_time/(cpuf*1000.0));
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
if (ue->phy_sim_mode) {
memcpy(ue->phy_sim_rxdataF, rxdataF, sizeof(int32_t)*rxdataF_sz*ue->frame_parms.nb_antennas_rx);
memcpy(ue->phy_sim_pdsch_llr, llr[0], sizeof(int16_t)*rx_llr_buf_sz);
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
for (int i=0; i<nb_codewords; i++)
free(llr[i]);
for (int i=0; i<NR_MAX_NB_LAYERS; i++)
free(layer_llr[i]);
}
// do procedures for CSI-IM
......@@ -1238,10 +1364,10 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
}
l_csiim[symb_idx] = ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx];
if(nr_slot_fep_done == false) {
nr_slot_fep(ue, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], nr_slot_rx);
nr_slot_fep(ue, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], nr_slot_rx, rxdataF);
}
}
nr_ue_csi_im_procedures(ue, proc, gNB_id);
nr_ue_csi_im_procedures(ue, proc, gNB_id, rxdataF);
ue->csiim_vars[gNB_id]->active = 0;
}
......@@ -1249,10 +1375,10 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
if ((ue->csirs_vars[gNB_id]) && (ue->csirs_vars[gNB_id]->active == 1)) {
for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) {
if(is_csi_rs_in_symbol(ue->csirs_vars[gNB_id]->csirs_config_pdu,symb)) {
nr_slot_fep(ue, proc, symb, nr_slot_rx);
nr_slot_fep(ue, proc, symb, nr_slot_rx, rxdataF);
}
}
nr_ue_csi_rs_procedures(ue, proc, gNB_id);
nr_ue_csi_rs_procedures(ue, proc, gNB_id, rxdataF);
ue->csirs_vars[gNB_id]->active = 0;
}
......@@ -1298,6 +1424,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx.p_time/(cpuf*1000.0));
LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_slot_rx);
UEscopeCopy(ue, commonRxdataF, rxdataF, sizeof(int32_t), ue->frame_parms.nb_antennas_rx, rxdataF_sz);
return (0);
}
......
......@@ -410,7 +410,7 @@ int main(int argc, char **argv)
nr_ue_dlsch_init(dlsch_ue, num_codeword, 5);
for (int i=0; i < num_codeword; i++)
dlsch_ue[0].rnti = n_rnti;
nr_init_dl_harq_processes(UE->dl_harq_processes[0], 8, nb_rb);
nr_init_dl_harq_processes(UE->dl_harq_processes, 8, nb_rb);
unsigned char harq_pid = 0; //dlsch->harq_ids[subframe];
processingData_L1tx_t msgDataTx;
......@@ -616,9 +616,7 @@ int main(int argc, char **argv)
free(RC.gNB[0]);
free(RC.gNB);
int num_cw = NR_MAX_NB_LAYERS > 4? 2:1;
for (int i = 0; i < num_cw; i++)
free_nr_ue_dl_harq(UE->dl_harq_processes[i], 8, nb_rb);
free_nr_ue_dl_harq(UE->dl_harq_processes, 8, nb_rb);
term_nr_ue_signal(UE, 1);
free(UE);
......
......@@ -957,6 +957,7 @@ int main(int argc, char **argv)
memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
UE->frame_parms.nb_antennas_rx = n_rx;
UE->max_ldpc_iterations = max_ldpc_iterations;
UE->phy_sim_mode = true;
if (run_initial_sync==1) UE->is_synchronized = 0;
else {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
......@@ -1049,6 +1050,14 @@ int main(int argc, char **argv)
msgDataTx->frame = frame;
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
// Buffers to store internal memory of slot process
UE->phy_sim_rxdataF = calloc(frame_parms->samples_per_slot_wCP*sizeof(int32_t), frame_parms->nb_antennas_rx);
UE->phy_sim_pdsch_llr = calloc((8*(3*8*8448))*sizeof(int16_t), 1); //Max length
UE->phy_sim_pdsch_rxdataF_ext = calloc(14*frame_parms->N_RB_DL*12*sizeof(int32_t), frame_parms->nb_antennas_rx);
UE->phy_sim_pdsch_rxdataF_comp = calloc(14*frame_parms->N_RB_DL*12*sizeof(int32_t), frame_parms->nb_antennas_rx);
UE->phy_sim_pdsch_dl_ch_estimates = calloc(14*frame_parms->ofdm_symbol_size*sizeof(int32_t), frame_parms->nb_antennas_rx);
UE->phy_sim_pdsch_dl_ch_estimates_ext = calloc(14*frame_parms->N_RB_DL*12*sizeof(int32_t), frame_parms->nb_antennas_rx);
for (SNR = snr0; SNR < snr1; SNR += .2) {
varArray_t *table_tx=initVarArray(1000,sizeof(double));
......@@ -1278,8 +1287,7 @@ int main(int argc, char **argv)
if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations+1)
n_errors[round]++;
NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars;
int16_t *UE_llr = pdsch_vars[0]->llr[0];
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
TBS = dlsch0->dlsch_config.TBS;//rel15->TBSize[0];
uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
......@@ -1417,11 +1425,11 @@ int main(int argc, char **argv)
LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1);
if (UE->frame_parms.nb_antennas_rx>1)
LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1);
LOG_M("rxF0.m","rxF0", UE->common_vars.rxdataF[0], frame_parms->samples_per_slot_wCP, 1, 1);
LOG_M("rxF_ext.m","rxFe",&UE->pdsch_vars[0]->rxdataF_ext[0][0],g_rbSize*12*14,1,1);
LOG_M("chestF0.m","chF0",&UE->pdsch_vars[0]->dl_ch_estimates_ext[0][0],g_rbSize*12*14,1,1);
write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1);
LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[0]->llr[0],available_bits,1,0);
LOG_M("rxF0.m","rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, 1, 1);
LOG_M("rxF_ext.m","rxFe",UE->phy_sim_pdsch_rxdataF_ext,g_rbSize*12*14,1,1);
LOG_M("chestF0.m","chF0",UE->phy_sim_pdsch_dl_ch_estimates_ext,g_rbSize*12*14,1,1);
write_output("rxF_comp.m","rxFc",UE->phy_sim_pdsch_rxdataF_comp,N_RB_DL*12*14,1,1);
LOG_M("rxF_llr.m","rxFllr",UE->phy_sim_pdsch_llr,available_bits,1,0);
break;
}
......@@ -1452,6 +1460,12 @@ int main(int argc, char **argv)
free(txdata);
free(test_input_bit);
free(estimated_output_bit);
free(UE->phy_sim_rxdataF);
free(UE->phy_sim_pdsch_llr);
free(UE->phy_sim_pdsch_rxdataF_ext);
free(UE->phy_sim_pdsch_rxdataF_comp);
free(UE->phy_sim_pdsch_dl_ch_estimates);
free(UE->phy_sim_pdsch_dl_ch_estimates_ext);
if (output_fd)
fclose(output_fd);
......
......@@ -87,22 +87,26 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id,
int32_t pdcch_est_size,
int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss) {
int n_ss,
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
return 0;
}
int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int eNB_id,
NR_UE_DLSCH_t *dlsch) {
int gNB_id,
NR_UE_DLSCH_t dlsch[2],
int16_t *llr[2],
int16_t *layer_llr[NR_MAX_NB_LAYERS],
int32_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
return 0;
}
bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int gNB_id,
NR_UE_DLSCH_t *dlsch0,
NR_UE_DLSCH_t *dlsch1) {
NR_UE_DLSCH_t dlsch[2],
int16_t *llr[2]) {
return false;
}
......@@ -592,6 +596,8 @@ int main(int argc, char **argv)
processingData_L1tx_t msgDataTx;
// generate signal
const uint32_t rxdataF_sz = UE->frame_parms.samples_per_slot_wCP;
__attribute__ ((aligned(32))) int32_t rxdataF[UE->frame_parms.nb_antennas_rx][rxdataF_sz];
if (input_fd==NULL) {
for (i=0; i<frame_parms->Lmax; i++) {
......@@ -760,10 +766,11 @@ int main(int argc, char **argv)
nr_slot_fep(UE,
&proc,
i%frame_parms->symbols_per_slot,
ssb_slot);
ssb_slot,
rxdataF);
nr_pbch_channel_estimation(UE,estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf);
0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf,rxdataF);
}
fapiPbch_t result;
......@@ -776,7 +783,8 @@ int main(int argc, char **argv)
ssb_index%8,
SISO,
&phy_data,
&result);
&result,
rxdataF);
if (ret==0) {
//UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically
......
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