From b4861bc59a1da71970abe9a34468bbab01883f91 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 7 Dec 2020 18:15:06 +0000 Subject: [PATCH] move sched params and sched helper methods to sched_helpers.h/cc files. Removed place in the scheduler where the mcs is increased forcefully to avoid segmentation --- srsenb/hdr/stack/mac/sched.h | 22 -- srsenb/hdr/stack/mac/sched_common.h | 43 +-- srsenb/hdr/stack/mac/sched_helpers.h | 59 ++++ .../hdr/stack/mac/sched_interface_helpers.h | 25 -- srsenb/src/stack/mac/CMakeLists.txt | 2 +- srsenb/src/stack/mac/sched.cc | 181 +---------- srsenb/src/stack/mac/sched_carrier.cc | 2 +- srsenb/src/stack/mac/sched_grid.cc | 4 +- srsenb/src/stack/mac/sched_helpers.cc | 283 ++++++++++++++++++ .../src/stack/mac/sched_interface_helpers.cc | 122 -------- srsenb/src/stack/mac/sched_ue.cc | 20 +- srsenb/test/mac/sched_test_common.cc | 5 +- srsenb/test/mac/sched_ue_ded_test_suite.cc | 10 +- 13 files changed, 365 insertions(+), 413 deletions(-) create mode 100644 srsenb/hdr/stack/mac/sched_helpers.h delete mode 100644 srsenb/hdr/stack/mac/sched_interface_helpers.h create mode 100644 srsenb/src/stack/mac/sched_helpers.cc delete mode 100644 srsenb/src/stack/mac/sched_interface_helpers.cc diff --git a/srsenb/hdr/stack/mac/sched.h b/srsenb/hdr/stack/mac/sched.h index 903abdc7e..de1f78c8c 100644 --- a/srsenb/hdr/stack/mac/sched.h +++ b/srsenb/hdr/stack/mac/sched.h @@ -26,28 +26,6 @@ namespace srsenb { -namespace sched_utils { - -inline bool is_in_tti_interval(uint32_t tti, uint32_t tti1, uint32_t tti2) -{ - tti %= 10240; - tti1 %= 10240; - tti2 %= 10240; - if (tti1 <= tti2) { - return tti >= tti1 and tti <= tti2; - } - return tti >= tti1 or tti <= tti2; -} - -} // namespace sched_utils - -/* Caution: User addition (ue_cfg) and removal (ue_rem) are not thread-safe - * Rest of operations are thread-safe - * - * The subclass sched_ue is thread-safe so that access to shared variables like buffer states - * from scheduler thread and other threads is protected for each individual user. - */ - class sched : public sched_interface { public: diff --git a/srsenb/hdr/stack/mac/sched_common.h b/srsenb/hdr/stack/mac/sched_common.h index 82e2537e2..b1ba52f3d 100644 --- a/srsenb/hdr/stack/mac/sched_common.h +++ b/srsenb/hdr/stack/mac/sched_common.h @@ -35,7 +35,7 @@ struct sched_dci_cce_t { uint32_t nof_loc[4]; ///< Number of possible CCE locations for each aggregation level index }; -//! structs to bundle together all the sched arguments, and share them with all the sched sub-components +/// structs to bundle together all the sched arguments, and share them with all the sched sub-components class sched_cell_params_t { struct regs_deleter { @@ -86,47 +86,6 @@ struct prb_interval : public srslte::interval { static prb_interval riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs = -1); }; -/*********************** - * Helper Functions - **********************/ - -namespace sched_utils { - -inline uint32_t aggr_level(uint32_t aggr_idx) -{ - return 1u << aggr_idx; -} - -//! Obtain rvidx from nof retxs. This value is stored in DCI -inline uint32_t get_rvidx(uint32_t retx_idx) -{ - const static uint32_t rv_idx[4] = {0, 2, 3, 1}; - return rv_idx[retx_idx % 4]; -} - -//! Obtain nof retxs from rvidx. -inline uint32_t get_nof_retx(uint32_t rv_idx) -{ - const static uint32_t nof_retxs[4] = {0, 3, 1, 2}; - return nof_retxs[rv_idx % 4]; -} - -/** - * Generate possible CCE locations a user can use to allocate DCIs - * @param regs Regs data for the given cell configuration - * @param location Result of the CCE location computation. - * @param cfi Number of control symbols used for the PDCCH - * @param sf_idx subframe index specific to the tx TTI (relevant only for data and RAR transmissions) - * @param rnti identity of the user (invalid RNTI for RAR and BC transmissions) - */ -void generate_cce_location(srslte_regs_t* regs, - sched_dci_cce_t* location, - uint32_t cfi, - uint32_t sf_idx = 0, - uint16_t rnti = SRSLTE_INVALID_RNTI); - -} // namespace sched_utils - } // namespace srsenb #endif // SRSLTE_SCHED_COMMON_H diff --git a/srsenb/hdr/stack/mac/sched_helpers.h b/srsenb/hdr/stack/mac/sched_helpers.h new file mode 100644 index 000000000..930d7a66b --- /dev/null +++ b/srsenb/hdr/stack/mac/sched_helpers.h @@ -0,0 +1,59 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2020 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 SRSLTE_SCHED_HELPERS_H +#define SRSLTE_SCHED_HELPERS_H + +#include "srsenb/hdr/stack/mac/sched_common.h" +#include "srslte/common/logmap.h" +#include "srslte/interfaces/sched_interface.h" + +namespace srsenb { + +inline uint32_t aggr_level(uint32_t aggr_idx) +{ + return 1u << aggr_idx; +} + +/// Obtain rvidx from nof retxs. This value is stored in DCI +inline uint32_t get_rvidx(uint32_t retx_idx) +{ + const static uint32_t rv_idx[4] = {0, 2, 3, 1}; + return rv_idx[retx_idx % 4]; +} + +/// Obtain nof retxs from rvidx. +inline uint32_t get_nof_retx(uint32_t rv_idx) +{ + const static uint32_t nof_retxs[4] = {0, 3, 1, 2}; + return nof_retxs[rv_idx % 4]; +} + +void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result); + +/** + * Generate possible CCE locations a user can use to allocate DCIs + * @param regs Regs data for the given cell configuration + * @param location Result of the CCE location computation. + * @param cfi Number of control symbols used for the PDCCH + * @param sf_idx subframe index specific to the tx TTI (relevant only for data and RAR transmissions) + * @param rnti identity of the user (invalid RNTI for RAR and BC transmissions) + */ +void generate_cce_location(srslte_regs_t* regs, + sched_dci_cce_t* location, + uint32_t cfi, + uint32_t sf_idx = 0, + uint16_t rnti = SRSLTE_INVALID_RNTI); + +} // namespace srsenb + +#endif // SRSLTE_SCHED_HELPERS_H diff --git a/srsenb/hdr/stack/mac/sched_interface_helpers.h b/srsenb/hdr/stack/mac/sched_interface_helpers.h deleted file mode 100644 index 46c91552d..000000000 --- a/srsenb/hdr/stack/mac/sched_interface_helpers.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2020 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 SRSLTE_SCHED_INTERFACE_HELPERS_H -#define SRSLTE_SCHED_INTERFACE_HELPERS_H - -#include "srslte/common/logmap.h" -#include "srslte/interfaces/sched_interface.h" - -namespace srsenb { - -void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result); - -} - -#endif // SRSLTE_SCHED_INTERFACE_HELPERS_H diff --git a/srsenb/src/stack/mac/CMakeLists.txt b/srsenb/src/stack/mac/CMakeLists.txt index 1ee710c51..758a4c4de 100644 --- a/srsenb/src/stack/mac/CMakeLists.txt +++ b/srsenb/src/stack/mac/CMakeLists.txt @@ -9,7 +9,7 @@ add_subdirectory(schedulers) set(SOURCES mac.cc ue.cc sched.cc sched_carrier.cc sched_grid.cc sched_harq.cc sched_ue.cc - sched_ue_ctrl/sched_lch.cc sched_interface_helpers.cc) + sched_ue_ctrl/sched_lch.cc sched_helpers.cc) add_library(srsenb_mac STATIC ${SOURCES} $) if(ENABLE_5GNR) diff --git a/srsenb/src/stack/mac/sched.cc b/srsenb/src/stack/mac/sched.cc index ba5dcd638..ae4d58084 100644 --- a/srsenb/src/stack/mac/sched.cc +++ b/srsenb/src/stack/mac/sched.cc @@ -15,6 +15,7 @@ #include "srsenb/hdr/stack/mac/sched.h" #include "srsenb/hdr/stack/mac/sched_carrier.h" +#include "srsenb/hdr/stack/mac/sched_helpers.h" #include "srslte/common/logmap.h" #include "srslte/srslte.h" @@ -25,103 +26,6 @@ using srslte::tti_point; namespace srsenb { -namespace sched_utils { - -uint32_t tti_subtract(uint32_t tti1, uint32_t tti2) -{ - return TTI_SUB(tti1, tti2); -} - -uint32_t max_tti(uint32_t tti1, uint32_t tti2) -{ - return ((tti1 - tti2) > 10240 / 2) ? SRSLTE_MIN(tti1, tti2) : SRSLTE_MAX(tti1, tti2); -} - -} // namespace sched_utils - -/******************************************************* - * Sched Params - *******************************************************/ - -bool sched_cell_params_t::set_cfg(uint32_t enb_cc_idx_, - const sched_interface::cell_cfg_t& cfg_, - const sched_interface::sched_args_t& sched_args) -{ - enb_cc_idx = enb_cc_idx_; - cfg = cfg_; - sched_cfg = &sched_args; - - // Basic cell config checks - if (cfg.si_window_ms == 0) { - Error("SCHED: Invalid si-window length 0 ms\n"); - return false; - } - - bool invalid_prach; - if (cfg.cell.nof_prb == 6) { - // PUCCH has to allow space for Msg3 - if (cfg.nrb_pucch > 1) { - Console("Invalid PUCCH configuration: nrb_pucch=%d does not allow space for Msg3 transmission..\n", - cfg.nrb_pucch); - return false; - } - // PRACH has to fit within the PUSCH+PUCCH space - invalid_prach = cfg.prach_freq_offset + 6 > cfg.cell.nof_prb; - } else { - // PRACH has to fit within the PUSCH space - invalid_prach = (cfg.prach_freq_offset + 6) > (cfg.cell.nof_prb - cfg.nrb_pucch) or - ((int)cfg.prach_freq_offset < cfg.nrb_pucch); - } - if (invalid_prach) { - Error("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset); - Console("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset); - return false; - } - - // Set derived sched parameters - - // init regs - regs.reset(new srslte_regs_t{}); - if (srslte_regs_init(regs.get(), cfg.cell) != SRSLTE_SUCCESS) { - Error("Getting DCI locations\n"); - return false; - } - - // Compute Common locations for DCI for each CFI - for (uint32_t cfix = 0; cfix < pdcch_grid_t::MAX_CFI; cfix++) { - sched_utils::generate_cce_location(regs.get(), &common_locations[cfix], cfix + 1); - } - if (common_locations[sched_cfg->max_nof_ctrl_symbols - 1].nof_loc[2] == 0) { - Error("SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n", - sched_cfg->max_nof_ctrl_symbols); - Console("SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n", - sched_cfg->max_nof_ctrl_symbols); - return false; - } - - // Compute UE locations for RA-RNTI - for (uint32_t cfi = 0; cfi < 3; cfi++) { - for (uint32_t sf_idx = 0; sf_idx < 10; sf_idx++) { - sched_utils::generate_cce_location(regs.get(), &rar_locations[cfi][sf_idx], cfi + 1, sf_idx); - } - } - - // precompute nof cces in PDCCH for each CFI - for (uint32_t cfix = 0; cfix < nof_cce_table.size(); ++cfix) { - int ret = srslte_regs_pdcch_ncce(regs.get(), cfix + 1); - if (ret < 0) { - Error("SCHED: Failed to calculate the number of CCEs in the PDCCH\n"); - return false; - } - nof_cce_table[cfix] = (uint32_t)ret; - } - - P = srslte_ra_type0_P(cfg.cell.nof_prb); - nof_rbgs = srslte::ceil_div(cfg.cell.nof_prb, P); - - return true; -} - /******************************************************* * * Initialization and sched configuration functions @@ -470,87 +374,4 @@ int sched::ue_db_access(uint16_t rnti, Func f, const char* func_name) return SRSLTE_SUCCESS; } -/******************************************************* - * - * Helper functions and common data types - * - *******************************************************/ - -void sched_cell_params_t::regs_deleter::operator()(srslte_regs_t* p) -{ - if (p != nullptr) { - srslte_regs_free(p); - delete p; - } -} - -rbg_interval rbg_interval::prbs_to_rbgs(const prb_interval& prbs, uint32_t P) -{ - return rbg_interval{srslte::ceil_div(prbs.start(), P), srslte::ceil_div(prbs.stop(), P)}; -} - -prb_interval prb_interval::rbgs_to_prbs(const rbg_interval& rbgs, uint32_t P) -{ - return prb_interval{rbgs.start() * P, rbgs.stop() * P}; -} - -rbg_interval rbg_interval::rbgmask_to_rbgs(const rbgmask_t& mask) -{ - int rb_start = -1; - for (uint32_t i = 0; i < mask.size(); i++) { - if (rb_start == -1) { - if (mask.test(i)) { - rb_start = i; - } - } else { - if (!mask.test(i)) { - return rbg_interval(rb_start, i); - } - } - } - if (rb_start != -1) { - return rbg_interval(rb_start, mask.size()); - } else { - return rbg_interval(); - } -} - -prb_interval prb_interval::riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs) -{ - if (nof_vrbs < 0) { - nof_vrbs = nof_prbs; - } - uint32_t rb_start, l_crb; - srslte_ra_type2_from_riv(riv, &l_crb, &rb_start, nof_prbs, (uint32_t)nof_vrbs); - return {rb_start, rb_start + l_crb}; -} - -namespace sched_utils { - -void generate_cce_location(srslte_regs_t* regs_, - sched_dci_cce_t* location, - uint32_t cfi, - uint32_t sf_idx, - uint16_t rnti) -{ - *location = {}; - - srslte_dci_location_t loc[64]; - uint32_t nloc = 0; - if (rnti == 0) { - nloc = srslte_pdcch_common_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64); - } else { - nloc = srslte_pdcch_ue_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64, sf_idx, rnti); - } - - // Save to different format - for (uint32_t i = 0; i < nloc; i++) { - uint32_t l = loc[i].L; - location->cce_start[l][location->nof_loc[l]] = loc[i].ncce; - location->nof_loc[l]++; - } -} - -} // namespace sched_utils - } // namespace srsenb diff --git a/srsenb/src/stack/mac/sched_carrier.cc b/srsenb/src/stack/mac/sched_carrier.cc index 66ae73387..27cbdc432 100644 --- a/srsenb/src/stack/mac/sched_carrier.cc +++ b/srsenb/src/stack/mac/sched_carrier.cc @@ -11,7 +11,7 @@ */ #include "srsenb/hdr/stack/mac/sched_carrier.h" -#include "srsenb/hdr/stack/mac/sched_interface_helpers.h" +#include "srsenb/hdr/stack/mac/sched_helpers.h" #include "srsenb/hdr/stack/mac/schedulers/sched_time_pf.h" #include "srsenb/hdr/stack/mac/schedulers/sched_time_rr.h" #include "srslte/common/logmap.h" diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 1ddbc8f2b..08bd1d39e 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -12,9 +12,9 @@ #include "srsenb/hdr/stack/mac/sched_grid.h" #include "srsenb/hdr/stack/mac/sched.h" +#include "srsenb/hdr/stack/mac/sched_helpers.h" #include "srslte/common/log_helper.h" #include "srslte/common/logmap.h" -#include using srslte::tti_point; @@ -649,7 +649,7 @@ sf_sched::ctrl_code_t sf_sched::alloc_dl_ctrl(uint32_t aggr_lvl, uint32_t tbs_by alloc_outcome_t sf_sched::alloc_bc(uint32_t aggr_lvl, uint32_t sib_idx, uint32_t sib_ntx) { uint32_t sib_len = cc_cfg->cfg.sibs[sib_idx].len; - uint32_t rv = sched_utils::get_rvidx(sib_ntx); + uint32_t rv = get_rvidx(sib_ntx); ctrl_code_t ret = alloc_dl_ctrl(aggr_lvl, sib_len, SRSLTE_SIRNTI); if (not ret.first) { Warning("SCHED: Could not allocate SIB=%d, L=%d, len=%d, cause=%s\n", diff --git a/srsenb/src/stack/mac/sched_helpers.cc b/srsenb/src/stack/mac/sched_helpers.cc new file mode 100644 index 000000000..a48851cab --- /dev/null +++ b/srsenb/src/stack/mac/sched_helpers.cc @@ -0,0 +1,283 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2020 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. + * + */ + +#include "srsenb/hdr/stack/mac/sched_helpers.h" +#include "srslte/mac/pdu.h" +#include "srslte/srslog/bundled/fmt/format.h" +#include + +#define Info(fmt, ...) srslte::logmap::get("MAC")->error(fmt, ##__VA_ARGS__) +#define Error(fmt, ...) srslte::logmap::get("MAC")->error(fmt, ##__VA_ARGS__) + +namespace srsenb { + +using dl_sched_res_t = sched_interface::dl_sched_res_t; +using dl_sched_data_t = sched_interface::dl_sched_data_t; +using custom_mem_buffer = fmt::basic_memory_buffer; + +const char* to_string_short(srslte_dci_format_t dcifmt) +{ + switch (dcifmt) { + case SRSLTE_DCI_FORMAT0: + return "0"; + case SRSLTE_DCI_FORMAT1: + return "1"; + case SRSLTE_DCI_FORMAT1A: + return "1A"; + case SRSLTE_DCI_FORMAT1B: + return "1B"; + case SRSLTE_DCI_FORMAT2: + return "2"; + case SRSLTE_DCI_FORMAT2A: + return "2A"; + case SRSLTE_DCI_FORMAT2B: + return "2B"; + default: + return "unknown"; + } +} + +void fill_dl_cc_result_info(custom_mem_buffer& strbuf, const dl_sched_data_t& data) +{ + uint32_t first_ce = sched_interface::MAX_RLC_PDU_LIST; + for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) { + if (srslte::is_mac_ce(static_cast(data.pdu[i]->lcid))) { + first_ce = i; + break; + } + } + if (first_ce == sched_interface::MAX_RLC_PDU_LIST) { + return; + } + const char* prefix = strbuf.size() > 0 ? " | " : ""; + fmt::format_to(strbuf, "{}rnti={:0x}: [", prefix, data.dci.rnti); + bool ces_found = false; + for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) { + const auto& pdu = data.pdu[0][i]; + prefix = (ces_found) ? " | " : ""; + srslte::dl_sch_lcid lcid = static_cast(pdu.lcid); + if (srslte::is_mac_ce(lcid)) { + fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid)); + ces_found = true; + } + } + fmt::format_to(strbuf, "]"); +} + +void fill_dl_cc_result_debug(custom_mem_buffer& strbuf, const dl_sched_data_t& data) +{ + if (data.nof_pdu_elems[0] == 0 and data.nof_pdu_elems[1] == 0) { + return; + } + fmt::format_to(strbuf, + " > rnti={:0x}, tbs={}, f={}, mcs={}: [", + data.dci.rnti, + data.tbs[0], + to_string_short(data.dci.format), + data.dci.tb[0].mcs_idx); + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; ++tb) { + for (uint32_t i = 0; i < data.nof_pdu_elems[tb]; ++i) { + const auto& pdu = data.pdu[tb][i]; + const char* prefix = (i == 0) ? "" : " | "; + srslte::dl_sch_lcid lcid = static_cast(pdu.lcid); + if (srslte::is_mac_ce(lcid)) { + fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid)); + } else { + fmt::format_to(strbuf, "{}MAC SDU lcid={}, tb={}, len={} B", prefix, pdu.lcid, tb, pdu.nbytes); + } + } + } + fmt::format_to(strbuf, "]\n"); +} + +void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result) +{ + if (log_h->get_level() < srslte::LOG_LEVEL_INFO) { + return; + } + custom_mem_buffer strbuf; + for (uint32_t i = 0; i < result.nof_data_elems; ++i) { + const dl_sched_data_t& data = result.data[i]; + if (log_h->get_level() == srslte::LOG_LEVEL_INFO) { + fill_dl_cc_result_info(strbuf, data); + } else if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) { + fill_dl_cc_result_debug(strbuf, data); + } + } + if (strbuf.size() != 0) { + if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) { + log_h->debug("SCHED: MAC LCID allocs cc=%d:\n%s", enb_cc_idx, fmt::to_string(strbuf).c_str()); + } else { + log_h->info("SCHED: MAC CE allocs cc=%d: %s", enb_cc_idx, fmt::to_string(strbuf).c_str()); + } + } +} + +rbg_interval rbg_interval::prbs_to_rbgs(const prb_interval& prbs, uint32_t P) +{ + return rbg_interval{srslte::ceil_div(prbs.start(), P), srslte::ceil_div(prbs.stop(), P)}; +} + +prb_interval prb_interval::rbgs_to_prbs(const rbg_interval& rbgs, uint32_t P) +{ + return prb_interval{rbgs.start() * P, rbgs.stop() * P}; +} + +rbg_interval rbg_interval::rbgmask_to_rbgs(const rbgmask_t& mask) +{ + int rb_start = -1; + for (uint32_t i = 0; i < mask.size(); i++) { + if (rb_start == -1) { + if (mask.test(i)) { + rb_start = i; + } + } else { + if (!mask.test(i)) { + return rbg_interval(rb_start, i); + } + } + } + if (rb_start != -1) { + return rbg_interval(rb_start, mask.size()); + } else { + return rbg_interval(); + } +} + +prb_interval prb_interval::riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs) +{ + if (nof_vrbs < 0) { + nof_vrbs = nof_prbs; + } + uint32_t rb_start, l_crb; + srslte_ra_type2_from_riv(riv, &l_crb, &rb_start, nof_prbs, (uint32_t)nof_vrbs); + return {rb_start, rb_start + l_crb}; +} + +/******************************************************* + * Sched Params + *******************************************************/ + +void sched_cell_params_t::regs_deleter::operator()(srslte_regs_t* p) +{ + if (p != nullptr) { + srslte_regs_free(p); + delete p; + } +} + +bool sched_cell_params_t::set_cfg(uint32_t enb_cc_idx_, + const sched_interface::cell_cfg_t& cfg_, + const sched_interface::sched_args_t& sched_args) +{ + enb_cc_idx = enb_cc_idx_; + cfg = cfg_; + sched_cfg = &sched_args; + + // Basic cell config checks + if (cfg.si_window_ms == 0) { + Error("SCHED: Invalid si-window length 0 ms\n"); + return false; + } + + bool invalid_prach; + if (cfg.cell.nof_prb == 6) { + // PUCCH has to allow space for Msg3 + if (cfg.nrb_pucch > 1) { + srslte::console("Invalid PUCCH configuration: nrb_pucch=%d does not allow space for Msg3 transmission..\n", + cfg.nrb_pucch); + return false; + } + // PRACH has to fit within the PUSCH+PUCCH space + invalid_prach = cfg.prach_freq_offset + 6 > cfg.cell.nof_prb; + } else { + // PRACH has to fit within the PUSCH space + invalid_prach = (cfg.prach_freq_offset + 6) > (cfg.cell.nof_prb - cfg.nrb_pucch) or + ((int)cfg.prach_freq_offset < cfg.nrb_pucch); + } + if (invalid_prach) { + Error("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset); + srslte::console("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", + cfg.prach_freq_offset); + return false; + } + + // Set derived sched parameters + + // init regs + regs.reset(new srslte_regs_t{}); + if (srslte_regs_init(regs.get(), cfg.cell) != SRSLTE_SUCCESS) { + Error("Getting DCI locations\n"); + return false; + } + + // Compute Common locations for DCI for each CFI + for (uint32_t cfix = 0; cfix < SRSLTE_NOF_CFI; cfix++) { + generate_cce_location(regs.get(), &common_locations[cfix], cfix + 1); + } + if (common_locations[sched_cfg->max_nof_ctrl_symbols - 1].nof_loc[2] == 0) { + Error("SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n", + sched_cfg->max_nof_ctrl_symbols); + srslte::console( + "SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n", + sched_cfg->max_nof_ctrl_symbols); + return false; + } + + // Compute UE locations for RA-RNTI + for (uint32_t cfi = 0; cfi < 3; cfi++) { + for (uint32_t sf_idx = 0; sf_idx < 10; sf_idx++) { + generate_cce_location(regs.get(), &rar_locations[cfi][sf_idx], cfi + 1, sf_idx); + } + } + + // precompute nof cces in PDCCH for each CFI + for (uint32_t cfix = 0; cfix < nof_cce_table.size(); ++cfix) { + int ret = srslte_regs_pdcch_ncce(regs.get(), cfix + 1); + if (ret < 0) { + Error("SCHED: Failed to calculate the number of CCEs in the PDCCH\n"); + return false; + } + nof_cce_table[cfix] = (uint32_t)ret; + } + + P = srslte_ra_type0_P(cfg.cell.nof_prb); + nof_rbgs = srslte::ceil_div(cfg.cell.nof_prb, P); + + return true; +} + +void generate_cce_location(srslte_regs_t* regs_, + sched_dci_cce_t* location, + uint32_t cfi, + uint32_t sf_idx, + uint16_t rnti) +{ + *location = {}; + + srslte_dci_location_t loc[64]; + uint32_t nloc = 0; + if (rnti == 0) { + nloc = srslte_pdcch_common_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64); + } else { + nloc = srslte_pdcch_ue_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64, sf_idx, rnti); + } + + // Save to different format + for (uint32_t i = 0; i < nloc; i++) { + uint32_t l = loc[i].L; + location->cce_start[l][location->nof_loc[l]] = loc[i].ncce; + location->nof_loc[l]++; + } +} + +} // namespace srsenb diff --git a/srsenb/src/stack/mac/sched_interface_helpers.cc b/srsenb/src/stack/mac/sched_interface_helpers.cc deleted file mode 100644 index dceb9679c..000000000 --- a/srsenb/src/stack/mac/sched_interface_helpers.cc +++ /dev/null @@ -1,122 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2020 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. - * - */ - -#include "srsenb/hdr/stack/mac/sched_interface_helpers.h" -#include "srslte/mac/pdu.h" -#include "srslte/srslog/bundled/fmt/format.h" -#include - -namespace srsenb { - -using dl_sched_res_t = sched_interface::dl_sched_res_t; -using dl_sched_data_t = sched_interface::dl_sched_data_t; -using custom_mem_buffer = fmt::basic_memory_buffer; - -const char* to_string_short(srslte_dci_format_t dcifmt) -{ - switch (dcifmt) { - case SRSLTE_DCI_FORMAT0: - return "0"; - case SRSLTE_DCI_FORMAT1: - return "1"; - case SRSLTE_DCI_FORMAT1A: - return "1A"; - case SRSLTE_DCI_FORMAT1B: - return "1B"; - case SRSLTE_DCI_FORMAT2: - return "2"; - case SRSLTE_DCI_FORMAT2A: - return "2A"; - case SRSLTE_DCI_FORMAT2B: - return "2B"; - default: - return "unknown"; - } -} - -void fill_dl_cc_result_info(custom_mem_buffer& strbuf, const dl_sched_data_t& data) -{ - uint32_t first_ce = sched_interface::MAX_RLC_PDU_LIST; - for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) { - if (srslte::is_mac_ce(static_cast(data.pdu[i]->lcid))) { - first_ce = i; - break; - } - } - if (first_ce == sched_interface::MAX_RLC_PDU_LIST) { - return; - } - const char* prefix = strbuf.size() > 0 ? " | " : ""; - fmt::format_to(strbuf, "{}rnti={:0x}: [", prefix, data.dci.rnti); - bool ces_found = false; - for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) { - const auto& pdu = data.pdu[0][i]; - prefix = (ces_found) ? " | " : ""; - srslte::dl_sch_lcid lcid = static_cast(pdu.lcid); - if (srslte::is_mac_ce(lcid)) { - fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid)); - ces_found = true; - } - } - fmt::format_to(strbuf, "]"); -} - -void fill_dl_cc_result_debug(custom_mem_buffer& strbuf, const dl_sched_data_t& data) -{ - if (data.nof_pdu_elems[0] == 0 and data.nof_pdu_elems[1] == 0) { - return; - } - fmt::format_to(strbuf, - " > rnti={:0x}, tbs={}, f={}, mcs={}: [", - data.dci.rnti, - data.tbs[0], - to_string_short(data.dci.format), - data.dci.tb[0].mcs_idx); - for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; ++tb) { - for (uint32_t i = 0; i < data.nof_pdu_elems[tb]; ++i) { - const auto& pdu = data.pdu[tb][i]; - const char* prefix = (i == 0) ? "" : " | "; - srslte::dl_sch_lcid lcid = static_cast(pdu.lcid); - if (srslte::is_mac_ce(lcid)) { - fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid)); - } else { - fmt::format_to(strbuf, "{}MAC SDU lcid={}, tb={}, len={} B", prefix, pdu.lcid, tb, pdu.nbytes); - } - } - } - fmt::format_to(strbuf, "]\n"); -} - -void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result) -{ - if (log_h->get_level() < srslte::LOG_LEVEL_INFO) { - return; - } - custom_mem_buffer strbuf; - for (uint32_t i = 0; i < result.nof_data_elems; ++i) { - const dl_sched_data_t& data = result.data[i]; - if (log_h->get_level() == srslte::LOG_LEVEL_INFO) { - fill_dl_cc_result_info(strbuf, data); - } else if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) { - fill_dl_cc_result_debug(strbuf, data); - } - } - if (strbuf.size() != 0) { - if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) { - log_h->debug("SCHED: MAC LCID allocs cc=%d:\n%s", enb_cc_idx, fmt::to_string(strbuf).c_str()); - } else { - log_h->info("SCHED: MAC CE allocs cc=%d: %s", enb_cc_idx, fmt::to_string(strbuf).c_str()); - } - } -} - -} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index 9fa108a1f..82ac80c0c 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -13,6 +13,7 @@ #include #include "srsenb/hdr/stack/mac/sched.h" +#include "srsenb/hdr/stack/mac/sched_helpers.h" #include "srsenb/hdr/stack/mac/sched_ue.h" #include "srslte/common/log_helper.h" #include "srslte/common/logmap.h" @@ -31,7 +32,7 @@ namespace srsenb { namespace sched_utils { -//! Obtains TB size *in bytes* for a given MCS and N_{PRB} +/// Obtains TB size *in bytes* for a given MCS and nof allocated prbs uint32_t get_tbs_bytes(uint32_t mcs, uint32_t nof_alloc_prb, bool use_tbs_index_alt, bool is_ul) { int tbs_idx = srslte_ra_tbs_idx_from_mcs(mcs, use_tbs_index_alt, is_ul); @@ -574,7 +575,7 @@ int sched_ue::generate_format1(uint32_t pid, SRSLTE_MIN(sched_utils::count_prb_per_tb(*carriers[ue_cc_idx].get_cell_cfg(), user_mask), cell.nof_prb); uint32_t RB_start = prb_int.start(); dci->type2_alloc.riv = srslte_ra_type2_to_riv(L_crb, RB_start, cell.nof_prb); - dci->format = SRSLTE_DCI_FORMAT1A; + dci->format = SRSLTE_DCI_FORMAT1A; if (prb_int.length() != P * user_mask.count()) { // This happens if Type0 was using distributed allocation Warning("SCHED: Can't use distributed RA due to DCI size ambiguity\n"); @@ -599,7 +600,7 @@ int sched_ue::generate_format1(uint32_t pid, dci->pid = h->get_id(); dci->ue_cc_idx = ue_cc_idx; dci->tb[0].mcs_idx = (uint32_t)mcs; - dci->tb[0].rv = sched_utils::get_rvidx(h->nof_retx(0)); + dci->tb[0].rv = get_rvidx(h->nof_retx(0)); dci->tb[0].ndi = h->get_ndi(0); dci->tpc_pucch = carriers[ue_cc_idx].tpc_fsm.encode_pucch_tpc(); @@ -647,11 +648,8 @@ std::pair sched_ue::compute_mcs_and_tbs(uint32_t ue_cc_i (uint32_t)carriers[ue_cc_idx].fixed_mcs_dl, nof_alloc_prbs, cfg.use_tbs_index_alt, false); } - // If the number of prbs is not sufficient to fit minimum required bytes, increase the mcs - // NOTE: this may happen during ConRes CE tx when DL-CQI is still not available - while (tbs_bytes > 0 and (uint32_t) tbs_bytes < req_bytes.start() and mcs < 28) { - mcs++; - tbs_bytes = sched_utils::get_tbs_bytes((uint32_t)mcs, nof_alloc_prbs, cfg.use_tbs_index_alt, false); + if (tbs_bytes > 0 and (uint32_t) tbs_bytes < req_bytes.start() and mcs < 28) { + log_h->warning("SCHED: Could not get PRB allocation that avoids MAC CE or RLC SBR0 PDU segmentation\n"); } return {mcs, tbs_bytes}; @@ -712,7 +710,7 @@ int sched_ue::generate_format2a(uint32_t pid, /* Fill DCI TB dedicated fields */ if (tbs > 0 && tb_en[tb]) { dci->tb[tb].mcs_idx = (uint32_t)mcs; - dci->tb[tb].rv = sched_utils::get_rvidx(h->nof_retx(tb)); + dci->tb[tb].rv = get_rvidx(h->nof_retx(tb)); if (!SRSLTE_DCI_IS_TB_EN(dci->tb[tb])) { dci->tb[tb].rv = 2; } @@ -855,7 +853,7 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, alloc.set(alloc.start(), alloc.start() + 4); } } else if (tbs > 0) { - dci->tb.rv = sched_utils::get_rvidx(h->nof_retx(0)); + dci->tb.rv = get_rvidx(h->nof_retx(0)); if (!is_newtx && data->needs_pdcch) { dci->tb.mcs_idx = 28 + dci->tb.rv; } else { @@ -1330,7 +1328,7 @@ cc_sched_ue::cc_sched_ue(const sched_interface::ue_cfg_t& cfg_, // Generate allowed CCE locations for (int cfi = 0; cfi < 3; cfi++) { for (int sf_idx = 0; sf_idx < 10; sf_idx++) { - sched_utils::generate_cce_location(cell_params->regs.get(), &dci_locations[cfi][sf_idx], cfi + 1, sf_idx, rnti); + generate_cce_location(cell_params->regs.get(), &dci_locations[cfi][sf_idx], cfi + 1, sf_idx, rnti); } } } diff --git a/srsenb/test/mac/sched_test_common.cc b/srsenb/test/mac/sched_test_common.cc index 411127926..8bdd58d3e 100644 --- a/srsenb/test/mac/sched_test_common.cc +++ b/srsenb/test/mac/sched_test_common.cc @@ -12,6 +12,7 @@ #include "sched_test_common.h" #include "srsenb/hdr/stack/mac/sched.h" +#include "srsenb/hdr/stack/mac/sched_helpers.h" #include "srsenb/hdr/stack/upper/common_enb.h" #include "srslte/mac/pdu.h" @@ -211,7 +212,7 @@ int ue_ctxt_test::schedule_acks(cc_result result) ack_data.tb = 0; ack_data.pid = data.dci.pid; ack_data.ue_cc_idx = data.dci.ue_cc_idx; - uint32_t nof_retx = sched_utils::get_nof_retx(data.dci.tb[0].rv); // 0..3 + uint32_t nof_retx = srsenb::get_nof_retx(data.dci.tb[0].rv); // 0..3 ack_data.ack = randf() < sim_cfg.prob_dl_ack_mask[nof_retx % sim_cfg.prob_dl_ack_mask.size()]; pending_dl_acks.push(ack_data); @@ -230,7 +231,7 @@ int ue_ctxt_test::schedule_acks(cc_result result) ack_data.ue_cc_idx = pusch.dci.ue_cc_idx; ack_data.tb = 0; ack_data.pid = to_tx_ul(current_tti_rx).to_uint() % (FDD_HARQ_DELAY_DL_MS + FDD_HARQ_DELAY_UL_MS); - uint32_t nof_retx = sched_utils::get_nof_retx(pusch.dci.tb.rv); // 0..3 + uint32_t nof_retx = srsenb::get_nof_retx(pusch.dci.tb.rv); // 0..3 ack_data.ack = randf() < sim_cfg.prob_ul_ack_mask[nof_retx % sim_cfg.prob_ul_ack_mask.size()]; pending_ul_acks.push(ack_data); diff --git a/srsenb/test/mac/sched_ue_ded_test_suite.cc b/srsenb/test/mac/sched_ue_ded_test_suite.cc index a3c02441d..893f679ab 100644 --- a/srsenb/test/mac/sched_ue_ded_test_suite.cc +++ b/srsenb/test/mac/sched_ue_ded_test_suite.cc @@ -12,6 +12,7 @@ #include "sched_ue_ded_test_suite.h" #include "lib/include/srslte/mac/pdu.h" +#include "srsenb/hdr/stack/mac/sched_helpers.h" #include "srslte/common/test_common.h" namespace srsenb { @@ -72,14 +73,14 @@ int test_pdsch_grant(const sim_enb_ctxt_t& enb_ctxt, // TEST: DCI is consistent with current UE DL harq state auto& h = ue_ctxt.cc_list[pdsch.dci.ue_cc_idx].dl_harqs[pdsch.dci.pid]; - uint32_t nof_retx = sched_utils::get_nof_retx(pdsch.dci.tb[0].rv); // 0..3 + uint32_t nof_retx = get_nof_retx(pdsch.dci.tb[0].rv); // 0..3 if (h.nof_txs == 0 or h.ndi != pdsch.dci.tb[0].ndi) { // It is newtx CONDERROR(nof_retx != 0, "Invalid rv index for new tx\n"); CONDERROR(h.active, "DL newtx for already active DL harq pid=%d\n", h.pid); } else { // it is retx - CONDERROR(sched_utils::get_rvidx(h.nof_retxs + 1) != (uint32_t)pdsch.dci.tb[0].rv, "Invalid rv index for retx\n"); + CONDERROR(get_rvidx(h.nof_retxs + 1) != (uint32_t)pdsch.dci.tb[0].rv, "Invalid rv index for retx\n"); CONDERROR(not h.active, "retx for inactive dl harq pid=%d\n", h.pid); CONDERROR(to_tx_dl_ack(h.last_tti_rx) > tti_rx, "harq pid=%d reused too soon\n", h.pid); CONDERROR(h.nof_retxs + 1 > ue_ctxt.ue_cfg.maxharq_tx, @@ -184,7 +185,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& CONDERROR(pusch_ptr->dci.ue_cc_idx != (uint32_t)ue_cc_idx, "Inconsistent enb_cc_idx -> ue_cc_idx mapping\n"); // TEST: DCI is consistent with current UE UL harq state - uint32_t nof_retx = sched_utils::get_nof_retx(pusch_ptr->dci.tb.rv); // 0..3 + uint32_t nof_retx = get_nof_retx(pusch_ptr->dci.tb.rv); // 0..3 if (h.nof_txs == 0 or h.ndi != pusch_ptr->dci.tb.ndi) { // newtx @@ -204,8 +205,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& CONDERROR(pusch_ptr->dci.type2_alloc.riv != h.riv, "Non-adaptive retx must keep the same riv\n"); } } - CONDERROR(sched_utils::get_rvidx(h.nof_retxs + 1) != (uint32_t)pusch_ptr->dci.tb.rv, - "Invalid rv index for retx\n"); + CONDERROR(get_rvidx(h.nof_retxs + 1) != (uint32_t)pusch_ptr->dci.tb.rv, "Invalid rv index for retx\n"); CONDERROR(h.tbs != pusch_ptr->tbs, "TBS changed during HARQ retx\n"); CONDERROR(to_tx_ul(h.last_tti_rx) > sf_out.tti_rx, "UL harq pid=%d was reused too soon\n", h.pid); }