From 949c34112ee3b0039505047a1f03fd2f60c06ecc Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 8 Dec 2021 11:33:51 +0000 Subject: [PATCH] nr,gnb,sched: implement pusch allocator and fix prb grant allocation when UEs are using common SS --- srsgnb/hdr/stack/mac/sched_nr_cfg.h | 3 + .../hdr/stack/mac/sched_nr_grant_allocator.h | 20 +- srsgnb/hdr/stack/mac/sched_nr_helpers.h | 26 +-- .../hdr/stack/mac/sched_nr_interface_utils.h | 6 + srsgnb/hdr/stack/mac/sched_nr_pdcch.h | 4 + .../mac/{sched_nr_pdsch.h => sched_nr_sch.h} | 53 ++++- srsgnb/hdr/stack/mac/sched_nr_ue.h | 2 + srsgnb/src/stack/mac/CMakeLists.txt | 2 +- .../src/stack/mac/sched_nr_grant_allocator.cc | 211 +++++++----------- srsgnb/src/stack/mac/sched_nr_helpers.cc | 78 +------ .../{sched_nr_pdsch.cc => sched_nr_sch.cc} | 121 +++++++++- srsgnb/src/stack/mac/sched_nr_signalling.cc | 26 --- srsgnb/src/stack/mac/sched_nr_time_rr.cc | 33 +-- srsgnb/src/stack/mac/sched_nr_ue.cc | 26 ++- srsgnb/src/stack/mac/test/CMakeLists.txt | 6 +- .../stack/mac/test/sched_nr_cfg_generators.h | 20 +- .../src/stack/mac/test/sched_nr_rar_test.cc | 2 +- ..._nr_pdsch_test.cc => sched_nr_sch_test.cc} | 75 ++++++- 18 files changed, 414 insertions(+), 300 deletions(-) rename srsgnb/hdr/stack/mac/{sched_nr_pdsch.h => sched_nr_sch.h} (57%) rename srsgnb/src/stack/mac/{sched_nr_pdsch.cc => sched_nr_sch.cc} (56%) rename srsgnb/src/stack/mac/test/{sched_nr_pdsch_test.cc => sched_nr_sch_test.cc} (83%) diff --git a/srsgnb/hdr/stack/mac/sched_nr_cfg.h b/srsgnb/hdr/stack/mac/sched_nr_cfg.h index 5d5a077cb..49c25ca7d 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_cfg.h +++ b/srsgnb/hdr/stack/mac/sched_nr_cfg.h @@ -188,6 +188,9 @@ public: int fixed_pdsch_mcs() const { return bwp_cfg->sched_cfg.fixed_dl_mcs; } int fixed_pusch_mcs() const { return bwp_cfg->sched_cfg.fixed_ul_mcs; } + srsran::bounded_vector + find_ss_candidates(uint32_t aggr_idx, srsran::const_span supported_dci_fmts) const; + private: const ue_cfg_t* cfg_ = nullptr; const bwp_params_t* bwp_cfg = nullptr; diff --git a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h index 6a4b0affc..0d2dca71d 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h +++ b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h @@ -17,7 +17,7 @@ #include "sched_nr_helpers.h" #include "sched_nr_interface.h" #include "sched_nr_pdcch.h" -#include "sched_nr_pdsch.h" +#include "sched_nr_sch.h" #include "sched_nr_ue.h" #include "srsenb/hdr/stack/mac/sched_common.h" @@ -45,12 +45,12 @@ struct bwp_slot_grid { uint32_t slot_idx = 0; const bwp_params_t* cfg = nullptr; - bwp_rb_bitmap ul_prbs; dl_sched_res_t dl; ul_sched_t ul; harq_ack_list_t pending_acks; bwp_pdcch_allocator pdcchs; /// slot PDCCH resource allocator pdsch_allocator pdschs; /// slot PDSCH resource allocator + pusch_allocator puschs; /// slot PUSCH resource allocator srsran::unique_pool_ptr rar_softbuffer; @@ -96,8 +96,8 @@ public: uint32_t aggr_idx, prb_interval interv, srsran::const_span pending_rars); - alloc_result alloc_pdsch(slot_ue& ue, prb_grant dl_grant); - alloc_result alloc_pusch(slot_ue& ue, prb_grant dl_mask); + alloc_result alloc_pdsch(slot_ue& ue, uint32_t ss_id, const prb_grant& dl_grant); + alloc_result alloc_pusch(slot_ue& ue, const prb_grant& grant); slot_point get_pdcch_tti() const { return pdcch_slot; } slot_point get_tti_rx() const { return pdcch_slot - TX_ENB_DELAY; } @@ -105,13 +105,17 @@ public: const bwp_slot_grid& tx_slot_grid() const { return bwp_grid[pdcch_slot]; } bwp_slot_grid& tx_slot_grid() { return bwp_grid[pdcch_slot]; } + prb_bitmap occupied_dl_prbs(slot_point sl_tx, uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const + { + return bwp_grid[sl_tx].pdschs.occupied_prbs(ss_id, dci_fmt); + } + const prb_bitmap& occupied_ul_prbs(slot_point sl_tx) const { return bwp_grid[sl_tx].puschs.occupied_prbs(); } + srslog::basic_logger& logger; const bwp_params_t& cfg; private: - alloc_result - verify_pdsch_space(bwp_slot_grid& pdsch_grid, bwp_slot_grid& pdcch_grid, bwp_slot_grid* uci_grid = nullptr) const; - alloc_result verify_pusch_space(bwp_slot_grid& pusch_grid) const; + alloc_result verify_uci_space(const bwp_slot_grid& uci_grid) const; alloc_result verify_ue_cfg(const ue_carrier_params_t& ue_cfg, harq_proc* harq) const; bwp_res_grid& bwp_grid; @@ -120,6 +124,8 @@ private: slot_ue_map_t& slot_ues; }; +prb_grant find_optimal_dl_grant(bwp_slot_allocator& slot_alloc, const slot_ue& ue, uint32_t ss_id); + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsgnb/hdr/stack/mac/sched_nr_helpers.h b/srsgnb/hdr/stack/mac/sched_nr_helpers.h index 588fd33d6..fdfddeeae 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_helpers.h +++ b/srsgnb/hdr/stack/mac/sched_nr_helpers.h @@ -48,35 +48,13 @@ inline bool is_rnti_type_valid_in_search_space(srsran_rnti_type_t rnti_type, srs return false; } -/// In case of Common SearchSpace, not all PRBs might be available -void reduce_to_dl_coreset_bw(const bwp_params_t& bwp_cfg, - uint32_t ss_id, - srsran_dci_format_nr_t dci_fmt, - prb_grant& grant); - -bool fill_dci_sib(prb_interval interv, - uint32_t sib_idx, - uint32_t si_ntx, - const bwp_params_t& bwp_cfg, - srsran_dci_dl_nr_t& dci); - -bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci); - bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& dci); /// Generate PDCCH DL DCI fields -void fill_dl_dci_ue_fields(const slot_ue& ue, - const bwp_params_t& bwp_cfg, - uint32_t ss_id, - srsran_dci_location_t dci_pos, - srsran_dci_dl_nr_t& dci); +void fill_dl_dci_ue_fields(const slot_ue& ue, srsran_dci_dl_nr_t& dci); /// Generate PDCCH UL DCI fields -void fill_ul_dci_ue_fields(const slot_ue& ue, - const bwp_params_t& bwp_cfg, - uint32_t ss_id, - srsran_dci_location_t dci_pos, - srsran_dci_ul_nr_t& dci); +void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_ul_nr_t& dci); /// Log UE state for slot being scheduled void log_sched_slot_ues(srslog::basic_logger& logger, diff --git a/srsgnb/hdr/stack/mac/sched_nr_interface_utils.h b/srsgnb/hdr/stack/mac/sched_nr_interface_utils.h index f07135b8f..781094331 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_interface_utils.h +++ b/srsgnb/hdr/stack/mac/sched_nr_interface_utils.h @@ -31,6 +31,12 @@ view_active_search_spaces(const srsran_pdcch_cfg_nr_t& pdcch) return srsran::split_optional_span{pdcch.search_space, pdcch.search_space_present}; } +inline bool contains_dci_format(const srsran_search_space_t& ss, srsran_dci_format_nr_t dci_fmt) +{ + auto is_dci_fmt = [dci_fmt](const srsran_dci_format_nr_t& f) { return f == dci_fmt; }; + return std::any_of(&ss.formats[0], &ss.formats[ss.nof_formats], is_dci_fmt); +} + //////////////////////////////////// CORESET Helpers //////////////////////////////////////////// /// Get a range of active coresets in a PDCCH configuration diff --git a/srsgnb/hdr/stack/mac/sched_nr_pdcch.h b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h index 48daac54c..a8ed68343 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_pdcch.h +++ b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h @@ -24,6 +24,10 @@ namespace srsenb { namespace sched_nr_impl { +/// Helper function to fill DCI with BWP params +void fill_dci_from_cfg(const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci); +void fill_dci_from_cfg(const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& dci); + using coreset_bitmap = srsran::bounded_bitset; class coreset_region diff --git a/srsgnb/hdr/stack/mac/sched_nr_pdsch.h b/srsgnb/hdr/stack/mac/sched_nr_sch.h similarity index 57% rename from srsgnb/hdr/stack/mac/sched_nr_pdsch.h rename to srsgnb/hdr/stack/mac/sched_nr_sch.h index 60cee7130..9378257f9 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_pdsch.h +++ b/srsgnb/hdr/stack/mac/sched_nr_sch.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_SCHED_NR_PDSCH_H -#define SRSRAN_SCHED_NR_PDSCH_H +#ifndef SRSRAN_SCHED_NR_SCH_H +#define SRSRAN_SCHED_NR_SCH_H #include "srsenb/hdr/stack/mac/sched_common.h" #include "srsgnb/hdr/stack/mac/sched_nr_cfg.h" @@ -76,8 +76,55 @@ private: bwp_rb_bitmap dl_prbs; }; +using pusch_alloc_result = srsran::expected; + +class pusch_allocator +{ +public: + pusch_allocator(const bwp_params_t& cfg_, uint32_t sl_index, pusch_list_t& pusch_lst); + + /// Get available RBGs for allocation + const rbg_bitmap& occupied_rbgs() const { return ul_prbs.rbgs(); } + /// Get available PRBs for allocation + const prb_bitmap& occupied_prbs() const { return ul_prbs.prbs(); } + + alloc_result has_grant_space(uint32_t nof_grants = 1, bool verbose = true) const; + + /// Checks if provided PDSCH arguments produce a valid PDSCH that fits into cell PRBs and does not collide with other + /// allocations + alloc_result is_grant_valid(srsran_search_space_type_t ss_type, const prb_grant& grant, bool verbose = true) const; + + /** + * @brief Tries to allocate PDSCH grant. Ensures that there are no collisions with other previous PDSCH allocations + * @param dci_ctx[in] PDCCH DL DCI context information + * @param grant[in] PRBs used for the grant + * @param pdcch[out] DCI where frequency_assignment and time_assignment get stored. + * @return pdsch_t object pointer in case of success. alloc_result error code in case of failure + */ + pusch_alloc_result alloc_pusch(const srsran_dci_ctx_t& dci_ctx, const prb_grant& grant, srsran_dci_ul_nr_t& dci); + + /** + * @brief Allocates PDSCH grant without verifying for collisions. Useful to avoid redundant is_grant_valid(...) calls + * @param dci_ctx[in] PDCCH DL DCI context information + * @param grant[in] PRBs used for the grant + * @param pdcch[out] DCI where frequency and time assignment get stored. + */ + pusch_t& alloc_pusch_unchecked(const prb_grant& grant, srsran_dci_ul_nr_t& dci); + + void cancel_last_pusch(); + + void reset(); + +private: + const bwp_params_t& bwp_cfg; + uint32_t slot_idx = 0; + + pusch_list_t& puschs; + bwp_rb_bitmap ul_prbs; +}; + } // namespace sched_nr_impl } // namespace srsenb -#endif // SRSRAN_SCHED_NR_PDSCH_H +#endif // SRSRAN_SCHED_NR_SCH_H diff --git a/srsgnb/hdr/stack/mac/sched_nr_ue.h b/srsgnb/hdr/stack/mac/sched_nr_ue.h index 59389d2a0..82ecf94dd 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_ue.h +++ b/srsgnb/hdr/stack/mac/sched_nr_ue.h @@ -171,6 +171,8 @@ public: dl_harq_proc* find_empty_dl_harq() { return ue->harq_ent.find_empty_dl_harq(); } ul_harq_proc* find_empty_ul_harq() { return ue->harq_ent.find_empty_ul_harq(); } + int find_ss_id(srsran_dci_format_nr_t dci_fmt) const; + void build_pdu(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu) { ue->pdu_builder.alloc_subpdus(rem_bytes, pdu); diff --git a/srsgnb/src/stack/mac/CMakeLists.txt b/srsgnb/src/stack/mac/CMakeLists.txt index eb21b0dd7..9dbcb085e 100644 --- a/srsgnb/src/stack/mac/CMakeLists.txt +++ b/srsgnb/src/stack/mac/CMakeLists.txt @@ -14,7 +14,7 @@ set(SOURCES mac_nr.cc sched_nr_grant_allocator.cc sched_nr_harq.cc sched_nr_pdcch.cc - sched_nr_pdsch.cc + sched_nr_sch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc diff --git a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index 2722c2a93..d3fbcc6d6 100644 --- a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -76,11 +76,11 @@ candidate_ss_list_t find_ss(const srsran_pdcch_cfg_nr_t& pdcch, //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bwp_slot_grid::bwp_slot_grid(const bwp_params_t& bwp_cfg_, uint32_t slot_idx_) : - ul_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1), slot_idx(slot_idx_), cfg(&bwp_cfg_), pdcchs(bwp_cfg_, slot_idx_, dl.phy.pdcch_dl, dl.phy.pdcch_ul), pdschs(bwp_cfg_, slot_idx_, dl.phy.pdsch), + puschs(bwp_cfg_, slot_idx_, ul.pusch), rar_softbuffer(harq_softbuffer_pool::get_instance().get_tx(bwp_cfg_.cfg.rb_width)) {} @@ -88,13 +88,12 @@ void bwp_slot_grid::reset() { pdcchs.reset(); pdschs.reset(); - ul_prbs.reset(); + puschs.reset(); dl.phy.ssb.clear(); dl.phy.nzp_csi_rs.clear(); dl.data.clear(); dl.rar.clear(); dl.sib_idxs.clear(); - ul.pusch.clear(); ul.pucch.clear(); pending_acks.clear(); } @@ -122,36 +121,29 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_slot]; - alloc_result ret = verify_pdsch_space(bwp_pdcch_slot, bwp_pdcch_slot); - if (ret != alloc_result::success) { - return ret; - } // Verify there is space in PDSCH - ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss_id, dci_fmt, prbs); + alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss_id, dci_fmt, prbs); if (ret != alloc_result::success) { return ret; } + // Allocate PDCCH auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_si_pdcch(ss_id, aggr_idx); if (pdcch_result.is_error()) { - logger.warning("SCHED: Cannot allocate SIB1 due to lack of PDCCH space."); + logger.warning("SCHED: Cannot allocate SIB due to lack of PDCCH space."); return pdcch_result.error(); } - pdcch_dl_t pdcch = *pdcch_result.value(); - - // SI allocation successful. + pdcch_dl_t& pdcch = *pdcch_result.value(); // Allocate PDSCH pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch.dci.ctx, prbs, pdcch.dci); // Generate DCI for SIB pdcch.dci_cfg.coreset0_bw = srsran_coreset_get_bw(&cfg.cfg.pdcch.coreset[0]); - if (not fill_dci_sib(prbs, si_idx, si_ntx, *bwp_grid.cfg, pdcch.dci)) { - // Cancel on-going PDCCH allocation - bwp_pdcch_slot.pdcchs.cancel_last_pdcch(); - return alloc_result::invalid_coderate; - } + pdcch.dci.mcs = 5; + pdcch.dci.rv = 0; + pdcch.dci.sii = si_idx == 0 ? 0 : 1; // Generate PDSCH srsran_slot_cfg_t slot_cfg; @@ -189,25 +181,6 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t if (ret != alloc_result::success) { return ret; } - - // Verify there is space in PUSCH - ret = verify_pusch_space(bwp_msg3_slot); - if (ret != alloc_result::success) { - return ret; - } - ret = verify_pdsch_space(bwp_pdcch_slot, bwp_pdcch_slot); - if (ret != alloc_result::success) { - return ret; - } - if (not bwp_pdcch_slot.dl.phy.ssb.empty()) { - // TODO: support concurrent PDSCH and SSB - logger.debug("SCHED: skipping RAR allocation. Cause: concurrent PDSCH and SSB not yet supported"); - return alloc_result::no_sch_space; - } - if (pending_rachs.size() > bwp_pdcch_slot.dl.rar.capacity() - bwp_pdcch_slot.dl.rar.size()) { - logger.error("SCHED: Trying to allocate too many Msg3 grants in a single slot (%zd)", pending_rachs.size()); - return alloc_result::invalid_grant_params; - } for (auto& rach : pending_rachs) { auto ue_it = slot_ues.find(rach.temp_crnti); if (ue_it == slot_ues.end()) { @@ -216,47 +189,53 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t return alloc_result::no_rnti_opportunity; } } + srsran_sanity_check(not bwp_pdcch_slot.dl.rar.full(), "The #RARs should be below #PDSCHs"); + if (not bwp_pdcch_slot.dl.phy.ssb.empty()) { + // TODO: support concurrent PDSCH and SSB + logger.debug("SCHED: skipping RAR allocation. Cause: concurrent PDSCH and SSB not yet supported"); + return alloc_result::no_sch_space; + } + // Verify there is space in PUSCH for Msg3s + ret = bwp_msg3_slot.puschs.has_grant_space(pending_rachs.size()); + if (ret != alloc_result::success) { + return ret; + } // Check Msg3 RB collision - uint32_t total_ul_nof_prbs = msg3_nof_prbs * pending_rachs.size(); - uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.nof_prbs(), false)); - prb_interval msg3_rbs = find_empty_interval_of_length(bwp_msg3_slot.ul_prbs.prbs(), total_ul_nof_rbgs); - if (msg3_rbs.length() < total_ul_nof_rbgs) { + uint32_t total_msg3_nof_prbs = msg3_nof_prbs * pending_rachs.size(); + prb_interval all_msg3_rbs = + find_empty_interval_of_length(bwp_msg3_slot.puschs.occupied_prbs(), total_msg3_nof_prbs, 0); + if (all_msg3_rbs.length() < total_msg3_nof_prbs) { logger.debug("SCHED: No space in PUSCH for Msg3."); return alloc_result::sch_collision; } - // Find PDCCH position + // Allocate PDCCH position auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_rar_pdcch(ra_rnti, aggr_idx); if (pdcch_result.is_error()) { // Could not find space in PDCCH return pdcch_result.error(); } - - // RAR allocation successful. - pdcch_dl_t* pdcch = pdcch_result.value(); - auto& phy_cfg = slot_ues[pending_rachs[0].temp_crnti]->phy(); - pdcch->dci_cfg = phy_cfg.get_dci_cfg(); + pdcch_dl_t& pdcch = *pdcch_result.value(); // Allocate PDSCH - pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch->dci.ctx, interv, pdcch->dci); + pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch.dci.ctx, interv, pdcch.dci); // Generate DCI for RAR with given RA-RNTI - if (not fill_dci_rar(interv, ra_rnti, *bwp_grid.cfg, pdcch->dci)) { - // Cancel on-going PDCCH allocation - bwp_pdcch_slot.pdcchs.cancel_last_pdcch(); - return alloc_result::invalid_coderate; - } + auto& phy_cfg = slot_ues[pending_rachs[0].temp_crnti]->phy(); + pdcch.dci_cfg = phy_cfg.get_dci_cfg(); + pdcch.dci.mcs = 5; + // Generate RAR PDSCH // TODO: Properly fill Msg3 grants srsran_slot_cfg_t slot_cfg; slot_cfg.idx = pdcch_slot.to_uint(); - bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch->dci, pdsch.sch); + bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); srsran_assert(success, "Error converting DCI to grant"); pdsch.sch.grant.tb[0].softbuffer.tx = bwp_pdcch_slot.rar_softbuffer->get(); // Generate Msg3 grants in PUSCH - uint32_t last_msg3 = msg3_rbs.start(); + uint32_t last_msg3 = all_msg3_rbs.start(); const int mcs = 0, max_harq_msg3_retx = 4; slot_cfg.idx = msg3_slot.to_uint(); bwp_pdcch_slot.dl.rar.emplace_back(); @@ -276,48 +255,35 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t fill_dci_msg3(ue, *bwp_grid.cfg, rar_grant.msg3_dci); // Generate PUSCH - bwp_msg3_slot.ul.pusch.emplace_back(); - pusch_t& pusch = bwp_msg3_slot.ul.pusch.back(); + pusch_t& pusch = bwp_msg3_slot.puschs.alloc_pusch_unchecked(msg3_interv, rar_grant.msg3_dci); success = ue->phy().get_pusch_cfg(slot_cfg, rar_grant.msg3_dci, pusch.sch); srsran_assert(success, "Error converting DCI to PUSCH grant"); pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get(); ue.h_ul->set_tbs(pusch.sch.grant.tb[0].tbs); } - bwp_msg3_slot.ul_prbs.add(msg3_rbs); return alloc_result::success; } // ue is the UE (1 only) that will be allocated // func computes the grant allocation for this UE -alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant) +alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, uint32_t ss_id, const prb_grant& dl_grant) { - static const uint32_t aggr_idx = 2; - static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; - static const std::array dci_fmt_list{srsran_dci_format_nr_1_0}; + static const uint32_t aggr_idx = 2; + static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; + static const srsran_rnti_type_t rnti_type = srsran_rnti_type_c; bwp_slot_grid& bwp_pdcch_slot = bwp_grid[ue.pdcch_slot]; bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_slot]; bwp_slot_grid& bwp_uci_slot = bwp_grid[ue.uci_slot]; // UCI : UL control info - // Choose SearchSpace + DCI format - srsran_rnti_type_t rnti_type = srsran_rnti_type_c; - // Choose the ss_id the highest number of candidates - candidate_ss_list_t ss_candidates = find_ss(ue->phy().pdcch, aggr_idx, rnti_type, dci_fmt_list); - if (ss_candidates.empty()) { - // Could not find space in PDCCH - logger.warning("SCHED: No PDCCH candidates for any of the rnti=0x%x search spaces", ue->rnti); - return alloc_result::no_cch_space; - } - const srsran_search_space_t& ss = *ss_candidates[0]; - // Verify there is space in PDSCH - alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss.id, dci_fmt, dl_grant); + alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss_id, dci_fmt, dl_grant); if (ret != alloc_result::success) { return ret; } - alloc_result result = verify_pdsch_space(bwp_pdsch_slot, bwp_pdcch_slot, &bwp_uci_slot); + alloc_result result = verify_uci_space(bwp_uci_slot); if (result != alloc_result::success) { return result; } @@ -335,13 +301,11 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant) // TODO // Find space and allocate PDCCH - auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_dl_pdcch(rnti_type, ss.id, aggr_idx, ue.cfg()); + auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_dl_pdcch(rnti_type, ss_id, aggr_idx, ue.cfg()); if (pdcch_result.is_error()) { // Could not find space in PDCCH return pdcch_result.error(); } - - // DL allocation successful. pdcch_dl_t& pdcch = *pdcch_result.value(); // Allocate PDSCH @@ -361,7 +325,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant) const static float max_R = 0.93; while (true) { // Generate PDCCH - fill_dl_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch.dci.ctx.location, pdcch.dci); + fill_dl_dci_ue_fields(ue, pdcch.dci); pdcch.dci.pucch_resource = 0; pdcch.dci.dai = std::count_if(bwp_uci_slot.pending_acks.begin(), bwp_uci_slot.pending_acks.end(), @@ -407,28 +371,21 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant) return alloc_result::success; } -alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) +alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const prb_grant& ul_grant) { static const uint32_t aggr_idx = 2; static const std::array dci_fmt_list{srsran_dci_format_nr_0_1, srsran_dci_format_nr_0_0}; + static const srsran_rnti_type_t rnti_type = srsran_rnti_type_c; - auto& bwp_pdcch_slot = bwp_grid[ue.pdcch_slot]; - auto& bwp_pusch_slot = bwp_grid[ue.pusch_slot]; - alloc_result ret = verify_pusch_space(bwp_pusch_slot); - if (ret != alloc_result::success) { - return ret; - } - ret = verify_ue_cfg(ue.cfg(), ue.h_ul); + auto& bwp_pdcch_slot = bwp_grid[ue.pdcch_slot]; + auto& bwp_pusch_slot = bwp_grid[ue.pusch_slot]; + + alloc_result ret = verify_ue_cfg(ue.cfg(), ue.h_ul); if (ret != alloc_result::success) { return ret; } - pdcch_ul_list_t& pdcchs = bwp_pdcch_slot.dl.phy.pdcch_ul; - if (bwp_pusch_slot.ul_prbs.collides(ul_grant)) { - return alloc_result::sch_collision; - } // Choose SearchSpace + DCI format - srsran_rnti_type_t rnti_type = srsran_rnti_type_c; candidate_ss_list_t ss_candidates = find_ss(ue->phy().pdcch, aggr_idx, rnti_type, dci_fmt_list); if (ss_candidates.empty()) { // Could not find space in PDCCH @@ -437,15 +394,23 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) } const srsran_search_space_t& ss = *ss_candidates[0]; + // Verify if PUSCH allocation is valid + ret = bwp_pusch_slot.puschs.is_grant_valid(ss.type, ul_grant); + if (ret != alloc_result::success) { + return ret; + } + auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_ul_pdcch(ss.id, aggr_idx, ue.cfg()); if (pdcch_result.is_error()) { // Could not find space in PDCCH - logger.debug("Could not find PDCCH space for rnti=0x%x PUSCH allocation", ue->rnti); return pdcch_result.error(); } - pdcch_ul_t* pdcch = pdcch_result.value(); // Allocation Successful + pdcch_ul_t& pdcch = *pdcch_result.value(); + + // Allocate PUSCH + pusch_t& pusch = bwp_pusch_slot.puschs.alloc_pusch_unchecked(ul_grant, pdcch.dci); if (ue.h_ul->empty()) { int mcs = ue->fixed_pusch_mcs(); @@ -456,17 +421,15 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) srsran_assert(success, "Failed to allocate UL HARQ retx"); } - // Generate PDCCH - fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch->dci.ctx.location, pdcch->dci); - pdcch->dci_cfg = ue->phy().get_dci_cfg(); - // Generate PUSCH - bwp_pusch_slot.ul_prbs |= ul_grant; - bwp_pusch_slot.ul.pusch.emplace_back(); - pusch_t& pusch = bwp_pusch_slot.ul.pusch.back(); + // Generate PDCCH content + fill_ul_dci_ue_fields(ue, pdcch.dci); + pdcch.dci_cfg = ue->phy().get_dci_cfg(); + + // Generate PUSCH content srsran_slot_cfg_t slot_cfg; slot_cfg.idx = ue.pusch_slot.to_uint(); pusch.pid = ue.h_ul->pid; - bool success = ue->phy().get_pusch_cfg(slot_cfg, pdcch->dci, pusch.sch); + bool success = ue->phy().get_pusch_cfg(slot_cfg, pdcch.dci, pusch.sch); srsran_assert(success, "Error converting DCI to PUSCH grant"); pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get(); if (ue.h_ul->nof_retx() == 0) { @@ -478,35 +441,10 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) return alloc_result::success; } -alloc_result bwp_slot_allocator::verify_pdsch_space(bwp_slot_grid& pdsch_grid, - bwp_slot_grid& pdcch_grid, - bwp_slot_grid* uci_grid) const -{ - if (not pdsch_grid.is_dl() or not pdcch_grid.is_dl()) { - logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", pdsch_grid.slot_idx); - return alloc_result::no_sch_space; - } - if (pdsch_grid.dl.phy.pdsch.full()) { - logger.warning("SCHED: Maximum number of DL PDSCH grants reached"); - return alloc_result::no_sch_space; - } - if (uci_grid != nullptr) { - if (uci_grid->pending_acks.full()) { - logger.warning("SCHED: No space for ACK."); - return alloc_result::no_grant_space; - } - } - return alloc_result::success; -} - -alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid) const +alloc_result bwp_slot_allocator::verify_uci_space(const bwp_slot_grid& uci_grid) const { - if (not pusch_grid.is_ul()) { - logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", pusch_grid.slot_idx); - return alloc_result::no_sch_space; - } - if (pusch_grid.ul.pusch.full()) { - logger.warning("SCHED: Maximum number of PUSCH allocations reached"); + if (uci_grid.pending_acks.full()) { + logger.warning("SCHED: No space for ACK."); return alloc_result::no_grant_space; } return alloc_result::success; @@ -526,5 +464,20 @@ alloc_result bwp_slot_allocator::verify_ue_cfg(const ue_carrier_params_t& ue_cfg return alloc_result::success; } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +prb_grant find_optimal_dl_grant(bwp_slot_allocator& slot_alloc, const slot_ue& ue, uint32_t ss_id) +{ + static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; // TODO: Support more DCI formats + + const bwp_slot_grid& sl_grid = slot_alloc.res_grid()[ue.pdsch_slot]; + + prb_bitmap used_prb_mask = sl_grid.pdschs.occupied_prbs(ss_id, dci_fmt); + + prb_interval prb_interv = find_empty_interval_of_length(used_prb_mask, used_prb_mask.size(), 0); + + return prb_interv; +} + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsgnb/src/stack/mac/sched_nr_helpers.cc b/srsgnb/src/stack/mac/sched_nr_helpers.cc index 66e9ca250..57f1a7cab 100644 --- a/srsgnb/src/stack/mac/sched_nr_helpers.cc +++ b/srsgnb/src/stack/mac/sched_nr_helpers.cc @@ -21,41 +21,6 @@ namespace sched_nr_impl { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void reduce_to_dl_coreset_bw(const bwp_params_t& bwp_cfg, - uint32_t ss_id, - srsran_dci_format_nr_t dci_fmt, - prb_grant& grant) -{ - const srsran_search_space_t& ss = - dci_fmt == srsran_dci_format_nr_rar ? bwp_cfg.cfg.pdcch.ra_search_space : bwp_cfg.cfg.pdcch.search_space[ss_id]; - if (not SRSRAN_SEARCH_SPACE_IS_COMMON(ss.type)) { - return; - } - uint32_t rb_start = 0, nof_prbs = bwp_cfg.nof_prb(); - if (dci_fmt == srsran_dci_format_nr_1_0) { - rb_start = srsran_coreset_start_rb(&bwp_cfg.cfg.pdcch.coreset[ss.coreset_id]); - } - if (ss.coreset_id == 0) { - nof_prbs = srsran_coreset_get_bw(&bwp_cfg.cfg.pdcch.coreset[0]); - } - grant &= prb_interval{rb_start, rb_start + nof_prbs}; -} - -void fill_dci_common(const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci) -{ - dci.bwp_id = bwp_cfg.bwp_id; - dci.cc_id = bwp_cfg.cc; - dci.tpc = 1; - dci.coreset0_bw = bwp_cfg.cfg.pdcch.coreset_present[0] ? srsran_coreset_get_bw(&bwp_cfg.cfg.pdcch.coreset[0]) : 0; -} - -void fill_dci_common(const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& dci) -{ - dci.bwp_id = bwp_cfg.bwp_id; - dci.cc_id = bwp_cfg.cc; - dci.tpc = 1; -} - template void fill_dci_harq(const slot_ue& ue, DciDlOrUl& dci) { @@ -70,25 +35,6 @@ void fill_dci_harq(const slot_ue& ue, DciDlOrUl& dci) dci.rv = rv_idx[h->nof_retx() % 4]; } -void fill_dci_grant(const bwp_params_t& bwp_cfg, const prb_grant& grant, srsran_dci_ul_nr_t& dci) -{ - dci.time_domain_assigment = 0; - if (grant.is_alloc_type0()) { - dci.freq_domain_assigment = grant.rbgs().to_uint64(); - } else { - uint32_t nof_prb = bwp_cfg.nof_prb(); - dci.freq_domain_assigment = srsran_ra_nr_type1_riv(nof_prb, grant.prbs().start(), grant.prbs().length()); - } -} - -bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci) -{ - dci.mcs = 5; - // TODO: Fill - - return true; -} - bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& msg3_dci) { // Fill DCI context @@ -103,18 +49,17 @@ bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul } // Fill DCI content - fill_dci_common(bwp_cfg, msg3_dci); + fill_dci_from_cfg(bwp_cfg, msg3_dci); + msg3_dci.time_domain_assigment = 0; + uint32_t nof_prb = bwp_cfg.nof_prb(); + msg3_dci.freq_domain_assigment = + srsran_ra_nr_type1_riv(nof_prb, ue.h_ul->prbs().prbs().start(), ue.h_ul->prbs().prbs().length()); fill_dci_harq(ue, msg3_dci); - fill_dci_grant(bwp_cfg, ue.h_ul->prbs(), msg3_dci); return true; } -void fill_dl_dci_ue_fields(const slot_ue& ue, - const bwp_params_t& bwp_cfg, - uint32_t ss_id, - srsran_dci_location_t dci_pos, - srsran_dci_dl_nr_t& dci) +void fill_dl_dci_ue_fields(const slot_ue& ue, srsran_dci_dl_nr_t& dci) { fill_dci_harq(ue, dci); if (dci.ctx.format == srsran_dci_format_nr_1_0) { @@ -124,18 +69,9 @@ void fill_dl_dci_ue_fields(const slot_ue& ue, } } -void fill_ul_dci_ue_fields(const slot_ue& ue, - const bwp_params_t& bwp_cfg, - uint32_t ss_id, - srsran_dci_location_t dci_pos, - srsran_dci_ul_nr_t& dci) +void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_ul_nr_t& dci) { - bool ret = ue->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(bwp_cfg, dci); fill_dci_harq(ue, dci); - fill_dci_grant(bwp_cfg, ue.h_ul->prbs(), dci); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/srsgnb/src/stack/mac/sched_nr_pdsch.cc b/srsgnb/src/stack/mac/sched_nr_sch.cc similarity index 56% rename from srsgnb/src/stack/mac/sched_nr_pdsch.cc rename to srsgnb/src/stack/mac/sched_nr_sch.cc index b5e0300e3..2a9e937ca 100644 --- a/srsgnb/src/stack/mac/sched_nr_pdsch.cc +++ b/srsgnb/src/stack/mac/sched_nr_sch.cc @@ -10,7 +10,7 @@ * */ -#include "srsgnb/hdr/stack/mac/sched_nr_pdsch.h" +#include "srsgnb/hdr/stack/mac/sched_nr_sch.h" #include "srsran/common/string_helpers.h" namespace srsenb { @@ -56,7 +56,7 @@ alloc_result pdsch_allocator::is_grant_valid(uint32_t ss_id, // No space in Scheduler PDSCH output list if (pdschs.full()) { - log_alloc_failure(bwp_cfg.logger.warning, ss_id, "SearchSpace has not been configured."); + log_alloc_failure(bwp_cfg.logger.warning, ss_id, "Maximum number of PDSCHs={} reached.", pdschs.size()); return alloc_result::no_sch_space; } @@ -68,7 +68,7 @@ alloc_result pdsch_allocator::is_grant_valid(uint32_t ss_id, return alloc_result::invalid_grant_params; } - if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss_id)) { + if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss->type)) { // In case of common SearchSpaces, the PRBs must be contiguous if (grant.is_alloc_type0()) { log_alloc_failure(bwp_cfg.logger.warning, ss_id, "AllocType0 not allowed in common SearchSpace."); @@ -142,5 +142,120 @@ void pdsch_allocator::cancel_last_pdsch() pdschs.pop_back(); } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +void log_pusch_alloc_failure(srslog::log_channel& log_ch, const char* cause_fmt, Args&&... args) +{ + if (not log_ch.enabled()) { + return; + } + + // Log allocation failure + fmt::memory_buffer fmtbuf; + fmt::format_to(fmtbuf, "SCHED: Failure to allocate PUSCH. Cause: "); + fmt::format_to(fmtbuf, cause_fmt, std::forward(args)...); + log_ch("%s", srsran::to_c_str(fmtbuf)); +} + +pusch_allocator::pusch_allocator(const bwp_params_t& cfg_, uint32_t sl_index, pusch_list_t& pusch_lst) : + bwp_cfg(cfg_), + slot_idx(sl_index), + puschs(pusch_lst), + ul_prbs(bwp_cfg.cfg.rb_width, bwp_cfg.cfg.start_rb, bwp_cfg.cfg.pdsch.rbg_size_cfg_1) +{} + +void pusch_allocator::reset() +{ + puschs.clear(); + ul_prbs.reset(); +} + +alloc_result pusch_allocator::has_grant_space(uint32_t nof_grants, bool verbose) const +{ + // UL must be active in given slot + if (not bwp_cfg.slots[slot_idx].is_ul) { + if (verbose) { + log_pusch_alloc_failure(bwp_cfg.logger.error, "UL is disabled for slot={}", slot_idx); + } + return alloc_result::no_sch_space; + } + + // No space in Scheduler PDSCH output list + if (puschs.size() + nof_grants > puschs.capacity()) { + if (verbose) { + log_pusch_alloc_failure(bwp_cfg.logger.warning, "Maximum number of PUSCHs={} reached.", puschs.capacity()); + } + return alloc_result::no_sch_space; + } + + return alloc_result::success; +} + +alloc_result +pusch_allocator::is_grant_valid(srsran_search_space_type_t ss_type, const prb_grant& grant, bool verbose) const +{ + alloc_result ret = has_grant_space(1, verbose); + if (ret != alloc_result::success) { + return ret; + } + + if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss_type)) { + // In case of common SearchSpaces, the PRBs must be contiguous + if (grant.is_alloc_type0()) { + log_pusch_alloc_failure(bwp_cfg.logger.warning, "AllocType0 not allowed in common SearchSpace."); + return alloc_result::invalid_grant_params; + } + } + + // Grant PRBs do not collide with previous PDSCH allocations + if (ul_prbs.collides(grant)) { + if (verbose) { + log_pusch_alloc_failure(bwp_cfg.logger.debug, "SCHED: Provided UL PRB mask collides with previous allocations."); + } + return alloc_result::sch_collision; + } + + return alloc_result::success; +} + +pusch_alloc_result +pusch_allocator::alloc_pusch(const srsran_dci_ctx_t& dci_ctx, const prb_grant& grant, srsran_dci_ul_nr_t& dci) +{ + alloc_result code = is_grant_valid(dci_ctx.ss_type, grant); + if (code != alloc_result::success) { + return code; + } + + return {&alloc_pusch_unchecked(grant, dci)}; +} + +pusch_t& pusch_allocator::alloc_pusch_unchecked(const prb_grant& grant, srsran_dci_ul_nr_t& out_dci) +{ + // Create new PUSCH entry in output PUSCH list + puschs.emplace_back(); + pusch_t& pusch = puschs.back(); + + // Register allocated PRBs in accumulated bitmap + ul_prbs |= grant; + + // Fill DCI with PUSCH freq/time allocation information + out_dci.time_domain_assigment = 0; + if (grant.is_alloc_type0()) { + out_dci.freq_domain_assigment = grant.rbgs().to_uint64(); + } else { + uint32_t nof_prb = bwp_cfg.nof_prb(); + out_dci.freq_domain_assigment = srsran_ra_nr_type1_riv(nof_prb, grant.prbs().start(), grant.prbs().length()); + } + + return pusch; +} + +void pusch_allocator::cancel_last_pusch() +{ + srsran_assert(not puschs.empty(), "Trying to abort PUSCH allocation that does not exist"); + puschs.pop_back(); +} + } // namespace sched_nr_impl } // namespace srsenb \ No newline at end of file diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index c0e9f27f3..1e84b79b3 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -102,32 +102,6 @@ void sched_dl_signalling(bwp_slot_allocator& bwp_alloc) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool fill_dci_sib(prb_interval interv, - uint32_t sib_id, - uint32_t si_ntx, - const bwp_params_t& bwp_cfg, - srsran_dci_dl_nr_t& dci) -{ - dci.mcs = 5; - dci.ctx.format = srsran_dci_format_nr_1_0; - dci.ctx.ss_type = srsran_search_space_type_common_0; - dci.ctx.rnti_type = srsran_rnti_type_si; - dci.ctx.rnti = SRSRAN_SIRNTI; - dci.ctx.coreset_id = 0; - dci.ctx.coreset_start_rb = bwp_cfg.cfg.pdcch.coreset[0].offset_rb; - dci.coreset0_bw = srsran_coreset_get_bw(&bwp_cfg.cfg.pdcch.coreset[0]); - dci.freq_domain_assigment = - srsran_ra_nr_type1_riv(srsran_coreset_get_bw(&bwp_cfg.cfg.pdcch.coreset[0]), interv.start(), interv.length()); - dci.time_domain_assigment = 0; - dci.tpc = 1; - dci.bwp_id = bwp_cfg.bwp_id; - dci.cc_id = bwp_cfg.cc; - dci.rv = 0; - dci.sii = sib_id == 0 ? 0 : 1; - - return true; -} - si_sched::si_sched(const bwp_params_t& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) { diff --git a/srsgnb/src/stack/mac/sched_nr_time_rr.cc b/srsgnb/src/stack/mac/sched_nr_time_rr.cc index 965dba181..0d05cd0d8 100644 --- a/srsgnb/src/stack/mac/sched_nr_time_rr.cc +++ b/srsgnb/src/stack/mac/sched_nr_time_rr.cc @@ -19,7 +19,7 @@ namespace sched_nr_impl { * @brief Algorithm to select next UE to allocate in a time-domain RR fashion * @param ue_db map of "slot_ue" * @param rr_count starting index to select next UE - * @param p callable that returns true if UE allocation was successful + * @param p callable with signature "bool(slot_ue&)" that returns true if UE allocation was successful * @return true if a UE was allocated */ template @@ -45,28 +45,35 @@ bool round_robin_apply(slot_ue_map_t& ue_db, uint32_t rr_count, Predicate p) void sched_nr_time_rr::sched_dl_users(slot_ue_map_t& ue_db, bwp_slot_allocator& slot_alloc) { // Start with retxs - if (round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), [&slot_alloc](slot_ue& ue) { - if (ue.h_dl != nullptr and ue.h_dl->has_pending_retx(slot_alloc.get_tti_rx())) { - alloc_result res = slot_alloc.alloc_pdsch(ue, ue.h_dl->prbs()); - if (res == alloc_result::success) { - return true; - } - } - return false; - })) { + auto retx_ue_function = [&slot_alloc](slot_ue& ue) { + if (ue.h_dl != nullptr and ue.h_dl->has_pending_retx(slot_alloc.get_tti_rx())) { + alloc_result res = slot_alloc.alloc_pdsch(ue, ue.find_ss_id(srsran_dci_format_nr_1_0), ue.h_dl->prbs()); + if (res == alloc_result::success) { + return true; + } + } + return false; + }; + if (round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), retx_ue_function)) { return; } // Move on to new txs - round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), [&slot_alloc](slot_ue& ue) { + auto newtx_ue_function = [&slot_alloc](slot_ue& ue) { if (ue.dl_bytes > 0 and ue.h_dl != nullptr and ue.h_dl->empty()) { - alloc_result res = slot_alloc.alloc_pdsch(ue, prb_interval{0, slot_alloc.cfg.cfg.rb_width}); + int ss_id = ue.find_ss_id(srsran_dci_format_nr_1_0); + if (ss_id < 0) { + return false; + } + prb_grant prbs = find_optimal_dl_grant(slot_alloc, ue, ss_id); + alloc_result res = slot_alloc.alloc_pdsch(ue, ss_id, prbs); if (res == alloc_result::success) { return true; } } return false; - }); + }; + round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), newtx_ue_function); } void sched_nr_time_rr::sched_ul_users(slot_ue_map_t& ue_db, bwp_slot_allocator& slot_alloc) diff --git a/srsgnb/src/stack/mac/sched_nr_ue.cc b/srsgnb/src/stack/mac/sched_nr_ue.cc index ba7431de4..5e734b70c 100644 --- a/srsgnb/src/stack/mac/sched_nr_ue.cc +++ b/srsgnb/src/stack/mac/sched_nr_ue.cc @@ -11,7 +11,7 @@ */ #include "srsgnb/hdr/stack/mac/sched_nr_ue.h" -#include "srsgnb/hdr/stack/mac/sched_nr_pdcch.h" +#include "srsgnb/hdr/stack/mac/sched_nr_helpers.h" #include "srsran/common/string_helpers.h" #include "srsran/mac/mac_sch_pdu_nr.h" @@ -83,6 +83,30 @@ slot_ue::slot_ue(ue_carrier& ue_, slot_point slot_tx_, uint32_t dl_pending_bytes } } +int slot_ue::find_ss_id(srsran_dci_format_nr_t dci_fmt) const +{ + static const uint32_t aggr_idx = 2; // TODO: Make it dynamic + static const srsran_rnti_type_t rnti_type = srsran_rnti_type_c; // TODO: Use TC-RNTI for Msg4 + + auto active_ss_lst = view_active_search_spaces(cfg().phy().pdcch); + + for (const srsran_search_space_t& ss : active_ss_lst) { + // Prioritize UE-dedicated SearchSpaces + if (ss.type == srsran_search_space_type_ue and ss.nof_candidates[aggr_idx] > 0 and + contains_dci_format(ss, dci_fmt) and is_rnti_type_valid_in_search_space(rnti_type, ss.type)) { + return ss.id; + } + } + // Search Common SearchSpaces + for (const srsran_search_space_t& ss : active_ss_lst) { + if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss.type) and ss.nof_candidates[aggr_idx] > 0 and + contains_dci_format(ss, dci_fmt) and is_rnti_type_valid_in_search_space(rnti_type, ss.type)) { + return ss.id; + } + } + return -1; +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ue_carrier::ue_carrier(uint16_t rnti_, diff --git a/srsgnb/src/stack/mac/test/CMakeLists.txt b/srsgnb/src/stack/mac/test/CMakeLists.txt index ebe92e9de..8edb0ccd4 100644 --- a/srsgnb/src/stack/mac/test/CMakeLists.txt +++ b/srsgnb/src/stack/mac/test/CMakeLists.txt @@ -30,9 +30,9 @@ add_executable(sched_nr_pdcch_test sched_nr_pdcch_test.cc) target_link_libraries(sched_nr_pdcch_test srsgnb_mac sched_nr_test_suite srsran_common) add_nr_test(sched_nr_pdcch_test sched_nr_pdcch_test) -add_executable(sched_nr_pdsch_test sched_nr_pdsch_test.cc) -target_link_libraries(sched_nr_pdsch_test srsgnb_mac sched_nr_test_suite srsran_common) -add_nr_test(sched_nr_pdsch_test sched_nr_pdsch_test) +add_executable(sched_nr_sch_test sched_nr_sch_test.cc) +target_link_libraries(sched_nr_sch_test srsgnb_mac sched_nr_test_suite srsran_common) +add_nr_test(sched_nr_sch_test sched_nr_sch_test) add_executable(sched_nr_rar_test sched_nr_rar_test.cc) target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common) diff --git a/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h index 216e99040..87e459fa1 100644 --- a/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h +++ b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h @@ -123,15 +123,17 @@ inline sched_nr_interface::ue_cfg_t get_default_ue_cfg( inline sched_nr_interface::cell_cfg_t get_default_sa_cell_cfg_common() { - sched_nr_interface::cell_cfg_t cell_cfg = get_default_cell_cfg(); - cell_cfg.bwps[0].pdcch.coreset_present[0] = true; - cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(52); - cell_cfg.bwps[0].pdcch.coreset[0].offset_rb = 1; - cell_cfg.bwps[0].pdcch.search_space_present[0] = true; - cell_cfg.bwps[0].pdcch.search_space[0] = get_default_search_space0(); - cell_cfg.bwps[0].pdcch.coreset_present[1] = false; - cell_cfg.bwps[0].pdcch.search_space[1].coreset_id = 0; - cell_cfg.bwps[0].pdcch.search_space[1].type = srsran_search_space_type_common_1; + srsran::phy_cfg_nr_default_t::reference_cfg_t ref; + ref.duplex = srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_FDD; + sched_nr_interface::cell_cfg_t cell_cfg = get_default_cell_cfg(srsran::phy_cfg_nr_default_t{ref}); + cell_cfg.bwps[0].pdcch.coreset_present[0] = true; + cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(52); + cell_cfg.bwps[0].pdcch.coreset[0].offset_rb = 1; + cell_cfg.bwps[0].pdcch.search_space_present[0] = true; + cell_cfg.bwps[0].pdcch.search_space[0] = get_default_search_space0(); + cell_cfg.bwps[0].pdcch.coreset_present[1] = false; + cell_cfg.bwps[0].pdcch.search_space[1].coreset_id = 0; + cell_cfg.bwps[0].pdcch.search_space[1].type = srsran_search_space_type_common_1; cell_cfg.bwps[0].pdcch.search_space[1].nof_candidates[2] = 1; cell_cfg.bwps[0].pdcch.search_space[1].nof_formats = 2; cell_cfg.bwps[0].pdcch.search_space[1].formats[0] = srsran_dci_format_nr_1_0; diff --git a/srsgnb/src/stack/mac/test/sched_nr_rar_test.cc b/srsgnb/src/stack/mac/test/sched_nr_rar_test.cc index 526b494ff..b250d7ecf 100644 --- a/srsgnb/src/stack/mac/test/sched_nr_rar_test.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_rar_test.cc @@ -104,7 +104,7 @@ void test_single_prach() result = run_slot(); if (bwpparams.slots[current_slot.slot_idx()].is_dl and bwpparams.slots[(current_slot + bwpparams.pusch_ra_list[0].msg3_delay).slot_idx()].is_ul) { - TESTASSERT_EQ(result->dl.phy.pdcch_dl.size(), 1); + TESTASSERT_EQ(1, result->dl.phy.pdcch_dl.size()); const auto& pdcch = result->dl.phy.pdcch_dl[0]; TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti); TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra); diff --git a/srsgnb/src/stack/mac/test/sched_nr_pdsch_test.cc b/srsgnb/src/stack/mac/test/sched_nr_sch_test.cc similarity index 83% rename from srsgnb/src/stack/mac/test/sched_nr_pdsch_test.cc rename to srsgnb/src/stack/mac/test/sched_nr_sch_test.cc index 8f8f263a6..7728dfd48 100644 --- a/srsgnb/src/stack/mac/test/sched_nr_pdsch_test.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_sch_test.cc @@ -12,7 +12,7 @@ #include "sched_nr_cfg_generators.h" #include "srsgnb/hdr/stack/mac/sched_nr_interface_utils.h" -#include "srsgnb/hdr/stack/mac/sched_nr_pdsch.h" +#include "srsgnb/hdr/stack/mac/sched_nr_sch.h" #include "srsran/common/test_common.h" extern "C" { #include "srsran/phy/common/sliv.h" @@ -80,7 +80,7 @@ void test_dci_freq_assignment(const bwp_params_t& bwp_params, prb_interval grant TESTASSERT(allocated_prbs == grant); } -void test_si_sched() +void test_si() { srsran::test_delimit_logger delimiter{"Test PDSCH SI Allocation"}; @@ -139,7 +139,7 @@ void test_si_sched() } } -void test_rar_sched() +void test_rar() { srsran::test_delimit_logger delimiter{"Test PDSCH RAR Allocation"}; static const uint32_t ss_id = 1; @@ -197,7 +197,7 @@ void test_rar_sched() } } -void test_ue_sched() +void test_ue_pdsch() { srsran::test_delimit_logger delimiter{"Test PDSCH UE Allocation"}; @@ -266,7 +266,7 @@ void test_ue_sched() } } -void test_multi_sched() +void test_multi_pdsch() { srsran::test_delimit_logger delimiter{"Test Multiple PDSCH Allocations"}; @@ -354,6 +354,62 @@ void test_multi_sched() TESTASSERT_EQ(0, pdsch_sched.occupied_prbs(2, srsran_dci_format_nr_1_0).count()); } +void test_multi_pusch() +{ + srsran::test_delimit_logger delimiter{"Test Multiple PUSCH Allocations"}; + + // Create Cell and UE configs + sched_nr_impl::cell_cfg_t cell_cfg = get_cell_cfg(); + sched_nr_impl::ue_cfg_t uecfg = get_ue_cfg(cell_cfg); + sched_nr_interface::sched_args_t sched_args; + bwp_params_t bwp_params{cell_cfg, sched_args, 0, 0}; + ue_carrier_params_t ue_cc{0x4601, bwp_params, uecfg}; + ue_carrier_params_t ue_cc2{0x4602, bwp_params, uecfg}; + + pusch_list_t puschs; + pusch_alloc_result alloc_res; + + pusch_allocator pusch_sched(bwp_params, 0, puschs); + + pdcch_ul_t pdcch_ue1, pdcch_ue2; + pdcch_ue1.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 1, srsran_rnti_type_c, 0x4601); + pdcch_ue2.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 2, srsran_rnti_type_c, 0x4602); + + // Allocate UE in common SearchSpace + uint32_t ss_id = 1; + pdcch_ul_t* pdcch = &pdcch_ue1; + prb_bitmap used_prbs = pusch_sched.occupied_prbs(); + uint32_t ue_grant_size = 10; + prb_interval ue_grant = find_empty_interval_of_length(used_prbs, ue_grant_size); + TESTASSERT_EQ(alloc_result::success, pusch_sched.is_grant_valid(srsran_search_space_type_common_1, ue_grant)); + alloc_res = pusch_sched.alloc_pusch(pdcch->dci.ctx, ue_grant, pdcch->dci); + TESTASSERT(alloc_res.has_value()); + prb_bitmap used_prbs_ue1 = pusch_sched.occupied_prbs(); + TESTASSERT_EQ(used_prbs_ue1.count(), used_prbs.count() + ue_grant.length()); + TESTASSERT_EQ(alloc_result::sch_collision, + pusch_sched.is_grant_valid(srsran_search_space_type_common_1, ue_grant, false)); + + prb_bitmap last_prb_bitmap(used_prbs.size()); + last_prb_bitmap.fill(ue_grant.start(), ue_grant.stop()); + fmt::print("C-RNTI allocated in Common SearchSpace. Occupied PRBs:\n{:b} -> {:b}\n", last_prb_bitmap, used_prbs_ue1); + + // Allocate UE in dedicated SearchSpace + ss_id = 2; + pdcch = &pdcch_ue2; + used_prbs = pusch_sched.occupied_prbs(); + prb_interval ue2_grant = find_empty_interval_of_length(used_prbs, used_prbs.size()); + TESTASSERT_EQ(alloc_result::success, pusch_sched.is_grant_valid(srsran_search_space_type_ue, ue2_grant)); + alloc_res = pusch_sched.alloc_pusch(pdcch->dci.ctx, ue2_grant, pdcch->dci); + TESTASSERT(alloc_res.has_value()); + prb_bitmap used_prbs_ue2 = pusch_sched.occupied_prbs(); + TESTASSERT_EQ(used_prbs_ue2.count(), used_prbs.count() + ue2_grant.length()); + TESTASSERT_EQ(alloc_result::sch_collision, pusch_sched.is_grant_valid(srsran_search_space_type_ue, ue2_grant, false)); + + last_prb_bitmap.reset(); + last_prb_bitmap.fill(ue2_grant.start(), ue2_grant.stop()); + fmt::print("C-RNTI allocated in Common SearchSpace. Occupied PRBs:\n{:b} -> {:b}\n", last_prb_bitmap, used_prbs_ue2); +} + } // namespace srsenb int main() @@ -368,8 +424,9 @@ int main() // Start the log backend. srslog::init(); - srsenb::test_si_sched(); - srsenb::test_rar_sched(); - srsenb::test_ue_sched(); - srsenb::test_multi_sched(); + srsenb::test_si(); + srsenb::test_rar(); + srsenb::test_ue_pdsch(); + srsenb::test_multi_pdsch(); + srsenb::test_multi_pusch(); } \ No newline at end of file