diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 4a0cbf4ea..e288098da 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -27,7 +27,8 @@ namespace srsenb { namespace sched_nr_impl { class sched_worker_manager; -} +class cell_sched; +} // namespace sched_nr_impl class ue_event_manager; class sched_result_manager; @@ -66,6 +67,9 @@ private: // management of Sched Result buffering std::unique_ptr pending_results; + + // management of cell resources + std::vector > cells; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h b/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h new file mode 100644 index 000000000..79fdb4fb9 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h @@ -0,0 +1,79 @@ +/** + * + * \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_BWP_H +#define SRSRAN_SCHED_NR_BWP_H + +#include "sched_nr_cfg.h" +#include "sched_nr_rb_grid.h" +#include "srsran/adt/pool/cached_alloc.h" + +namespace srsenb { +namespace sched_nr_impl { + +using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t; + +struct pending_rar_t { + uint16_t ra_rnti = 0; + tti_point prach_tti; + srsran::bounded_vector msg3_grant; +}; + +/// RAR/Msg3 scheduler +class ra_sched +{ +public: + explicit ra_sched(const sched_cell_params& cell_cfg_); + + int dl_rach_info(const dl_sched_rar_info_t& rar_info); + void run_slot(bwp_slot_allocator& slot_grid); + size_t empty() const { return pending_rars.empty(); } + +private: + alloc_result + allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc); + + const sched_cell_params* cell_cfg = nullptr; + srslog::basic_logger& logger; + + srsran::deque pending_rars; +}; + +class bwp_sched +{ +public: + explicit bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_); + + const sched_cell_params* cell_cfg; + const uint32_t bwp_id; + + // channel-specific schedulers + ra_sched ra; + + // Pending allocations + bwp_res_grid grid; +}; + +class cell_sched +{ +public: + srsran::bounded_vector bwps; + + explicit cell_sched(const sched_cell_params& cell_cfg_); + + const sched_cell_params* cfg; +}; + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_BWP_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 1bcf2d9ae..c12dd70af 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -33,6 +33,7 @@ using pucch_list_t = sched_nr_interface::pucch_list_t; using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; +using bwp_cfg_t = sched_nr_interface::bwp_cfg_t; struct sched_cell_params { const uint32_t cc; @@ -49,8 +50,51 @@ struct sched_params { explicit sched_params(const sched_cfg_t& sched_cfg_); }; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using rbgmask_t = srsran::bounded_bitset; + using pdcchmask_t = srsran::bounded_bitset; -using rbgmask_t = srsran::bounded_bitset; + +using pdcch_cce_pos_list = srsran::bounded_vector; +using bwp_cce_pos_list = std::array, SRSRAN_NOF_SF_X_FRAME>; +void get_dci_locs(const srsran_coreset_t& coreset, + const srsran_search_space_t& search_space, + uint16_t rnti, + bwp_cce_pos_list& cce_locs); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using ue_cfg_t = sched_nr_interface::ue_cfg_t; +using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; + +class ue_cfg_extended : public ue_cfg_t +{ +public: + struct search_space_params { + srsran_search_space_t* cfg = nullptr; + }; + struct coreset_params { + srsran_coreset_t* cfg = nullptr; + std::vector ss_list; + bwp_cce_pos_list cce_positions; + }; + struct bwp_params { + std::vector search_spaces; + std::vector coresets; + }; + struct cc_params { + srsran::bounded_vector bwps; + }; + + uint16_t rnti; + std::vector cc_params; + + ue_cfg_extended() = default; + explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct resource_guard { public: @@ -92,44 +136,6 @@ private: bool flag = false; }; -using pdcch_cce_pos_list = srsran::bounded_vector; -using bwp_cce_pos_list = std::array, SRSRAN_NOF_SF_X_FRAME>; -void get_dci_locs(const srsran_coreset_t& coreset, - const srsran_search_space_t& search_space, - uint16_t rnti, - bwp_cce_pos_list& cce_locs); - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -using ue_cfg_t = sched_nr_interface::ue_cfg_t; -using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t; - -class ue_cfg_extended : public ue_cfg_t -{ -public: - struct search_space_params { - srsran_search_space_t* cfg = nullptr; - }; - struct coreset_params { - srsran_coreset_t* cfg = nullptr; - std::vector ss_list; - bwp_cce_pos_list cce_positions; - }; - struct bwp_params { - std::vector search_spaces; - std::vector coresets; - }; - struct cc_params { - srsran::bounded_vector bwps; - }; - - uint16_t rnti; - std::vector cc_params; - - ue_cfg_extended() = default; - explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg); -}; - } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 2b82bf83e..4060766b5 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -26,7 +26,7 @@ namespace srsenb { const static size_t SCHED_NR_MAX_CARRIERS = 4; const static uint16_t SCHED_NR_INVALID_RNTI = 0; -const static size_t SCHED_NR_MAX_NOF_RBGS = 25; +const static size_t SCHED_NR_MAX_NOF_RBGS = 17; const static size_t SCHED_NR_MAX_TB = 1; const static size_t SCHED_NR_MAX_HARQ = 16; const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2; @@ -52,14 +52,17 @@ public: using pusch_td_res_alloc_list = srsran::bounded_vector; struct bwp_cfg_t { - uint32_t bwp_id = 1; - uint32_t start_rb = 0; - uint32_t rb_width = 100; + uint32_t bwp_id = 1; + uint32_t start_rb = 0; + uint32_t rb_width = 100; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; std::array, SRSRAN_UE_DL_NR_MAX_NOF_CORESET> coresets; }; struct cell_cfg_t { + uint32_t rar_window_size; uint32_t nof_prb = 100; uint32_t nof_rbg = 25; srsran_tdd_config_nr_t tdd = {}; @@ -82,6 +85,16 @@ public: srsran::phy_cfg_nr_t phy_cfg = {}; }; + ////// RACH ////// + + struct dl_sched_rar_info_t { + uint32_t preamble_idx; + uint32_t ta_cmd; + uint16_t temp_crnti; + uint32_t msg3_size; + uint32_t prach_tti; + }; + ///// Sched Result ///// using dl_sched_t = mac_interface_phy_nr::dl_sched_t; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h index f7fe40bda..ba39e671b 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h @@ -25,7 +25,7 @@ namespace sched_nr_impl { using coreset_bitmap = srsran::bounded_bitset; -enum class pdcch_grant_type_t { sib, dl_data, ul_data }; +enum class pdcch_grant_type_t { sib, rar, dl_data, ul_data }; class slot_ue; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h similarity index 70% rename from srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h rename to srsenb/hdr/stack/mac/nr/sched_nr_phy.h index 071d779f3..ac032bcdf 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_phy.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_SCHED_NR_PHY_HELPERS_H -#define SRSRAN_SCHED_NR_PHY_HELPERS_H +#ifndef SRSRAN_SCHED_NR_PHY_H +#define SRSRAN_SCHED_NR_PHY_H #include "sched_nr_cfg.h" @@ -21,6 +21,16 @@ namespace sched_nr_impl { uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2); uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2); +using pdsch_bitmap = srsran::bounded_bitset; +using pusch_bitmap = srsran::bounded_bitset; +using rbg_interval = srsran::interval; + +rbg_interval find_empty_rbg_interval(const pdsch_bitmap& bitmap, uint32_t max_nof_rbgs); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci); + class slot_ue; void fill_dci_ue_cfg(const slot_ue& ue, const rbgmask_t& rbgmask, @@ -44,4 +54,4 @@ pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbg } // namespace sched_nr_impl } // namespace srsenb -#endif // SRSRAN_SCHED_NR_PHY_HELPERS_H +#endif // SRSRAN_SCHED_NR_PHY_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h index 92a15f54c..a925aaf35 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h @@ -17,13 +17,15 @@ #include "lib/include/srsran/adt/circular_array.h" #include "sched_nr_interface.h" #include "sched_nr_pdcch.h" +#include "sched_nr_phy.h" #include "sched_nr_ue.h" namespace srsenb { namespace sched_nr_impl { -using pdsch_bitmap = srsran::bounded_bitset<25, true>; -using pusch_bitmap = srsran::bounded_bitset<25, true>; +struct pending_rar_t; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = srsran::bounded_vector; @@ -54,35 +56,35 @@ struct bwp_res_grid { const sched_cell_params& cell_params() const { return *cell_cfg; } const bwp_cfg_t& bwp_cfg() const { return cell_cfg->cell_cfg.bwps[id() - 1]; } -private: - uint32_t bwp_id; const sched_cell_params* cell_cfg = nullptr; +private: + uint32_t bwp_id; + srsran::bounded_vector slots; }; -struct cell_res_grid { - const sched_cell_params* cell_cfg = nullptr; - srsran::bounded_vector bwps; - - explicit cell_res_grid(const sched_cell_params& cell_cfg); -}; - -class slot_bwp_sched +class bwp_slot_allocator { public: - explicit slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_); + explicit bwp_slot_allocator(bwp_res_grid& bwp_grid_); + void new_slot(tti_point pdcch_tti_) { pdcch_tti = pdcch_tti_; } + + alloc_result alloc_rar(uint32_t aggr_idx, const pending_rar_t& rar, rbg_interval interv, uint32_t max_nof_grants); alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask); alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask); + tti_point get_pdcch_tti() const { return pdcch_tti; } + const bwp_res_grid& res_grid() const { return bwp_grid; } + const sched_cell_params& cfg; private: srslog::basic_logger& logger; bwp_res_grid& bwp_grid; - tti_point tti_rx; + tti_point pdcch_tti; }; } // namespace sched_nr_impl diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 0b4d4c45f..86c2af5ed 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_SCHED_NR_WORKER_H #define SRSRAN_SCHED_NR_WORKER_H +#include "sched_nr_bwp.h" #include "sched_nr_cfg.h" #include "sched_nr_rb_grid.h" #include "sched_nr_ue.h" @@ -32,9 +33,7 @@ using ul_sched_t = sched_nr_interface::ul_sched_t; class slot_cc_worker { public: - explicit slot_cc_worker(const sched_cell_params& cell_params, cell_res_grid& phy_grid) : - cfg(cell_params), res_grid(0, phy_grid) - {} + explicit slot_cc_worker(cell_sched& sched); void start(tti_point tti_rx_, ue_map_t& ue_db_); void run(); @@ -46,9 +45,10 @@ private: void alloc_ul_ues(); const sched_cell_params& cfg; + cell_sched& cell; - tti_point tti_rx; - slot_bwp_sched res_grid; + tti_point tti_rx; + bwp_slot_allocator bwp_alloc; srsran::static_circular_map slot_ues; }; @@ -80,9 +80,9 @@ private: ue_map_t& ue_db; std::mutex ue_db_mutex; - std::vector > slot_ctxts; + std::vector > slot_worker_ctxts; - srsran::bounded_vector cell_grid_list; + srsran::bounded_vector cell_grid_list; slot_worker_ctxt& get_sf(tti_point tti_rx); }; diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 2f18bc2c3..d91ec20ae 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -6,6 +6,7 @@ # the distribution. # -set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy_helpers.cc) +set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc + sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy.cc sched_nr_bwp.cc) add_library(srsgnb_mac STATIC ${SOURCES}) diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index bd9022ff2..c25ca4bfe 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" #include "srsran/common/thread_pool.h" diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc new file mode 100644 index 000000000..ac59dcbd9 --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_bwp.cc @@ -0,0 +1,157 @@ +/** + * + * \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. + * + */ + +#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" +#include "srsran/common/standard_streams.h" +#include "srsran/common/string_helpers.h" + +namespace srsenb { +namespace sched_nr_impl { + +ra_sched::ra_sched(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_), logger(srslog::fetch_basic_logger("MAC")) +{} + +alloc_result +ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) +{ + const uint32_t rar_aggr_level = 2; + auto& pdsch_bitmap = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_rbgs; + + alloc_result ret = alloc_result::other_cause; + for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) { + ret = alloc_result::invalid_coderate; + for (uint32_t nrbg = 1; nrbg < cell_cfg->cell_cfg.nof_rbg and ret == alloc_result::invalid_coderate; ++nrbg) { + rbg_interval rbg_interv = find_empty_rbg_interval(pdsch_bitmap, nrbg); + if (rbg_interv.length() == nrbg) { + ret = slot_grid.alloc_rar(rar_aggr_level, rar, rbg_interv, nof_grants_alloc); + } else { + ret = alloc_result::no_sch_space; + } + } + + // If allocation was not successful because there were not enough RBGs, try allocating fewer Msg3 grants + if (ret != alloc_result::invalid_coderate and ret != alloc_result::no_sch_space) { + break; + } + } + if (ret != alloc_result::success) { + logger.info("SCHED: RAR allocation for L=%d was postponed. Cause=%s", rar_aggr_level, to_string(ret)); + } + return ret; +} + +void ra_sched::run_slot(bwp_slot_allocator& slot_grid) +{ + static const uint32_t PRACH_RAR_OFFSET = 3; + tti_point pdcch_tti = slot_grid.get_pdcch_tti(); + + for (auto it = pending_rars.begin(); it != pending_rars.end();) { + pending_rar_t& rar = *it; + + // In case of RAR outside RAR window: + // - if window has passed, discard RAR + // - if window hasn't started, stop loop, as RARs are ordered by TTI + tti_interval rar_window{rar.prach_tti + PRACH_RAR_OFFSET, + rar.prach_tti + PRACH_RAR_OFFSET + cell_cfg->cell_cfg.rar_window_size}; + if (not rar_window.contains(pdcch_tti)) { + if (pdcch_tti >= rar_window.stop()) { + fmt::memory_buffer str_buffer; + fmt::format_to(str_buffer, + "SCHED: Could not transmit RAR within the window (RA={}, Window={}, RAR={}", + rar.prach_tti, + rar_window, + pdcch_tti); + srsran::console("%s\n", srsran::to_c_str(str_buffer)); + logger.warning("%s", srsran::to_c_str(str_buffer)); + it = pending_rars.erase(it); + continue; + } + return; + } + + // Try to schedule DCI + RBGs for RAR Grant + uint32_t nof_rar_allocs = 0; + alloc_result ret = allocate_pending_rar(slot_grid, rar, nof_rar_allocs); + + if (ret == alloc_result::success) { + // If RAR allocation was successful: + // - in case all Msg3 grants were allocated, remove pending RAR, and continue with following RAR + // - otherwise, erase only Msg3 grants that were allocated, and stop iteration + + if (nof_rar_allocs == rar.msg3_grant.size()) { + it = pending_rars.erase(it); + } else { + std::copy(rar.msg3_grant.begin() + nof_rar_allocs, rar.msg3_grant.end(), rar.msg3_grant.begin()); + rar.msg3_grant.resize(rar.msg3_grant.size() - nof_rar_allocs); + break; + } + } else { + // If RAR allocation was not successful: + // - in case of unavailable PDCCH space, try next pending RAR allocation + // - otherwise, stop iteration + if (ret != alloc_result::no_cch_space) { + break; + } + ++it; + } + } +} + +int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info) +{ + logger.info("SCHED: New PRACH tti=%d, preamble=%d, temp_crnti=0x%x, ta_cmd=%d, msg3_size=%d", + rar_info.prach_tti, + rar_info.preamble_idx, + rar_info.temp_crnti, + rar_info.ta_cmd, + rar_info.msg3_size); + + // RA-RNTI = 1 + t_id + f_id + // t_id = index of first subframe specified by PRACH (0<=t_id<10) + // f_id = index of the PRACH within subframe, in ascending order of freq domain (0<=f_id<6) (for FDD, f_id=0) + uint16_t ra_rnti = 1 + (uint16_t)(rar_info.prach_tti % 10u); + + // find pending rar with same RA-RNTI + for (pending_rar_t& r : pending_rars) { + if (r.prach_tti.to_uint() == rar_info.prach_tti and ra_rnti == r.ra_rnti) { + if (r.msg3_grant.size() >= sched_interface::MAX_RAR_LIST) { + logger.warning("PRACH ignored, as the the maximum number of RAR grants per tti has been reached"); + return SRSRAN_ERROR; + } + r.msg3_grant.push_back(rar_info); + return SRSRAN_SUCCESS; + } + } + + // create new RAR + pending_rar_t p; + p.ra_rnti = ra_rnti; + p.prach_tti = tti_point{rar_info.prach_tti}; + p.msg3_grant.push_back(rar_info); + pending_rars.push_back(p); + + return SRSRAN_SUCCESS; +} + +bwp_sched::bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : + cell_cfg(&cell_cfg_), bwp_id(bwp_id_), ra(cell_cfg_), grid(cell_cfg_, bwp_id_) +{} + +cell_sched::cell_sched(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_) +{ + for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) { + bwps.emplace_back(cell_cfg_, bwp_id); + } +} + +} // namespace sched_nr_impl +} // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index ce61367c5..99fe100ba 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_phy.cc similarity index 84% rename from srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc rename to srsenb/src/stack/mac/nr/sched_nr_phy.cc index 779f7c041..e8403abe0 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_phy.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" @@ -82,6 +82,38 @@ int bitmap_to_riv(const rbgmask_t& bitmap, uint32_t cell_nof_prb) return srsran_ra_nr_type1_riv(cell_nof_prb, interv.start(), interv.length()); } +rbg_interval find_empty_rbg_interval(const pdsch_bitmap& in_mask, uint32_t max_size) +{ + rbg_interval max_interv; + + for (size_t n = 0; n < in_mask.size();) { + int pos = in_mask.find_lowest(n, in_mask.size(), false); + if (pos < 0) { + break; + } + + size_t max_pos = std::min(in_mask.size(), (size_t)pos + max_size); + int pos2 = in_mask.find_lowest(pos + 1, max_pos, true); + rbg_interval interv(pos, pos2 < 0 ? max_pos : pos2); + if (interv.length() >= max_size) { + return interv; + } + if (interv.length() > max_interv.length()) { + max_interv = interv; + } + n = interv.stop(); + } + return max_interv; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci) +{ + dci.mcs = 5; + return true; +} + template void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cell_params& cc_cfg, DciDlOrUl& 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 cd70a26ed..57a0a0caa 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_rb_grid.cc @@ -11,7 +11,7 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h" namespace srsenb { namespace sched_nr_impl { @@ -49,20 +49,68 @@ bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) } } -cell_res_grid::cell_res_grid(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_) -{ - for (uint32_t bwp_id = 0; bwp_id < cell_cfg->cell_cfg.bwps.size(); ++bwp_id) { - bwps.emplace_back(cell_cfg_, bwp_id); - } -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -slot_bwp_sched::slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_) : - logger(srslog::fetch_basic_logger("MAC")), cfg(*phy_grid_.cell_cfg), bwp_grid(phy_grid_.bwps[bwp_id]) +bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) : + logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cell_cfg), bwp_grid(bwp_grid_) {} -alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) +alloc_result bwp_slot_allocator::alloc_rar(uint32_t aggr_idx, + const srsenb::sched_nr_impl::pending_rar_t& rar, + srsenb::sched_nr_impl::rbg_interval interv, + uint32_t nof_grants) +{ + static const uint32_t msg3_nof_prbs = 3; + + bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_tti]; + bwp_slot_grid& bwp_msg3_slot = bwp_grid[pdcch_tti + 4]; + + if (bwp_pdcch_slot.dl_pdcchs.full()) { + logger.warning("SCHED: Maximum number of DL allocations reached"); + return alloc_result::no_grant_space; + } + + // Check DL RB collision + rbgmask_t& pdsch_mask = bwp_pdcch_slot.dl_rbgs; + rbgmask_t dl_mask(pdsch_mask.size()); + dl_mask.fill(interv.start(), interv.stop()); + if ((pdsch_mask & dl_mask).any()) { + logger.debug("SCHED: Provided RBG mask collides with allocation previously made."); + return alloc_result::sch_collision; + } + + // Check Msg3 RB collision + uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants; + uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.bwp_cfg().rb_width, false)); + rbg_interval msg3_rbgs = find_empty_rbg_interval(bwp_msg3_slot.ul_rbgs, total_ul_nof_rbgs); + if (msg3_rbgs.length() < total_ul_nof_rbgs) { + logger.debug("SCHED: No space in PUSCH for Msg3."); + return alloc_result::sch_collision; + } + + // Find PDCCH position + const uint32_t coreset_id = 0; + if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::rar, aggr_idx, nullptr)) { + // Could not find space in PDCCH + logger.debug("SCHED: No space in PDCCH for DL tx."); + return alloc_result::no_cch_space; + } + + // Generate DCI for RAR + pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back(); + if (not fill_dci_rar(interv, bwp_grid.cell_params(), pdcch.dci)) { + // Cancel on-going PDCCH allocation + bwp_pdcch_slot.coresets[coreset_id].rem_last_dci(); + return alloc_result::invalid_coderate; + } + + // RAR allocation successful. + bwp_pdcch_slot.dl_rbgs.fill(interv.start(), interv.stop()); + + return alloc_result::success; +} + +alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) { if (ue.h_dl == nullptr) { logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti); @@ -121,7 +169,7 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask) return alloc_result::success; } -alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) +alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask) { if (ue.h_ul == nullptr) { logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti); diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index f07fa9368..2895ada6b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -15,6 +15,10 @@ namespace srsenb { namespace sched_nr_impl { +slot_cc_worker::slot_cc_worker(cell_sched& cc_sched) : + cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid) +{} + /// Called at the beginning of TTI in a locked context, to reserve available UE resources void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) { @@ -34,15 +38,18 @@ void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db) } // UE acquired successfully for scheduling in this {tti, cc} } - - tti_rx = tti_rx_; } void slot_cc_worker::run() { srsran_assert(running(), "scheduler worker::run() called for non-active worker"); - // Prioritize PDCCH scheduling for DL and UL data in a RoundRobin fashion + bwp_alloc.new_slot(tti_rx + TX_ENB_DELAY); + + // Allocate pending RARs + cell.bwps[0].ra.run_slot(bwp_alloc); + + // Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion if ((tti_rx.to_uint() & 0x1u) == 0) { alloc_dl_ues(); alloc_ul_ues(); @@ -74,8 +81,9 @@ void slot_cc_worker::alloc_dl_ues() rbgmask_t dlmask(cfg.cell_cfg.nof_rbg); dlmask.fill(0, dlmask.size(), true); - res_grid.alloc_pdsch(ue, dlmask); + bwp_alloc.alloc_pdsch(ue, dlmask); } + void slot_cc_worker::alloc_ul_ues() { if (slot_ues.empty()) { @@ -88,7 +96,7 @@ void slot_cc_worker::alloc_ul_ues() rbgmask_t ulmask(cfg.cell_cfg.nof_rbg); ulmask.fill(0, ulmask.size(), true); - res_grid.alloc_pusch(ue, ulmask); + bwp_alloc.alloc_pusch(ue, ulmask); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -100,12 +108,12 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& } // Note: For now, we only allow parallelism at the sector level - slot_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); + slot_worker_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes); for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) { - slot_ctxts[i].reset(new slot_worker_ctxt()); - slot_ctxts[i]->workers.reserve(cfg.cells.size()); + slot_worker_ctxts[i].reset(new slot_worker_ctxt()); + slot_worker_ctxts[i]->workers.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { - slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], cell_grid_list[cc]); + slot_worker_ctxts[i]->workers.emplace_back(cell_grid_list[cc]); } } } @@ -114,7 +122,7 @@ sched_worker_manager::~sched_worker_manager() = default; sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx) { - return *slot_ctxts[tti_rx.to_uint() % slot_ctxts.size()]; + return *slot_worker_ctxts[tti_rx.to_uint() % slot_worker_ctxts.size()]; } void sched_worker_manager::start_slot(tti_point tti_rx, srsran::move_callback process_feedback) @@ -189,7 +197,7 @@ void sched_worker_manager::release_slot(tti_point tti_rx_) bool sched_worker_manager::get_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res) { - auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0][pdcch_tti]; + auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0].grid[pdcch_tti]; dl_res.pdcch_dl = pdcch_bwp_slot.dl_pdcchs; dl_res.pdcch_ul = pdcch_bwp_slot.ul_pdcchs;