From 660b66dbe391cb1b4e5aab12897fe86b4d0235b5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 16 Jul 2021 15:53:12 +0100 Subject: [PATCH] sched,nr: add option to run phy nr test with real NR scheduler --- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 4 +- srsenb/src/stack/mac/nr/sched_nr.cc | 3 +- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 4 +- srsenb/src/stack/mac/nr/sched_nr_helpers.cc | 2 +- srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc | 10 ++- srsenb/src/stack/mac/nr/sched_nr_worker.cc | 25 +++++- srsenb/test/mac/nr/sched_nr_cfg_generators.h | 95 ++++++++++++++++++++ srsenb/test/mac/nr/sched_nr_test.cc | 72 ++------------- test/phy/CMakeLists.txt | 1 + test/phy/dummy_gnb_stack.h | 53 ++++++++++- test/phy/nr_phy_test.cc | 1 + 11 files changed, 191 insertions(+), 79 deletions(-) create mode 100644 srsenb/test/mac/nr/sched_nr_cfg_generators.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 44e140ddf..2c99fa06d 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -71,7 +71,9 @@ public: }; struct ue_cfg_t { - uint32_t maxharq_tx = 4; + uint32_t maxharq_tx = 4; + int fixed_dl_mcs = -1; + int fixed_ul_mcs = -1; srsran::bounded_vector carriers; srsran::phy_cfg_nr_t phy_cfg = {}; }; diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index 3311942f2..77460f88a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -151,7 +151,8 @@ int sched_nr::get_dl_sched(tti_point tti_tx, uint32_t cc, dl_sched_t& result) int sched_nr::get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) { if (not pending_results->has_ul_result(tti_rx, cc)) { - return SRSRAN_ERROR; + // sched result hasn't been generated + return SRSRAN_SUCCESS; } result = pending_results->pop_ul_result(tti_rx, cc); diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 89ad86a49..da954d094 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -29,8 +29,8 @@ sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_) { bwps.reserve(cell.bwps.size()); - for (uint32_t i = 0; i < cell.bwps.size(); ++i) { - bwps.emplace_back(cell, sched_cfg_, cc, i); + for (uint32_t i = 0; i < cell_cfg.bwps.size(); ++i) { + bwps.emplace_back(cell_cfg, sched_cfg_, cc, i); } srsran_assert(not bwps.empty(), "No BWPs were configured"); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index cc9469fa7..a9f4efe4a 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -75,7 +75,7 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_location_t dci_pos, srsran_dci_ul_nr_t& dci) { - bool ret = ue.cfg->phy().get_dci_ctx_pdsch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx); + bool ret = ue.cfg->phy().get_dci_ctx_pusch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx); srsran_assert(ret, "Invalid DL DCI format"); fill_dci_common(ue, bwp_cfg, dci); diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc index edee6804b..fafa3cd62 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -45,6 +45,8 @@ void bwp_slot_grid::reset() ul_prbs.reset(); dl_pdcchs.clear(); ul_pdcchs.clear(); + pdschs.clear(); + puschs.clear(); pending_acks.clear(); } @@ -157,7 +159,8 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr // Allocate HARQ if (ue.h_dl->empty()) { - int mcs = 20; + srsran_assert(ue.cfg->ue_cfg()->fixed_dl_mcs >= 0, "Dynamic MCS not yet supported"); + int mcs = ue.cfg->ue_cfg()->fixed_dl_mcs; int tbs = 100; bool ret = ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_grant, mcs, tbs, 4); srsran_assert(ret, "Failed to allocate DL HARQ"); @@ -176,6 +179,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr bwp_uci_slot.pending_acks.end(), [&ue](const harq_ack_t& p) { return p.res.rnti == ue.rnti; }); pdcch.dci.dai %= 4; + pdcch.dci_cfg = ue.cfg->phy().get_dci_cfg(); // Generate PUCCH bwp_uci_slot.pending_acks.emplace_back(); @@ -230,7 +234,8 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_m } if (ue.h_ul->empty()) { - int mcs = 20; + srsran_assert(ue.cfg->ue_cfg()->fixed_ul_mcs >= 0, "Dynamic MCS not yet supported"); + int mcs = ue.cfg->ue_cfg()->fixed_ul_mcs; int tbs = 100; bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->ue_cfg()->maxharq_tx); srsran_assert(ret, "Failed to allocate UL HARQ"); @@ -242,6 +247,7 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_m // Generate PDCCH pdcch_ul_t& pdcch = pdcchs.back(); fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci); + pdcch.dci_cfg = ue.cfg->phy().get_dci_cfg(); // Generate PUSCH bwp_pusch_slot.ul_prbs.add(ul_mask); diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 283bd5d9f..e8a1f544d 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -138,12 +138,13 @@ void slot_cc_worker::log_result() const if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; fmt::format_to(fmtbuf, - "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, dai={}, tti_pdsch={}, tti_ack={}", + "SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, f={}, dai={}, tti_pdsch={}, tti_ack={}", ue.h_dl->nof_retx() == 0 ? "tx" : "retx", cell.cfg.cc, ue.rnti, - ue.h_dl->pid, + pdcch.dci.pid, ue.h_dl->nof_retx(), + srsran_dci_format_nr_string(pdcch.dci.ctx.format), pdcch.dci.dai, ue.pdsch_tti, ue.uci_tti); @@ -153,6 +154,26 @@ void slot_cc_worker::log_result() const fmt::format_to(fmtbuf, "SCHED: unknown format"); } + logger.info("%s", srsran::to_c_str(fmtbuf)); + } + for (const pdcch_ul_t& pdcch : bwp_slot.ul_pdcchs) { + fmt::memory_buffer fmtbuf; + if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { + const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; + fmt::format_to(fmtbuf, + "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, f={}, tti_pusch={}, tti_ack={}", + ue.h_dl->nof_retx() == 0 ? "tx" : "retx", + cell.cfg.cc, + ue.rnti, + pdcch.dci.pid, + ue.h_dl->nof_retx(), + srsran_dci_format_nr_string(pdcch.dci.ctx.format), + ue.pusch_tti, + ue.uci_tti); + } else { + fmt::format_to(fmtbuf, "SCHED: unknown rnti format"); + } + logger.info("%s", srsran::to_c_str(fmtbuf)); } } diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h new file mode 100644 index 000000000..2587b8c24 --- /dev/null +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -0,0 +1,95 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_SCHED_NR_CFG_GENERATORS_H +#define SRSRAN_SCHED_NR_CFG_GENERATORS_H + +#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" +#include "srsran/common/phy_cfg_nr_default.h" + +namespace srsenb { + +srsran_coreset_t get_default_coreset0() +{ + srsran_coreset_t coreset{}; + coreset.id = 0; + coreset.duration = 1; + coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; ++i) { + coreset.freq_resources[i] = i < 8; + } + return coreset; +} + +sched_nr_interface::cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& phy_cfg) +{ + sched_nr_interface::cell_cfg_t cell_cfg{}; + + cell_cfg.carrier = phy_cfg.carrier; + cell_cfg.tdd = phy_cfg.tdd; + + cell_cfg.bwps.resize(1); + cell_cfg.bwps[0].pdcch = phy_cfg.pdcch; + cell_cfg.bwps[0].pdsch = phy_cfg.pdsch; + cell_cfg.bwps[0].rb_width = phy_cfg.carrier.nof_prb; + + cell_cfg.bwps[0].pdcch.coreset_present[0] = true; + cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); + cell_cfg.bwps[0].pdcch.search_space_present[0] = true; + auto& ss = cell_cfg.bwps[0].pdcch.search_space[0]; + ss.id = 0; + ss.coreset_id = 0; + ss.duration = 1; + ss.type = srsran_search_space_type_common_0; + ss.nof_candidates[0] = 1; + ss.nof_candidates[1] = 1; + ss.nof_candidates[2] = 1; + ss.nof_candidates[3] = 0; + ss.nof_candidates[4] = 0; + ss.nof_formats = 1; + ss.formats[0] = srsran_dci_format_nr_1_0; + cell_cfg.bwps[0].pdcch.ra_search_space_present = true; + cell_cfg.bwps[0].pdcch.ra_search_space = cell_cfg.bwps[0].pdcch.search_space[1]; + + return cell_cfg; +} + +std::vector get_default_cells_cfg( + uint32_t nof_sectors, + const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) +{ + std::vector cells; + cells.reserve(nof_sectors); + for (uint32_t i = 0; i < nof_sectors; ++i) { + cells.push_back(get_default_cell_cfg(phy_cfg)); + } + return cells; +} + +sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc, + const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{ + srsran::phy_cfg_nr_default_t::reference_cfg_t{}}) +{ + sched_nr_interface::ue_cfg_t uecfg{}; + uecfg.carriers.resize(nof_cc); + for (uint32_t cc = 0; cc < nof_cc; ++cc) { + uecfg.carriers[cc].cc = cc; + uecfg.carriers[cc].active = true; + } + uecfg.phy_cfg = phy_cfg; + + return uecfg; +} + +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_CFG_GENERATORS_H diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index 8daadc738..2704ad637 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -10,6 +10,7 @@ * */ +#include "sched_nr_cfg_generators.h" #include "sched_nr_sim_ue.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h" #include "srsran/common/phy_cfg_nr_default.h" @@ -24,72 +25,6 @@ using dl_sched_t = sched_nr_interface::dl_sched_t; static const srsran::phy_cfg_nr_t default_phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}; -srsran_coreset_t get_default_coreset0() -{ - srsran_coreset_t coreset{}; - coreset.id = 0; - coreset.duration = 1; - coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; ++i) { - coreset.freq_resources[i] = i < 8; - } - return coreset; -} - -sched_nr_interface::cell_cfg_t get_default_cell_cfg() -{ - sched_nr_interface::cell_cfg_t cell_cfg{}; - - cell_cfg.carrier = default_phy_cfg.carrier; - cell_cfg.tdd = default_phy_cfg.tdd; - - cell_cfg.bwps.resize(1); - cell_cfg.bwps[0].pdcch = default_phy_cfg.pdcch; - cell_cfg.bwps[0].pdsch = default_phy_cfg.pdsch; - cell_cfg.bwps[0].rb_width = default_phy_cfg.carrier.nof_prb; - - cell_cfg.bwps[0].pdcch.coreset_present[0] = true; - cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(); - cell_cfg.bwps[0].pdcch.search_space_present[0] = true; - auto& ss = cell_cfg.bwps[0].pdcch.search_space[0]; - ss.id = 0; - ss.coreset_id = 0; - ss.duration = 1; - ss.type = srsran_search_space_type_common_0; - ss.nof_candidates[0] = 1; - ss.nof_candidates[1] = 1; - ss.nof_candidates[2] = 1; - ss.nof_candidates[3] = 0; - ss.nof_candidates[4] = 0; - ss.nof_formats = 1; - ss.formats[0] = srsran_dci_format_nr_1_0; - cell_cfg.bwps[0].pdcch.ra_search_space_present = true; - cell_cfg.bwps[0].pdcch.ra_search_space = cell_cfg.bwps[0].pdcch.search_space[1]; - - return cell_cfg; -} -std::vector get_default_cells_cfg(uint32_t nof_sectors) -{ - std::vector cells; - cells.reserve(nof_sectors); - for (uint32_t i = 0; i < nof_sectors; ++i) { - cells.push_back(get_default_cell_cfg()); - } - return cells; -} - -sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc) -{ - sched_nr_interface::ue_cfg_t uecfg{}; - uecfg.carriers.resize(nof_cc); - for (uint32_t cc = 0; cc < nof_cc; ++cc) { - uecfg.carriers[cc].active = true; - } - uecfg.phy_cfg = default_phy_cfg; - - return uecfg; -} - struct task_job_manager { std::mutex mutex; int res_count = 0; @@ -151,7 +86,8 @@ void sched_nr_cfg_serialized_test() sched_nr_sim_base sched_tester(cfg, cells_cfg, "Serialized Test"); sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(nof_sectors); - + uecfg.fixed_dl_mcs = 15; + uecfg.fixed_ul_mcs = 15; sched_tester.add_user(0x46, uecfg, 0); std::vector count_per_cc(nof_sectors, 0); @@ -198,6 +134,8 @@ void sched_nr_cfg_parallel_cc_test() sched_nr_sim_base sched_tester(cfg, cells_cfg, "Parallel CC Test"); sched_nr_interface::ue_cfg_t uecfg = get_default_ue_cfg(cells_cfg.size()); + uecfg.fixed_dl_mcs = 15; + uecfg.fixed_ul_mcs = 15; sched_tester.add_user(0x46, uecfg, 0); std::array, SRSRAN_MAX_CARRIERS> nano_count{}; diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 034f235fb..bfce9bf25 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -17,6 +17,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) srsran_phy srsran_radio srsenb_phy + srsgnb_mac ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 9d6258ffc..a5828c23d 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -15,6 +15,8 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" #include #include #include @@ -38,8 +40,9 @@ public: }; private: - srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); - const uint16_t rnti = 0x1234; + srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB STK"); + bool use_dummy_sched = true; + const uint16_t rnti = 0x1234; struct { srsran::circular_array dci_location; uint32_t mcs; @@ -51,6 +54,9 @@ private: srsran::phy_cfg_nr_t phy_cfg = {}; bool valid = false; + srsenb::sched_nr sched; + srsran::tti_point pdsch_tti, pusch_tti; + std::mutex metrics_mutex; metrics_t metrics = {}; @@ -271,6 +277,7 @@ private: public: struct args_t { srsran::phy_cfg_nr_t phy_cfg; ///< Physical layer configuration + bool use_dummy_sched = false; ///< Use dummy or real NR scheduler uint16_t rnti = 0x1234; ///< C-RNTI uint32_t ss_id = 1; ///< Search Space identifier uint32_t pdcch_aggregation_level = 0; ///< PDCCH aggregation level @@ -285,10 +292,21 @@ public: std::string log_level = "warning"; }; - gnb_dummy_stack(const args_t& args) : rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id) + gnb_dummy_stack(const args_t& args) : + rnti(args.rnti), phy_cfg(args.phy_cfg), ss_id(args.ss_id), sched(srsenb::sched_nr_interface::sched_cfg_t{}) { logger.set_level(srslog::str_to_basic_level(args.log_level)); + // create sched object + std::vector cells_cfg = srsenb::get_default_cells_cfg(1, phy_cfg); + sched.cell_cfg(cells_cfg); + + // add UE to scheduler + srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); + ue_cfg.fixed_dl_mcs = args.pdsch.mcs; + ue_cfg.fixed_ul_mcs = args.pusch.mcs; + sched.ue_cfg(args.rnti, ue_cfg); + dl.mcs = args.pdsch.mcs; ul.mcs = args.pusch.mcs; @@ -351,6 +369,26 @@ public: int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override { logger.set_context(slot_cfg.idx); + if (not pdsch_tti.is_valid()) { + pdsch_tti = srsran::tti_point{slot_cfg.idx}; + } else { + pdsch_tti++; + } + + if (not use_dummy_sched) { + int ret = sched.get_dl_sched(pdsch_tti, 0, dl_sched); + + for (pdsch_t& pdsch : dl_sched.pdsch) { + // Set TBS + // Select grant and set data + pdsch.data[0] = tx_harq_proc[slot_cfg.idx].get_tb(pdsch.sch.grant.tb[0].tbs).data(); + + // Generate random data + srsran_random_byte_vector(random_gen, pdsch.data[0], pdsch.sch.grant.tb[0].tbs / 8); + } + + return ret; + } // Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) { @@ -378,6 +416,15 @@ public: int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override { logger.set_context(slot_cfg.idx); + if (not pusch_tti.is_valid()) { + pusch_tti = srsran::tti_point{slot_cfg.idx}; + } else { + pusch_tti++; + } + + if (not use_dummy_sched) { + return sched.get_ul_sched(pusch_tti, 0, ul_sched); + } // Get ACK information srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx % pending_ack.size()].get_ack(); diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 2f2d25a77..6ba631cc1 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -54,6 +54,7 @@ test_bench::args_t::args_t(int argc, char** argv) ("gnb.stack.pusch.slots", bpo::value(&gnb_stack.pusch.slots)->default_value(gnb_stack.pusch.slots), "Slots enabled for PUSCH") ("gnb.stack.pusch.mcs", bpo::value(&gnb_stack.pusch.mcs)->default_value(gnb_stack.pusch.mcs), "PUSCH scheduling modulation code scheme") ("gnb.stack.log.level", bpo::value(&gnb_stack.log_level)->default_value(gnb_stack.log_level), "Stack log level") + ("gnb.stack.use_dummy_sched", bpo::value(&gnb_stack.use_dummy_sched)->default_value(true), "Use dummy or real NR scheduler") ; options_gnb_phy.add_options()