nr_phy test: add AWGN channel simulator, add High Speed Train channel (#3288)

Add channel simulator to nr_phy tests.

UL and DL channel simulators added, with AWGN and CFO using the HST scenario. The DL AWGN is adjusted according to signal power.
master
Joaquim 3 years ago committed by GitHub
parent 5c3f0a39ee
commit 82ae0e6c37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -344,7 +344,10 @@ bool cc_worker::decode_pdsch_dl()
dl_m.evm = pdsch_res.evm[0];
phy.set_dl_metrics(dl_m);
}
ch_metrics_t ch_metrics = {};
ch_metrics.sinr = ue_dl.chest.snr_db;
ch_metrics.sync_err = ue_dl.chest.sync_error;
phy.set_channel_metrics(ch_metrics);
return true;
}

@ -35,7 +35,6 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB)
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}
${ATOMIC_LIBS})
# For each supported bandwidth
foreach (NR_PHY_TEST_BW "10MHz" "20MHz")
# For each supported frame structure

@ -43,11 +43,17 @@ test_bench::args_t::args_t(int argc, char** argv)
// clang-format off
options.add_options()
("rnti", bpo::value<uint16_t>(&rnti)->default_value(rnti), "UE RNTI")
("duration", bpo::value<uint64_t>(&durations_slots)->default_value(durations_slots), "Test duration in slots")
("lib.log.level", bpo::value<std::string>(&phy_lib_log_level)->default_value(phy_lib_log_level), "PHY librray log level")
("reference", bpo::value<std::string>(&reference_cfg_str)->default_value(reference_cfg_str), "Reference PHY configuration arguments")
;
("rnti", bpo::value<uint16_t>(&rnti)->default_value(rnti), "UE RNTI")
("duration", bpo::value<uint64_t>(&durations_slots)->default_value(durations_slots), "Test duration in slots")
("lib.log.level", bpo::value<std::string>(&phy_lib_log_level)->default_value(phy_lib_log_level), "PHY librray log level")
("reference", bpo::value<std::string>(&reference_cfg_str)->default_value(reference_cfg_str), "Reference PHY configuration arguments")
("dl_channel.awgn_enable", bpo::value<bool>(&dl_channel.awgn_enable)->default_value(dl_channel.awgn_enable), "DL Channel AWGN enable / disable")
("dl_channel.awgn_snr", bpo::value<float>(&dl_channel.awgn_snr_dB)->default_value(dl_channel.awgn_snr_dB), "DL Channel AWGN SNR in dB")
("ul_channel.awgn_enable", bpo::value<bool>(&ul_channel.awgn_enable)->default_value(ul_channel.awgn_enable), "UL Channel AWGN enable / disable")
("ul_channel.awgn_snr", bpo::value<float>(&ul_channel.awgn_snr_dB)->default_value(ul_channel.awgn_snr_dB), "UL Channel AWGN SNR in dB")
("ul_channel.signal_power_dBfs", bpo::value<float>(&ul_channel.awgn_signal_power_dBfs)->default_value(ul_channel.awgn_signal_power_dBfs), "UL Channel expected signal power")
("channel.cfo", bpo::value<float>(&ul_channel.hst_fd_hz)->default_value(0), "Channel HST Doppler frequency")
;
options_gnb_stack.add_options()
("gnb.stack.pdcch.aggregation_level", bpo::value<uint32_t>(&gnb_stack.pdcch_aggregation_level)->default_value(gnb_stack.pdcch_aggregation_level), "PDCCH aggregation level")
@ -102,6 +108,11 @@ test_bench::args_t::args_t(int argc, char** argv)
try {
bpo::store(bpo::command_line_parser(argc, argv).options(options).run(), vm);
bpo::notify(vm);
// Apply the High Speed Train args to the DL channel as well
ul_channel.hst_enable = std::isnormal(ul_channel.hst_fd_hz);
dl_channel.hst_enable = ul_channel.hst_enable;
dl_channel.hst_fd_hz = ul_channel.hst_fd_hz;
} catch (bpo::error& e) {
std::cerr << e.what() << std::endl;
return;
@ -117,6 +128,12 @@ test_bench::args_t::args_t(int argc, char** argv)
// Load default reference configuration
phy_cfg = srsran::phy_cfg_nr_default_t(srsran::phy_cfg_nr_default_t::reference_cfg_t(reference_cfg_str));
// Calulate the DL signal power from the number of PRBs
dl_channel.awgn_signal_power_dBfs = srsran_gnb_dl_get_maximum_signal_power_dBfs(phy_cfg.carrier.nof_prb);
// Reverses the Doppler shift for the UL
ul_channel.hst_init_time_s = 0.5 * dl_channel.hst_period_s;
// Calculate sampling rate in Hz
srate_hz = (double)(srsran_min_symbol_sz_rb(phy_cfg.carrier.nof_prb) * SRSRAN_SUBC_SPACING_NR(phy_cfg.carrier.scs));
@ -174,22 +191,26 @@ int main(int argc, char** argv)
srslog::flush();
// Retrieve MAC metrics
test_bench::metrics_t metrics = tb.get_gnb_metrics();
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_shed_rate = 0.0f;
pdsch_shed_rate = (float)metrics.gnb_stack.mac.tx_brate / (float)metrics.gnb_stack.mac.tx_pkts / 1000.0f;
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;
float decode_iterations = metrics.ue_phy.dl[0].fec_iters;
float ue_snr = metrics.ue_phy.ch[0].sinr;
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(" 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(" Measured SNR: %f dB\n", ue_snr);
srsran::console(" Dec Iterations: %f\n", decode_iterations);
srsran::console("\n");
}
@ -206,11 +227,11 @@ int main(int argc, char** argv)
}
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(" 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");
}

@ -22,6 +22,7 @@ class test_bench
private:
const std::string UE_PHY_COM_LOG_NAME = "UE /PHY/COM";
const std::string GNB_PHY_COM_LOG_NAME = "GNB/PHY/COM";
const std::string CHANNEL_LOG_NAME = "CHANNEL";
uint32_t slot_idx = 0;
uint64_t slot_count = 0;
uint64_t duration_slots = 0;
@ -33,6 +34,9 @@ private:
phy_common ue_phy_com;
bool initialised = false;
uint32_t sf_sz = 0;
// Channel simulator
srsran::channel dl_channel;
srsran::channel ul_channel;
public:
struct args_t {
@ -50,12 +54,16 @@ public:
std::string phy_lib_log_level = "none";
uint64_t durations_slots = 100;
// channel simulator args
srsran::channel::args_t dl_channel;
srsran::channel::args_t ul_channel;
args_t(int argc, char** argv);
};
struct metrics_t {
gnb_dummy_stack::metrics_t gnb_stack = {};
ue_dummy_stack::metrics_t ue_stack = {};
srsue::phy_metrics_t ue_phy = {};
};
test_bench(const args_t& args) :
@ -69,10 +77,13 @@ public:
gnb_phy_com(phy_common::args_t(args.srate_hz, args.buffer_sz_ms, args.nof_channels),
srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME, srslog::get_default_sink(), false)),
sf_sz((uint32_t)std::round(args.srate_hz * 1e-3)),
duration_slots(args.durations_slots)
duration_slots(args.durations_slots),
dl_channel(args.dl_channel, 1, srslog::fetch_basic_logger(CHANNEL_LOG_NAME, srslog::get_default_sink(), false)),
ul_channel(args.ul_channel, 1, srslog::fetch_basic_logger(CHANNEL_LOG_NAME, srslog::get_default_sink(), false))
{
srslog::fetch_basic_logger(UE_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level));
srslog::fetch_basic_logger(GNB_PHY_COM_LOG_NAME).set_level(srslog::str_to_basic_level(args.phy_com_log_level));
srslog::fetch_basic_logger(CHANNEL_LOG_NAME).set_level(srslog::basic_levels::error);
if (not gnb_phy.init(args.gnb_phy, args.cell_list)) {
return;
@ -109,6 +120,9 @@ public:
srsran_verbose = SRSRAN_VERBOSE_NONE;
}
// Configure channel
dl_channel.set_srate((uint32_t)args.srate_hz);
ul_channel.set_srate((uint32_t)args.srate_hz);
initialised = true;
}
@ -141,6 +155,9 @@ public:
// Set gNb time
gnb_time.add(TX_ENB_DELAY * 1e-3);
// Run the UL channel simulator
ul_channel.run(gnb_rx_buffers.data(), gnb_rx_buffers.data(), (uint32_t)sf_sz, gnb_time.get(0));
// Set gnb context
srsran::phy_common_interface::worker_context_t gnb_context;
gnb_context.sf_idx = slot_idx;
@ -168,6 +185,9 @@ public:
// Set UE time
ue_time.add(TX_ENB_DELAY * 1e-3);
// Run the DL channel simulator
dl_channel.run(ue_rx_buffers.data(), ue_rx_buffers.data(), (uint32_t)sf_sz, ue_time.get(0));
// Set gnb context
srsran::phy_common_interface::worker_context_t ue_context;
ue_context.sf_idx = slot_idx;
@ -188,11 +208,12 @@ public:
return slot_count <= duration_slots;
}
metrics_t get_gnb_metrics()
metrics_t get_metrics()
{
metrics_t metrics = {};
metrics.gnb_stack = gnb_stack.get_metrics();
metrics.ue_stack = ue_stack.get_metrics();
ue_phy.get_metrics(metrics.ue_phy); // get the metrics from the ue_phy
return metrics;
}
};

Loading…
Cancel
Save