diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 25d126193..9d1f04e8e 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -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; } diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 2e9ea2f3c..518a9b53c 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -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 diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index bdf8d7222..b5df81698 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -43,11 +43,17 @@ test_bench::args_t::args_t(int argc, char** argv) // clang-format off options.add_options() - ("rnti", bpo::value(&rnti)->default_value(rnti), "UE RNTI") - ("duration", bpo::value(&durations_slots)->default_value(durations_slots), "Test duration in slots") - ("lib.log.level", bpo::value(&phy_lib_log_level)->default_value(phy_lib_log_level), "PHY librray log level") - ("reference", bpo::value(&reference_cfg_str)->default_value(reference_cfg_str), "Reference PHY configuration arguments") - ; + ("rnti", bpo::value(&rnti)->default_value(rnti), "UE RNTI") + ("duration", bpo::value(&durations_slots)->default_value(durations_slots), "Test duration in slots") + ("lib.log.level", bpo::value(&phy_lib_log_level)->default_value(phy_lib_log_level), "PHY librray log level") + ("reference", bpo::value(&reference_cfg_str)->default_value(reference_cfg_str), "Reference PHY configuration arguments") + ("dl_channel.awgn_enable", bpo::value(&dl_channel.awgn_enable)->default_value(dl_channel.awgn_enable), "DL Channel AWGN enable / disable") + ("dl_channel.awgn_snr", bpo::value(&dl_channel.awgn_snr_dB)->default_value(dl_channel.awgn_snr_dB), "DL Channel AWGN SNR in dB") + ("ul_channel.awgn_enable", bpo::value(&ul_channel.awgn_enable)->default_value(ul_channel.awgn_enable), "UL Channel AWGN enable / disable") + ("ul_channel.awgn_snr", bpo::value(&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(&ul_channel.awgn_signal_power_dBfs)->default_value(ul_channel.awgn_signal_power_dBfs), "UL Channel expected signal power") + ("channel.cfo", bpo::value(&ul_channel.hst_fd_hz)->default_value(0), "Channel HST Doppler frequency") +; options_gnb_stack.add_options() ("gnb.stack.pdcch.aggregation_level", bpo::value(&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"); } diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index 8269652c3..bd169475c 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -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; } };