Commit 45fff9fc authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/dmrs_channel_estimation_parallelization'...

Merge remote-tracking branch 'origin/dmrs_channel_estimation_parallelization' into integration_2024_w47 (!2972)

Parallelize PUSCH channel estimation

This MR adds PUSCH channel estimation parallelization which reduces the
processing time. It also adds time measurements for each antenna and makes
num_antennas_per_thread configurable in nr_ulsim and the gNB config file.

Some results:

- **273 PRBs 4 antennas** `./nr_ulsim -n200 -m25 -s40 -S40 -q1 -R273 -r273 -z4 -P`

| Number of threads | ULSCH channel estimation time (us) develop| ULSCH channel estimation time (us)| Antenna Processing time (us) |
| ------            | ------                                    | ------                            | ------ |
| 0                 | 194.06                                    |193.17                             |  134.82|
| 2                 | 194.88                                    |154.02                             |  93.43 |
| 4                 | 195.23                                    |134.27                             |   72.71|
- **273 PRBs 8 antennas** `./nr_ulsim -n200 -m25 -s40 -S40 -q1 -R273 -r273 -z8 -P`

| Number of threads | ULSCH channel estimation time (us) develop| ULSCH channel estimation time (us)| Antenna Processing time (us) |
| ------            | ------                                    | ------                            | ------ |
| 0                 | 387.93                                    |384.99                             |  269.39|
| 2                 | 388.10                                    |279.47                             |  161.32|
| 4                 | 387.47                                    |225.37                             |  106.52|
| 8                 | 390.53                                    |204.48                             |   83.74|

- **106 PRBs MIMO 4 layers** `./nr_ulsim -n100 -m9 -r106 -s10 -W4 -y4 -z4 -P`

| Number of threads | ULSCH channel estimation time (us) develop| ULSCH channel estimation time (us)| Antenna Processing time (us) |
| ------            | ------                                    | ------                            | ------ |
| 0                 | 263.20                                    |268.97                             |  57.49 |
| 2                 | 263.90                                    |252.61                             |  51.22 |
| 4                 | 264.17                                    |192.49                             |  36.29 |
parents 68191088 ba0cad20
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#include <string.h> #include <string.h>
#include "nr_ul_estimation.h" #include "nr_ul_estimation.h"
...@@ -35,13 +34,12 @@ ...@@ -35,13 +34,12 @@
#include "executables/softmodem-common.h" #include "executables/softmodem-common.h"
#include "nr_phy_common.h" #include "nr_phy_common.h"
//#define DEBUG_CH //#define DEBUG_CH
//#define DEBUG_PUSCH //#define DEBUG_PUSCH
//#define SRS_DEBUG //#define SRS_DEBUG
#define NO_INTERP 1 #define NO_INTERP 1
#define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y))) #define dBc(x, y) (dB_fixed(((int32_t)(x)) * (x) + ((int32_t)(y)) * (y)))
__attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t *in1, __attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t *in1,
int *offset1, int *offset1,
...@@ -50,50 +48,58 @@ __attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t * ...@@ -50,50 +48,58 @@ __attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t *
int *offset2, int *offset2,
const int step2, const int step2,
const int modulo2, const int modulo2,
const int N) { const int N)
{
int localOffset1=*offset1; int localOffset1 = *offset1;
int localOffset2=*offset2; int localOffset2 = *offset2;
c32_t cumul={0}; c32_t cumul = {0};
for (int i=0; i<N; i++) { for (int i = 0; i < N; i++) {
cumul=c32x16maddShift(in1[localOffset1], in2[localOffset2], cumul, 15); cumul = c32x16maddShift(in1[localOffset1], in2[localOffset2], cumul, 15);
localOffset1+=step1; localOffset1 += step1;
localOffset2= (localOffset2 + step2) % modulo2; localOffset2 = (localOffset2 + step2) % modulo2;
} }
*offset1=localOffset1; *offset1 = localOffset1;
*offset2=localOffset2; *offset2 = localOffset2;
return c16x32div(cumul, N); return c16x32div(cumul, N);
} }
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, static void nr_pusch_antenna_processing(void *arg)
unsigned char Ns,
int nl,
unsigned short p,
unsigned char symbol,
int ul_id,
int beam_nb,
unsigned short bwp_start_subcarrier,
nfapi_nr_pusch_pdu_t *pusch_pdu,
int *max_ch,
uint32_t *nvar)
{ {
c16_t pilot[3280] __attribute__((aligned(32))); puschAntennaProc_t *rdata = (puschAntennaProc_t *)arg;
const int chest_freq = gNB->chest_freq; unsigned char Ns = rdata->Ns;
int nl = rdata->nl;
#ifdef DEBUG_CH unsigned short p = rdata->p;
FILE *debug_ch_est; unsigned char symbol = rdata->symbol;
debug_ch_est = fopen("debug_ch_est.txt","w"); int aarx = rdata->aarx;
#endif int numAntennas = rdata->numAntennas;
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ul_id]; unsigned short bwp_start_subcarrier = rdata->bwp_start_subcarrier;
nfapi_nr_pusch_pdu_t *pusch_pdu = rdata->pusch_pdu;
int *max_ch = rdata->max_ch;
c16_t *pilot = rdata->pilot;
uint64_t noise_amp2 = *(rdata->noise_amp2);
int nest_count = *(rdata->nest_count);
delay_t *delay = rdata->delay;
const int chest_freq = rdata->chest_freq;
NR_gNB_PUSCH *pusch_vars = rdata->pusch_vars;
c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates; c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates;
const int symbolSize = gNB->frame_parms.ofdm_symbol_size; NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms;
const int slot_offset = (Ns & 3) * gNB->frame_parms.symbols_per_slot * symbolSize; const int symbolSize = frame_parms->ofdm_symbol_size;
const int slot_offset = (Ns & 3) * frame_parms->symbols_per_slot * symbolSize;
const int delta = get_delta(p, pusch_pdu->dmrs_config_type); const int delta = get_delta(p, pusch_pdu->dmrs_config_type);
const int symbol_offset = symbolSize * symbol; const int symbol_offset = symbolSize * symbol;
const int k0 = bwp_start_subcarrier; const int k0 = bwp_start_subcarrier;
const int nb_rb_pusch = pusch_pdu->rb_size; const int nb_rb_pusch = pusch_pdu->rb_size;
const int beam_nb = rdata->beam_nb;
for (int antenna = aarx; antenna < aarx + numAntennas; antenna++) {
c16_t ul_ls_est[symbolSize] __attribute__((aligned(32)));
memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize);
c16_t *rxdataF = (c16_t *)&rdata->rxdataF[beam_nb][antenna][symbol_offset + slot_offset];
c16_t *ul_ch = &ul_ch_estimates[nl * frame_parms->nb_antennas_rx + antenna][symbol_offset];
memset(ul_ch, 0, sizeof(*ul_ch) * symbolSize);
LOG_D(PHY, "symbol_offset %d, slot_offset %d, OFDM size %d, Ns = %d, k0 = %d, symbol %d\n", LOG_D(PHY,
"symbol_offset %d, slot_offset %d, OFDM size %d, Ns = %d, k0 = %d, symbol %d\n",
symbol_offset, symbol_offset,
slot_offset, slot_offset,
symbolSize, symbolSize,
...@@ -101,71 +107,14 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -101,71 +107,14 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
k0, k0,
symbol); symbol);
//------------------generate DMRS------------------//
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
const uint32_t *gold = nr_gold_pusch(fp->N_RB_UL,
fp->symbols_per_slot,
gNB->gNB_config.cell_config.phy_cell_id.value,
pusch_pdu->scid,
Ns,
symbol);
nr_pusch_dmrs_rx(gNB,
Ns,
gold,
pilot,
(1000 + p),
0,
nb_rb_pusch,
(pusch_pdu->bwp_start + pusch_pdu->rb_start) * NR_NB_SC_PER_RB,
pusch_pdu->dmrs_config_type);
} else { // if transform precoding or SC-FDMA is enabled in Uplink
// NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible
const int index = get_index_for_dmrs_lowpapr_seq(nb_rb_pusch * (NR_NB_SC_PER_RB / 2));
const uint8_t u = pusch_pdu->dfts_ofdm.low_papr_group_number;
const uint8_t v = pusch_pdu->dfts_ofdm.low_papr_sequence_number;
c16_t *dmrs_seq = gNB_dmrs_lowpaprtype1_sequence[u][v][index];
LOG_D(PHY,"Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index);
AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n");
AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
nr_pusch_lowpaprtype1_dmrs_rx(gNB, Ns, dmrs_seq, pilot, 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type);
#ifdef DEBUG_PUSCH
printf ("NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v);
LOG_M("gNb_DMRS_SEQ.m","gNb_DMRS_SEQ", dmrs_seq,6*nb_rb_pusch,1,1);
#endif
}
//------------------------------------------------//
#ifdef DEBUG_PUSCH
for (int i = 0; i < (6 * nb_rb_pusch); i++) {
LOG_I(PHY, "In %s: %d + j*(%d)\n", __FUNCTION__, pilot[i].r,pilot[i].i);
}
#endif
int nest_count = 0;
uint64_t noise_amp2 = 0;
c16_t ul_ls_est[symbolSize] __attribute__((aligned(32)));
memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize);
delay_t *delay = &gNB->ulsch[ul_id].delay;
memset(delay, 0, sizeof(*delay));
for (int aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[beam_nb][aarx][symbol_offset + slot_offset];
c16_t *ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][symbol_offset];
memset(ul_ch, 0, sizeof(*ul_ch) * symbolSize);
#ifdef DEBUG_PUSCH #ifdef DEBUG_PUSCH
LOG_I(PHY, "symbol_offset %d, delta %d\n", symbol_offset, delta); LOG_I(PHY, "symbol_offset %d, delta %d\n", symbol_offset, delta);
LOG_I(PHY, "ch est pilot, N_RB_UL %d\n", gNB->frame_parms.N_RB_UL); LOG_I(PHY, "ch est pilot, N_RB_UL %d\n", frame_parms->N_RB_UL);
LOG_I(PHY, LOG_I(PHY,
"bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n", "bwp_start_subcarrier %d, k0 %d, first_carrier %d, nb_rb_pusch %d\n",
bwp_start_subcarrier, bwp_start_subcarrier,
k0, k0,
gNB->frame_parms.first_carrier_offset, frame_parms->first_carrier_offset,
nb_rb_pusch); nb_rb_pusch);
LOG_I(PHY, "ul_ch addr %p \n", ul_ch); LOG_I(PHY, "ul_ch addr %p \n", ul_ch);
#endif #endif
...@@ -173,7 +122,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -173,7 +122,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && chest_freq == 0) { if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && chest_freq == 0) {
c16_t *pil = pilot; c16_t *pil = pilot;
int re_offset = k0; int re_offset = k0;
LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation"); LOG_D(PHY, "PUSCH estimation DMRS type 1, Freq-domain interpolation");
int pilot_cnt = 0; int pilot_cnt = 0;
for (int n = 0; n < 3 * nb_rb_pusch; n++) { for (int n = 0; n < 3 * nb_rb_pusch; n++) {
...@@ -187,27 +136,25 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -187,27 +136,25 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
} }
c16_t ch16 = {.r = (int16_t)ch.r, .i = (int16_t)ch.i}; c16_t ch16 = {.r = (int16_t)ch.r, .i = (int16_t)ch.i};
*max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i))); *max_ch = max(abs(ch.r), abs(ch.i));
for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) { for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) {
ul_ls_est[k] = ch16; ul_ls_est[k] = ch16;
} }
pilot_cnt += 2; pilot_cnt += 2;
} }
nr_est_delay(gNB->frame_parms.ofdm_symbol_size, ul_ls_est, (c16_t *)pusch_vars->ul_ch_estimates_time[aarx], delay); nr_est_delay(frame_parms->ofdm_symbol_size, ul_ls_est, (c16_t *)pusch_vars->ul_ch_estimates_time[antenna], delay);
int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP); int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP);
c16_t *ul_delay_table = gNB->frame_parms.delay_table[delay_idx]; c16_t *ul_delay_table = frame_parms->delay_table[delay_idx];
#ifdef DEBUG_PUSCH #ifdef DEBUG_PUSCH
printf("Estimated delay = %i\n", delay->est_delay >> 1); printf("Estimated delay = %i\n", delay->est_delay >> 1);
#endif #endif
pilot_cnt = 0; pilot_cnt = 0;
for (int n = 0; n < 3*nb_rb_pusch; n++) { for (int n = 0; n < 3 * nb_rb_pusch; n++) {
// Channel interpolation // Channel interpolation
for (int k_line = 0; k_line <= 1; k_line++) { for (int k_line = 0; k_line <= 1; k_line++) {
// Apply delay // Apply delay
int k = pilot_cnt << 1; int k = pilot_cnt << 1;
c16_t ch16 = c16mulShift(ul_ls_est[k], ul_delay_table[k], 8); c16_t ch16 = c16mulShift(ul_ls_est[k], ul_delay_table[k], 8);
...@@ -216,7 +163,13 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -216,7 +163,13 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize; re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize;
c16_t *rxF = &rxdataF[re_offset]; c16_t *rxF = &rxdataF[re_offset];
printf("pilot %4d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n", printf("pilot %4d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n",
pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ch16.r, ch16.i); pilot_cnt,
pil->r,
pil->i,
rxF->r,
rxF->i,
ch.r,
ch.i);
#endif #endif
if (pilot_cnt == 0) { if (pilot_cnt == 0) {
...@@ -238,9 +191,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -238,9 +191,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
// Revert delay // Revert delay
pilot_cnt = 0; pilot_cnt = 0;
ul_ch = &ul_ch_estimates[nl * gNB->frame_parms.nb_antennas_rx + aarx][symbol_offset]; ul_ch = &ul_ch_estimates[nl * frame_parms->nb_antennas_rx + antenna][symbol_offset];
int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP); int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
c16_t *ul_inv_delay_table = gNB->frame_parms.delay_table[inv_delay_idx]; c16_t *ul_inv_delay_table = frame_parms->delay_table[inv_delay_idx];
for (int n = 0; n < 3 * nb_rb_pusch; n++) { for (int n = 0; n < 3 * nb_rb_pusch; n++) {
for (int k_line = 0; k_line <= 1; k_line++) { for (int k_line = 0; k_line <= 1; k_line++) {
int k = pilot_cnt << 1; int k = pilot_cnt << 1;
...@@ -258,7 +211,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -258,7 +211,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
} }
} }
} else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && chest_freq == 0) { // pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| } else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2
&& chest_freq == 0) { // pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d|
LOG_D(PHY, "PUSCH estimation DMRS type 2, Freq-domain interpolation\n"); LOG_D(PHY, "PUSCH estimation DMRS type 2, Freq-domain interpolation\n");
c16_t *pil = pilot; c16_t *pil = pilot;
c16_t *rx = &rxdataF[delta]; c16_t *rx = &rxdataF[delta];
...@@ -268,26 +222,27 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -268,26 +222,27 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
c16_t ch1 = c16mulShift(*pil, rx[(k0 + n + 1) % symbolSize], 15); c16_t ch1 = c16mulShift(*pil, rx[(k0 + n + 1) % symbolSize], 15);
pil++; pil++;
c16_t ch = c16addShift(ch0, ch1, 1); c16_t ch = c16addShift(ch0, ch1, 1);
*max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i))); *max_ch = max(abs(ch.r), abs(ch.i));
multadd_real_four_symbols_vector_complex_scalar(filt8_rep4, &ch, &ul_ls_est[n]); multadd_real_four_symbols_vector_complex_scalar(filt8_rep4, &ch, &ul_ls_est[n]);
ul_ls_est[n + 4] = ch; ul_ls_est[n + 4] = ch;
ul_ls_est[n + 5] = ch; ul_ls_est[n + 5] = ch;
noise_amp2 += c16amp2(c16sub(ch0, ch)); noise_amp2 += c16amp2(c16sub(ch0, ch));
nest_count++; nest_count += 1;
} }
// Delay compensation // Delay compensation
nr_est_delay(gNB->frame_parms.ofdm_symbol_size, ul_ls_est, (c16_t *)pusch_vars->ul_ch_estimates_time[aarx], delay); nr_est_delay(frame_parms->ofdm_symbol_size, ul_ls_est, (c16_t *)pusch_vars->ul_ch_estimates_time[antenna], delay);
int delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP); int delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
c16_t *ul_delay_table = gNB->frame_parms.delay_table[delay_idx]; c16_t *ul_delay_table = frame_parms->delay_table[delay_idx];
for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n++) { for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n++) {
ul_ch[n] = c16mulShift(ul_ls_est[n], ul_delay_table[n % 6], 8); ul_ch[n] = c16mulShift(ul_ls_est[n], ul_delay_table[n % 6], 8);
} }
} }
// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a
// common value for the whole PRB
else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) { else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {
LOG_D(PHY,"PUSCH estimation DMRS type 1, no Freq-domain interpolation\n"); LOG_D(PHY, "PUSCH estimation DMRS type 1, no Freq-domain interpolation\n");
c16_t *rxF = &rxdataF[delta]; c16_t *rxF = &rxdataF[delta];
int pil_offset = 0; int pil_offset = 0;
int re_offset = k0; int re_offset = k0;
...@@ -297,8 +252,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -297,8 +252,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
ch = c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6); ch = c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
#if NO_INTERP #if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++) for (c16_t *end = ul_ch + 12; ul_ch < end; ul_ch++)
*ul_ch=ch; *ul_ch = ch;
#else #else
c16multaddVectRealComplex(filt8_avlip0, &ch, ul_ch, 8); c16multaddVectRealComplex(filt8_avlip0, &ch, ul_ch, 8);
ul_ch += 8; ul_ch += 8;
...@@ -308,16 +263,16 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -308,16 +263,16 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
ul_ch -= 12; ul_ch -= 12;
#endif #endif
for (int pilot_cnt=6; pilot_cnt<6*(nb_rb_pusch-1); pilot_cnt += 6) { for (int pilot_cnt = 6; pilot_cnt < 6 * (nb_rb_pusch - 1); pilot_cnt += 6) {
ch = c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6); ch = c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
*max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i))); *max_ch = max(abs(ch.r), abs(ch.i));
#if NO_INTERP #if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++) for (c16_t *end = ul_ch + 12; ul_ch < end; ul_ch++)
*ul_ch=ch; *ul_ch = ch;
#else #else
ul_ch[3].r += (ch.r * 1365)>>15; // 1/12*16384 ul_ch[3].r += (ch.r * 1365) >> 15; // 1/12*16384
ul_ch[3].i += (ch.i * 1365)>>15; // 1/12*16384 ul_ch[3].i += (ch.i * 1365) >> 15; // 1/12*16384
ul_ch += 4; ul_ch += 4;
c16multaddVectRealComplex(filt8_avlip3, &ch, ul_ch, 8); c16multaddVectRealComplex(filt8_avlip3, &ch, ul_ch, 8);
...@@ -329,26 +284,27 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -329,26 +284,27 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
#endif #endif
} }
// Last PRB // Last PRB
ch=c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6); ch = c32x16cumulVectVectWithSteps(pilot, &pil_offset, 1, rxF, &re_offset, 2, symbolSize, 6);
#if NO_INTERP #if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++) for (c16_t *end = ul_ch + 12; ul_ch < end; ul_ch++)
*ul_ch=ch; *ul_ch = ch;
#else #else
ul_ch[3].r += (ch.r * 1365)>>15; // 1/12*16384 ul_ch[3].r += (ch.r * 1365) >> 15; // 1/12*16384
ul_ch[3].i += (ch.i * 1365)>>15; // 1/12*16384 ul_ch[3].i += (ch.i * 1365) >> 15; // 1/12*16384
ul_ch += 4; ul_ch += 4;
c16multaddVectRealComplex(filt8_avlip3, &ch, ul_ch, 8); c16multaddVectRealComplex(filt8_avlip3, &ch, ul_ch, 8);
ul_ch += 8; ul_ch += 8;
c16multaddVectRealComplex(filt8_avlip6, &ch, ul_ch, 8); c16multaddVectRealComplex(filt8_avlip6, &ch, ul_ch, 8);
#endif #endif
} else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs
LOG_D(PHY,"PUSCH estimation DMRS type 2, no Freq-domain interpolation"); // and use a common value for the whole PRB
LOG_D(PHY, "PUSCH estimation DMRS type 2, no Freq-domain interpolation");
c16_t *pil = pilot; c16_t *pil = pilot;
int re_offset = (k0 + delta) % symbolSize; int re_offset = (k0 + delta) % symbolSize;
c32_t ch0 = {0}; c32_t ch0 = {0};
//First PRB // First PRB
ch0 = c32x16mulShift(*pil, rxdataF[re_offset], 15); ch0 = c32x16mulShift(*pil, rxdataF[re_offset], 15);
pil++; pil++;
re_offset = (re_offset + 1) % symbolSize; re_offset = (re_offset + 1) % symbolSize;
...@@ -361,10 +317,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -361,10 +317,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
pil++; pil++;
re_offset = (re_offset + 5) % symbolSize; re_offset = (re_offset + 5) % symbolSize;
c16_t ch=c16x32div(ch0, 4); c16_t ch = c16x32div(ch0, 4);
#if NO_INTERP #if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++) for (c16_t *end = ul_ch + 12; ul_ch < end; ul_ch++)
*ul_ch=ch; *ul_ch = ch;
#else #else
c16multaddVectRealComplex(filt8_avlip0, &ch, ul_ch, 8); c16multaddVectRealComplex(filt8_avlip0, &ch, ul_ch, 8);
ul_ch += 8; ul_ch += 8;
...@@ -374,7 +330,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -374,7 +330,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
ul_ch -= 12; ul_ch -= 12;
#endif #endif
for (int pilot_cnt=4; pilot_cnt<4*(nb_rb_pusch-1); pilot_cnt += 4) { for (int pilot_cnt = 4; pilot_cnt < 4 * (nb_rb_pusch - 1); pilot_cnt += 4) {
c32_t ch0; c32_t ch0;
ch0 = c32x16mulShift(*pil, rxdataF[re_offset], 15); ch0 = c32x16mulShift(*pil, rxdataF[re_offset], 15);
pil++; pil++;
...@@ -390,14 +346,14 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -390,14 +346,14 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15); ch0 = c32x16maddShift(*pil, rxdataF[re_offset], ch0, 15);
pil++; pil++;
re_offset = (re_offset+5) % symbolSize; re_offset = (re_offset + 5) % symbolSize;
ch=c16x32div(ch0, 4); ch = c16x32div(ch0, 4);
*max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i))); *max_ch = max(abs(ch.r), abs(ch.i));
#if NO_INTERP #if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++) for (c16_t *end = ul_ch + 12; ul_ch < end; ul_ch++)
*ul_ch=ch; *ul_ch = ch;
#else #else
ul_ch[3] = c16maddShift(ch, (c16_t){1365, 1365}, (c16_t){0, 0}, 15); // 1365 = 1/12*16384 (full range is +/- 32768) ul_ch[3] = c16maddShift(ch, (c16_t){1365, 1365}, (c16_t){0, 0}, 15); // 1365 = 1/12*16384 (full range is +/- 32768)
ul_ch += 4; ul_ch += 4;
...@@ -427,10 +383,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -427,10 +383,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
pil++; pil++;
re_offset = (re_offset + 5) % symbolSize; re_offset = (re_offset + 5) % symbolSize;
ch=c16x32div(ch0, 4); ch = c16x32div(ch0, 4);
#if NO_INTERP #if NO_INTERP
for (c16_t *end=ul_ch+12; ul_ch<end; ul_ch++) for (c16_t *end = ul_ch + 12; ul_ch < end; ul_ch++)
*ul_ch=ch; *ul_ch = ch;
#else #else
ul_ch[3] = c16maddShift(ch, (c16_t){1365, 1365}, (c16_t){0, 0}, 15); // 1365 = 1/12*16384 (full range is +/- 32768) ul_ch[3] = c16maddShift(ch, (c16_t){1365, 1365}, (c16_t){0, 0}, 15); // 1365 = 1/12*16384 (full range is +/- 32768)
ul_ch += 4; ul_ch += 4;
...@@ -449,7 +405,157 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -449,7 +405,157 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
printf("%d\n", idxP); printf("%d\n", idxP);
} }
#endif #endif
// update the values inside the arrays
*(rdata->noise_amp2) = noise_amp2;
*(rdata->nest_count) = nest_count;
}
}
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
unsigned char Ns,
int nl,
unsigned short p,
unsigned char symbol,
int ul_id,
int beam_nb,
unsigned short bwp_start_subcarrier,
nfapi_nr_pusch_pdu_t *pusch_pdu,
int *max_ch,
uint32_t *nvar)
{
c16_t pilot[3280] __attribute__((aligned(32)));
#ifdef DEBUG_CH
FILE *debug_ch_est;
debug_ch_est = fopen("debug_ch_est.txt", "w");
#endif
const int nb_rb_pusch = pusch_pdu->rb_size;
//------------------generate DMRS------------------//
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
const uint32_t *gold = nr_gold_pusch(fp->N_RB_UL,
fp->symbols_per_slot,
gNB->gNB_config.cell_config.phy_cell_id.value,
pusch_pdu->scid,
Ns,
symbol);
nr_pusch_dmrs_rx(gNB,
Ns,
gold,
pilot,
(1000 + p),
0,
nb_rb_pusch,
(pusch_pdu->bwp_start + pusch_pdu->rb_start) * NR_NB_SC_PER_RB,
pusch_pdu->dmrs_config_type);
} else { // if transform precoding or SC-FDMA is enabled in Uplink
// NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible
const int index = get_index_for_dmrs_lowpapr_seq(nb_rb_pusch * (NR_NB_SC_PER_RB / 2));
const uint8_t u = pusch_pdu->dfts_ofdm.low_papr_group_number;
const uint8_t v = pusch_pdu->dfts_ofdm.low_papr_sequence_number;
c16_t *dmrs_seq = gNB_dmrs_lowpaprtype1_sequence[u][v][index];
LOG_D(PHY, "Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index);
AssertFatal(index >= 0,
"Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs "
"cannot be multiple of any other primenumber other than 2,3,5\n");
AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
nr_pusch_lowpaprtype1_dmrs_rx(gNB, Ns, dmrs_seq, pilot, 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type);
#ifdef DEBUG_PUSCH
printf("NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v);
LOG_M("gNb_DMRS_SEQ.m", "gNb_DMRS_SEQ", dmrs_seq, 6 * nb_rb_pusch, 1, 1);
#endif
}
//------------------------------------------------//
#ifdef DEBUG_PUSCH
for (int i = 0; i < (6 * nb_rb_pusch); i++) {
LOG_I(PHY, "In %s: %d + j*(%d)\n", __FUNCTION__, pilot[i].r, pilot[i].i);
}
#endif
int nbAarx = 0;
int nest_count = 0;
uint64_t noise_amp2 = 0;
delay_t *delay = &gNB->ulsch[ul_id].delay;
memset(delay, 0, sizeof(*delay));
int nb_antennas_rx = gNB->frame_parms.nb_antennas_rx;
delay_t delay_arr[nb_antennas_rx];
uint64_t noise_amp2_arr[nb_antennas_rx];
int max_ch_arr[nb_antennas_rx];
int nest_count_arr[nb_antennas_rx];
for (int i = 0; i < nb_antennas_rx; ++i) {
max_ch_arr[i] = *max_ch;
nest_count_arr[i] = nest_count;
noise_amp2_arr[i] = noise_amp2;
delay_arr[i] = *delay;
}
notifiedFIFO_t respPuschAarx;
initNotifiedFIFO(&respPuschAarx);
start_meas(&gNB->pusch_channel_estimation_antenna_processing_stats);
int numAntennas = gNB->dmrs_num_antennas_per_thread;
for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx += numAntennas) {
union puschAntennaReqUnion id = {.s = {ul_id, 0}};
id.p = 1 + aarx;
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschAntennaProc_t),
id.p,
&respPuschAarx,
&nr_pusch_antenna_processing); // create a job for Tpool
puschAntennaProc_t *rdata = (puschAntennaProc_t *)NotifiedFifoData(req); // data for the job
// Local init in the current loop
rdata->Ns = Ns;
rdata->nl = nl;
rdata->p = p;
rdata->symbol = symbol;
rdata->aarx = aarx;
rdata->numAntennas = numAntennas;
rdata->bwp_start_subcarrier = bwp_start_subcarrier;
rdata->pusch_pdu = pusch_pdu;
rdata->max_ch = &max_ch_arr[rdata->aarx];
rdata->pilot = pilot;
rdata->nest_count = &nest_count_arr[rdata->aarx];
rdata->noise_amp2 = &noise_amp2_arr[rdata->aarx];
rdata->delay = &delay_arr[rdata->aarx];
rdata->beam_nb = beam_nb;
rdata->frame_parms = &gNB->frame_parms;
rdata->pusch_vars = &gNB->pusch_vars[ul_id];
rdata->chest_freq = gNB->chest_freq;
rdata->rxdataF = gNB->common_vars.rxdataF;
// Call the nr_pusch_antenna_processing function
pushTpool(&gNB->threadPool, req);
nbAarx++;
LOG_D(PHY, "Added Antenna (count %d) to process, in pipe\n", nbAarx);
} // Antenna Loop
while (nbAarx > 0) {
notifiedFIFO_elt_t *req = pullTpool(&respPuschAarx, &gNB->threadPool);
nbAarx--;
delNotifiedFIFO_elt(req);
}
stop_meas(&gNB->pusch_channel_estimation_antenna_processing_stats);
for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) {
*max_ch = max(*max_ch, max_ch_arr[aarx]);
noise_amp2 += noise_amp2_arr[aarx];
nest_count += nest_count_arr[aarx];
}
// get the maximum delay
*delay = delay_arr[0];
for (int aarx = 1; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) {
if (delay_arr[aarx].est_delay >= delay->est_delay) {
*delay = delay_arr[aarx];
}
} }
#ifdef DEBUG_CH #ifdef DEBUG_CH
...@@ -463,7 +569,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ...@@ -463,7 +569,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
return 0; return 0;
} }
/******************************************************************* /*******************************************************************
* *
* NAME : nr_pusch_ptrs_processing * NAME : nr_pusch_ptrs_processing
...@@ -509,37 +614,32 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -509,37 +614,32 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
/* loop over antennas */ /* loop over antennas */
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
c16_t *phase_per_symbol = (c16_t *)pusch_vars->ptrs_phase_per_slot[aarx]; c16_t *phase_per_symbol = (c16_t *)pusch_vars->ptrs_phase_per_slot[aarx];
ptrs_re_symbol = &pusch_vars->ptrs_re_per_slot; ptrs_re_symbol = &pusch_vars->ptrs_re_per_slot;
*ptrs_re_symbol = 0; *ptrs_re_symbol = 0;
phase_per_symbol[symbol].i = 0; phase_per_symbol[symbol].i = 0;
/* set DMRS estimates to 0 angle with magnitude 1 */ /* set DMRS estimates to 0 angle with magnitude 1 */
if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { if (is_dmrs_symbol(symbol, *dmrsSymbPos)) {
/* set DMRS real estimation to 32767 */ /* set DMRS real estimation to 32767 */
phase_per_symbol[symbol].r=INT16_MAX; // 32767 phase_per_symbol[symbol].r = INT16_MAX; // 32767
#ifdef DEBUG_UL_PTRS #ifdef DEBUG_UL_PTRS
printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i); printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r, phase_per_symbol[symbol].i);
#endif #endif
} } else { // real ptrs value is set to 0
else {// real ptrs value is set to 0
phase_per_symbol[symbol].r = 0; phase_per_symbol[symbol].r = 0;
} }
if(symbol == *startSymbIndex) { if (symbol == *startSymbIndex) {
*ptrsSymbPos = 0; *ptrsSymbPos = 0;
set_ptrs_symb_idx(ptrsSymbPos, set_ptrs_symb_idx(ptrsSymbPos, *nbSymb, *startSymbIndex, 1 << *L_ptrs, *dmrsSymbPos);
*nbSymb,
*startSymbIndex,
1<< *L_ptrs,
*dmrsSymbPos);
} }
/* if not PTRS symbol set current ptrs symbol index to zero*/ /* if not PTRS symbol set current ptrs symbol index to zero*/
*ptrsSymbIdx = 0; *ptrsSymbIdx = 0;
/* Check if current symbol contains PTRS */ /* Check if current symbol contains PTRS */
if(is_ptrs_symbol(symbol, *ptrsSymbPos)) { if (is_ptrs_symbol(symbol, *ptrsSymbPos)) {
*ptrsSymbIdx = symbol; *ptrsSymbIdx = symbol;
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 1) Estimate common phase error per PTRS symbol */ /* 1) Estimate common phase error per PTRS symbol */
...@@ -564,27 +664,27 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, ...@@ -564,27 +664,27 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
} }
/* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
if(symbol == (symbInSlot -1)) { if (symbol == (symbInSlot - 1)) {
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 2) Interpolate PTRS estimated value in TD */ /* 2) Interpolate PTRS estimated value in TD */
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* If L-PTRS is > 0 then we need interpolation */ /* If L-PTRS is > 0 then we need interpolation */
if(*L_ptrs > 0) { if (*L_ptrs > 0) {
ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, *startSymbIndex, *nbSymb); ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t *)phase_per_symbol, *startSymbIndex, *nbSymb);
if(ret != 0) { if (ret != 0) {
LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); LOG_W(PHY, "[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
} }
} }
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 3) Compensated DMRS based estimated signal with PTRS estimation */ /* 3) Compensated DMRS based estimated signal with PTRS estimation */
/*--------------------------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------------------------*/
for(uint8_t i = *startSymbIndex; i < symbInSlot; i++) { for (uint8_t i = *startSymbIndex; i < symbInSlot; i++) {
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
/* Skip rotation if the slot processing is wrong */ /* Skip rotation if the slot processing is wrong */
if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { if ((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) {
#ifdef DEBUG_UL_PTRS #ifdef DEBUG_UL_PTRS
printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i);
#endif #endif
rotate_cpx_vector((c16_t *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch], rotate_cpx_vector((c16_t *)&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
&phase_per_symbol[i], &phase_per_symbol[i],
...@@ -613,22 +713,22 @@ int nr_srs_channel_estimation( ...@@ -613,22 +713,22 @@ int nr_srs_channel_estimation(
int8_t *snr) int8_t *snr)
{ {
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
LOG_I(NR_PHY,"Calling %s function\n", __FUNCTION__); LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__);
#endif #endif
const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB; const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB;
const uint8_t N_ap = 1<<srs_pdu->num_ant_ports; const uint8_t N_ap = 1 << srs_pdu->num_ant_ports;
const uint8_t K_TC = 2<<srs_pdu->comb_size; const uint8_t K_TC = 2 << srs_pdu->comb_size;
const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);
const uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC; const uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB / K_TC;
uint8_t fd_cdm = N_ap; uint8_t fd_cdm = N_ap;
if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) { if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) {
fd_cdm = 2; fd_cdm = 2;
} }
c16_t srs_ls_estimated_channel[frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)]; c16_t srs_ls_estimated_channel[frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)];
uint32_t noise_power_per_rb[srs_pdu->bwp_size]; uint32_t noise_power_per_rb[srs_pdu->bwp_size];
const uint32_t arr_len = frame_parms->nb_antennas_rx * N_ap * M_sc_b_SRS; const uint32_t arr_len = frame_parms->nb_antennas_rx * N_ap * M_sc_b_SRS;
...@@ -639,7 +739,8 @@ int nr_srs_channel_estimation( ...@@ -639,7 +739,8 @@ int nr_srs_channel_estimation(
c16_t noise[arr_len]; c16_t noise[arr_len];
memset(noise, 0, arr_len * sizeof(c16_t)); memset(noise, 0, arr_len * sizeof(c16_t));
uint8_t mem_offset = ((16 - ((long)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF) >> 2; // >> 2 <=> /sizeof(int32_t) uint8_t mem_offset = ((16 - ((long)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF)
>> 2; // >> 2 <=> /sizeof(int32_t)
// filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0} // filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0}
// The End of OFDM symbol corresponds to the position of last 16384 in the filter // The End of OFDM symbol corresponds to the position of last 16384 in the filter
...@@ -649,26 +750,23 @@ int nr_srs_channel_estimation( ...@@ -649,26 +750,23 @@ int nr_srs_channel_estimation(
c16_t ls_estimated = {0}; c16_t ls_estimated = {0};
for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
for (int p_index = 0; p_index < N_ap; p_index++) { for (int p_index = 0; p_index < N_ap; p_index++) {
memset(srs_ls_estimated_channel, 0, frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols) * sizeof(c16_t));
memset(srs_ls_estimated_channel, 0, frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)*sizeof(c16_t)); memset(srs_est, 0, (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols) + mem_offset) * sizeof(int32_t));
memset(srs_est, 0, (frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols) + mem_offset)*sizeof(int32_t));
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
LOG_I(NR_PHY,"====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant); LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant);
#endif #endif
uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier>frame_parms->ofdm_symbol_size) { if (subcarrier > frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size; subcarrier -= frame_parms->ofdm_symbol_size;
} }
c16_t *srs_estimated_channel16 = (c16_t *)&srs_est[subcarrier + mem_offset]; c16_t *srs_estimated_channel16 = (c16_t *)&srs_est[subcarrier + mem_offset];
for (int k = 0; k < M_sc_b_SRS; k++) { for (int k = 0; k < M_sc_b_SRS; k++) {
if (k % fd_cdm == 0) {
if (k%fd_cdm==0) {
ls_estimated = (c16_t){0, 0}; ls_estimated = (c16_t){0, 0};
uint16_t subcarrier_cdm = subcarrier; uint16_t subcarrier_cdm = subcarrier;
...@@ -676,18 +774,21 @@ int nr_srs_channel_estimation( ...@@ -676,18 +774,21 @@ int nr_srs_channel_estimation(
int16_t generated_real = srs_generated_signal[p_index][subcarrier_cdm].r; int16_t generated_real = srs_generated_signal[p_index][subcarrier_cdm].r;
int16_t generated_imag = srs_generated_signal[p_index][subcarrier_cdm].i; int16_t generated_imag = srs_generated_signal[p_index][subcarrier_cdm].i;
int16_t received_real = ((c16_t*)srs_received_signal[ant])[subcarrier_cdm].r; int16_t received_real = ((c16_t *)srs_received_signal[ant])[subcarrier_cdm].r;
int16_t received_imag = ((c16_t*)srs_received_signal[ant])[subcarrier_cdm].i; int16_t received_imag = ((c16_t *)srs_received_signal[ant])[subcarrier_cdm].i;
// We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and generated_imag. // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and
// So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 bits. // generated_imag. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16
ls_estimated.r += (int16_t)(((int32_t)generated_real*received_real + (int32_t)generated_imag*received_imag)>>nr_srs_info->srs_generated_signal_bits); // bits.
ls_estimated.i += (int16_t)(((int32_t)generated_real*received_imag - (int32_t)generated_imag*received_real)>>nr_srs_info->srs_generated_signal_bits); ls_estimated.r += (int16_t)(((int32_t)generated_real * received_real + (int32_t)generated_imag * received_imag)
>> nr_srs_info->srs_generated_signal_bits);
ls_estimated.i += (int16_t)(((int32_t)generated_real * received_imag - (int32_t)generated_imag * received_real)
>> nr_srs_info->srs_generated_signal_bits);
// Subcarrier increment // Subcarrier increment
subcarrier_cdm += K_TC; subcarrier_cdm += K_TC;
if (subcarrier_cdm >= frame_parms->ofdm_symbol_size) { if (subcarrier_cdm >= frame_parms->ofdm_symbol_size) {
subcarrier_cdm=subcarrier_cdm-frame_parms->ofdm_symbol_size; subcarrier_cdm = subcarrier_cdm - frame_parms->ofdm_symbol_size;
} }
} }
} }
...@@ -695,19 +796,23 @@ int nr_srs_channel_estimation( ...@@ -695,19 +796,23 @@ int nr_srs_channel_estimation(
srs_ls_estimated_channel[subcarrier] = ls_estimated; srs_ls_estimated_channel[subcarrier] = ls_estimated;
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
int subcarrier_log = subcarrier-subcarrier_offset; int subcarrier_log = subcarrier - subcarrier_offset;
if(subcarrier_log < 0) { if (subcarrier_log < 0) {
subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size; subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size;
} }
if(subcarrier_log%12 == 0) { if (subcarrier_log % 12 == 0) {
LOG_I(NR_PHY,"------------------------------------ %d ------------------------------------\n", subcarrier_log/12); LOG_I(NR_PHY, "------------------------------------ %d ------------------------------------\n", subcarrier_log / 12);
LOG_I(NR_PHY,"\t __genRe________genIm__|____rxRe_________rxIm__|____lsRe________lsIm_\n"); LOG_I(NR_PHY, "\t __genRe________genIm__|____rxRe_________rxIm__|____lsRe________lsIm_\n");
} }
LOG_I(NR_PHY,"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n", LOG_I(NR_PHY,
"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
subcarrier_log, subcarrier_log,
((c16_t*)srs_generated_signal[p_index])[subcarrier].r, ((c16_t*)srs_generated_signal[p_index])[subcarrier].i, ((c16_t *)srs_generated_signal[p_index])[subcarrier].r,
((c16_t*)srs_received_signal[ant])[subcarrier].r, ((c16_t*)srs_received_signal[ant])[subcarrier].i, ((c16_t *)srs_generated_signal[p_index])[subcarrier].i,
ls_estimated.r, ls_estimated.i); ((c16_t *)srs_received_signal[ant])[subcarrier].r,
((c16_t *)srs_received_signal[ant])[subcarrier].i,
ls_estimated.r,
ls_estimated.i);
#endif #endif
const uint16_t sc_offset = subcarrier + mem_offset; const uint16_t sc_offset = subcarrier + mem_offset;
...@@ -722,7 +827,8 @@ int nr_srs_channel_estimation( ...@@ -722,7 +827,8 @@ int nr_srs_channel_estimation(
srs_estimated_channel16 = (c16_t *)&srs_est[subcarrier]; srs_estimated_channel16 = (c16_t *)&srs_est[subcarrier];
const short *filter = mem_offset == 0 ? filt8_start : filt8_start_shift2; const short *filter = mem_offset == 0 ? filt8_start : filt8_start_shift2;
c16multaddVectRealComplex(filter, &ls_estimated, srs_estimated_channel16, 8); c16multaddVectRealComplex(filter, &ls_estimated, srs_estimated_channel16, 8);
} else if ((subcarrier + K_TC) >= frame_parms->ofdm_symbol_size || k == (M_sc_b_SRS - 1)) { // End of OFDM symbol or last subcarrier cases } else if ((subcarrier + K_TC) >= frame_parms->ofdm_symbol_size
|| k == (M_sc_b_SRS - 1)) { // End of OFDM symbol or last subcarrier cases
// filt8_end is {4096,8192,12288,16384,0,0,0,0} // filt8_end is {4096,8192,12288,16384,0,0,0,0}
const short *filter = mem_offset == 0 || k == (M_sc_b_SRS - 1) ? filt8_end : filt8_end_shift2; const short *filter = mem_offset == 0 || k == (M_sc_b_SRS - 1) ? filt8_end : filt8_end_shift2;
c16multaddVectRealComplex(filter, &ls_estimated, srs_estimated_channel16, 8); c16multaddVectRealComplex(filter, &ls_estimated, srs_estimated_channel16, 8);
...@@ -742,7 +848,8 @@ int nr_srs_channel_estimation( ...@@ -742,7 +848,8 @@ int nr_srs_channel_estimation(
srs_estimated_channel16 = (c16_t *)&srs_est[sc_offset]; srs_estimated_channel16 = (c16_t *)&srs_est[sc_offset];
// filt16_start is {12288,8192,8192,8192,4096,0,0,0,0,0,0,0,0,0,0,0} // filt16_start is {12288,8192,8192,8192,4096,0,0,0,0,0,0,0,0,0,0,0}
c16multaddVectRealComplex(filt16_start, &ls_estimated, srs_estimated_channel16, 16); c16multaddVectRealComplex(filt16_start, &ls_estimated, srs_estimated_channel16, 16);
} else if ((subcarrier + K_TC) >= frame_parms->ofdm_symbol_size || k == (M_sc_b_SRS - 1)) { // End of OFDM symbol or last subcarrier cases } else if ((subcarrier + K_TC) >= frame_parms->ofdm_symbol_size
|| k == (M_sc_b_SRS - 1)) { // End of OFDM symbol or last subcarrier cases
// filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0} // filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0}
c16multaddVectRealComplex(filt16_end, &ls_estimated, srs_estimated_channel16, 16); c16multaddVectRealComplex(filt16_end, &ls_estimated, srs_estimated_channel16, 16);
} else { // Middle case } else { // Middle case
...@@ -755,18 +862,18 @@ int nr_srs_channel_estimation( ...@@ -755,18 +862,18 @@ int nr_srs_channel_estimation(
// Subcarrier increment // Subcarrier increment
subcarrier += K_TC; subcarrier += K_TC;
if (subcarrier >= frame_parms->ofdm_symbol_size) { if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier=subcarrier-frame_parms->ofdm_symbol_size; subcarrier = subcarrier - frame_parms->ofdm_symbol_size;
} }
} // for (int k = 0; k < M_sc_b_SRS; k++) } // for (int k = 0; k < M_sc_b_SRS; k++)
memcpy(&srs_estimated_channel_freq[ant][p_index][0], memcpy(&srs_estimated_channel_freq[ant][p_index][0],
&srs_est[mem_offset], &srs_est[mem_offset],
(frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols))*sizeof(int32_t)); (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)) * sizeof(int32_t));
// Compute noise // Compute noise
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier>frame_parms->ofdm_symbol_size) { if (subcarrier > frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size; subcarrier -= frame_parms->ofdm_symbol_size;
} }
uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS; uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS;
...@@ -782,23 +889,23 @@ int nr_srs_channel_estimation( ...@@ -782,23 +889,23 @@ int nr_srs_channel_estimation(
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier>frame_parms->ofdm_symbol_size) { if (subcarrier > frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size; subcarrier -= frame_parms->ofdm_symbol_size;
} }
for (int k = 0; k < K_TC*M_sc_b_SRS; k++) { for (int k = 0; k < K_TC * M_sc_b_SRS; k++) {
int subcarrier_log = subcarrier - subcarrier_offset;
int subcarrier_log = subcarrier-subcarrier_offset; if (subcarrier_log < 0) {
if(subcarrier_log < 0) {
subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size; subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size;
} }
if(subcarrier_log%12 == 0) { if (subcarrier_log % 12 == 0) {
LOG_I(NR_PHY,"------------------------------------- %d -------------------------------------\n", subcarrier_log/12); LOG_I(NR_PHY, "------------------------------------- %d -------------------------------------\n", subcarrier_log / 12);
LOG_I(NR_PHY,"\t __lsRe__________lsIm__|____intRe_______intIm__|____noiRe_______noiIm__\n"); LOG_I(NR_PHY, "\t __lsRe__________lsIm__|____intRe_______intIm__|____noiRe_______noiIm__\n");
} }
LOG_I(NR_PHY,"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n", LOG_I(NR_PHY,
"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
subcarrier_log, subcarrier_log,
srs_ls_estimated_channel[subcarrier].r, srs_ls_estimated_channel[subcarrier].r,
srs_ls_estimated_channel[subcarrier].i, srs_ls_estimated_channel[subcarrier].i,
...@@ -810,23 +917,23 @@ int nr_srs_channel_estimation( ...@@ -810,23 +917,23 @@ int nr_srs_channel_estimation(
// Subcarrier increment // Subcarrier increment
subcarrier++; subcarrier++;
if (subcarrier >= frame_parms->ofdm_symbol_size) { if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier=subcarrier-frame_parms->ofdm_symbol_size; subcarrier = subcarrier - frame_parms->ofdm_symbol_size;
} }
} }
#endif #endif
// Convert to time domain // Convert to time domain
freq2time(gNB->frame_parms.ofdm_symbol_size, freq2time(gNB->frame_parms.ofdm_symbol_size,
(int16_t*) srs_estimated_channel_freq[ant][p_index], (int16_t *)srs_estimated_channel_freq[ant][p_index],
(int16_t*) srs_estimated_channel_time[ant][p_index]); (int16_t *)srs_estimated_channel_time[ant][p_index]);
memcpy(&srs_estimated_channel_time_shifted[ant][p_index][0], memcpy(&srs_estimated_channel_time_shifted[ant][p_index][0],
&srs_estimated_channel_time[ant][p_index][gNB->frame_parms.ofdm_symbol_size>>1], &srs_estimated_channel_time[ant][p_index][gNB->frame_parms.ofdm_symbol_size >> 1],
(gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t)); (gNB->frame_parms.ofdm_symbol_size >> 1) * sizeof(int32_t));
memcpy(&srs_estimated_channel_time_shifted[ant][p_index][gNB->frame_parms.ofdm_symbol_size>>1], memcpy(&srs_estimated_channel_time_shifted[ant][p_index][gNB->frame_parms.ofdm_symbol_size >> 1],
&srs_estimated_channel_time[ant][p_index][0], &srs_estimated_channel_time[ant][p_index][0],
(gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t)); (gNB->frame_parms.ofdm_symbol_size >> 1) * sizeof(int32_t));
} // for (int p_index = 0; p_index < N_ap; p_index++) } // for (int p_index = 0; p_index < N_ap; p_index++)
} // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) } // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++)
...@@ -835,7 +942,7 @@ int nr_srs_channel_estimation( ...@@ -835,7 +942,7 @@ int nr_srs_channel_estimation(
uint32_t signal_power = max(signal_energy_nodc(ch, arr_len), 1); uint32_t signal_power = max(signal_energy_nodc(ch, arr_len), 1);
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
LOG_I(NR_PHY,"signal_power = %u\n", signal_power); LOG_I(NR_PHY, "signal_power = %u\n", signal_power);
#endif #endif
if (signal_power == 0) { if (signal_power == 0) {
...@@ -845,14 +952,13 @@ int nr_srs_channel_estimation( ...@@ -845,14 +952,13 @@ int nr_srs_channel_estimation(
// Compute noise power // Compute noise power
const uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3; const uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3;
const uint8_t n_noise_est = frame_parms->nb_antennas_rx*N_ap*srs_symbols_per_rb; const uint8_t n_noise_est = frame_parms->nb_antennas_rx * N_ap * srs_symbols_per_rb;
uint64_t sum_re = 0; uint64_t sum_re = 0;
uint64_t sum_re2 = 0; uint64_t sum_re2 = 0;
uint64_t sum_im = 0; uint64_t sum_im = 0;
uint64_t sum_im2 = 0; uint64_t sum_im2 = 0;
for (int rb = 0; rb < m_SRS_b; rb++) { for (int rb = 0; rb < m_SRS_b; rb++) {
sum_re = 0; sum_re = 0;
sum_re2 = 0; sum_re2 = 0;
sum_im = 0; sum_im = 0;
...@@ -870,12 +976,13 @@ int nr_srs_channel_estimation( ...@@ -870,12 +976,13 @@ int nr_srs_channel_estimation(
} // for (int p_index = 0; p_index < N_ap; p_index++) } // for (int p_index = 0; p_index < N_ap; p_index++)
} // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) } // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++)
noise_power_per_rb[rb] = max(sum_re2 / n_noise_est - (sum_re / n_noise_est) * (sum_re / n_noise_est) + noise_power_per_rb[rb] = max(sum_re2 / n_noise_est - (sum_re / n_noise_est) * (sum_re / n_noise_est) + sum_im2 / n_noise_est
sum_im2 / n_noise_est - (sum_im / n_noise_est) * (sum_im / n_noise_est), 1); - (sum_im / n_noise_est) * (sum_im / n_noise_est),
1);
snr_per_rb[rb] = dB_fixed(signal_power) - dB_fixed(noise_power_per_rb[rb]); snr_per_rb[rb] = dB_fixed(signal_power) - dB_fixed(noise_power_per_rb[rb]);
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
LOG_I(NR_PHY,"noise_power_per_rb[%i] = %i, snr_per_rb[%i] = %i dB\n", rb, noise_power_per_rb[rb], rb, snr_per_rb[rb]); LOG_I(NR_PHY, "noise_power_per_rb[%i] = %i, snr_per_rb[%i] = %i dB\n", rb, noise_power_per_rb[rb], rb, snr_per_rb[rb]);
#endif #endif
} // for (int rb = 0; rb < m_SRS_b; rb++) } // for (int rb = 0; rb < m_SRS_b; rb++)
...@@ -885,7 +992,7 @@ int nr_srs_channel_estimation( ...@@ -885,7 +992,7 @@ int nr_srs_channel_estimation(
*snr = dB_fixed(signal_power) - dB_fixed(noise_power); *snr = dB_fixed(signal_power) - dB_fixed(noise_power);
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
LOG_I(NR_PHY,"noise_power = %u, SNR = %i dB\n", noise_power, *snr); LOG_I(NR_PHY, "noise_power = %u, SNR = %i dB\n", noise_power, *snr);
#endif #endif
return 0; return 0;
......
...@@ -543,6 +543,7 @@ typedef struct PHY_VARS_gNB_s { ...@@ -543,6 +543,7 @@ typedef struct PHY_VARS_gNB_s {
time_stats_t ulsch_decoding_stats; time_stats_t ulsch_decoding_stats;
time_stats_t ulsch_deinterleaving_stats; time_stats_t ulsch_deinterleaving_stats;
time_stats_t ulsch_channel_estimation_stats; time_stats_t ulsch_channel_estimation_stats;
time_stats_t pusch_channel_estimation_antenna_processing_stats;
time_stats_t ulsch_llr_stats; time_stats_t ulsch_llr_stats;
time_stats_t rx_srs_stats; time_stats_t rx_srs_stats;
time_stats_t generate_srs_stats; time_stats_t generate_srs_stats;
...@@ -562,7 +563,10 @@ typedef struct PHY_VARS_gNB_s { ...@@ -562,7 +563,10 @@ typedef struct PHY_VARS_gNB_s {
notifiedFIFO_t L1_rx_out; notifiedFIFO_t L1_rx_out;
notifiedFIFO_t resp_RU_tx; notifiedFIFO_t resp_RU_tx;
tpool_t threadPool; tpool_t threadPool;
int nbSymb;
int nbAarx;
int num_pusch_symbols_per_thread; int num_pusch_symbols_per_thread;
int dmrs_num_antennas_per_thread;
pthread_t L1_rx_thread; pthread_t L1_rx_thread;
int L1_rx_thread_core; int L1_rx_thread_core;
pthread_t L1_tx_thread; pthread_t L1_tx_thread;
...@@ -585,6 +589,37 @@ union puschSymbolReqUnion { ...@@ -585,6 +589,37 @@ union puschSymbolReqUnion {
uint64_t p; uint64_t p;
}; };
typedef struct puschAntennaProc_s {
unsigned char Ns;
int nl;
unsigned short p;
unsigned char symbol;
unsigned short bwp_start_subcarrier;
int aarx;
int beam_nb;
int numAntennas;
nfapi_nr_pusch_pdu_t *pusch_pdu;
int *max_ch;
c16_t *pilot;
int *nest_count;
uint64_t *noise_amp2;
delay_t *delay;
int chest_freq;
NR_gNB_PUSCH *pusch_vars;
NR_DL_FRAME_PARMS *frame_parms;
c16_t ***rxdataF;
} puschAntennaProc_t;
struct puschAntennaReqId {
uint16_t ul_id;
uint16_t spare;
} __attribute__((packed));
union puschAntennaReqUnion {
struct puschAntennaReqId s;
uint64_t p;
};
typedef struct LDPCDecode_s { typedef struct LDPCDecode_s {
PHY_VARS_gNB *gNB; PHY_VARS_gNB *gNB;
NR_UL_gNB_HARQ_t *ulsch_harq; NR_UL_gNB_HARQ_t *ulsch_harq;
......
...@@ -213,6 +213,7 @@ int main(int argc, char *argv[]) ...@@ -213,6 +213,7 @@ int main(int argc, char *argv[])
int params_from_file = 0; int params_from_file = 0;
int threadCnt=0; int threadCnt=0;
int max_ldpc_iterations = 5; int max_ldpc_iterations = 5;
int num_antennas_per_thread = 1;
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) { if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
exit_fun("[NR_ULSIM] Error, configuration module init failed\n"); exit_fun("[NR_ULSIM] Error, configuration module init failed\n");
} }
...@@ -224,7 +225,7 @@ int main(int argc, char *argv[]) ...@@ -224,7 +225,7 @@ int main(int argc, char *argv[])
InitSinLUT(); InitSinLUT();
int c; int c;
while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:k:m:n:op:q:r:s:t:u:v:w:y:z:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) { while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:k:m:n:op:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) {
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */ /* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */ /* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
...@@ -395,6 +396,10 @@ int main(int argc, char *argv[]) ...@@ -395,6 +396,10 @@ int main(int argc, char *argv[])
} }
break; break;
case 'A':
num_antennas_per_thread = atoi(optarg);
break;
case 'F': case 'F':
input_fd = fopen(optarg, "r"); input_fd = fopen(optarg, "r");
if (input_fd == NULL) { if (input_fd == NULL) {
...@@ -512,6 +517,7 @@ int main(int argc, char *argv[]) ...@@ -512,6 +517,7 @@ int main(int argc, char *argv[])
printf("-w Start PRB for PUSCH\n"); printf("-w Start PRB for PUSCH\n");
printf("-y Number of TX antennas used at UE\n"); printf("-y Number of TX antennas used at UE\n");
printf("-z Number of RX antennas used at gNB\n"); printf("-z Number of RX antennas used at gNB\n");
printf("-A Number of antennas per thread for PUSCH channel estimation\n");
printf("-C Specify the number of threads for the simulation\n"); printf("-C Specify the number of threads for the simulation\n");
printf("-E {SRS: [0] Disabled, [1] Enabled} e.g. -E 1\n"); printf("-E {SRS: [0] Disabled, [1] Enabled} e.g. -E 1\n");
printf("-F Input filename (.txt format) for RX conformance testing\n"); printf("-F Input filename (.txt format) for RX conformance testing\n");
...@@ -559,6 +565,7 @@ int main(int argc, char *argv[]) ...@@ -559,6 +565,7 @@ int main(int argc, char *argv[])
gNB = RC.gNB[0]; gNB = RC.gNB[0];
gNB->ofdm_offset_divisor = UINT_MAX; gNB->ofdm_offset_divisor = UINT_MAX;
gNB->num_pusch_symbols_per_thread = 1; gNB->num_pusch_symbols_per_thread = 1;
gNB->dmrs_num_antennas_per_thread = num_antennas_per_thread;
gNB->RU_list[0] = calloc(1, sizeof(**gNB->RU_list)); gNB->RU_list[0] = calloc(1, sizeof(**gNB->RU_list));
gNB->RU_list[0]->rfdevice.openair0_cfg = openair0_cfg; gNB->RU_list[0]->rfdevice.openair0_cfg = openair0_cfg;
...@@ -952,6 +959,7 @@ int main(int argc, char *argv[]) ...@@ -952,6 +959,7 @@ int main(int argc, char *argv[])
reset_meas(&gNB->rx_pusch_symbol_processing_stats); reset_meas(&gNB->rx_pusch_symbol_processing_stats);
reset_meas(&gNB->ulsch_decoding_stats); reset_meas(&gNB->ulsch_decoding_stats);
reset_meas(&gNB->ulsch_channel_estimation_stats); reset_meas(&gNB->ulsch_channel_estimation_stats);
reset_meas(&gNB->pusch_channel_estimation_antenna_processing_stats);
reset_meas(&gNB->rx_srs_stats); reset_meas(&gNB->rx_srs_stats);
reset_meas(&gNB->generate_srs_stats); reset_meas(&gNB->generate_srs_stats);
reset_meas(&gNB->get_srs_signal_stats); reset_meas(&gNB->get_srs_signal_stats);
...@@ -1512,6 +1520,7 @@ int main(int argc, char *argv[]) ...@@ -1512,6 +1520,7 @@ int main(int argc, char *argv[])
printDistribution(&gNB->phy_proc_rx,table_rx, "Total PHY proc rx"); printDistribution(&gNB->phy_proc_rx,table_rx, "Total PHY proc rx");
printStatIndent(&gNB->rx_pusch_stats, "RX PUSCH time"); printStatIndent(&gNB->rx_pusch_stats, "RX PUSCH time");
printStatIndent2(&gNB->ulsch_channel_estimation_stats, "ULSCH channel estimation time"); printStatIndent2(&gNB->ulsch_channel_estimation_stats, "ULSCH channel estimation time");
printStatIndent3(&gNB->pusch_channel_estimation_antenna_processing_stats, "Antenna Processing time");
printStatIndent2(&gNB->rx_pusch_init_stats, "RX PUSCH Initialization time"); printStatIndent2(&gNB->rx_pusch_init_stats, "RX PUSCH Initialization time");
printStatIndent2(&gNB->rx_pusch_symbol_processing_stats, "RX PUSCH Symbol Processing time"); printStatIndent2(&gNB->rx_pusch_symbol_processing_stats, "RX PUSCH Symbol Processing time");
printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time");
......
...@@ -59,6 +59,8 @@ ...@@ -59,6 +59,8 @@
#define HLP_L1TX_BO "Backoff from full-scale output at the L1 entity(frequency domain), ex. 12 would corresponding to 14-bit input level (6 dB/bit). Default 36 dBFS for OAI RU entity" #define HLP_L1TX_BO "Backoff from full-scale output at the L1 entity(frequency domain), ex. 12 would corresponding to 14-bit input level (6 dB/bit). Default 36 dBFS for OAI RU entity"
#define CONFIG_STRING_L1_PHASE_COMP "phase_compensation" #define CONFIG_STRING_L1_PHASE_COMP "phase_compensation"
#define HLP_L1_PHASE_COMP "Apply NR symbolwise phase rotation" #define HLP_L1_PHASE_COMP "Apply NR symbolwise phase rotation"
#define CONFIG_STRING_NUM_ANTENNAS_PER_THREAD "dmrs_num_antennas_per_thread"
#define HLP_NUM_ARX "Number of antennas per thread for PUSCH channel estimation"
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* L1 configuration parameters */ /* L1 configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */ /* optname helpstr paramflags XXXptr defXXXval type numelt */
...@@ -84,6 +86,7 @@ ...@@ -84,6 +86,7 @@
{CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
{CONFIG_STRING_L1_TX_AMP_BACKOFF_dB, HLP_L1TX_BO,0, .uptr=NULL, .defintval=36, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_TX_AMP_BACKOFF_dB, HLP_L1TX_BO,0, .uptr=NULL, .defintval=36, TYPE_UINT, 0}, \
{CONFIG_STRING_L1_PHASE_COMP, HLP_L1_PHASE_COMP,PARAMFLAG_BOOL, .uptr=NULL,.defintval=1, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PHASE_COMP, HLP_L1_PHASE_COMP,PARAMFLAG_BOOL, .uptr=NULL,.defintval=1, TYPE_UINT, 0}, \
{CONFIG_STRING_NUM_ANTENNAS_PER_THREAD, HLP_NUM_ARX,0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
} }
// clang-format on // clang-format on
#define L1_CC_IDX 0 #define L1_CC_IDX 0
...@@ -105,6 +108,7 @@ ...@@ -105,6 +108,7 @@
#define L1_TX_THREAD_CORE 16 #define L1_TX_THREAD_CORE 16
#define L1_TX_AMP_BACKOFF_dB 17 #define L1_TX_AMP_BACKOFF_dB 17
#define L1_PHASE_COMP 18 #define L1_PHASE_COMP 18
#define NUM_ANTENNAS_PER_THREAD 19
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif #endif
...@@ -914,6 +914,7 @@ void RCconfig_NR_L1(void) ...@@ -914,6 +914,7 @@ void RCconfig_NR_L1(void)
LOG_I(NR_PHY, "L1_RX_THREAD_CORE %d (%d)\n", *(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr), L1_RX_THREAD_CORE); LOG_I(NR_PHY, "L1_RX_THREAD_CORE %d (%d)\n", *(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr), L1_RX_THREAD_CORE);
gNB->TX_AMP = (int16_t)(32767.0 / pow(10.0, .05 * (double)(*L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr))); gNB->TX_AMP = (int16_t)(32767.0 / pow(10.0, .05 * (double)(*L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr)));
gNB->phase_comp = *L1_ParamList.paramarray[j][L1_PHASE_COMP].uptr; gNB->phase_comp = *L1_ParamList.paramarray[j][L1_PHASE_COMP].uptr;
gNB->dmrs_num_antennas_per_thread = *(L1_ParamList.paramarray[j][NUM_ANTENNAS_PER_THREAD].uptr);
LOG_I(NR_PHY, "TX_AMP = %d (-%d dBFS)\n", gNB->TX_AMP, *L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr); LOG_I(NR_PHY, "TX_AMP = %d (-%d dBFS)\n", gNB->TX_AMP, *L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr);
AssertFatal(gNB->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", gNB->TX_AMP); AssertFatal(gNB->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", gNB->TX_AMP);
// Midhaul configuration // Midhaul configuration
......
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