nr,gnb,sched: wrap coreset list in pdcch_scheduler

This commit is contained in:
Francisco 2021-12-03 23:43:18 +00:00 committed by Francisco Paisana
parent 8f6ead0d55
commit 0929177fa2
6 changed files with 244 additions and 89 deletions

View File

@ -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<prb_bitmap> 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<uint32_t> 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]) {

View File

@ -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<tx_harq_softbuffer> 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;

View File

@ -27,8 +27,6 @@ using coreset_bitmap = srsran::bounded_bitset<SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZ
enum class pdcch_grant_type_t { sib, rar, dl_data, ul_data };
class slot_ue;
class coreset_region
{
public:
@ -46,12 +44,12 @@ public:
* @param user UE object or null in case of broadcast/RAR/paging allocation
* @return if the allocation was successful
*/
bool alloc_dci(pdcch_grant_type_t alloc_type,
uint32_t aggr_idx,
uint32_t search_space_id,
const ue_carrier_params_t* user = nullptr);
bool alloc_pdcch(pdcch_grant_type_t alloc_type,
uint32_t aggr_idx,
uint32_t search_space_id,
const ue_carrier_params_t* user = nullptr);
void rem_last_dci();
void rem_last_pdcch();
uint32_t get_td_symbols() const { return coreset_cfg->duration; }
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<srsran::optional<coreset_region>, 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

View File

@ -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;

View File

@ -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<const uint32_t> 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

View File

@ -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 <typename Predicate>
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)) {