Sepparate CSI report configuration from quantification and integrate in nr_phy_test with assertions

This commit is contained in:
Xavier Arteaga 2021-10-04 12:29:35 +02:00 committed by Andre Puschmann
parent a9c65bd369
commit d5b34696b4
13 changed files with 204 additions and 92 deletions

View File

@ -31,18 +31,26 @@ srsran_csi_new_nzp_csi_rs_measurement(const srsran_csi_hl_resource_cfg_t csi_res
uint32_t nzp_csi_rs_id);
/**
* @brief Generates CSI report configuration and values from the higher layer configuration and a list of measurements
* @brief Generates CSI report configuration from the higher layer configuration for a given slot
* @param cfg Higher layer report configuration
* @param slot_idx Slot index within the radio frame
* @param measurements Filtered CSI measurements
* @param[out] report_cfg Report configuration re
* @param slot_cfg Current slot configuration
* @param[out] report_cfg Report configuration for the given slot
* @return The number CSI reports for transmission if the provided data is valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
const srsran_slot_cfg_t* slot_cfg,
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT]);
/**
* @brief Quantifies a given set of CSI reports from the given set of measurements
* @param reports Set of report configuration
* @param measurements Set of measurements to quantify
* @param report_value Set of report values
* @return The number CSI reports for transmission if the provided data is valid, SRSRAN_ERROR code otherwise
*/
SRSRAN_API int
srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
uint32_t slot_idx,
srsran_csi_reports_quantify(const srsran_csi_report_cfg_t reports[SRSRAN_CSI_MAX_NOF_REPORT],
const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT],
srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT]);
/**

View File

@ -162,12 +162,10 @@ typedef struct SRSRAN_API {
/**
* @brief CSI report configuration
* @note An unset report is marked with `cfg.type = SRSRAN_CSI_REPORT_TYPE_NONE`
*/
typedef struct SRSRAN_API {
srsran_csi_report_type_t type; ///< CSI report type (none, periodic, semiPersistentOnPUCCH, ...)
srsran_csi_report_quantity_t quantity; ///< Report quantity
srsran_pucch_nr_resource_t pucch_resource; ///< PUCCH resource to use for periodic reporting
srsran_csi_report_freq_t freq_cfg; ///< Determine whether it is wideband or subband
srsran_csi_hl_report_cfg_t cfg; ///< Higher layer CSI report configuration
// Resource set context
uint32_t nof_ports; ///< Number of antenna ports
@ -193,7 +191,6 @@ typedef struct SRSRAN_API {
void* none;
srsran_csi_report_wideband_cri_ri_pmi_cqi_t wideband_cri_ri_pmi_cqi;
};
bool valid; ///< Used by receiver only
} srsran_csi_report_value_t;
/**

View File

@ -307,7 +307,10 @@ bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
}
// Generate configuration for CSI reports
// ...
n = srsran_csi_reports_generate(&csi, &slot_cfg, uci_cfg.csi);
if (n > SRSRAN_SUCCESS) {
uci_cfg.nof_csi = (uint32_t)n;
}
return true;
}

View File

@ -472,6 +472,24 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
}
prach.tdd_config.configured = (duplex.mode == SRSRAN_DUPLEX_MODE_TDD);
// Make default CSI report configuration always
csi.reports[0].channel_meas_id = 0;
csi.reports[0].type = SRSRAN_CSI_REPORT_TYPE_PERIODIC;
csi.reports[0].periodic.period = 20;
csi.reports[0].periodic.offset = 9;
csi.reports[0].periodic.resource.format = SRSRAN_PUCCH_NR_FORMAT_2;
csi.reports[0].periodic.resource.starting_prb = 51;
csi.reports[0].periodic.resource.format = SRSRAN_PUCCH_NR_FORMAT_2;
csi.reports[0].periodic.resource.nof_prb = 1;
csi.reports[0].periodic.resource.nof_symbols = 2;
csi.reports[0].periodic.resource.start_symbol_idx = 10;
csi.reports[0].quantity = SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI;
csi.reports[0].cqi_table = SRSRAN_CSI_CQI_TABLE_1;
csi.reports[0].freq_cfg = SRSRAN_CSI_REPORT_FREQ_WIDEBAND;
csi.csi_resources[0].type = srsran_csi_hl_resource_cfg_t::SRSRAN_CSI_HL_RESOURCE_CFG_TYPE_NZP_CSI_RS_SSB;
csi.csi_resources[0].nzp_csi_rs_ssb.nzp_csi_rs_resource_set_id_list[0] = 0;
csi.csi_resources[0].nzp_csi_rs_ssb.nzp_csi_rs_resource_set_id_list_count = 1;
}
} // namespace srsran

View File

@ -39,7 +39,6 @@ static bool csi_report_trigger(const srsran_csi_hl_report_cfg_t* cfg, uint32_t s
static void csi_wideband_cri_ri_pmi_cqi_quantify(const srsran_csi_hl_report_cfg_t* cfg,
const srsran_csi_channel_measurements_t* channel_meas,
const srsran_csi_channel_measurements_t* interf_meas,
srsran_csi_report_cfg_t* report_cfg,
srsran_csi_report_value_t* report_value)
{
// Take SNR by default
@ -50,18 +49,6 @@ static void csi_wideband_cri_ri_pmi_cqi_quantify(const srsran_csi_hl_report_cfg_
wideband_sinr_db = channel_meas->wideband_rsrp_dBm - interf_meas->wideband_epre_dBm;
}
// Fill report configuration
report_cfg->type = cfg->type;
report_cfg->quantity = SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI;
report_cfg->freq_cfg = SRSRAN_CSI_REPORT_FREQ_WIDEBAND;
report_cfg->nof_ports = channel_meas->nof_ports;
report_cfg->K_csi_rs = channel_meas->K_csi_rs;
// Save PUCCH resource only if periodic type
if (cfg->type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) {
report_cfg->pucch_resource = cfg->periodic.resource;
}
// Fill quantified values
report_value->wideband_cri_ri_pmi_cqi.cqi = csi_snri_db_to_cqi(cfg->cqi_table, wideband_sinr_db);
report_value->wideband_cri_ri_pmi_cqi.ri = 0;
@ -190,48 +177,79 @@ int srsran_csi_new_nzp_csi_rs_measurement(
return SRSRAN_SUCCESS;
}
int srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
uint32_t slot_idx,
int srsran_csi_reports_generate(const srsran_csi_hl_cfg_t* cfg,
const srsran_slot_cfg_t* slot_cfg,
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT])
{
uint32_t count = 0;
// Check inputs
if (cfg == NULL || report_cfg == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Make sure report configuration is initialised to zero
SRSRAN_MEM_ZERO(report_cfg, srsran_csi_report_cfg_t, SRSRAN_CSI_MAX_NOF_REPORT);
// Iterate every possible configured CSI report
for (uint32_t i = 0; i < SRSRAN_CSI_MAX_NOF_REPORT; i++) {
// Skip if report is not configured or triggered
if (!csi_report_trigger(&cfg->reports[i], slot_cfg->idx)) {
continue;
}
// Configure report
report_cfg[count].cfg = cfg->reports[i];
report_cfg[count].nof_ports = 1;
report_cfg[count].K_csi_rs = 1;
report_cfg[count].has_part2 = false;
count++;
}
return (int)count;
}
int srsran_csi_reports_quantify(const srsran_csi_report_cfg_t reports[SRSRAN_CSI_MAX_NOF_REPORT],
const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT],
srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT])
{
uint32_t count = 0;
// Check inputs
if (cfg == NULL || measurements == NULL || report_cfg == NULL || report_value == NULL) {
if (reports == NULL || measurements == NULL || report_value == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
// Iterate every possible configured CSI report
for (uint32_t i = 0; i < SRSRAN_CSI_MAX_NOF_REPORT; i++) {
// Skip if report is not configured or triggered
if (!csi_report_trigger(&cfg->reports[i], slot_idx)) {
continue;
// If the report is the last one, break
if (reports->cfg.type == SRSRAN_CSI_REPORT_TYPE_NONE) {
break;
}
// Select channel measurement
if (cfg->reports->channel_meas_id >= SRSRAN_CSI_MAX_NOF_RESOURCES) {
ERROR("Channel measurement ID (%d) is out of range", cfg->reports->channel_meas_id);
uint32_t channel_meas_id = reports[i].cfg.channel_meas_id;
if (channel_meas_id >= SRSRAN_CSI_MAX_NOF_RESOURCES) {
ERROR("Channel measurement ID (%d) is out of range", channel_meas_id);
return SRSRAN_ERROR;
}
const srsran_csi_channel_measurements_t* channel_meas = &measurements[cfg->reports->channel_meas_id];
const srsran_csi_channel_measurements_t* channel_meas = &measurements[channel_meas_id];
// Select interference measurement
const srsran_csi_channel_measurements_t* interf_meas = NULL;
if (cfg->reports->interf_meas_present) {
if (cfg->reports->interf_meas_id >= SRSRAN_CSI_MAX_NOF_RESOURCES) {
ERROR("Interference measurement ID (%d) is out of range", cfg->reports->interf_meas_id);
if (reports[i].cfg.interf_meas_present) {
uint32_t interf_meas_id = reports[i].cfg.interf_meas_id;
if (interf_meas_id >= SRSRAN_CSI_MAX_NOF_RESOURCES) {
ERROR("Interference measurement ID (%d) is out of range", interf_meas_id);
return SRSRAN_ERROR;
}
interf_meas = &measurements[cfg->reports->interf_meas_id];
interf_meas = &measurements[interf_meas_id];
}
// Quantify measurements according to frequency and quantity configuration
if (cfg->reports->freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
cfg->reports->quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
csi_wideband_cri_ri_pmi_cqi_quantify(
&cfg->reports[i], channel_meas, interf_meas, &report_cfg[count], &report_value[count]);
if (reports[i].cfg.freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
reports[i].cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
csi_wideband_cri_ri_pmi_cqi_quantify(&reports[i].cfg, channel_meas, interf_meas, &report_value[count]);
count++;
} else {
; // Ignore other types
@ -253,9 +271,9 @@ int srsran_csi_part1_nof_bits(const srsran_csi_report_cfg_t* report_list, uint32
// Iterate all report configurations
for (uint32_t i = 0; i < nof_reports; i++) {
const srsran_csi_report_cfg_t* report = &report_list[i];
if (report->quantity && report->quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
if (report->cfg.quantity && report->cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
count += csi_wideband_cri_ri_pmi_cqi_nof_bits(report);
} else if (report->quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
} else if (report->cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
count += csi_none_nof_bits(report);
}
}
@ -308,15 +326,15 @@ int srsran_csi_part1_pack(const srsran_csi_report_cfg_t* report_cfg,
}
for (uint32_t i = 0; i < nof_reports && count < max_o_csi1; i++) {
if (report_cfg[i].freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
if (report_cfg[i].cfg.freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
count += csi_wideband_cri_ri_pmi_cqi_pack(&report_cfg[i], &report_value[i], &o_csi1[count]);
} else if (report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
} else if (report_cfg[i].cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
count += csi_none_pack(&report_cfg[i], &report_value[i], &o_csi1[count]);
} else {
ERROR("CSI frequency (%d) and quantity (%d) combination is not implemented",
report_cfg[i].freq_cfg,
report_cfg[i].quantity);
report_cfg[i].cfg.freq_cfg,
report_cfg[i].cfg.quantity);
}
}
@ -342,15 +360,15 @@ int srsran_csi_part1_unpack(const srsran_csi_report_cfg_t* report_cfg,
}
for (uint32_t i = 0; i < nof_reports && count < max_o_csi1; i++) {
if (report_cfg[i].freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
if (report_cfg[i].cfg.freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
count += csi_wideband_cri_ri_pmi_cqi_unpack(&report_cfg[i], &o_csi1[count], &report_value[i]);
} else if (report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
} else if (report_cfg[i].cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
count += csi_none_unpack(&report_cfg[i], &o_csi1[count], &report_value[i]);
} else {
ERROR("CSI frequency (%d) and quantity (%d) combination is not implemented",
report_cfg[i].freq_cfg,
report_cfg[i].quantity);
report_cfg[i].cfg.freq_cfg,
report_cfg[i].cfg.quantity);
}
}
@ -365,10 +383,10 @@ uint32_t srsran_csi_str(const srsran_csi_report_cfg_t* report_cfg,
{
uint32_t len = 0;
for (uint32_t i = 0; i < nof_reports; i++) {
if (report_cfg[i].freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
if (report_cfg[i].cfg.freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND &&
report_cfg[i].cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
len = srsran_print_check(str, str_len, len, "cqi=%d ", report_value[i].wideband_cri_ri_pmi_cqi.cqi);
} else if (report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
} else if (report_cfg[i].cfg.quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) {
char tmp[20] = {};
srsran_vec_sprint_bin(tmp, sizeof(tmp), report_value[i].none, report_cfg->K_csi_rs);
len = srsran_print_check(str, str_len, len, "csi=%s ", tmp);

View File

@ -614,8 +614,8 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg,
// - Irrelevant SR opportunities
// - No HARQ-ACK
// - Single periodic CSI report
if (uci_cfg->ack.count == 0 && uci_cfg->nof_csi == 1 && uci_cfg->csi[0].type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) {
*resource = uci_cfg->csi[0].pucch_resource;
if (uci_cfg->ack.count == 0 && uci_cfg->nof_csi == 1 && uci_cfg->csi[0].cfg.type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) {
*resource = uci_cfg->csi[0].cfg.periodic.resource;
return SRSRAN_SUCCESS;
}

View File

@ -225,10 +225,10 @@ int main(int argc, char** argv)
uint8_t csi_report_tx[SRSRAN_UCI_NR_MAX_CSI1_BITS] = {};
uint8_t csi_report_rx[SRSRAN_UCI_NR_MAX_CSI1_BITS] = {};
if (nof_csi_bits > 0) {
pusch_cfg.uci.csi[0].quantity = SRSRAN_CSI_REPORT_QUANTITY_NONE;
pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits;
pusch_cfg.uci.nof_csi = 1;
data_tx.uci.csi[0].none = csi_report_tx;
pusch_cfg.uci.csi[0].cfg.quantity = SRSRAN_CSI_REPORT_QUANTITY_NONE;
pusch_cfg.uci.csi[0].K_csi_rs = nof_csi_bits;
pusch_cfg.uci.nof_csi = 1;
data_tx.uci.csi[0].none = csi_report_tx;
for (uint32_t i = 0; i < nof_csi_bits; i++) {
csi_report_tx[i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, 1);
}

View File

@ -299,8 +299,7 @@ static int uci_nr_A(const srsran_uci_cfg_nr_t* cfg)
}
// 6.3.1.1.3 HARQ-ACK/SR and CSI
ERROR("HARQ-ACK/SR and CSI encoding are not implemented");
return SRSRAN_ERROR;
return cfg->ack.count + cfg->o_sr + o_csi;
}
static int uci_nr_pack_pucch(const srsran_uci_cfg_nr_t* cfg, const srsran_uci_value_nr_t* value, uint8_t* sequence)
@ -332,8 +331,7 @@ static int uci_nr_unpack_pucch(const srsran_uci_cfg_nr_t* cfg, uint8_t* sequence
// 6.3.1.1.2 CSI only
if (cfg->ack.count == 0 && cfg->o_sr == 0) {
ERROR("CSI only are not implemented");
return SRSRAN_ERROR;
return srsran_csi_part1_unpack(cfg->csi, cfg->nof_csi, sequence, SRSRAN_UCI_NR_MAX_NOF_BITS, value->csi);
}
// 6.3.1.1.3 HARQ-ACK/SR and CSI

View File

@ -344,14 +344,21 @@ public:
uci_data.value.sr = sr_count_positive;
}
void get_periodic_csi(const uint32_t& tti, srsran_uci_data_nr_t& uci_data)
void get_periodic_csi(const srsran_slot_cfg_t& slot_cfg, srsran_uci_data_nr_t& uci_data)
{
int n = srsran_csi_generate_reports(&cfg.csi, tti, csi_measurements.data(), uci_data.cfg.csi, uci_data.value.csi);
// Generate report configurations
int n = srsran_csi_reports_generate(&cfg.csi, &slot_cfg, uci_data.cfg.csi);
if (n > SRSRAN_SUCCESS) {
uci_data.cfg.nof_csi = n;
}
uci_data.cfg.pucch.rnti = stack->get_ul_sched_rnti_nr(tti).id;
// Quantify reports from measurements
n = srsran_csi_reports_quantify(uci_data.cfg.csi, csi_measurements.data(), uci_data.value.csi);
if (n > SRSRAN_SUCCESS) {
uci_data.cfg.nof_csi = n;
}
uci_data.cfg.pucch.rnti = stack->get_ul_sched_rnti_nr(slot_cfg.idx).id;
}
/**

View File

@ -590,7 +590,7 @@ bool cc_worker::work_ul()
}
// Add CSI reports to UCI data if available
phy.get_periodic_csi(ul_slot_cfg.idx, uci_data);
phy.get_periodic_csi(ul_slot_cfg, uci_data);
// Setup frequency offset
srsran_ue_ul_nr_set_freq_offset(&ue_ul, phy.get_ul_cfo());

View File

@ -40,7 +40,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
foreach (NR_PHY_TEST_BW "10MHz" "20MHz")
# For each supported frame structure
foreach (NR_PHY_TEST_DUPLEX "FDD" "6D+4U" "FR1.15-1")
set(NR_PHY_TEST_DURATION_MS 20)
set(NR_PHY_TEST_DURATION_MS 50)
# DL flooding only
foreach (NR_PHY_TEST_PDSCH "default" "ts38101/5.2-1")

View File

@ -55,10 +55,12 @@ public:
};
struct metrics_t {
std::map<uint32_t, prach_metrics_t> prach = {}; ///< PRACH metrics indexed with premable index
srsenb::mac_ue_metrics_t mac = {}; ///< MAC metrics
uint32_t sr_count = 0; ///< SR counter
pucch_metrics_t pucch = {};
std::map<uint32_t, prach_metrics_t> prach = {}; ///< PRACH metrics indexed with premable index
srsenb::mac_ue_metrics_t mac = {}; ///< MAC metrics
uint32_t sr_count = 0; ///< SR counter
uint32_t cqi_count = 0; ///< CQI opportunity counter
uint32_t cqi_valid_count = 0; ///< Valid CQI counter
pucch_metrics_t pucch = {};
};
private:
@ -304,6 +306,23 @@ private:
metrics.sr_count++;
}
// Process CQI
for (uint32_t i = 0; i < cfg.nof_csi; i++) {
// Increment CQI opportunity
metrics.cqi_count++;
// Skip if invalid or not supported CSI report
if (not value.valid or cfg.csi[i].cfg.quantity != SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI or
cfg.csi[i].cfg.freq_cfg != SRSRAN_CSI_REPORT_FREQ_WIDEBAND) {
continue;
}
// Add statistics
metrics.mac.dl_cqi =
SRSRAN_VEC_SAFE_CMA(value.csi->wideband_cri_ri_pmi_cqi.cqi, metrics.mac.dl_cqi, metrics.cqi_count);
metrics.cqi_valid_count++;
}
return true;
}

View File

@ -21,6 +21,11 @@
// shorten boost program options namespace
namespace bpo = boost::program_options;
static double assert_sr_detection_min = 1.000;
static double assert_cqi_detection_min = 1.000;
static double assert_pusch_bler_max = 0.000;
static double assert_pdsch_bler_max = 0.000;
test_bench::args_t::args_t(int argc, char** argv)
{
std::string reference_cfg_str = "";
@ -29,6 +34,7 @@ test_bench::args_t::args_t(int argc, char** argv)
bpo::options_description options_gnb_phy("gNb PHY related options");
bpo::options_description options_ue_stack("UE stack options");
bpo::options_description options_ue_phy("UE stack options");
bpo::options_description options_assertion("Test assertions");
uint16_t rnti = 17921;
@ -80,6 +86,13 @@ test_bench::args_t::args_t(int argc, char** argv)
("ue.stack.prach.preamble", bpo::value<uint32_t>(&ue_stack.prach_preamble)->default_value(ue_stack.prach_preamble), "PRACH preamble. Set 0 to disable and 1 for all.")
;
options_assertion.add_options()
("assert.sr.detection.min", bpo::value<double>(&assert_sr_detection_min)->default_value(assert_sr_detection_min), "Scheduling request minimum detection threshold")
("assert.cqi.detection.min", bpo::value<double>(&assert_cqi_detection_min)->default_value(assert_cqi_detection_min), "CQI report minimum detection threshold")
("assert.pusch.bler.max", bpo::value<double>(&assert_pusch_bler_max)->default_value(assert_pusch_bler_max), "PUSCH maximum BLER threshold")
("assert.pdsch.bler.max", bpo::value<double>(&assert_pdsch_bler_max)->default_value(assert_pdsch_bler_max), "PDSCH maximum BLER threshold")
;
options.add(options_gnb_stack).add(options_gnb_phy).add(options_ue_stack).add(options_ue_phy).add_options()
("help", "Show this message")
;
@ -164,9 +177,9 @@ int main(int argc, char** argv)
test_bench::metrics_t metrics = tb.get_gnb_metrics();
// Print PDSCH metrics if scheduled
double pdsch_bler = 0.0;
if (metrics.gnb_stack.mac.tx_pkts > 0) {
float pdsch_bler = 0.0f;
pdsch_bler = (float)metrics.gnb_stack.mac.tx_errors / (float)metrics.gnb_stack.mac.tx_pkts;
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;
@ -181,10 +194,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 = (float)metrics.gnb_stack.mac.rx_errors / (float)metrics.gnb_stack.mac.rx_pkts;
pusch_bler = (double)metrics.gnb_stack.mac.rx_errors / (double)metrics.gnb_stack.mac.rx_pkts;
}
float pusch_shed_rate = 0.0f;
@ -261,23 +274,54 @@ int main(int argc, char** argv)
srsran::console(" +------------+------------+------------+------------+\n");
}
srsran::console("UCI stats:\n");
srsran::console(" +------------+------------+------------+------------+------------+\n");
srsran::console(
" | %10s | %10s | %10s | %10s | %10s |\n", "Field", "Transmit'd", "Received", "Detection", "Avg. Val.");
srsran::console(" +------------+------------+------------+------------+------------+\n");
// Print SR
double sr_detection = 0.0;
if (metrics.ue_stack.sr_count > 0) {
srsran::console("SR:\n");
srsran::console(" +------------+------------+------------+\n");
srsran::console(" | %10s | %10s | %10s |\n", "Transmit'd", "Received", "Detection");
srsran::console(" +------------+------------+------------+\n");
srsran::console(" | %10d | %10d | %10.5f |\n",
sr_detection = (double)metrics.gnb_stack.sr_count / (double)metrics.ue_stack.sr_count;
srsran::console(" | %10s | %10d | %10d | %10.5f | %10s |\n",
"SR",
metrics.ue_stack.sr_count,
metrics.gnb_stack.sr_count,
(double)metrics.gnb_stack.sr_count / (double)metrics.ue_stack.sr_count);
srsran::console(" +------------+------------+------------+\n");
sr_detection,
"-");
}
// Print SR
double cqi_detection = 0.0;
if (metrics.gnb_stack.cqi_count > 0) {
cqi_detection = (double)metrics.gnb_stack.cqi_valid_count / (double)metrics.gnb_stack.cqi_count;
srsran::console(" | %10s | %10d | %10d | %10.5f | %10.5f |\n",
"CQI",
metrics.gnb_stack.cqi_count,
metrics.gnb_stack.cqi_valid_count,
cqi_detection,
metrics.gnb_stack.mac.dl_cqi);
}
srsran::console(" +------------+------------+------------+------------+------------+\n");
// Assert metrics
TESTASSERT_EQ(0, metrics.gnb_stack.mac.tx_errors);
TESTASSERT_EQ(0, metrics.gnb_stack.mac.rx_errors);
TESTASSERT(metrics.ue_stack.sr_count == metrics.gnb_stack.sr_count);
srsran_assert(metrics.gnb_stack.mac.tx_pkts == 0 or pdsch_bler <= assert_pdsch_bler_max,
"PDSCH BLER (%f) exceeds the assertion maximum (%f)",
pdsch_bler,
assert_pusch_bler_max);
srsran_assert(metrics.gnb_stack.mac.rx_pkts == 0 or pusch_bler <= assert_pusch_bler_max,
"PUSCH BLER (%f) exceeds the assertion maximum (%f)",
pusch_bler,
assert_pusch_bler_max);
srsran_assert(metrics.ue_stack.sr_count == 0 or sr_detection >= assert_sr_detection_min,
"SR detection probability (%f) did not reach the assertion minimum (%f)",
sr_detection,
assert_sr_detection_min);
srsran_assert(metrics.gnb_stack.cqi_count == 0 or cqi_detection >= assert_cqi_detection_min,
"CQI report detection probability (%f) did not reach the assertion minimum (%f)",
cqi_detection,
assert_sr_detection_min);
// If reached here, the test is successful
return SRSRAN_SUCCESS;