srsgnb,metrics: add ul_pucch_ni metric and refactor rssi/epre nomenclature. Fix bug in rsrp_avg computation in pucch

master
Ismael Gomez 3 years ago
parent cf647b1fd5
commit 2bbeef6068

@ -40,7 +40,7 @@ typedef struct SRSRAN_API {
cf_t* ce; cf_t* ce;
uint32_t nof_re; uint32_t nof_re;
float noise_estimate; float noise_estimate;
float noise_estimate_dbm; float noise_estimate_dbFs;
float rsrp; float rsrp;
float rsrp_dBfs; float rsrp_dBfs;
float epre; float epre;

@ -75,7 +75,8 @@ typedef struct SRSRAN_API {
srsran_uci_value_t uci_data; srsran_uci_value_t uci_data;
float dmrs_correlation; float dmrs_correlation;
float snr_db; float snr_db;
float rsrp_db; float rssi_dbFs;
float ni_dbFs;
float correlation; float correlation;
bool detected; bool detected;

@ -346,19 +346,30 @@ static void chest_ul_estimate(srsran_chest_ul_t* q,
} }
} }
// Estimate received pilot power // Measure reference signal RE average power
float signal_power = srsran_vec_avg_power_cf(q->pilot_recv_signal, nslots * nrefs_sym); cf_t corr = srsran_vec_acc_cc(q->pilot_recv_signal, nslots * nrefs_sym) / (nslots * nrefs_sym);
float rsrp_avg = __real__ corr * __real__ corr + __imag__ corr * __imag__ corr;
// Measure EPRE
float epre = srsran_vec_avg_power_cf(q->pilot_recv_signal, nslots * nrefs_sym);
// RSRP shall not be greater than EPRE
rsrp_avg = SRSRAN_MIN(rsrp_avg, epre);
// Calculate SNR
if (isnormal(res->noise_estimate)) { if (isnormal(res->noise_estimate)) {
res->snr = signal_power / res->noise_estimate; res->snr = rsrp_avg / res->noise_estimate;
} else { } else {
res->snr = NAN; res->snr = NAN;
} }
// Convert measurements in logarithm scale // Set EPRE and RSRP
res->rsrp = signal_power; res->epre = epre;
res->rsrp_dBfs = srsran_convert_power_to_dB(signal_power); res->epre_dBfs = srsran_convert_power_to_dB(res->epre);
res->rsrp = rsrp_avg;
res->rsrp_dBfs = srsran_convert_power_to_dB(res->rsrp);
res->snr_db = srsran_convert_power_to_dB(res->snr); res->snr_db = srsran_convert_power_to_dB(res->snr);
res->noise_estimate_dbm = srsran_convert_power_to_dBm(res->noise_estimate); res->noise_estimate_dbFs = srsran_convert_power_to_dBm(res->noise_estimate);
} }
int srsran_chest_ul_estimate_pusch(srsran_chest_ul_t* q, int srsran_chest_ul_estimate_pusch(srsran_chest_ul_t* q,
@ -473,15 +484,12 @@ int srsran_chest_ul_estimate_pucch(srsran_chest_ul_t* q,
srsran_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf); srsran_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf);
} }
// Measure power // Measure reference signal RE average power
float rsrp_avg = 0.0f; cf_t corr = srsran_vec_acc_cc(q->pilot_estimates, SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs) /
for (int ns = 0; ns < SRSRAN_NOF_SLOTS_PER_SF; ns++) { (SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs);
for (int i = 0; i < n_rs; i++) { float rsrp_avg = __real__ corr * __real__ corr + __imag__ corr * __imag__ corr;
cf_t corr = srsran_vec_acc_cc(q->pilot_estimates, SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs) / (SRSRAN_NRE);
rsrp_avg += __real__ corr * __real__ corr + __imag__ corr * __imag__ corr; // Measure EPRE
}
}
rsrp_avg /= SRSRAN_NOF_SLOTS_PER_SF * n_rs;
float epre = srsran_vec_avg_power_cf(q->pilot_estimates, SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs); float epre = srsran_vec_avg_power_cf(q->pilot_estimates, SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs);
// RSRP shall not be greater than EPRE // RSRP shall not be greater than EPRE
@ -556,7 +564,7 @@ int srsran_chest_ul_estimate_pucch(srsran_chest_ul_t* q,
if (fpclassify(res->noise_estimate) == FP_ZERO) { if (fpclassify(res->noise_estimate) == FP_ZERO) {
res->noise_estimate = FLT_MIN; res->noise_estimate = FLT_MIN;
} }
res->noise_estimate_dbm = srsran_convert_power_to_dBm(res->noise_estimate); res->noise_estimate_dbFs = srsran_convert_power_to_dBm(res->noise_estimate);
// Estimate SINR // Estimate SINR
if (isnormal(res->noise_estimate)) { if (isnormal(res->noise_estimate)) {

@ -283,7 +283,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
res->epre = epre; res->epre = epre;
res->epre_dBfs = srsran_convert_power_to_dB(epre); res->epre_dBfs = srsran_convert_power_to_dB(epre);
res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f); res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f);
res->noise_estimate_dbm = srsran_convert_power_to_dB(res->noise_estimate); res->noise_estimate_dbFs = srsran_convert_power_to_dB(res->noise_estimate);
res->snr = rsrp / res->noise_estimate; res->snr = rsrp / res->noise_estimate;
res->snr_db = srsran_convert_power_to_dB(res->snr); res->snr_db = srsran_convert_power_to_dB(res->snr);
@ -458,7 +458,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
res->epre = epre; res->epre = epre;
res->epre_dBfs = srsran_convert_power_to_dB(epre); res->epre_dBfs = srsran_convert_power_to_dB(epre);
res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f); res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f);
res->noise_estimate_dbm = srsran_convert_power_to_dB(res->noise_estimate); res->noise_estimate_dbFs = srsran_convert_power_to_dB(res->noise_estimate);
res->snr = rsrp / res->noise_estimate; res->snr = rsrp / res->noise_estimate;
res->snr_db = srsran_convert_power_to_dB(res->snr); res->snr_db = srsran_convert_power_to_dB(res->snr);

@ -150,12 +150,12 @@ int srs_test_context_run(srs_test_context_t* q)
INFO("RESULTS: tti=%d; snr_db=%+.1f; noise_estimate_dbm=%+.1f; ta_us=%+.1f;", INFO("RESULTS: tti=%d; snr_db=%+.1f; noise_estimate_dbm=%+.1f; ta_us=%+.1f;",
ul_sf_cfg.tti, ul_sf_cfg.tti,
q->chest_ul_res.snr_db, q->chest_ul_res.snr_db,
q->chest_ul_res.noise_estimate_dbm, q->chest_ul_res.noise_estimate_dbFs,
q->chest_ul_res.ta_us); q->chest_ul_res.ta_us);
// Assert SRS measurements // Assert SRS measurements
TESTASSERT(fabsf(q->chest_ul_res.snr_db - snr_db) < CHEST_TEST_SRS_SNR_DB_TOLERANCE); TESTASSERT(fabsf(q->chest_ul_res.snr_db - snr_db) < CHEST_TEST_SRS_SNR_DB_TOLERANCE);
TESTASSERT(fabsf(q->chest_ul_res.noise_estimate_dbm - n0_dbm) < CHEST_TEST_SRS_SNR_DB_TOLERANCE); TESTASSERT(fabsf(q->chest_ul_res.noise_estimate_dbFs - n0_dbm) < CHEST_TEST_SRS_SNR_DB_TOLERANCE);
TESTASSERT(fabsf(q->chest_ul_res.ta_us) < CHEST_TEST_SRS_TA_US_TOLERANCE); TESTASSERT(fabsf(q->chest_ul_res.ta_us) < CHEST_TEST_SRS_TA_US_TOLERANCE);
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;

@ -185,7 +185,8 @@ static int get_pucch(srsran_enb_ul_t* q, srsran_ul_sf_cfg_t* ul_sf, srsran_pucch
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
pucch_res.snr_db = q->chest_res.snr_db; pucch_res.snr_db = q->chest_res.snr_db;
pucch_res.rsrp_db = q->chest_res.rsrp_dBfs; pucch_res.rssi_dbFs = q->chest_res.epre_dBfs;
pucch_res.ni_dbFs = q->chest_res.noise_estimate_dbFs;
ret = srsran_pucch_decode(&q->pucch, ul_sf, cfg, &q->chest_res, q->sf_symbols, &pucch_res); ret = srsran_pucch_decode(&q->pucch, ul_sf, cfg, &q->chest_res, q->sf_symbols, &pucch_res);
if (ret < SRSRAN_SUCCESS) { if (ret < SRSRAN_SUCCESS) {

@ -308,7 +308,7 @@ int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q,
meas->epre = q->chest_pucch.epre; meas->epre = q->chest_pucch.epre;
meas->epre_dB = q->chest_pucch.epre_dBfs; meas->epre_dB = q->chest_pucch.epre_dBfs;
meas->n0 = q->chest_pucch.noise_estimate; meas->n0 = q->chest_pucch.noise_estimate;
meas->n0_dB = q->chest_pucch.noise_estimate_dbm; meas->n0_dB = q->chest_pucch.noise_estimate_dbFs;
meas->snr_dB = q->chest_pucch.snr_db; meas->snr_dB = q->chest_pucch.snr_db;
meas->cfo_hz = q->chest_pucch.cfo_hz; meas->cfo_hz = q->chest_pucch.cfo_hz;
meas->cfo_hz_max = NAN; // Unavailable meas->cfo_hz_max = NAN; // Unavailable

@ -100,7 +100,7 @@ private:
void metrics_read(phy_metrics_t* metrics); void metrics_read(phy_metrics_t* metrics);
void metrics_dl(uint32_t mcs); void metrics_dl(uint32_t mcs);
void metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo_iters); void metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo_iters);
void metrics_ul_pucch(float rssi, float sinr); void metrics_ul_pucch(float rssi, float ni, float sinr);
uint32_t get_rnti() const { return rnti; } uint32_t get_rnti() const { return rnti; }
private: private:

@ -364,7 +364,7 @@ bool cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
if (ul_grant.data != nullptr) { if (ul_grant.data != nullptr) {
// Save metrics stats // Save metrics stats
ue_db[rnti]->metrics_ul(ul_grant.dci.tb.mcs_idx, ue_db[rnti]->metrics_ul(ul_grant.dci.tb.mcs_idx,
enb_ul.chest_res.rsrp_dBfs - phy->params.rx_gain_offset, enb_ul.chest_res.epre_dBfs - phy->params.rx_gain_offset,
enb_ul.chest_res.snr_db, enb_ul.chest_res.snr_db,
pusch_res.avg_iterations_block); pusch_res.avg_iterations_block);
} }
@ -455,7 +455,9 @@ int cc_worker::decode_pucch()
// Save metrics // Save metrics
if (pucch_res.detected) { if (pucch_res.detected) {
ue_db[rnti]->metrics_ul_pucch(pucch_res.rsrp_db - phy->params.rx_gain_offset, pucch_res.snr_db); ue_db[rnti]->metrics_ul_pucch(pucch_res.rssi_dbFs - phy->params.rx_gain_offset,
pucch_res.ni_dbFs - -phy->params.rx_gain_offset,
pucch_res.snr_db);
} }
} }
} }
@ -681,12 +683,13 @@ void cc_worker::ue::metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo
metrics.ul.n_samples++; metrics.ul.n_samples++;
} }
void cc_worker::ue::metrics_ul_pucch(float rssi, float sinr) void cc_worker::ue::metrics_ul_pucch(float rssi, float ni, float sinr)
{ {
if (isnan(rssi)) { if (isnan(rssi)) {
rssi = 0; rssi = 0;
} }
metrics.ul.pucch_rssi = SRSRAN_VEC_CMA((float)rssi, metrics.ul.pucch_rssi, metrics.ul.n_samples_pucch); metrics.ul.pucch_rssi = SRSRAN_VEC_CMA((float)rssi, metrics.ul.pucch_rssi, metrics.ul.n_samples_pucch);
metrics.ul.pucch_ni = SRSRAN_VEC_CMA((float)ni, metrics.ul.pucch_ni, metrics.ul.n_samples_pucch);
metrics.ul.pucch_sinr = SRSRAN_VEC_CMA((float)sinr, metrics.ul.pucch_sinr, metrics.ul.n_samples_pucch); metrics.ul.pucch_sinr = SRSRAN_VEC_CMA((float)sinr, metrics.ul.pucch_sinr, metrics.ul.n_samples_pucch);
metrics.ul.n_samples_pucch++; metrics.ul.n_samples_pucch++;
} }

@ -278,6 +278,8 @@ uint32_t sf_worker::get_metrics(std::vector<phy_metrics_t>& metrics)
m->ul.pusch_rssi = SRSRAN_VEC_SAFE_PMA(m->ul.pusch_rssi, m->ul.n_samples, m_->ul.pusch_rssi, m_->ul.n_samples); m->ul.pusch_rssi = SRSRAN_VEC_SAFE_PMA(m->ul.pusch_rssi, m->ul.n_samples, m_->ul.pusch_rssi, m_->ul.n_samples);
m->ul.pucch_rssi = m->ul.pucch_rssi =
SRSRAN_VEC_SAFE_PMA(m->ul.pucch_rssi, m->ul.n_samples_pucch, m_->ul.pucch_rssi, m_->ul.n_samples_pucch); SRSRAN_VEC_SAFE_PMA(m->ul.pucch_rssi, m->ul.n_samples_pucch, m_->ul.pucch_rssi, m_->ul.n_samples_pucch);
m->ul.pucch_ni =
SRSRAN_VEC_SAFE_PMA(m->ul.pucch_ni, m->ul.n_samples_pucch, m_->ul.pucch_ni, m_->ul.n_samples_pucch);
m->ul.turbo_iters = SRSRAN_VEC_SAFE_PMA(m->ul.turbo_iters, m->ul.n_samples, m_->ul.turbo_iters, m_->ul.n_samples); m->ul.turbo_iters = SRSRAN_VEC_SAFE_PMA(m->ul.turbo_iters, m->ul.n_samples, m_->ul.turbo_iters, m_->ul.n_samples);
m->ul.n_samples += m_->ul.n_samples; m->ul.n_samples += m_->ul.n_samples;
m->ul.n_samples_pucch += m_->ul.n_samples_pucch; m->ul.n_samples_pucch += m_->ul.n_samples_pucch;

@ -255,6 +255,7 @@ void phy::get_metrics(std::vector<phy_metrics_t>& metrics)
metrics[j].ul.pusch_rssi += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_rssi; metrics[j].ul.pusch_rssi += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_rssi;
metrics[j].ul.pusch_sinr += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_sinr; metrics[j].ul.pusch_sinr += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_sinr;
metrics[j].ul.pucch_rssi += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_rssi; metrics[j].ul.pucch_rssi += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_rssi;
metrics[j].ul.pucch_ni += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_ni;
metrics[j].ul.pucch_sinr += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_sinr; metrics[j].ul.pucch_sinr += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_sinr;
metrics[j].ul.turbo_iters += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.turbo_iters; metrics[j].ul.turbo_iters += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.turbo_iters;
} }
@ -269,6 +270,7 @@ void phy::get_metrics(std::vector<phy_metrics_t>& metrics)
metrics[j].ul.pusch_rssi /= metrics[j].ul.n_samples; metrics[j].ul.pusch_rssi /= metrics[j].ul.n_samples;
metrics[j].ul.pusch_sinr /= metrics[j].ul.n_samples; metrics[j].ul.pusch_sinr /= metrics[j].ul.n_samples;
metrics[j].ul.pucch_rssi /= metrics[j].ul.n_samples_pucch; metrics[j].ul.pucch_rssi /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.pucch_ni /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.pucch_sinr /= metrics[j].ul.n_samples_pucch; metrics[j].ul.pucch_sinr /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.turbo_iters /= metrics[j].ul.n_samples; metrics[j].ul.turbo_iters /= metrics[j].ul.n_samples;
} }

Loading…
Cancel
Save