diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 8dd5052714..2f17b62ea5 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -143,6 +143,10 @@ ID = GNB_PHY_UL_TIME_CHANNEL_ESTIMATE DESC = gNodeB channel estimation in the time domain GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB FORMAT = int,gNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,chest_t +ID = GNB_PHY_UL_SNR_ESTIMATE + DESC = gNodeB SNR estimation based on SRS + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,gNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,snr ID = GNB_PHY_PRACH_INPUT_SIGNAL DESC = gNodeB input data in the time domain for slots with PRACH detection GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c index 22567492f8..d47f627341 100644 --- a/common/utils/T/tracer/gnb.c +++ b/common/utils/T/tracer/gnb.c @@ -19,6 +19,7 @@ typedef struct { widget *pucch_pusch_iq_plot; widget *ul_freq_estimate_ue_xy_plot; widget *ul_time_estimate_ue_xy_plot; + widget *ul_snr_estimate_ue_xy_plot; widget *current_ue_label; widget *current_ue_button; widget *prev_ue_button; @@ -26,6 +27,7 @@ typedef struct { logger *pucch_pusch_iq_logger; logger *ul_freq_estimate_ue_logger; logger *ul_time_estimate_ue_logger; + logger *ul_snr_ue_logger; } gnb_gui; typedef struct { @@ -98,6 +100,9 @@ static void set_current_ue(gui *g, gnb_data *e, int ue) sprintf(s, "UL channel estimation in time domain [UE %d]", ue); xy_plot_set_title(g, e->e->ul_time_estimate_ue_xy_plot, s); + + sprintf(s, "UL SNR per RB based on SRS [UE %d]", ue); + xy_plot_set_title(g, e->e->ul_snr_estimate_ue_xy_plot, s); } void reset_ue_ids(void) @@ -146,12 +151,13 @@ static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, g logger *l; view *v; - main_window = new_toplevel_window(g, 1500, 230, "gNB tracer"); + main_window = new_toplevel_window(g, 1500, 460, "gNB tracer"); top_container = new_container(g, VERTICAL); widget_add_child(g, main_window, top_container, -1); line = new_container(g, HORIZONTAL); widget_add_child(g, top_container, line, -1); + logo = new_image(g, openair_logo_png, openair_logo_png_len); /* logo + prev/next UE buttons */ @@ -206,6 +212,21 @@ static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, g logger_add_view(l, v); e->ul_time_estimate_ue_logger = l; + line = new_container(g, HORIZONTAL); + widget_add_child(g, top_container, line, -1); + + /* UL SNR based on SRS */ + w = new_xy_plot(g, 1280, 200, "", 190); + e->ul_snr_estimate_ue_xy_plot = w; + widget_add_child(g, line, w, -1); + xy_plot_set_range(g, w, 0, 273, -10, 65); + l = new_framelog(h, database, "GNB_PHY_UL_SNR_ESTIMATE", "subframe", "snr"); + framelog_set_update_only_at_sf9(l, 0); + framelog_set_type_buffer_db(l); + v = new_view_xy(273, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE); + logger_add_view(l, v); + e->ul_snr_ue_logger = l; + set_current_ue(g, ed, ed->ue); register_notifier(g, "click", e->current_ue_button, click, ed); register_notifier(g, "click", e->prev_ue_button, click, ed); @@ -251,6 +272,7 @@ int main(int n, char **v) on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1); on_off(database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", is_on, 1); on_off(database, "GNB_PHY_UL_TIME_CHANNEL_ESTIMATE", is_on, 1); + on_off(database, "GNB_PHY_UL_SNR_ESTIMATE", is_on, 1); gnb_data.ue = 0; gnb_data.e = ⪚ diff --git a/common/utils/T/tracer/logger/framelog.c b/common/utils/T/tracer/logger/framelog.c index 45ae3e399f..040482278f 100644 --- a/common/utils/T/tracer/logger/framelog.c +++ b/common/utils/T/tracer/logger/framelog.c @@ -8,6 +8,11 @@ #include #include +typedef enum { + FRAMELOG_BUFFER, + FRAMELOG_BUFFER_dB, +} framelog_buffer_type_t; + struct framelog { struct logger common; void *database; @@ -22,6 +27,7 @@ struct framelog { int skip_current; /* internal data for the skip mechanism */ int skip_on; /* internal data for the skip mechanism */ int update_only_at_sf9; + framelog_buffer_type_t type; }; static void _event(void *p, event e) @@ -52,7 +58,10 @@ static void _event(void *p, event e) } if (l->skip_on) return; - nsamples = bsize / (2*sizeof(int16_t)); + if (l->type == FRAMELOG_BUFFER) + nsamples = bsize / (2 * sizeof(int16_t)); + else + nsamples = bsize / sizeof(int16_t); if (l->blength != nsamples * 10) { l->blength = nsamples * 10; @@ -71,10 +80,15 @@ static void _event(void *p, event e) } /* TODO: compute the LOGs in the plotter (too much useless computations) */ - for (i = 0; i < nsamples; i++) { - int I = ((int16_t *)buffer)[i*2]; - int Q = ((int16_t *)buffer)[i*2+1]; - l->buffer[subframe * nsamples + i] = 10*log10(1.0+(float)(I*I+Q*Q)); + if (l->type == FRAMELOG_BUFFER_dB) { + for (i = 0; i < nsamples; i++) + l->buffer[subframe * nsamples + i] = ((int16_t *)buffer)[i]; + } else { + for (i = 0; i < nsamples; i++) { + int I = ((int16_t *)buffer)[i * 2]; + int Q = ((int16_t *)buffer)[i * 2 + 1]; + l->buffer[subframe * nsamples + i] = 10 * log10(1.0 + (float)(I * I + Q * Q)); + } } if (l->update_only_at_sf9 == 0 || subframe == 9) @@ -132,6 +146,8 @@ logger *new_framelog(event_handler *h, void *database, abort(); } + ret->type = FRAMELOG_BUFFER; + return ret; } @@ -153,3 +169,9 @@ void framelog_set_update_only_at_sf9(logger *_this, int update_only_at_sf9) struct framelog *l = _this; l->update_only_at_sf9 = update_only_at_sf9; } + +void framelog_set_type_buffer_db(logger *_this) +{ + struct framelog *l = _this; + l->type = FRAMELOG_BUFFER_dB; +} diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index b78fa1b359..d8458ef104 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -30,6 +30,7 @@ logger *new_iqdotlog(void *event_handler, void *database, void framelog_set_skip(logger *_this, int skip_delay); void framelog_set_update_only_at_sf9(logger *_this, int update_only_at_sf9); +void framelog_set_type_buffer_db(logger *_this); void textlog_dump_buffer(logger *_this, int dump_buffer); void textlog_raw_time(logger *_this, int raw_time); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 7ec67ffbc5..93d7feebe0 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -777,11 +777,12 @@ int nr_srs_channel_estimation( const nr_srs_info_t *nr_srs_info, const c16_t **srs_generated_signal, c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], c16_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], - int8_t *snr_per_rb, + int16_t *snr_per_rb, int8_t *snr) { #ifdef SRS_DEBUG @@ -801,16 +802,6 @@ int nr_srs_channel_estimation( } 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]; - - const uint32_t arr_len = frame_parms->nb_antennas_rx * N_ap * M_sc_b_SRS; - - c16_t ch[arr_len]; - memset(ch, 0, arr_len * sizeof(c16_t)); - - c16_t noise[arr_len]; - memset(noise, 0, arr_len * sizeof(c16_t)); - uint8_t mem_offset = ((16 - ((intptr_t)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF) >> 2; // >> 2 <=> /sizeof(int32_t) @@ -831,7 +822,7 @@ int nr_srs_channel_estimation( #endif 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; } @@ -843,19 +834,12 @@ int nr_srs_channel_estimation( uint16_t subcarrier_cdm = subcarrier; for (int cdm_idx = 0; cdm_idx < fd_cdm; cdm_idx++) { - 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 received_real = srs_received_signal[ant][subcarrier_cdm].r; - int16_t received_imag = 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. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 + c16_t generated_srs = srs_generated_signal[p_index][subcarrier_cdm]; + c16_t received_srs = srs_received_signal[ant][subcarrier_cdm]; + // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the real and imaginary parts of + // generated_srs. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 // 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); + ls_estimated = c16maddConjShift(generated_srs, received_srs, ls_estimated, nr_srs_info->srs_generated_signal_bits); // Subcarrier increment subcarrier_cdm += K_TC; @@ -934,7 +918,7 @@ int nr_srs_channel_estimation( // Subcarrier increment subcarrier += K_TC; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier = subcarrier - frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } // for (int k = 0; k < M_sc_b_SRS; k++) @@ -943,25 +927,9 @@ int nr_srs_channel_estimation( &srs_est[mem_offset], (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)) * sizeof(c16_t)); - // Compute noise - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - if (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; - for (int k = 0; k < M_sc_b_SRS; k++) { - ch[base_idx + k] = srs_estimated_channel_freq[ant][p_index][subcarrier]; - noise[base_idx + k].r = abs(srs_ls_estimated_channel[subcarrier].r - ch[base_idx + k].r); - noise[base_idx + k].i = abs(srs_ls_estimated_channel[subcarrier].i - ch[base_idx + k].i); - subcarrier += K_TC; - if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier = subcarrier - frame_parms->ofdm_symbol_size; - } - } - #ifdef SRS_DEBUG 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; } @@ -983,13 +951,13 @@ int nr_srs_channel_estimation( srs_ls_estimated_channel[subcarrier].i, srs_estimated_channel_freq[ant][p_index][subcarrier].r, srs_estimated_channel_freq[ant][p_index][subcarrier].i, - noise[base_idx + (k / K_TC)].r, - noise[base_idx + (k / K_TC)].i); + srs_received_noise[ant][subcarrier].r, + srs_received_noise[ant][subcarrier].i); // Subcarrier increment subcarrier++; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier = subcarrier - frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } #endif @@ -1010,61 +978,71 @@ int nr_srs_channel_estimation( } // for (int p_index = 0; p_index < N_ap; p_index++) } // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) - // Compute signal power - uint32_t signal_power = max(signal_energy_nodc(ch, arr_len), 1); - -#ifdef SRS_DEBUG - LOG_I(NR_PHY, "signal_power = %u\n", signal_power); -#endif - + // Compute wideband SNR + int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB; + uint32_t signal_power = 0; + uint32_t noise_power = 0; + for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { + for (int p_index = 0; p_index < N_ap; p_index++) { + uint16_t subcarrier0 = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; + if (subcarrier0 >= frame_parms->ofdm_symbol_size) { + subcarrier0 -= frame_parms->ofdm_symbol_size; + } + if (subcarrier0 + tot_subcarriers < frame_parms->ofdm_symbol_size) { + signal_power += signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][subcarrier0], tot_subcarriers); + if (p_index == 0) + noise_power += signal_energy_nodc(&srs_received_noise[ant][subcarrier0], tot_subcarriers); + } else { + int size1 = frame_parms->ofdm_symbol_size - subcarrier0; + int size2 = tot_subcarriers - size1; + uint64_t signal_power_p1 = signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][subcarrier0], size1) * size1; + uint64_t signal_power_p2 = signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][0], size2) * size2; + signal_power += (signal_power_p1 + signal_power_p2) / tot_subcarriers; + if (p_index == 0) { + uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[ant][subcarrier0], size1) * size1; + uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[ant][0], size2) * size2; + noise_power += (noise_power_p1 + noise_power_p2) / tot_subcarriers; + } + } + } + } + signal_power = max(signal_power / (frame_parms->nb_antennas_rx * N_ap), 1); + noise_power = max(noise_power / (frame_parms->nb_antennas_rx), 1); if (signal_power == 0) { LOG_W(NR_PHY, "Received SRS signal power is 0\n"); return -1; } - - // Compute noise power - 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; - uint64_t sum_re = 0; - uint64_t sum_re2 = 0; - uint64_t sum_im = 0; - uint64_t sum_im2 = 0; - - for (int rb = 0; rb < m_SRS_b; rb++) { - sum_re = 0; - sum_re2 = 0; - sum_im = 0; - sum_im2 = 0; - - for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { - for (int p_index = 0; p_index < N_ap; p_index++) { - uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS + rb * srs_symbols_per_rb; - for (int srs_symb = 0; srs_symb < srs_symbols_per_rb; srs_symb++) { - sum_re = sum_re + noise[base_idx + srs_symb].r; - sum_re2 = sum_re2 + noise[base_idx + srs_symb].r * noise[base_idx + srs_symb].r; - sum_im = sum_im + noise[base_idx + srs_symb].i; - sum_im2 = sum_im2 + noise[base_idx + srs_symb].i * noise[base_idx + srs_symb].i; - } // for (int srs_symb = 0; srs_symb < srs_symbols_per_rb; srs_symb++) - } // for (int p_index = 0; p_index < N_ap; p_index++) - } // 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) + sum_im2 / n_noise_est - - (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]); - -#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]); -#endif - - } // for (int rb = 0; rb < m_SRS_b; rb++) - - const uint32_t noise_power = max(signal_energy_nodc(noise, arr_len), 1); - *snr = dB_fixed(signal_power) - dB_fixed(noise_power); + // Compute SNR per RB + uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[0][0]; + for (int rb = 0; rb < m_SRS_b; rb++) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { + subcarrier -= frame_parms->ofdm_symbol_size; + } + uint32_t noise_power_per_rb = 0; + for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { + if (subcarrier + NR_NB_SC_PER_RB < frame_parms->ofdm_symbol_size) { + noise_power_per_rb += signal_energy_nodc(&srs_received_noise[ant][subcarrier], NR_NB_SC_PER_RB); + } else { + int size1 = frame_parms->ofdm_symbol_size - subcarrier; + int size2 = NR_NB_SC_PER_RB - size1; + uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[ant][subcarrier], size1) * size1; + uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[ant][0], size2) * size2; + noise_power_per_rb += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB; + } + } + noise_power_per_rb = max(noise_power_per_rb / (frame_parms->nb_antennas_rx), 1); + snr_per_rb[rb] = dB_fixed(signal_power) - dB_fixed(noise_power_per_rb); + subcarrier += NR_NB_SC_PER_RB; + #ifdef SRS_DEBUG - LOG_I(NR_PHY, "noise_power = %u, SNR = %i dB\n", noise_power, *snr); + LOG_I(NR_PHY, "[RB %3i] noise_power_per_rb = %i, snr_per_rb = %i dB\n", rb, noise_power_per_rb, snr_per_rb[rb]); +#endif + } + +#ifdef SRS_DEBUG + LOG_I(NR_PHY, "signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n", dB_fixed(signal_power), dB_fixed(noise_power), *snr); #endif return 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 203021101c..04377db1b8 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -84,11 +84,12 @@ int nr_srs_channel_estimation( const nr_srs_info_t *nr_srs_info, const c16_t **srs_generated_signal, c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], c16_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], - int8_t *snr_per_rb, + int16_t *snr_per_rb, int8_t *snr); void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 1aabf118ef..a7769dc84d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -242,7 +242,8 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); void init_prach_list(PHY_VARS_gNB *gNB); void init_prach_ru_list(RU_t *ru); diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index bab88344de..3da018bf84 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -79,59 +79,67 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) { const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const uint16_t n_symbols = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot; // number of symbols until this slot - const uint8_t l0 = srs_pdu->time_start_position; // starting symbol in this slot + const uint8_t l0 = srs_pdu->time_start_position; // starting symbol in this slot const uint64_t symbol_offset = (n_symbols + l0) * frame_parms->ofdm_symbol_size; - 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<num_ant_ports; + const uint8_t N_ap = 1 << srs_pdu->num_ant_ports; const uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; const uint8_t K_TC = 2 << srs_pdu->comb_size; const uint16_t M_sc_b_SRS = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index) * NR_NB_SC_PER_RB / K_TC; - c16_t *rx_signal; bool no_srs_signal = true; for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size * sizeof(c16_t)); - rx_signal = &rxdataF[ant][symbol_offset]; + memset(srs_received_noise[ant], 0, frame_parms->ofdm_symbol_size * sizeof(c16_t)); + c16_t *rx_signal = &rxdataF[ant][symbol_offset]; for (int p_index = 0; p_index < N_ap; p_index++) { - #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 for (int l_line = 0; l_line < N_symb_SRS; l_line++) { - #ifdef SRS_DEBUG - LOG_I(NR_PHY,":::::::: OFDM symbol %d ::::::::\n", l0+l_line); + LOG_I(NR_PHY, ":::::::: OFDM symbol %d ::::::::\n", l0 + l_line); #endif uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][l_line]; - if (subcarrier>frame_parms->ofdm_symbol_size) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { subcarrier -= frame_parms->ofdm_symbol_size; } - uint16_t l_line_offset = l_line*frame_parms->ofdm_symbol_size; + uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size; for (int k = 0; k < M_sc_b_SRS; k++) { - - srs_received_signal[ant][l_line_offset+subcarrier] = rx_signal[l_line_offset+subcarrier]; - + // Subcarriers with SRS symbols + srs_received_signal[ant][l_line_offset + subcarrier] = rx_signal[l_line_offset + subcarrier]; if (rx_signal[l_line_offset + subcarrier].r || rx_signal[l_line_offset + subcarrier].i) { no_srs_signal = false; } + // Subcarriers without SRS symbols and only noise + srs_received_noise[ant][l_line_offset + subcarrier] = rx_signal[l_line_offset + subcarrier + 1]; + for (int n = 1; n < K_TC; n++) { + uint16_t subcarrier_n = subcarrier + n; + if (subcarrier_n >= frame_parms->ofdm_symbol_size) { + subcarrier_n -= frame_parms->ofdm_symbol_size; + } + srs_received_noise[ant][l_line_offset + subcarrier_n] = rx_signal[l_line_offset + subcarrier_n]; + } + #ifdef SRS_DEBUG - int subcarrier_log = subcarrier-subcarrier_offset; - if(subcarrier_log < 0) { + int subcarrier_log = subcarrier - subcarrier_offset; + if (subcarrier_log < 0) { subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size; } - if(subcarrier_log%12 == 0) { - LOG_I(NR_PHY,"------------ %d ------------\n", subcarrier_log/12); + if (subcarrier_log % 12 == 0) { + LOG_I(NR_PHY, "------------ %d ------------\n", subcarrier_log / 12); } LOG_I(NR_PHY, "(%i) \t%i\t%i\n", @@ -143,7 +151,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, // Subcarrier increment subcarrier += K_TC; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier=subcarrier-frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } // for (int k = 0; k < M_sc_b_SRS; k++) diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 9ee558c72b..281d7860e8 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -219,6 +219,7 @@ extern "C" { { return (c16_t){.r = (int16_t)((a.r * b) >> Shift), .i = (int16_t)((a.i * b) >> Shift)}; } + __attribute__((always_inline)) inline c16_t c16MulConjShift(const c16_t a, const c16_t b, const int Shift) { return (c16_t) { @@ -234,6 +235,14 @@ extern "C" { }; } + __attribute__((always_inline)) inline c16_t c16maddConjShift(const c16_t a, const c16_t b, c16_t c, const int Shift) + { + return (c16_t) { + .r = (int16_t)(((a.r * b.r + a.i * b.i ) >> Shift) + c.r), + .i = (int16_t)(((a.r * b.i - a.i * b.r ) >> Shift) + c.i) + }; + } + __attribute__((always_inline)) inline c32_t c32x16mulShift(const c16_t a, const c16_t b, const int Shift) { return (c32_t) { .r = (a.r * b.r - a.i * b.i) >> Shift, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c index dce62add0b..ba5d792428 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -304,7 +304,7 @@ bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, #endif uint16_t subcarrier = subcarrier_offset + k_0_p; - if (subcarrier>frame_parms->ofdm_symbol_size) + if (subcarrier >= frame_parms->ofdm_symbol_size) subcarrier -= frame_parms->ofdm_symbol_size; uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size; // For each port, and for each OFDM symbol, here it is computed and mapped an SRS sequence with M_sc_b_SRS symbols @@ -333,9 +333,8 @@ bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, // Subcarrier increment subcarrier += K_TC; - if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier=subcarrier-frame_parms->ofdm_symbol_size; - } + if (subcarrier >= frame_parms->ofdm_symbol_size) + subcarrier -= frame_parms->ofdm_symbol_size; } // for (int k = 0; k < M_sc_b_SRS; k++) } // for (int l_line = 0; l_line < N_symb_SRS; l_line++) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 406fcc8038..51e8c771e5 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -710,7 +710,7 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_symbol, const nfapi_nr_srs_pdu_t *srs_pdu, const int N_RB_UL, - const int8_t *snr_per_rb, + const int16_t *snr_per_rb, const int srs_est) { reported_symbol->num_prgs = srs_pdu->beamforming.num_prgs; for (int prg_idx = 0; prg_idx < reported_symbol->num_prgs; prg_idx++) { @@ -750,7 +750,7 @@ int fill_srs_channel_matrix(uint8_t *channel_matrix, for(int gI = 0; gI < num_gnb_antenna_elements; gI++) { uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[uI][0]; - if (subcarrier>frame_parms->ofdm_symbol_size) { + if (subcarrier >= frame_parms->ofdm_symbol_size) { subcarrier -= frame_parms->ofdm_symbol_size; } @@ -769,7 +769,7 @@ int fill_srs_channel_matrix(uint8_t *channel_matrix, // Subcarrier increment subcarrier += step; if (subcarrier >= frame_parms->ofdm_symbol_size) { - subcarrier=subcarrier-frame_parms->ofdm_symbol_size; + subcarrier -= frame_parms->ofdm_symbol_size; } } } @@ -1045,13 +1045,14 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; c16_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; + c16_t srs_received_noise[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; c16_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] [frame_parms->ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); c16_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); c16_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] [frame_parms->ofdm_symbol_size]; - int8_t snr_per_rb[srs_pdu->bwp_size]; + int16_t snr_per_rb[srs_pdu->bwp_size]; start_meas(&gNB->generate_srs_stats); @@ -1068,7 +1069,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N stop_meas(&gNB->generate_srs_stats); c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; start_meas(&gNB->get_srs_signal_stats); - int srs_est = nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal); + int srs_est = nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal, srs_received_noise); stop_meas(&gNB->get_srs_signal_stats); if (srs_est >= 0) { @@ -1080,6 +1081,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N gNB->nr_srs_info[i], (const c16_t**)gNB->nr_srs_info[i]->srs_generated_signal, srs_received_signal, + srs_received_noise, srs_estimated_channel_freq, srs_estimated_channel_time, srs_estimated_channel_time_shifted, @@ -1108,6 +1110,14 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N T_INT(0), T_BUFFER(srs_estimated_channel_time_shifted[0][0], frame_parms->ofdm_symbol_size * sizeof(int32_t))); + T(T_GNB_PHY_UL_SNR_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(snr_per_rb, srs_pdu->bwp_size * sizeof(int16_t))); + UL_INFO->srs_ind.sfn = frame_rx; UL_INFO->srs_ind.slot = slot_rx; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index edab935e15..93789ba737 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1733,7 +1733,12 @@ int main(int argc, char *argv[]) if (print_perf==1) { - printf("gNB RX\n"); + printf("UE TX\n"); + for (int i = PHY_PROC_TX; i <= OFDM_MOD_STATS; i++) { + printStatIndent(&UE->phy_cpu_stats.cpu_time_stats[i], UE->phy_cpu_stats.cpu_time_stats[i].meas_name); + } + + printf("\ngNB RX\n"); printDistribution(&gNB->phy_proc_rx,table_rx, "Total PHY proc rx"); printStatIndent(&gNB->rx_pusch_stats, "RX PUSCH time"); printStatIndent2(&gNB->ulsch_channel_estimation_stats, "ULSCH channel estimation time"); @@ -1744,11 +1749,6 @@ int main(int argc, char *argv[]) printStatIndent2(&gNB->ts_deinterleave, "ULSCH segment deinterleaving time"); printStatIndent2(&gNB->ts_rate_unmatch, "ULSCH segment rate recovery time"); printStatIndent2(&gNB->ts_ldpc_decode, "ULSCH segments decoding time"); - - printf("\nUE TX\n"); - for (int i = PHY_PROC_TX; i <= OFDM_MOD_STATS; i++) { - printStatIndent(&UE->phy_cpu_stats.cpu_time_stats[i], UE->phy_cpu_stats.cpu_time_stats[i].meas_name); - } printStatIndent(&gNB->rx_srs_stats,"RX SRS time"); printStatIndent2(&gNB->generate_srs_stats,"Generate SRS sequence time"); printStatIndent2(&gNB->get_srs_signal_stats,"Get SRS signal time");