diff --git a/srsgnb/hdr/stack/mac/sched_nr_cfg.h b/srsgnb/hdr/stack/mac/sched_nr_cfg.h index 1d986e95d..b42f874cb 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_cfg.h +++ b/srsgnb/hdr/stack/mac/sched_nr_cfg.h @@ -106,6 +106,11 @@ struct bwp_params_t { return cached_empty_prb_mask; } + const srsran_search_space_t* get_ss(uint32_t ss_id) const + { + return cfg.pdcch.search_space_present[ss_id] ? &cfg.pdcch.search_space[ss_id] : nullptr; + } + private: prb_bitmap cached_empty_prb_mask; srsran::optional_vector used_common_prb_masks; @@ -148,6 +153,16 @@ public: const srsran::phy_cfg_nr_t& phy() const { return cfg_->phy_cfg; } const bwp_params_t& active_bwp() const { return *bwp_cfg; } + /// Get SearchSpace based on SearchSpaceId + const srsran_search_space_t* get_ss(uint32_t ss_id) const + { + if (phy().pdcch.search_space_present[ss_id]) { + // UE-dedicated SearchSpace + return &bwp_cfg->cfg.pdcch.search_space[ss_id]; + } + return nullptr; + } + srsran::const_span cce_pos_list(uint32_t search_id, uint32_t slot_idx, uint32_t aggr_idx) const { if (cce_positions_list.size() > ss_id_to_cce_idx[search_id]) { diff --git a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h index b7b4455eb..1cd6812b9 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h +++ b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h @@ -47,22 +47,20 @@ struct bwp_slot_grid { uint32_t slot_idx = 0; const bwp_params_t* cfg = nullptr; - bwp_rb_bitmap dl_prbs; - bwp_rb_bitmap ul_prbs; - dl_sched_res_t dl; - ul_sched_t ul; - slot_coreset_list coresets; - harq_ack_list_t pending_acks; + bwp_rb_bitmap dl_prbs; + bwp_rb_bitmap ul_prbs; + dl_sched_res_t dl; + ul_sched_t ul; + harq_ack_list_t pending_acks; + pdcch_scheduler pdcch_sched; /// slot PDCCH resource scheduler srsran::unique_pool_ptr rar_softbuffer; - bwp_slot_grid() = default; explicit bwp_slot_grid(const bwp_params_t& bwp_params, uint32_t slot_idx_); void reset(); - bool is_dl() const { return cfg->slots[slot_idx].is_dl; } - bool is_ul() const { return cfg->slots[slot_idx].is_ul; } - + bool is_dl() const { return cfg->slots[slot_idx].is_dl; } + bool is_ul() const { return cfg->slots[slot_idx].is_ul; } prb_bitmap used_prbs(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const { return dl_prbs.prbs() | cfg->used_prbs(ss_id, dci_fmt); @@ -119,7 +117,7 @@ public: 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, bwp_slot_grid* pdcch_grid = nullptr) const; + alloc_result verify_pusch_space(bwp_slot_grid& pusch_grid) const; alloc_result verify_ue_cfg(const ue_carrier_params_t& ue_cfg, harq_proc* harq) const; bwp_res_grid& bwp_grid; diff --git a/srsgnb/hdr/stack/mac/sched_nr_pdcch.h b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h index 99841ac7d..5e25d5a8b 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_pdcch.h +++ b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h @@ -27,8 +27,6 @@ using coreset_bitmap = srsran::bounded_bitsetduration; } uint32_t get_freq_resources() const { return nof_freq_res; } @@ -96,6 +94,60 @@ private: bool get_next_dfs(); }; +class pdcch_scheduler +{ +public: + pdcch_scheduler(const bwp_params_t& bwp_cfg_, + uint32_t slot_idx, + pdcch_dl_list_t& pdcch_dl_list, + pdcch_ul_list_t& pdcch_ul_list); + + void reset(); + + /** + * Allocates RE space for DL DCI in PDCCH, avoiding in the process collisions with other PDCCH allocations + * @param pdcch_grant_type_t allocation type (e.g. DL data, UL data, SI, RAR) + * @param ss_id Search space ID + * @param aggr_idx Aggregation level index (0..4) + * @param user UE object or null in case of broadcast/RAR/paging allocation + * @return pdcch object if the allocation was successful + */ + pdcch_dl_t* alloc_dl_pdcch(pdcch_grant_type_t alloc_type, + uint32_t ss_id, + uint32_t aggr_idx, + const ue_carrier_params_t* user = nullptr); + + /** + * Allocates RE space for UL DCI in PDCCH, avoiding in the process collisions with other PDCCH allocations + * @param ss_id Search space ID + * @param aggr_idx Aggregation level index (0..4) + * @param user UE object parameters + * @return pdcch object if the allocation was successful + */ + pdcch_ul_t* alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t* user); + + /** + * Cancel and remove last PDCCH allocation + * @param ss_id Search space ID + */ + void rem_last_pdcch(uint32_t ss_id); + +private: + const static size_t MAX_CORESET_PER_BWP = 3; /// limit set in TS 38.331, ControlResourceSetId + using slot_coreset_list = std::array, MAX_CORESET_PER_BWP>; + + bool check_args_valid(uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t* user, bool is_dl) const; + + // args + const bwp_params_t& bwp_cfg; + srslog::basic_logger& logger; + const uint32_t slot_idx; + + pdcch_dl_list_t& pdcch_dl_list; + pdcch_ul_list_t& pdcch_ul_list; + slot_coreset_list coresets; +}; + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index a0cd09e0a..8519e0d15 100644 --- a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -80,23 +80,13 @@ 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_), + pdcch_sched(bwp_cfg_, slot_idx_, dl.phy.pdcch_dl, dl.phy.pdcch_ul), rar_softbuffer(harq_softbuffer_pool::get_instance().get_tx(bwp_cfg_.cfg.rb_width)) -{ - for (uint32_t cs_idx = 0; cs_idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++cs_idx) { - if (cfg->cfg.pdcch.coreset_present[cs_idx]) { - uint32_t cs_id = cfg->cfg.pdcch.coreset[cs_idx].id; - coresets[cs_id].emplace(*cfg, cs_id, slot_idx_, dl.phy.pdcch_dl, dl.phy.pdcch_ul); - } - } -} +{} void bwp_slot_grid::reset() { - for (auto& coreset : coresets) { - if (coreset.has_value()) { - coreset->reset(); - } - } + pdcch_sched.reset(); dl_prbs.reset(); ul_prbs.reset(); dl.phy.ssb.clear(); @@ -140,9 +130,9 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, return alloc_result::sch_collision; } - const uint32_t coreset_id = 0; - const uint32_t ss_id = 0; - if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::sib, aggr_idx, ss_id)) { + const uint32_t ss_id = 0; + pdcch_dl_t* pdcch = bwp_pdcch_slot.pdcch_sched.alloc_dl_pdcch(pdcch_grant_type_t::sib, ss_id, aggr_idx); + if (pdcch == nullptr) { logger.warning("SCHED: Cannot allocate SIB1 due to lack of PDCCH space."); return alloc_result::no_cch_space; } @@ -150,11 +140,10 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, // RAR allocation successful. bwp_pdcch_slot.dl_prbs |= prbs; // Generate DCI for SIB - pdcch_dl_t& pdcch = bwp_pdcch_slot.dl.phy.pdcch_dl.back(); - 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)) { + 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.coresets[coreset_id]->rem_last_dci(); + bwp_pdcch_slot.pdcch_sched.rem_last_pdcch(ss_id); return alloc_result::invalid_coderate; } @@ -164,10 +153,10 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, srsran_slot_cfg_t slot_cfg; slot_cfg.idx = pdcch_slot.to_uint(); int code = srsran_ra_dl_dci_to_grant_nr( - &cfg.cell_cfg.carrier, &slot_cfg, &cfg.cfg.pdsch, &pdcch.dci, &pdsch.sch, &pdsch.sch.grant); + &cfg.cell_cfg.carrier, &slot_cfg, &cfg.cfg.pdsch, &pdcch->dci, &pdsch.sch, &pdsch.sch.grant); if (code != SRSRAN_SUCCESS) { logger.warning("Error generating SIB PDSCH grant."); - bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); + bwp_pdcch_slot.pdcch_sched.rem_last_pdcch(ss_id); bwp_pdcch_slot.dl.phy.pdsch.pop_back(); return alloc_result::other_cause; } @@ -189,7 +178,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_slot]; slot_point msg3_slot = pdcch_slot + cfg.pusch_ra_list[m].msg3_delay; bwp_slot_grid& bwp_msg3_slot = bwp_grid[msg3_slot]; - alloc_result ret = verify_pusch_space(bwp_msg3_slot, nullptr); + alloc_result ret = verify_pusch_space(bwp_msg3_slot); if (ret != alloc_result::success) { return ret; } @@ -233,7 +222,8 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t // Find PDCCH position const uint32_t coreset_id = cfg.cfg.pdcch.ra_search_space.coreset_id; const uint32_t search_space_id = cfg.cfg.pdcch.ra_search_space.id; - if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::rar, aggr_idx, search_space_id, nullptr)) { + pdcch_dl_t* pdcch = bwp_pdcch_slot.pdcch_sched.alloc_dl_pdcch(pdcch_grant_type_t::rar, search_space_id, aggr_idx); + if (pdcch == nullptr) { // Could not find space in PDCCH logger.debug("SCHED: No space in PDCCH for DL tx."); return alloc_result::no_cch_space; @@ -242,21 +232,20 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t // RAR allocation successful. bwp_pdcch_slot.dl_prbs |= interv; // Generate DCI for RAR with given RA-RNTI - pdcch_dl_t& pdcch = bwp_pdcch_slot.dl.phy.pdcch_dl.back(); - if (not fill_dci_rar(interv, ra_rnti, *bwp_grid.cfg, pdcch.dci)) { + if (not fill_dci_rar(interv, ra_rnti, *bwp_grid.cfg, pdcch->dci)) { // Cancel on-going PDCCH allocation - bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); + bwp_pdcch_slot.pdcch_sched.rem_last_pdcch(search_space_id); return alloc_result::invalid_coderate; } - auto& phy_cfg = slot_ues[pending_rachs[0].temp_crnti]->phy(); - pdcch.dci_cfg = phy_cfg.get_dci_cfg(); + auto& phy_cfg = slot_ues[pending_rachs[0].temp_crnti]->phy(); + pdcch->dci_cfg = phy_cfg.get_dci_cfg(); // Generate RAR PDSCH // TODO: Properly fill Msg3 grants bwp_pdcch_slot.dl.phy.pdsch.emplace_back(); pdsch_t& pdsch = bwp_pdcch_slot.dl.phy.pdsch.back(); 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(); @@ -336,9 +325,11 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant) const srsran_search_space_t& ss = *ss_candidates[0]; // Find space and allocate PDCCH - uint32_t coreset_id = ss.coreset_id; - if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, ss.id, &ue.cfg())) { + pdcch_dl_t* pdcch = + bwp_pdcch_slot.pdcch_sched.alloc_dl_pdcch(pdcch_grant_type_t::dl_data, ss.id, aggr_idx, &ue.cfg()); + if (pdcch == nullptr) { // Could not find space in PDCCH + logger.debug("Could not find PDCCH space for rnti=0x%x PDSCH allocation", ue->rnti); return alloc_result::no_cch_space; } @@ -361,19 +352,18 @@ 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 - pdcch_dl_t& pdcch = bwp_pdcch_slot.dl.phy.pdcch_dl.back(); - fill_dl_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch.dci.ctx.location, 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(), - [&ue](const harq_ack_t& p) { return p.res.rnti == ue->rnti; }); - pdcch.dci.dai %= 4; - pdcch.dci_cfg = ue->phy().get_dci_cfg(); + fill_dl_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch->dci.ctx.location, 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(), + [&ue](const harq_ack_t& p) { return p.res.rnti == ue->rnti; }); + pdcch->dci.dai %= 4; + pdcch->dci_cfg = ue->phy().get_dci_cfg(); // Generate PUCCH bwp_uci_slot.pending_acks.emplace_back(); bwp_uci_slot.pending_acks.back().phy_cfg = &ue->phy(); - srsran_assert(ue->phy().get_pdsch_ack_resource(pdcch.dci, bwp_uci_slot.pending_acks.back().res), + srsran_assert(ue->phy().get_pdsch_ack_resource(pdcch->dci, bwp_uci_slot.pending_acks.back().res), "Error getting ack resource"); // Generate PDSCH @@ -382,7 +372,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant) pdsch_t& pdsch = bwp_pdsch_slot.dl.phy.pdsch.back(); srsran_slot_cfg_t slot_cfg; slot_cfg.idx = ue.pdsch_slot.to_uint(); - bool ret = ue->phy().get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch); + bool ret = ue->phy().get_pdsch_cfg(slot_cfg, pdcch->dci, pdsch.sch); srsran_assert(ret, "Error converting DCI to grant"); pdsch.sch.grant.tb[0].softbuffer.tx = ue.h_dl->get_softbuffer().get(); @@ -419,7 +409,7 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) 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, &bwp_pdcch_slot); + alloc_result ret = verify_pusch_space(bwp_pusch_slot); if (ret != alloc_result::success) { return ret; } @@ -443,10 +433,10 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) } const srsran_search_space_t& ss = *ss_candidates[0]; - uint32_t coreset_id = ss.coreset_id; - if (not bwp_pdcch_slot.coresets[coreset_id].value().alloc_dci( - pdcch_grant_type_t::ul_data, aggr_idx, ss.id, &ue.cfg())) { + pdcch_ul_t* pdcch = bwp_pdcch_slot.pdcch_sched.alloc_ul_pdcch(ss.id, aggr_idx, &ue.cfg()); + if (pdcch == nullptr) { // Could not find space in PDCCH + logger.debug("Could not find PDCCH space for rnti=0x%x PUSCH allocation", ue->rnti); return alloc_result::no_cch_space; } @@ -462,9 +452,8 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) } // Generate PDCCH - pdcch_ul_t& pdcch = pdcchs.back(); - fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch.dci.ctx.location, pdcch.dci); - pdcch.dci_cfg = ue->phy().get_dci_cfg(); + 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(); @@ -472,7 +461,7 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant) 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) { @@ -492,10 +481,6 @@ alloc_result bwp_slot_allocator::verify_pdsch_space(bwp_slot_grid& pdsch_grid, 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 (pdcch_grid.dl.phy.pdcch_dl.full()) { - logger.warning("SCHED: Maximum number of DL PDCCH allocations reached"); - return alloc_result::no_cch_space; - } if (pdsch_grid.dl.phy.pdsch.full()) { logger.warning("SCHED: Maximum number of DL PDSCH grants reached"); return alloc_result::no_sch_space; @@ -509,23 +494,12 @@ alloc_result bwp_slot_allocator::verify_pdsch_space(bwp_slot_grid& pdsch_grid, return alloc_result::success; } -alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_grid, bwp_slot_grid* pdcch_grid) const +alloc_result bwp_slot_allocator::verify_pusch_space(bwp_slot_grid& pusch_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 (pdcch_grid != nullptr) { - // DCI needed - if (not pdcch_grid->is_dl()) { - logger.warning("SCHED: Trying to allocate PDCCH in TDD non-DL slot index=%d", pdcch_grid->slot_idx); - return alloc_result::no_sch_space; - } - if (pdcch_grid->dl.phy.pdcch_ul.full()) { - logger.warning("SCHED: Maximum number of PUSCH allocations reached"); - return alloc_result::no_grant_space; - } - } if (pusch_grid.ul.pusch.full()) { logger.warning("SCHED: Maximum number of PUSCH allocations reached"); return alloc_result::no_grant_space; diff --git a/srsgnb/src/stack/mac/sched_nr_pdcch.cc b/srsgnb/src/stack/mac/sched_nr_pdcch.cc index 3fd35746c..dffa002a8 100644 --- a/srsgnb/src/stack/mac/sched_nr_pdcch.cc +++ b/srsgnb/src/stack/mac/sched_nr_pdcch.cc @@ -47,10 +47,10 @@ void coreset_region::reset() pdcch_ul_list.clear(); } -bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, - uint32_t aggr_idx, - uint32_t search_space_id, - const ue_carrier_params_t* user) +bool coreset_region::alloc_pdcch(pdcch_grant_type_t alloc_type, + uint32_t aggr_idx, + uint32_t search_space_id, + const ue_carrier_params_t* user) { srsran_assert(aggr_idx <= 4, "Invalid DCI aggregation level=%d", 1U << aggr_idx); srsran_assert((user == nullptr) xor @@ -63,6 +63,7 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, record.aggr_idx = aggr_idx; record.ss_id = search_space_id; record.alloc_type = alloc_type; + if (record.alloc_type == pdcch_grant_type_t::ul_data) { record.idx = pdcch_ul_list.size(); pdcch_ul_list.emplace_back(); @@ -95,7 +96,7 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, return false; } -void coreset_region::rem_last_dci() +void coreset_region::rem_last_pdcch() { srsran_assert(not dci_list.empty(), "%s called when no PDCCH have yet been allocated", __FUNCTION__); @@ -191,5 +192,112 @@ srsran::span coreset_region::get_cce_loc_table(const alloc_recor return {}; } +pdcch_scheduler::pdcch_scheduler(const bwp_params_t& bwp_cfg_, + uint32_t slot_idx_, + pdcch_dl_list_t& dl_pdcchs, + pdcch_ul_list_t& ul_pdcchs) : + bwp_cfg(bwp_cfg_), pdcch_dl_list(dl_pdcchs), pdcch_ul_list(ul_pdcchs), slot_idx(slot_idx_), logger(bwp_cfg_.logger) +{ + for (uint32_t cs_idx = 0; cs_idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++cs_idx) { + if (bwp_cfg.cfg.pdcch.coreset_present[cs_idx]) { + uint32_t cs_id = bwp_cfg.cfg.pdcch.coreset[cs_idx].id; + coresets[cs_id].emplace(bwp_cfg, cs_id, slot_idx, pdcch_dl_list, pdcch_ul_list); + } + } +} + +/// Helper function to verify valid inputs +bool pdcch_scheduler::check_args_valid(uint32_t ss_id, + uint32_t aggr_idx, + const ue_carrier_params_t* user, + bool is_dl) const +{ + srsran_assert(ss_id < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE, "Invalid SearchSpace#%d", ss_id); + srsran_assert( + aggr_idx < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR, "Invalid aggregation level index=%d", aggr_idx); + + // Common checks + if (not bwp_cfg.slots[slot_idx].is_dl) { + logger.warning("SCHED: Trying to allocate PDCCH in non"); + return false; + } + + const srsran_search_space_t* ss = (user == nullptr) ? bwp_cfg.get_ss(ss_id) : user->get_ss(ss_id); + if (ss == nullptr) { + logger.error("Failure to allocate PDCCH. Cause: SearchSpace#%d has not been configured in the scheduler", ss_id); + return false; + } + + if (ss->nof_candidates[aggr_idx] == 0) { + logger.warning("Chosen PDCCH doesn't have any valid candidates"); + return false; + } + if (is_dl and pdcch_dl_list.full()) { + logger.warning("SCHED: Maximum number of DL PDCCH allocations=%zd was reached for BWP#%d, CORESET#%d", + pdcch_dl_list.size(), + bwp_cfg.bwp_id, + bwp_cfg.cfg.pdcch.search_space[ss_id].coreset_id); + return false; + } + if (not is_dl and pdcch_ul_list.full()) { + logger.warning("SCHED: Maximum number of UL PDCCH allocations=%zd was reached for BWP#%d", + pdcch_ul_list.size(), + bwp_cfg.bwp_id); + return false; + } + return true; +} + +pdcch_dl_t* pdcch_scheduler::alloc_dl_pdcch(pdcch_grant_type_t alloc_type, + uint32_t ss_id, + uint32_t aggr_idx, + const ue_carrier_params_t* user) +{ + if (not check_args_valid(ss_id, aggr_idx, user, true)) { + return nullptr; + } + const srsran_search_space_t& ss = (user == nullptr) ? *bwp_cfg.get_ss(ss_id) : *user->get_ss(ss_id); + + if (alloc_type == pdcch_grant_type_t::rar) { + srsran_assert(ss_id == bwp_cfg.cfg.pdcch.ra_search_space.id and bwp_cfg.cfg.pdcch.ra_search_space_present, + "PDCCH grant type does not match search space"); + } + + if (coresets[ss.coreset_id]->alloc_pdcch(alloc_type, aggr_idx, ss_id, user)) { + return &pdcch_dl_list.back(); + } + return nullptr; +} + +pdcch_ul_t* pdcch_scheduler::alloc_ul_pdcch(uint32_t ss_id, uint32_t aggr_idx, const ue_carrier_params_t* user) +{ + if (not check_args_valid(ss_id, aggr_idx, user, false)) { + return nullptr; + } + const srsran_search_space_t& ss = *user->get_ss(ss_id); + + if (coresets[ss.coreset_id]->alloc_pdcch(pdcch_grant_type_t::ul_data, aggr_idx, ss_id, user)) { + return &pdcch_ul_list.back(); + } + return nullptr; +} + +void pdcch_scheduler::rem_last_pdcch(uint32_t ss_id) +{ + const srsran_search_space_t& ss = bwp_cfg.cfg.pdcch.search_space[ss_id]; + + uint32_t coreset_id = ss.coreset_id; + coresets[coreset_id]->rem_last_pdcch(); +} + +void pdcch_scheduler::reset() +{ + for (uint32_t i = 0; i < coresets.size(); ++i) { + if (coresets[i].has_value()) { + coresets[i]->reset(); + } + } +} + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsgnb/src/stack/mac/sched_nr_time_rr.cc b/srsgnb/src/stack/mac/sched_nr_time_rr.cc index 34b7f3806..965dba181 100644 --- a/srsgnb/src/stack/mac/sched_nr_time_rr.cc +++ b/srsgnb/src/stack/mac/sched_nr_time_rr.cc @@ -15,6 +15,13 @@ namespace srsenb { 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 + * @return true if a UE was allocated + */ template bool round_robin_apply(slot_ue_map_t& ue_db, uint32_t rr_count, Predicate p) { @@ -25,6 +32,7 @@ bool round_robin_apply(slot_ue_map_t& ue_db, uint32_t rr_count, Predicate p) std::advance(it, (rr_count % ue_db.size())); for (uint32_t count = 0; count < ue_db.size(); ++count, ++it) { if (it == ue_db.end()) { + // wrap-around it = ue_db.begin(); } if (p(it->second)) {