Store PUSCH CSI from PUSCH DMRS

This commit is contained in:
Xavier Arteaga 2021-10-05 11:56:48 +02:00
parent 82ae0e6c37
commit 1bdb1bb62d
6 changed files with 125 additions and 21 deletions

View File

@ -268,7 +268,7 @@ public:
srsran::unique_byte_buffer_t pdu = nullptr;
// PUSCH signal measurements
// ...
srsran_csi_trs_measurements_t csi; ///< DMRS based signal Channel State Information (CSI)
};
struct rach_info_t {

View File

@ -50,6 +50,8 @@ typedef struct {
cf_t* temp; /// Temporal data vector of size SRSRAN_NRE * carrier.nof_prb
float* filter; ///< Smoothing filter
srsran_csi_trs_measurements_t csi; ///< Last estimated channel state information
} srsran_dmrs_sch_t;
/**

View File

@ -808,7 +808,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
sync_err += srsran_vec_estimate_frequency(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol);
}
sync_err /= (float)nof_symbols;
chest_res->sync_error = sync_err / (dmrs_stride * SRSRAN_SUBC_SPACING_NR(q->carrier.scs));
float delay_us = sync_err / (dmrs_stride * SRSRAN_SUBC_SPACING_NR(q->carrier.scs));
#if DMRS_SCH_SYNC_PRECOMPENSATE
// Pre-compensate synchronization error
@ -836,36 +836,52 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
epre /= nof_symbols;
rsrp = SRSRAN_MIN(rsrp, epre - epre * 1e-7);
chest_res->rsrp = rsrp;
chest_res->rsrp_dbm = srsran_convert_power_to_dB(chest_res->rsrp);
chest_res->noise_estimate = epre - rsrp;
chest_res->noise_estimate_dbm = srsran_convert_power_to_dB(chest_res->noise_estimate);
chest_res->snr_db = chest_res->rsrp_dbm - chest_res->noise_estimate_dbm;
// Measure CFO if more than one symbol is used
float cfo_avg = 0.0;
float cfo_avg_hz = 0.0;
float cfo_hz_max = INFINITY;
for (uint32_t i = 0; i < nof_symbols - 1; i++) {
float time_diff = srsran_symbol_distance_s(symbols[i], symbols[i + 1], q->carrier.scs);
float phase_diff = cargf(corr[i + 1] * conjf(corr[i]));
if (isnormal(time_diff)) {
cfo_avg += phase_diff / (2.0f * M_PI * time_diff * (nof_symbols - 1));
cfo_avg_hz += phase_diff / (2.0f * M_PI * time_diff * (nof_symbols - 1));
// The maximum measured CFO depends on the symbol time difference
cfo_hz_max = SRSRAN_MIN(cfo_hz_max, 1 / time_diff);
}
}
chest_res->cfo = cfo_avg;
// Store internal CSI
q->csi.rsrp = rsrp;
q->csi.rsrp_dB = srsran_convert_power_to_dB(rsrp);
q->csi.epre = epre;
q->csi.epre_dB = srsran_convert_power_to_dB(epre);
q->csi.n0 = epre - rsrp;
q->csi.n0_dB = srsran_convert_power_to_dB(q->csi.n0);
q->csi.snr_dB = q->csi.rsrp_dB - q->csi.n0_dB;
q->csi.cfo_hz = cfo_avg_hz;
q->csi.cfo_hz_max = cfo_hz_max;
q->csi.delay_us = delay_us;
// Write CSI in estimated channel result
chest_res->rsrp = q->csi.rsrp;
chest_res->rsrp_dbm = q->csi.rsrp_dB;
chest_res->noise_estimate = q->csi.n0;
chest_res->noise_estimate_dbm = q->csi.n0_dB;
chest_res->snr_db = q->csi.snr_dB;
chest_res->cfo = q->csi.cfo_hz;
chest_res->sync_error = q->csi.delay_us;
#if DMRS_SCH_CFO_PRECOMPENSATE
// Pre-compensate CFO
cf_t cfo_correction[SRSRAN_NSYMB_PER_SLOT_NR] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
if (isnormal(cfo_avg)) {
if (isnormal(cfo_avg_hz)) {
// Calculate phase of the first OFDM symbol (l = 0)
float arg0 = cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.scs) * cfo_avg;
float arg0 = cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.scs) * cfo_avg_hz;
// Calculate CFO corrections
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
float arg = arg0 + 2.0f * M_PI * cfo_avg * srsran_symbol_distance_s(0, l, q->carrier.scs);
float arg = arg0 + 2.0f * M_PI * cfo_avg_hz * srsran_symbol_distance_s(0, l, q->carrier.scs);
cfo_correction[l] = cexpf(I * arg);
}
@ -883,7 +899,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
INFO("PDSCH-DMRS: RSRP=%+.2fdB EPRE=%+.2fdB CFO=%+.0fHz Sync=%.3fus",
chest_res->rsrp_dbm,
srsran_convert_power_to_dB(epre),
cfo_avg,
cfo_avg_hz,
chest_res->sync_error * 1e6);
// Average over time, only if more than one DMRS symbol

View File

@ -224,6 +224,9 @@ bool slot_worker::work_ul()
return false;
}
// Extract DMRS information
pusch_info.csi = gnb_ul.dmrs.csi;
// Inform stack
if (stack.pusch_info(ul_slot_cfg, pusch_info) < SRSRAN_SUCCESS) {
logger.error("Error pushing PUSCH information to stack");

View File

@ -61,6 +61,7 @@ public:
uint32_t cqi_count = 0; ///< CQI opportunity counter
uint32_t cqi_valid_count = 0; ///< Valid CQI counter
pucch_metrics_t pucch = {};
pucch_metrics_t pusch = {};
};
private:
@ -662,6 +663,21 @@ public:
metrics.mac.rx_brate += rx_harq_proc[pusch_info.pid].get_tbs();
metrics.mac.rx_pkts++;
// Handle PHY metrics
metrics.pusch.epre_db_avg = SRSRAN_VEC_CMA(pusch_info.csi.epre_dB, metrics.pusch.epre_db_avg, metrics.pusch.count);
metrics.pusch.epre_db_min = SRSRAN_MIN(metrics.pusch.epre_db_min, pusch_info.csi.epre_dB);
metrics.pusch.epre_db_max = SRSRAN_MAX(metrics.pusch.epre_db_max, pusch_info.csi.epre_dB);
metrics.pusch.rsrp_db_avg = SRSRAN_VEC_CMA(pusch_info.csi.rsrp_dB, metrics.pusch.rsrp_db_avg, metrics.pusch.count);
metrics.pusch.rsrp_db_min = SRSRAN_MIN(metrics.pusch.rsrp_db_min, pusch_info.csi.rsrp_dB);
metrics.pusch.rsrp_db_max = SRSRAN_MAX(metrics.pusch.rsrp_db_max, pusch_info.csi.rsrp_dB);
metrics.pusch.snr_db_avg = SRSRAN_VEC_CMA(pusch_info.csi.snr_dB, metrics.pusch.snr_db_avg, metrics.pusch.count);
metrics.pusch.snr_db_min = SRSRAN_MIN(metrics.pusch.snr_db_min, pusch_info.csi.snr_dB);
metrics.pusch.snr_db_max = SRSRAN_MAX(metrics.pusch.snr_db_max, pusch_info.csi.snr_dB);
metrics.pusch.ta_us_avg = SRSRAN_VEC_CMA(pusch_info.csi.delay_us, metrics.pusch.ta_us_avg, metrics.pusch.count);
metrics.pusch.ta_us_min = SRSRAN_MIN(metrics.pusch.ta_us_min, pusch_info.csi.delay_us);
metrics.pusch.ta_us_max = SRSRAN_MAX(metrics.pusch.ta_us_max, pusch_info.csi.delay_us);
metrics.pusch.count++;
return SRSRAN_SUCCESS;
}

View File

@ -194,9 +194,9 @@ int main(int argc, char** argv)
test_bench::metrics_t metrics = tb.get_metrics();
// Print PDSCH metrics if scheduled
double pdsch_bler = 0.0;
if (metrics.gnb_stack.mac.tx_pkts > 0) {
pdsch_bler = (double)metrics.gnb_stack.mac.tx_errors / (double)metrics.gnb_stack.mac.tx_pkts;
float pdsch_bler = 0.0f;
pdsch_bler = (float)metrics.gnb_stack.mac.tx_errors / (float)metrics.gnb_stack.mac.tx_pkts;
float pdsch_shed_rate = 0.0f;
pdsch_shed_rate = (float)metrics.gnb_stack.mac.tx_brate / (float)metrics.gnb_stack.mac.tx_pkts / 1000.0f;
@ -215,10 +215,10 @@ int main(int argc, char** argv)
}
// Print PUSCH metrics if scheduled
double pusch_bler = 0.0;
if (metrics.gnb_stack.mac.rx_pkts > 0) {
float pusch_bler = 0.0f;
if (metrics.gnb_stack.mac.rx_pkts != 0) {
pusch_bler = (double)metrics.gnb_stack.mac.rx_errors / (double)metrics.gnb_stack.mac.rx_pkts;
pusch_bler = (float)metrics.gnb_stack.mac.rx_errors / (float)metrics.gnb_stack.mac.rx_pkts;
}
float pusch_shed_rate = 0.0f;
@ -295,6 +295,73 @@ int main(int argc, char** argv)
srsran::console(" +------------+------------+------------+------------+\n");
}
// Print PDSCH metrics if scheduled
double pdsch_bler = 0.0;
if (metrics.gnb_stack.mac.tx_pkts > 0) {
pdsch_bler = (double)metrics.gnb_stack.mac.tx_errors / (double)metrics.gnb_stack.mac.tx_pkts;
float pdsch_shed_rate = 0.0f;
pdsch_shed_rate = (float)metrics.gnb_stack.mac.tx_brate / (float)metrics.gnb_stack.mac.tx_pkts / 1000.0f;
srsran::console("PDSCH:\n");
srsran::console(" Count: %d\n", metrics.gnb_stack.mac.tx_pkts);
srsran::console(" BLER: %f\n", pdsch_bler);
srsran::console(" Sched Rate: %f Mbps\n", pdsch_shed_rate);
srsran::console(" Net Rate: %f Mbps\n", (1.0f - pdsch_bler) * pdsch_shed_rate);
srsran::console(" Retx Rate: %f Mbps\n", pdsch_bler * pdsch_shed_rate);
srsran::console("\n");
}
// Print PUSCH metrics if scheduled
double pusch_bler = 0.0;
if (metrics.gnb_stack.mac.rx_pkts > 0) {
if (metrics.gnb_stack.mac.rx_pkts != 0) {
pusch_bler = (double)metrics.gnb_stack.mac.rx_errors / (double)metrics.gnb_stack.mac.rx_pkts;
}
float pusch_shed_rate = 0.0f;
if (metrics.gnb_stack.mac.rx_pkts != 0) {
pusch_shed_rate = (float)metrics.gnb_stack.mac.rx_brate / (float)metrics.gnb_stack.mac.rx_pkts / 1000.0f;
}
srsran::console("PUSCH:\n");
srsran::console(" Count: %d\n", metrics.gnb_stack.mac.rx_pkts);
srsran::console(" BLER: %f\n", pusch_bler);
srsran::console(" Sched Rate: %f Mbps\n", pusch_shed_rate);
srsran::console(" Net Rate: %f Mbps\n", (1.0f - pusch_bler) * pusch_shed_rate);
srsran::console(" Retx Rate: %f Mbps\n", pusch_bler * pusch_shed_rate);
srsran::console("\n");
}
// Print PUSCH
if (metrics.gnb_stack.pusch.count > 0) {
srsran::console("PUSCH DMRS Receiver metrics:\n");
srsran::console(" +------------+------------+------------+------------+\n");
srsran::console(" | %10s | %10s | %10s | %10s |\n", "Measure", "Average", "Min", "Max");
srsran::console(" +------------+------------+------------+------------+\n");
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
"EPRE (dB)",
metrics.gnb_stack.pusch.epre_db_avg,
metrics.gnb_stack.pusch.epre_db_min,
metrics.gnb_stack.pusch.epre_db_min);
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
"RSRP (dB)",
metrics.gnb_stack.pusch.rsrp_db_avg,
metrics.gnb_stack.pusch.rsrp_db_min,
metrics.gnb_stack.pusch.rsrp_db_max);
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
"SINR (dB)",
metrics.gnb_stack.pusch.snr_db_avg,
metrics.gnb_stack.pusch.snr_db_min,
metrics.gnb_stack.pusch.snr_db_max);
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
"TA (us)",
metrics.gnb_stack.pusch.ta_us_avg,
metrics.gnb_stack.pusch.ta_us_min,
metrics.gnb_stack.pusch.ta_us_max);
srsran::console(" +------------+------------+------------+------------+\n");
}
srsran::console("UCI stats:\n");
srsran::console(" +------------+------------+------------+------------+------------+\n");
srsran::console(