nr,gnb,sched: implement pusch allocator and fix prb grant allocation when UEs are using common SS

master
Francisco 3 years ago committed by Francisco Paisana
parent 70c5eff6d0
commit 949c34112e

@ -188,6 +188,9 @@ public:
int fixed_pdsch_mcs() const { return bwp_cfg->sched_cfg.fixed_dl_mcs; } 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; } int fixed_pusch_mcs() const { return bwp_cfg->sched_cfg.fixed_ul_mcs; }
srsran::bounded_vector<uint32_t, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE>
find_ss_candidates(uint32_t aggr_idx, srsran::const_span<srsran_dci_format_nr_t> supported_dci_fmts) const;
private: private:
const ue_cfg_t* cfg_ = nullptr; const ue_cfg_t* cfg_ = nullptr;
const bwp_params_t* bwp_cfg = nullptr; const bwp_params_t* bwp_cfg = nullptr;

@ -17,7 +17,7 @@
#include "sched_nr_helpers.h" #include "sched_nr_helpers.h"
#include "sched_nr_interface.h" #include "sched_nr_interface.h"
#include "sched_nr_pdcch.h" #include "sched_nr_pdcch.h"
#include "sched_nr_pdsch.h" #include "sched_nr_sch.h"
#include "sched_nr_ue.h" #include "sched_nr_ue.h"
#include "srsenb/hdr/stack/mac/sched_common.h" #include "srsenb/hdr/stack/mac/sched_common.h"
@ -45,12 +45,12 @@ struct bwp_slot_grid {
uint32_t slot_idx = 0; uint32_t slot_idx = 0;
const bwp_params_t* cfg = nullptr; const bwp_params_t* cfg = nullptr;
bwp_rb_bitmap ul_prbs;
dl_sched_res_t dl; dl_sched_res_t dl;
ul_sched_t ul; ul_sched_t ul;
harq_ack_list_t pending_acks; harq_ack_list_t pending_acks;
bwp_pdcch_allocator pdcchs; /// slot PDCCH resource allocator bwp_pdcch_allocator pdcchs; /// slot PDCCH resource allocator
pdsch_allocator pdschs; /// slot PDSCH resource allocator pdsch_allocator pdschs; /// slot PDSCH resource allocator
pusch_allocator puschs; /// slot PUSCH resource allocator
srsran::unique_pool_ptr<tx_harq_softbuffer> rar_softbuffer; srsran::unique_pool_ptr<tx_harq_softbuffer> rar_softbuffer;
@ -96,8 +96,8 @@ public:
uint32_t aggr_idx, uint32_t aggr_idx,
prb_interval interv, prb_interval interv,
srsran::const_span<dl_sched_rar_info_t> pending_rars); srsran::const_span<dl_sched_rar_info_t> pending_rars);
alloc_result alloc_pdsch(slot_ue& ue, prb_grant dl_grant); alloc_result alloc_pdsch(slot_ue& ue, uint32_t ss_id, const prb_grant& dl_grant);
alloc_result alloc_pusch(slot_ue& ue, prb_grant dl_mask); alloc_result alloc_pusch(slot_ue& ue, const prb_grant& grant);
slot_point get_pdcch_tti() const { return pdcch_slot; } slot_point get_pdcch_tti() const { return pdcch_slot; }
slot_point get_tti_rx() const { return pdcch_slot - TX_ENB_DELAY; } 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]; } const bwp_slot_grid& tx_slot_grid() const { return bwp_grid[pdcch_slot]; }
bwp_slot_grid& tx_slot_grid() { 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; srslog::basic_logger& logger;
const bwp_params_t& cfg; const bwp_params_t& cfg;
private: private:
alloc_result alloc_result verify_uci_space(const bwp_slot_grid& uci_grid) const;
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_ue_cfg(const ue_carrier_params_t& ue_cfg, harq_proc* harq) const; alloc_result verify_ue_cfg(const ue_carrier_params_t& ue_cfg, harq_proc* harq) const;
bwp_res_grid& bwp_grid; bwp_res_grid& bwp_grid;
@ -120,6 +124,8 @@ private:
slot_ue_map_t& slot_ues; 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 sched_nr_impl
} // namespace srsenb } // namespace srsenb

@ -48,35 +48,13 @@ inline bool is_rnti_type_valid_in_search_space(srsran_rnti_type_t rnti_type, srs
return false; 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); 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 /// Generate PDCCH DL DCI fields
void fill_dl_dci_ue_fields(const slot_ue& ue, void fill_dl_dci_ue_fields(const slot_ue& ue, srsran_dci_dl_nr_t& dci);
const bwp_params_t& bwp_cfg,
uint32_t ss_id,
srsran_dci_location_t dci_pos,
srsran_dci_dl_nr_t& dci);
/// Generate PDCCH UL DCI fields /// Generate PDCCH UL DCI fields
void fill_ul_dci_ue_fields(const slot_ue& ue, void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_ul_nr_t& dci);
const bwp_params_t& bwp_cfg,
uint32_t ss_id,
srsran_dci_location_t dci_pos,
srsran_dci_ul_nr_t& dci);
/// Log UE state for slot being scheduled /// Log UE state for slot being scheduled
void log_sched_slot_ues(srslog::basic_logger& logger, void log_sched_slot_ues(srslog::basic_logger& logger,

@ -31,6 +31,12 @@ view_active_search_spaces(const srsran_pdcch_cfg_nr_t& pdcch)
return srsran::split_optional_span<const srsran_search_space_t>{pdcch.search_space, pdcch.search_space_present}; return srsran::split_optional_span<const srsran_search_space_t>{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 //////////////////////////////////////////// //////////////////////////////////// CORESET Helpers ////////////////////////////////////////////
/// Get a range of active coresets in a PDCCH configuration /// Get a range of active coresets in a PDCCH configuration

@ -24,6 +24,10 @@ namespace srsenb {
namespace sched_nr_impl { 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<SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE * SRSRAN_CORESET_DURATION_MAX, true>; using coreset_bitmap = srsran::bounded_bitset<SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE * SRSRAN_CORESET_DURATION_MAX, true>;
class coreset_region class coreset_region

@ -10,8 +10,8 @@
* *
*/ */
#ifndef SRSRAN_SCHED_NR_PDSCH_H #ifndef SRSRAN_SCHED_NR_SCH_H
#define SRSRAN_SCHED_NR_PDSCH_H #define SRSRAN_SCHED_NR_SCH_H
#include "srsenb/hdr/stack/mac/sched_common.h" #include "srsenb/hdr/stack/mac/sched_common.h"
#include "srsgnb/hdr/stack/mac/sched_nr_cfg.h" #include "srsgnb/hdr/stack/mac/sched_nr_cfg.h"
@ -76,8 +76,55 @@ private:
bwp_rb_bitmap dl_prbs; bwp_rb_bitmap dl_prbs;
}; };
using pusch_alloc_result = srsran::expected<pusch_t*, alloc_result>;
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 sched_nr_impl
} // namespace srsenb } // namespace srsenb
#endif // SRSRAN_SCHED_NR_PDSCH_H #endif // SRSRAN_SCHED_NR_SCH_H

@ -171,6 +171,8 @@ public:
dl_harq_proc* find_empty_dl_harq() { return ue->harq_ent.find_empty_dl_harq(); } 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(); } 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) void build_pdu(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu)
{ {
ue->pdu_builder.alloc_subpdus(rem_bytes, pdu); ue->pdu_builder.alloc_subpdus(rem_bytes, pdu);

@ -14,7 +14,7 @@ set(SOURCES mac_nr.cc
sched_nr_grant_allocator.cc sched_nr_grant_allocator.cc
sched_nr_harq.cc sched_nr_harq.cc
sched_nr_pdcch.cc sched_nr_pdcch.cc
sched_nr_pdsch.cc sched_nr_sch.cc
sched_nr_cfg.cc sched_nr_cfg.cc
sched_nr_helpers.cc sched_nr_helpers.cc
sched_nr_bwp.cc sched_nr_bwp.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_) : 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_), slot_idx(slot_idx_),
cfg(&bwp_cfg_), cfg(&bwp_cfg_),
pdcchs(bwp_cfg_, slot_idx_, dl.phy.pdcch_dl, dl.phy.pdcch_ul), pdcchs(bwp_cfg_, slot_idx_, dl.phy.pdcch_dl, dl.phy.pdcch_ul),
pdschs(bwp_cfg_, slot_idx_, dl.phy.pdsch), 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)) 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(); pdcchs.reset();
pdschs.reset(); pdschs.reset();
ul_prbs.reset(); puschs.reset();
dl.phy.ssb.clear(); dl.phy.ssb.clear();
dl.phy.nzp_csi_rs.clear(); dl.phy.nzp_csi_rs.clear();
dl.data.clear(); dl.data.clear();
dl.rar.clear(); dl.rar.clear();
dl.sib_idxs.clear(); dl.sib_idxs.clear();
ul.pusch.clear();
ul.pucch.clear(); ul.pucch.clear();
pending_acks.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; 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]; 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 // 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) { if (ret != alloc_result::success) {
return ret; return ret;
} }
// Allocate PDCCH
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_si_pdcch(ss_id, aggr_idx); auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_si_pdcch(ss_id, aggr_idx);
if (pdcch_result.is_error()) { 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(); return pdcch_result.error();
} }
pdcch_dl_t pdcch = *pdcch_result.value(); pdcch_dl_t& pdcch = *pdcch_result.value();
// SI allocation successful.
// Allocate PDSCH // Allocate PDSCH
pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch.dci.ctx, prbs, pdcch.dci); pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch.dci.ctx, prbs, pdcch.dci);
// Generate DCI for SIB // Generate DCI for SIB
pdcch.dci_cfg.coreset0_bw = srsran_coreset_get_bw(&cfg.cfg.pdcch.coreset[0]); 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.mcs = 5;
// Cancel on-going PDCCH allocation pdcch.dci.rv = 0;
bwp_pdcch_slot.pdcchs.cancel_last_pdcch(); pdcch.dci.sii = si_idx == 0 ? 0 : 1;
return alloc_result::invalid_coderate;
}
// Generate PDSCH // Generate PDSCH
srsran_slot_cfg_t slot_cfg; 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) { if (ret != alloc_result::success) {
return ret; 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) { for (auto& rach : pending_rachs) {
auto ue_it = slot_ues.find(rach.temp_crnti); auto ue_it = slot_ues.find(rach.temp_crnti);
if (ue_it == slot_ues.end()) { 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; 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 // Check Msg3 RB collision
uint32_t total_ul_nof_prbs = msg3_nof_prbs * pending_rachs.size(); uint32_t total_msg3_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 all_msg3_rbs =
prb_interval msg3_rbs = find_empty_interval_of_length(bwp_msg3_slot.ul_prbs.prbs(), total_ul_nof_rbgs); find_empty_interval_of_length(bwp_msg3_slot.puschs.occupied_prbs(), total_msg3_nof_prbs, 0);
if (msg3_rbs.length() < total_ul_nof_rbgs) { if (all_msg3_rbs.length() < total_msg3_nof_prbs) {
logger.debug("SCHED: No space in PUSCH for Msg3."); logger.debug("SCHED: No space in PUSCH for Msg3.");
return alloc_result::sch_collision; 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); auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_rar_pdcch(ra_rnti, aggr_idx);
if (pdcch_result.is_error()) { if (pdcch_result.is_error()) {
// Could not find space in PDCCH // Could not find space in PDCCH
return pdcch_result.error(); return pdcch_result.error();
} }
pdcch_dl_t& pdcch = *pdcch_result.value();
// 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();
// Allocate PDSCH // 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 // Generate DCI for RAR with given RA-RNTI
if (not fill_dci_rar(interv, ra_rnti, *bwp_grid.cfg, pdcch->dci)) { auto& phy_cfg = slot_ues[pending_rachs[0].temp_crnti]->phy();
// Cancel on-going PDCCH allocation pdcch.dci_cfg = phy_cfg.get_dci_cfg();
bwp_pdcch_slot.pdcchs.cancel_last_pdcch(); pdcch.dci.mcs = 5;
return alloc_result::invalid_coderate;
}
// Generate RAR PDSCH // Generate RAR PDSCH
// TODO: Properly fill Msg3 grants // TODO: Properly fill Msg3 grants
srsran_slot_cfg_t slot_cfg; srsran_slot_cfg_t slot_cfg;
slot_cfg.idx = pdcch_slot.to_uint(); 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"); srsran_assert(success, "Error converting DCI to grant");
pdsch.sch.grant.tb[0].softbuffer.tx = bwp_pdcch_slot.rar_softbuffer->get(); pdsch.sch.grant.tb[0].softbuffer.tx = bwp_pdcch_slot.rar_softbuffer->get();
// Generate Msg3 grants in PUSCH // 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; const int mcs = 0, max_harq_msg3_retx = 4;
slot_cfg.idx = msg3_slot.to_uint(); slot_cfg.idx = msg3_slot.to_uint();
bwp_pdcch_slot.dl.rar.emplace_back(); 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); fill_dci_msg3(ue, *bwp_grid.cfg, rar_grant.msg3_dci);
// Generate PUSCH // Generate PUSCH
bwp_msg3_slot.ul.pusch.emplace_back(); pusch_t& pusch = bwp_msg3_slot.puschs.alloc_pusch_unchecked(msg3_interv, rar_grant.msg3_dci);
pusch_t& pusch = bwp_msg3_slot.ul.pusch.back();
success = ue->phy().get_pusch_cfg(slot_cfg, rar_grant.msg3_dci, pusch.sch); success = ue->phy().get_pusch_cfg(slot_cfg, rar_grant.msg3_dci, pusch.sch);
srsran_assert(success, "Error converting DCI to PUSCH grant"); srsran_assert(success, "Error converting DCI to PUSCH grant");
pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get(); pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get();
ue.h_ul->set_tbs(pusch.sch.grant.tb[0].tbs); ue.h_ul->set_tbs(pusch.sch.grant.tb[0].tbs);
} }
bwp_msg3_slot.ul_prbs.add(msg3_rbs);
return alloc_result::success; return alloc_result::success;
} }
// ue is the UE (1 only) that will be allocated // ue is the UE (1 only) that will be allocated
// func computes the grant allocation for this UE // 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 uint32_t aggr_idx = 2;
static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0;
static const std::array<srsran_dci_format_nr_t, 1> dci_fmt_list{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_pdcch_slot = bwp_grid[ue.pdcch_slot];
bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_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 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 // 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) { if (ret != alloc_result::success) {
return ret; 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) { if (result != alloc_result::success) {
return result; return result;
} }
@ -335,13 +301,11 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant)
// TODO // TODO
// Find space and allocate PDCCH // 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()) { if (pdcch_result.is_error()) {
// Could not find space in PDCCH // Could not find space in PDCCH
return pdcch_result.error(); return pdcch_result.error();
} }
// DL allocation successful.
pdcch_dl_t& pdcch = *pdcch_result.value(); pdcch_dl_t& pdcch = *pdcch_result.value();
// Allocate PDSCH // 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; const static float max_R = 0.93;
while (true) { while (true) {
// Generate PDCCH // 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.pucch_resource = 0;
pdcch.dci.dai = std::count_if(bwp_uci_slot.pending_acks.begin(), pdcch.dci.dai = std::count_if(bwp_uci_slot.pending_acks.begin(),
bwp_uci_slot.pending_acks.end(), 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; 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 uint32_t aggr_idx = 2;
static const std::array<srsran_dci_format_nr_t, 2> dci_fmt_list{srsran_dci_format_nr_0_1, srsran_dci_format_nr_0_0}; static const std::array<srsran_dci_format_nr_t, 2> 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_pdcch_slot = bwp_grid[ue.pdcch_slot];
auto& bwp_pusch_slot = bwp_grid[ue.pusch_slot]; auto& bwp_pusch_slot = bwp_grid[ue.pusch_slot];
alloc_result ret = verify_pusch_space(bwp_pusch_slot);
if (ret != alloc_result::success) { alloc_result ret = verify_ue_cfg(ue.cfg(), ue.h_ul);
return ret;
}
ret = verify_ue_cfg(ue.cfg(), ue.h_ul);
if (ret != alloc_result::success) { if (ret != alloc_result::success) {
return ret; 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 // 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); candidate_ss_list_t ss_candidates = find_ss(ue->phy().pdcch, aggr_idx, rnti_type, dci_fmt_list);
if (ss_candidates.empty()) { if (ss_candidates.empty()) {
// Could not find space in PDCCH // 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]; 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()); auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_ul_pdcch(ss.id, aggr_idx, ue.cfg());
if (pdcch_result.is_error()) { if (pdcch_result.is_error()) {
// Could not find space in PDCCH // 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(); return pdcch_result.error();
} }
pdcch_ul_t* pdcch = pdcch_result.value();
// Allocation Successful // 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()) { if (ue.h_ul->empty()) {
int mcs = ue->fixed_pusch_mcs(); 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"); srsran_assert(success, "Failed to allocate UL HARQ retx");
} }
// Generate PDCCH // Generate PDCCH content
fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch->dci.ctx.location, pdcch->dci); fill_ul_dci_ue_fields(ue, pdcch.dci);
pdcch->dci_cfg = ue->phy().get_dci_cfg(); pdcch.dci_cfg = ue->phy().get_dci_cfg();
// Generate PUSCH
bwp_pusch_slot.ul_prbs |= ul_grant; // Generate PUSCH content
bwp_pusch_slot.ul.pusch.emplace_back();
pusch_t& pusch = bwp_pusch_slot.ul.pusch.back();
srsran_slot_cfg_t slot_cfg; srsran_slot_cfg_t slot_cfg;
slot_cfg.idx = ue.pusch_slot.to_uint(); slot_cfg.idx = ue.pusch_slot.to_uint();
pusch.pid = ue.h_ul->pid; 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"); srsran_assert(success, "Error converting DCI to PUSCH grant");
pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get(); pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get();
if (ue.h_ul->nof_retx() == 0) { 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; return alloc_result::success;
} }
alloc_result bwp_slot_allocator::verify_pdsch_space(bwp_slot_grid& pdsch_grid, alloc_result bwp_slot_allocator::verify_uci_space(const bwp_slot_grid& uci_grid) const
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
{ {
if (not pusch_grid.is_ul()) { if (uci_grid.pending_acks.full()) {
logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", pusch_grid.slot_idx); logger.warning("SCHED: No space for ACK.");
return alloc_result::no_sch_space;
}
if (pusch_grid.ul.pusch.full()) {
logger.warning("SCHED: Maximum number of PUSCH allocations reached");
return alloc_result::no_grant_space; return alloc_result::no_grant_space;
} }
return alloc_result::success; 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; 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 sched_nr_impl
} // namespace srsenb } // namespace srsenb

@ -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 <typename DciDlOrUl> template <typename DciDlOrUl>
void fill_dci_harq(const slot_ue& ue, DciDlOrUl& dci) 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]; 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) bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& msg3_dci)
{ {
// Fill DCI context // 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 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_harq(ue, msg3_dci);
fill_dci_grant(bwp_cfg, ue.h_ul->prbs(), msg3_dci);
return true; return true;
} }
void fill_dl_dci_ue_fields(const slot_ue& ue, void fill_dl_dci_ue_fields(const slot_ue& ue, srsran_dci_dl_nr_t& dci)
const bwp_params_t& bwp_cfg,
uint32_t ss_id,
srsran_dci_location_t dci_pos,
srsran_dci_dl_nr_t& dci)
{ {
fill_dci_harq(ue, dci); fill_dci_harq(ue, dci);
if (dci.ctx.format == srsran_dci_format_nr_1_0) { 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, void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_ul_nr_t& dci)
const bwp_params_t& bwp_cfg,
uint32_t ss_id,
srsran_dci_location_t dci_pos,
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_harq(ue, dci);
fill_dci_grant(bwp_cfg, ue.h_ul->prbs(), dci);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

@ -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" #include "srsran/common/string_helpers.h"
namespace srsenb { namespace srsenb {
@ -56,7 +56,7 @@ alloc_result pdsch_allocator::is_grant_valid(uint32_t ss_id,
// No space in Scheduler PDSCH output list // No space in Scheduler PDSCH output list
if (pdschs.full()) { 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; 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; 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 // In case of common SearchSpaces, the PRBs must be contiguous
if (grant.is_alloc_type0()) { if (grant.is_alloc_type0()) {
log_alloc_failure(bwp_cfg.logger.warning, ss_id, "AllocType0 not allowed in common SearchSpace."); 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(); pdschs.pop_back();
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename... Args>
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>(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 sched_nr_impl
} // namespace srsenb } // namespace srsenb

@ -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_) : 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)) bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name))
{ {

@ -19,7 +19,7 @@ namespace sched_nr_impl {
* @brief Algorithm to select next UE to allocate in a time-domain RR fashion * @brief Algorithm to select next UE to allocate in a time-domain RR fashion
* @param ue_db map of "slot_ue" * @param ue_db map of "slot_ue"
* @param rr_count starting index to select next 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 * @return true if a UE was allocated
*/ */
template <typename Predicate> template <typename Predicate>
@ -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) void sched_nr_time_rr::sched_dl_users(slot_ue_map_t& ue_db, bwp_slot_allocator& slot_alloc)
{ {
// Start with retxs // Start with retxs
if (round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), [&slot_alloc](slot_ue& ue) { 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())) { 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()); 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) { if (res == alloc_result::success) {
return true; return true;
} }
} }
return false; return false;
})) { };
if (round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), retx_ue_function)) {
return; return;
} }
// Move on to new txs // 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()) { 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) { if (res == alloc_result::success) {
return true; return true;
} }
} }
return false; 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) void sched_nr_time_rr::sched_ul_users(slot_ue_map_t& ue_db, bwp_slot_allocator& slot_alloc)

@ -11,7 +11,7 @@
*/ */
#include "srsgnb/hdr/stack/mac/sched_nr_ue.h" #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/common/string_helpers.h"
#include "srsran/mac/mac_sch_pdu_nr.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_, ue_carrier::ue_carrier(uint16_t rnti_,

@ -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) 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_nr_test(sched_nr_pdcch_test sched_nr_pdcch_test)
add_executable(sched_nr_pdsch_test sched_nr_pdsch_test.cc) add_executable(sched_nr_sch_test sched_nr_sch_test.cc)
target_link_libraries(sched_nr_pdsch_test srsgnb_mac sched_nr_test_suite srsran_common) target_link_libraries(sched_nr_sch_test srsgnb_mac sched_nr_test_suite srsran_common)
add_nr_test(sched_nr_pdsch_test sched_nr_pdsch_test) add_nr_test(sched_nr_sch_test sched_nr_sch_test)
add_executable(sched_nr_rar_test sched_nr_rar_test.cc) 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) target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common)

@ -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() 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(); srsran::phy_cfg_nr_default_t::reference_cfg_t ref;
cell_cfg.bwps[0].pdcch.coreset_present[0] = true; ref.duplex = srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_FDD;
cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(52); 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[0].offset_rb = 1; cell_cfg.bwps[0].pdcch.coreset_present[0] = true;
cell_cfg.bwps[0].pdcch.search_space_present[0] = true; cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(52);
cell_cfg.bwps[0].pdcch.search_space[0] = get_default_search_space0(); cell_cfg.bwps[0].pdcch.coreset[0].offset_rb = 1;
cell_cfg.bwps[0].pdcch.coreset_present[1] = false; cell_cfg.bwps[0].pdcch.search_space_present[0] = true;
cell_cfg.bwps[0].pdcch.search_space[1].coreset_id = 0; cell_cfg.bwps[0].pdcch.search_space[0] = get_default_search_space0();
cell_cfg.bwps[0].pdcch.search_space[1].type = srsran_search_space_type_common_1; 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_candidates[2] = 1;
cell_cfg.bwps[0].pdcch.search_space[1].nof_formats = 2; 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; cell_cfg.bwps[0].pdcch.search_space[1].formats[0] = srsran_dci_format_nr_1_0;

@ -104,7 +104,7 @@ void test_single_prach()
result = run_slot(); result = run_slot();
if (bwpparams.slots[current_slot.slot_idx()].is_dl and 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) { 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]; const auto& pdcch = result->dl.phy.pdcch_dl[0];
TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti); TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti);
TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra); TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra);

@ -12,7 +12,7 @@
#include "sched_nr_cfg_generators.h" #include "sched_nr_cfg_generators.h"
#include "srsgnb/hdr/stack/mac/sched_nr_interface_utils.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" #include "srsran/common/test_common.h"
extern "C" { extern "C" {
#include "srsran/phy/common/sliv.h" #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); TESTASSERT(allocated_prbs == grant);
} }
void test_si_sched() void test_si()
{ {
srsran::test_delimit_logger delimiter{"Test PDSCH SI Allocation"}; 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"}; srsran::test_delimit_logger delimiter{"Test PDSCH RAR Allocation"};
static const uint32_t ss_id = 1; 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"}; 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"}; 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()); 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 } // namespace srsenb
int main() int main()
@ -368,8 +424,9 @@ int main()
// Start the log backend. // Start the log backend.
srslog::init(); srslog::init();
srsenb::test_si_sched(); srsenb::test_si();
srsenb::test_rar_sched(); srsenb::test_rar();
srsenb::test_ue_sched(); srsenb::test_ue_pdsch();
srsenb::test_multi_sched(); srsenb::test_multi_pdsch();
srsenb::test_multi_pusch();
} }
Loading…
Cancel
Save