mirror of https://github.com/PentHertz/srsLTE.git
nr,gnb,sched: implement pusch allocator and fix prb grant allocation when UEs are using common SS
This commit is contained in:
parent
70c5eff6d0
commit
949c34112e
|
@ -188,6 +188,9 @@ public:
|
|||
int fixed_pdsch_mcs() const { return bwp_cfg->sched_cfg.fixed_dl_mcs; }
|
||||
int fixed_pusch_mcs() const { return bwp_cfg->sched_cfg.fixed_ul_mcs; }
|
||||
|
||||
srsran::bounded_vector<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:
|
||||
const ue_cfg_t* cfg_ = nullptr;
|
||||
const bwp_params_t* bwp_cfg = nullptr;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "sched_nr_helpers.h"
|
||||
#include "sched_nr_interface.h"
|
||||
#include "sched_nr_pdcch.h"
|
||||
#include "sched_nr_pdsch.h"
|
||||
#include "sched_nr_sch.h"
|
||||
#include "sched_nr_ue.h"
|
||||
#include "srsenb/hdr/stack/mac/sched_common.h"
|
||||
|
||||
|
@ -45,12 +45,12 @@ struct bwp_slot_grid {
|
|||
uint32_t slot_idx = 0;
|
||||
const bwp_params_t* cfg = nullptr;
|
||||
|
||||
bwp_rb_bitmap ul_prbs;
|
||||
dl_sched_res_t dl;
|
||||
ul_sched_t ul;
|
||||
harq_ack_list_t pending_acks;
|
||||
bwp_pdcch_allocator pdcchs; /// slot PDCCH resource allocator
|
||||
pdsch_allocator pdschs; /// slot PDSCH resource allocator
|
||||
pusch_allocator puschs; /// slot PUSCH resource allocator
|
||||
|
||||
srsran::unique_pool_ptr<tx_harq_softbuffer> rar_softbuffer;
|
||||
|
||||
|
@ -96,8 +96,8 @@ public:
|
|||
uint32_t aggr_idx,
|
||||
prb_interval interv,
|
||||
srsran::const_span<dl_sched_rar_info_t> pending_rars);
|
||||
alloc_result alloc_pdsch(slot_ue& ue, prb_grant dl_grant);
|
||||
alloc_result alloc_pusch(slot_ue& ue, prb_grant dl_mask);
|
||||
alloc_result alloc_pdsch(slot_ue& ue, uint32_t ss_id, const prb_grant& dl_grant);
|
||||
alloc_result alloc_pusch(slot_ue& ue, const prb_grant& grant);
|
||||
|
||||
slot_point get_pdcch_tti() const { return pdcch_slot; }
|
||||
slot_point get_tti_rx() const { return pdcch_slot - TX_ENB_DELAY; }
|
||||
|
@ -105,13 +105,17 @@ public:
|
|||
const bwp_slot_grid& tx_slot_grid() const { return bwp_grid[pdcch_slot]; }
|
||||
bwp_slot_grid& tx_slot_grid() { return bwp_grid[pdcch_slot]; }
|
||||
|
||||
prb_bitmap occupied_dl_prbs(slot_point sl_tx, uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const
|
||||
{
|
||||
return bwp_grid[sl_tx].pdschs.occupied_prbs(ss_id, dci_fmt);
|
||||
}
|
||||
const prb_bitmap& occupied_ul_prbs(slot_point sl_tx) const { return bwp_grid[sl_tx].puschs.occupied_prbs(); }
|
||||
|
||||
srslog::basic_logger& logger;
|
||||
const bwp_params_t& cfg;
|
||||
|
||||
private:
|
||||
alloc_result
|
||||
verify_pdsch_space(bwp_slot_grid& pdsch_grid, bwp_slot_grid& pdcch_grid, bwp_slot_grid* uci_grid = nullptr) const;
|
||||
alloc_result verify_pusch_space(bwp_slot_grid& pusch_grid) const;
|
||||
alloc_result verify_uci_space(const bwp_slot_grid& uci_grid) const;
|
||||
alloc_result verify_ue_cfg(const ue_carrier_params_t& ue_cfg, harq_proc* harq) const;
|
||||
|
||||
bwp_res_grid& bwp_grid;
|
||||
|
@ -120,6 +124,8 @@ private:
|
|||
slot_ue_map_t& slot_ues;
|
||||
};
|
||||
|
||||
prb_grant find_optimal_dl_grant(bwp_slot_allocator& slot_alloc, const slot_ue& ue, uint32_t ss_id);
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
||||
|
||||
|
|
|
@ -48,35 +48,13 @@ inline bool is_rnti_type_valid_in_search_space(srsran_rnti_type_t rnti_type, srs
|
|||
return false;
|
||||
}
|
||||
|
||||
/// In case of Common SearchSpace, not all PRBs might be available
|
||||
void reduce_to_dl_coreset_bw(const bwp_params_t& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_format_nr_t dci_fmt,
|
||||
prb_grant& grant);
|
||||
|
||||
bool fill_dci_sib(prb_interval interv,
|
||||
uint32_t sib_idx,
|
||||
uint32_t si_ntx,
|
||||
const bwp_params_t& bwp_cfg,
|
||||
srsran_dci_dl_nr_t& dci);
|
||||
|
||||
bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci);
|
||||
|
||||
bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& dci);
|
||||
|
||||
/// Generate PDCCH DL DCI fields
|
||||
void fill_dl_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params_t& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_dl_nr_t& dci);
|
||||
void fill_dl_dci_ue_fields(const slot_ue& ue, srsran_dci_dl_nr_t& dci);
|
||||
|
||||
/// Generate PDCCH UL DCI fields
|
||||
void fill_ul_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params_t& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_ul_nr_t& dci);
|
||||
void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_ul_nr_t& dci);
|
||||
|
||||
/// Log UE state for slot being scheduled
|
||||
void log_sched_slot_ues(srslog::basic_logger& logger,
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
|
||||
inline bool contains_dci_format(const srsran_search_space_t& ss, srsran_dci_format_nr_t dci_fmt)
|
||||
{
|
||||
auto is_dci_fmt = [dci_fmt](const srsran_dci_format_nr_t& f) { return f == dci_fmt; };
|
||||
return std::any_of(&ss.formats[0], &ss.formats[ss.nof_formats], is_dci_fmt);
|
||||
}
|
||||
|
||||
//////////////////////////////////// CORESET Helpers ////////////////////////////////////////////
|
||||
|
||||
/// Get a range of active coresets in a PDCCH configuration
|
||||
|
|
|
@ -24,6 +24,10 @@ namespace srsenb {
|
|||
|
||||
namespace sched_nr_impl {
|
||||
|
||||
/// Helper function to fill DCI with BWP params
|
||||
void fill_dci_from_cfg(const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci);
|
||||
void fill_dci_from_cfg(const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& dci);
|
||||
|
||||
using coreset_bitmap = srsran::bounded_bitset<SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE * SRSRAN_CORESET_DURATION_MAX, true>;
|
||||
|
||||
class coreset_region
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SCHED_NR_PDSCH_H
|
||||
#define SRSRAN_SCHED_NR_PDSCH_H
|
||||
#ifndef SRSRAN_SCHED_NR_SCH_H
|
||||
#define SRSRAN_SCHED_NR_SCH_H
|
||||
|
||||
#include "srsenb/hdr/stack/mac/sched_common.h"
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_cfg.h"
|
||||
|
@ -76,8 +76,55 @@ private:
|
|||
bwp_rb_bitmap dl_prbs;
|
||||
};
|
||||
|
||||
using pusch_alloc_result = srsran::expected<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 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(); }
|
||||
ul_harq_proc* find_empty_ul_harq() { return ue->harq_ent.find_empty_ul_harq(); }
|
||||
|
||||
int find_ss_id(srsran_dci_format_nr_t dci_fmt) const;
|
||||
|
||||
void build_pdu(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu)
|
||||
{
|
||||
ue->pdu_builder.alloc_subpdus(rem_bytes, pdu);
|
||||
|
|
|
@ -14,7 +14,7 @@ set(SOURCES mac_nr.cc
|
|||
sched_nr_grant_allocator.cc
|
||||
sched_nr_harq.cc
|
||||
sched_nr_pdcch.cc
|
||||
sched_nr_pdsch.cc
|
||||
sched_nr_sch.cc
|
||||
sched_nr_cfg.cc
|
||||
sched_nr_helpers.cc
|
||||
sched_nr_bwp.cc
|
||||
|
|
|
@ -76,11 +76,11 @@ candidate_ss_list_t find_ss(const srsran_pdcch_cfg_nr_t& pdcch,
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bwp_slot_grid::bwp_slot_grid(const bwp_params_t& bwp_cfg_, uint32_t slot_idx_) :
|
||||
ul_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1),
|
||||
slot_idx(slot_idx_),
|
||||
cfg(&bwp_cfg_),
|
||||
pdcchs(bwp_cfg_, slot_idx_, dl.phy.pdcch_dl, dl.phy.pdcch_ul),
|
||||
pdschs(bwp_cfg_, slot_idx_, dl.phy.pdsch),
|
||||
puschs(bwp_cfg_, slot_idx_, ul.pusch),
|
||||
rar_softbuffer(harq_softbuffer_pool::get_instance().get_tx(bwp_cfg_.cfg.rb_width))
|
||||
{}
|
||||
|
||||
|
@ -88,13 +88,12 @@ void bwp_slot_grid::reset()
|
|||
{
|
||||
pdcchs.reset();
|
||||
pdschs.reset();
|
||||
ul_prbs.reset();
|
||||
puschs.reset();
|
||||
dl.phy.ssb.clear();
|
||||
dl.phy.nzp_csi_rs.clear();
|
||||
dl.data.clear();
|
||||
dl.rar.clear();
|
||||
dl.sib_idxs.clear();
|
||||
ul.pusch.clear();
|
||||
ul.pucch.clear();
|
||||
pending_acks.clear();
|
||||
}
|
||||
|
@ -122,36 +121,29 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx,
|
|||
static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0;
|
||||
|
||||
bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_slot];
|
||||
alloc_result ret = verify_pdsch_space(bwp_pdcch_slot, bwp_pdcch_slot);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Verify there is space in PDSCH
|
||||
ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss_id, dci_fmt, prbs);
|
||||
alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss_id, dci_fmt, prbs);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Allocate PDCCH
|
||||
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_si_pdcch(ss_id, aggr_idx);
|
||||
if (pdcch_result.is_error()) {
|
||||
logger.warning("SCHED: Cannot allocate SIB1 due to lack of PDCCH space.");
|
||||
logger.warning("SCHED: Cannot allocate SIB due to lack of PDCCH space.");
|
||||
return pdcch_result.error();
|
||||
}
|
||||
pdcch_dl_t pdcch = *pdcch_result.value();
|
||||
|
||||
// SI allocation successful.
|
||||
pdcch_dl_t& pdcch = *pdcch_result.value();
|
||||
|
||||
// Allocate PDSCH
|
||||
pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch.dci.ctx, prbs, pdcch.dci);
|
||||
|
||||
// Generate DCI for SIB
|
||||
pdcch.dci_cfg.coreset0_bw = srsran_coreset_get_bw(&cfg.cfg.pdcch.coreset[0]);
|
||||
if (not fill_dci_sib(prbs, si_idx, si_ntx, *bwp_grid.cfg, pdcch.dci)) {
|
||||
// Cancel on-going PDCCH allocation
|
||||
bwp_pdcch_slot.pdcchs.cancel_last_pdcch();
|
||||
return alloc_result::invalid_coderate;
|
||||
}
|
||||
pdcch.dci.mcs = 5;
|
||||
pdcch.dci.rv = 0;
|
||||
pdcch.dci.sii = si_idx == 0 ? 0 : 1;
|
||||
|
||||
// Generate PDSCH
|
||||
srsran_slot_cfg_t slot_cfg;
|
||||
|
@ -189,25 +181,6 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
|
|||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Verify there is space in PUSCH
|
||||
ret = verify_pusch_space(bwp_msg3_slot);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
ret = verify_pdsch_space(bwp_pdcch_slot, bwp_pdcch_slot);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
if (not bwp_pdcch_slot.dl.phy.ssb.empty()) {
|
||||
// TODO: support concurrent PDSCH and SSB
|
||||
logger.debug("SCHED: skipping RAR allocation. Cause: concurrent PDSCH and SSB not yet supported");
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
if (pending_rachs.size() > bwp_pdcch_slot.dl.rar.capacity() - bwp_pdcch_slot.dl.rar.size()) {
|
||||
logger.error("SCHED: Trying to allocate too many Msg3 grants in a single slot (%zd)", pending_rachs.size());
|
||||
return alloc_result::invalid_grant_params;
|
||||
}
|
||||
for (auto& rach : pending_rachs) {
|
||||
auto ue_it = slot_ues.find(rach.temp_crnti);
|
||||
if (ue_it == slot_ues.end()) {
|
||||
|
@ -216,47 +189,53 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
|
|||
return alloc_result::no_rnti_opportunity;
|
||||
}
|
||||
}
|
||||
srsran_sanity_check(not bwp_pdcch_slot.dl.rar.full(), "The #RARs should be below #PDSCHs");
|
||||
if (not bwp_pdcch_slot.dl.phy.ssb.empty()) {
|
||||
// TODO: support concurrent PDSCH and SSB
|
||||
logger.debug("SCHED: skipping RAR allocation. Cause: concurrent PDSCH and SSB not yet supported");
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
|
||||
// Verify there is space in PUSCH for Msg3s
|
||||
ret = bwp_msg3_slot.puschs.has_grant_space(pending_rachs.size());
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
// Check Msg3 RB collision
|
||||
uint32_t total_ul_nof_prbs = msg3_nof_prbs * pending_rachs.size();
|
||||
uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.nof_prbs(), false));
|
||||
prb_interval msg3_rbs = find_empty_interval_of_length(bwp_msg3_slot.ul_prbs.prbs(), total_ul_nof_rbgs);
|
||||
if (msg3_rbs.length() < total_ul_nof_rbgs) {
|
||||
uint32_t total_msg3_nof_prbs = msg3_nof_prbs * pending_rachs.size();
|
||||
prb_interval all_msg3_rbs =
|
||||
find_empty_interval_of_length(bwp_msg3_slot.puschs.occupied_prbs(), total_msg3_nof_prbs, 0);
|
||||
if (all_msg3_rbs.length() < total_msg3_nof_prbs) {
|
||||
logger.debug("SCHED: No space in PUSCH for Msg3.");
|
||||
return alloc_result::sch_collision;
|
||||
}
|
||||
|
||||
// Find PDCCH position
|
||||
// Allocate PDCCH position
|
||||
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_rar_pdcch(ra_rnti, aggr_idx);
|
||||
if (pdcch_result.is_error()) {
|
||||
// Could not find space in PDCCH
|
||||
return pdcch_result.error();
|
||||
}
|
||||
|
||||
// RAR allocation successful.
|
||||
pdcch_dl_t* pdcch = pdcch_result.value();
|
||||
auto& phy_cfg = slot_ues[pending_rachs[0].temp_crnti]->phy();
|
||||
pdcch->dci_cfg = phy_cfg.get_dci_cfg();
|
||||
pdcch_dl_t& pdcch = *pdcch_result.value();
|
||||
|
||||
// Allocate PDSCH
|
||||
pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch->dci.ctx, interv, pdcch->dci);
|
||||
pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch.dci.ctx, interv, pdcch.dci);
|
||||
|
||||
// Generate DCI for RAR with given RA-RNTI
|
||||
if (not fill_dci_rar(interv, ra_rnti, *bwp_grid.cfg, pdcch->dci)) {
|
||||
// Cancel on-going PDCCH allocation
|
||||
bwp_pdcch_slot.pdcchs.cancel_last_pdcch();
|
||||
return alloc_result::invalid_coderate;
|
||||
}
|
||||
auto& phy_cfg = slot_ues[pending_rachs[0].temp_crnti]->phy();
|
||||
pdcch.dci_cfg = phy_cfg.get_dci_cfg();
|
||||
pdcch.dci.mcs = 5;
|
||||
|
||||
// Generate RAR PDSCH
|
||||
// TODO: Properly fill Msg3 grants
|
||||
srsran_slot_cfg_t slot_cfg;
|
||||
slot_cfg.idx = pdcch_slot.to_uint();
|
||||
bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch->dci, pdsch.sch);
|
||||
bool success = phy_cfg.get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch);
|
||||
srsran_assert(success, "Error converting DCI to grant");
|
||||
pdsch.sch.grant.tb[0].softbuffer.tx = bwp_pdcch_slot.rar_softbuffer->get();
|
||||
|
||||
// Generate Msg3 grants in PUSCH
|
||||
uint32_t last_msg3 = msg3_rbs.start();
|
||||
uint32_t last_msg3 = all_msg3_rbs.start();
|
||||
const int mcs = 0, max_harq_msg3_retx = 4;
|
||||
slot_cfg.idx = msg3_slot.to_uint();
|
||||
bwp_pdcch_slot.dl.rar.emplace_back();
|
||||
|
@ -276,48 +255,35 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
|
|||
fill_dci_msg3(ue, *bwp_grid.cfg, rar_grant.msg3_dci);
|
||||
|
||||
// Generate PUSCH
|
||||
bwp_msg3_slot.ul.pusch.emplace_back();
|
||||
pusch_t& pusch = bwp_msg3_slot.ul.pusch.back();
|
||||
pusch_t& pusch = bwp_msg3_slot.puschs.alloc_pusch_unchecked(msg3_interv, rar_grant.msg3_dci);
|
||||
success = ue->phy().get_pusch_cfg(slot_cfg, rar_grant.msg3_dci, pusch.sch);
|
||||
srsran_assert(success, "Error converting DCI to PUSCH grant");
|
||||
pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get();
|
||||
ue.h_ul->set_tbs(pusch.sch.grant.tb[0].tbs);
|
||||
}
|
||||
bwp_msg3_slot.ul_prbs.add(msg3_rbs);
|
||||
|
||||
return alloc_result::success;
|
||||
}
|
||||
|
||||
// ue is the UE (1 only) that will be allocated
|
||||
// func computes the grant allocation for this UE
|
||||
alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant)
|
||||
alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, uint32_t ss_id, const prb_grant& dl_grant)
|
||||
{
|
||||
static const uint32_t aggr_idx = 2;
|
||||
static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0;
|
||||
static const std::array<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_pdsch_slot = bwp_grid[ue.pdsch_slot];
|
||||
bwp_slot_grid& bwp_uci_slot = bwp_grid[ue.uci_slot]; // UCI : UL control info
|
||||
|
||||
// Choose SearchSpace + DCI format
|
||||
srsran_rnti_type_t rnti_type = srsran_rnti_type_c;
|
||||
// Choose the ss_id the highest number of candidates
|
||||
candidate_ss_list_t ss_candidates = find_ss(ue->phy().pdcch, aggr_idx, rnti_type, dci_fmt_list);
|
||||
if (ss_candidates.empty()) {
|
||||
// Could not find space in PDCCH
|
||||
logger.warning("SCHED: No PDCCH candidates for any of the rnti=0x%x search spaces", ue->rnti);
|
||||
return alloc_result::no_cch_space;
|
||||
}
|
||||
const srsran_search_space_t& ss = *ss_candidates[0];
|
||||
|
||||
// Verify there is space in PDSCH
|
||||
alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss.id, dci_fmt, dl_grant);
|
||||
alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss_id, dci_fmt, dl_grant);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
alloc_result result = verify_pdsch_space(bwp_pdsch_slot, bwp_pdcch_slot, &bwp_uci_slot);
|
||||
alloc_result result = verify_uci_space(bwp_uci_slot);
|
||||
if (result != alloc_result::success) {
|
||||
return result;
|
||||
}
|
||||
|
@ -335,13 +301,11 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant)
|
|||
// TODO
|
||||
|
||||
// Find space and allocate PDCCH
|
||||
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_dl_pdcch(rnti_type, ss.id, aggr_idx, ue.cfg());
|
||||
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_dl_pdcch(rnti_type, ss_id, aggr_idx, ue.cfg());
|
||||
if (pdcch_result.is_error()) {
|
||||
// Could not find space in PDCCH
|
||||
return pdcch_result.error();
|
||||
}
|
||||
|
||||
// DL allocation successful.
|
||||
pdcch_dl_t& pdcch = *pdcch_result.value();
|
||||
|
||||
// Allocate PDSCH
|
||||
|
@ -361,7 +325,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant)
|
|||
const static float max_R = 0.93;
|
||||
while (true) {
|
||||
// Generate PDCCH
|
||||
fill_dl_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch.dci.ctx.location, pdcch.dci);
|
||||
fill_dl_dci_ue_fields(ue, pdcch.dci);
|
||||
pdcch.dci.pucch_resource = 0;
|
||||
pdcch.dci.dai = std::count_if(bwp_uci_slot.pending_acks.begin(),
|
||||
bwp_uci_slot.pending_acks.end(),
|
||||
|
@ -407,28 +371,21 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, prb_grant dl_grant)
|
|||
return alloc_result::success;
|
||||
}
|
||||
|
||||
alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant)
|
||||
alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const prb_grant& ul_grant)
|
||||
{
|
||||
static const uint32_t aggr_idx = 2;
|
||||
static const std::array<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_pusch_slot = bwp_grid[ue.pusch_slot];
|
||||
alloc_result ret = verify_pusch_space(bwp_pusch_slot);
|
||||
|
||||
alloc_result ret = verify_ue_cfg(ue.cfg(), ue.h_ul);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
ret = verify_ue_cfg(ue.cfg(), ue.h_ul);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
pdcch_ul_list_t& pdcchs = bwp_pdcch_slot.dl.phy.pdcch_ul;
|
||||
if (bwp_pusch_slot.ul_prbs.collides(ul_grant)) {
|
||||
return alloc_result::sch_collision;
|
||||
}
|
||||
|
||||
// Choose SearchSpace + DCI format
|
||||
srsran_rnti_type_t rnti_type = srsran_rnti_type_c;
|
||||
candidate_ss_list_t ss_candidates = find_ss(ue->phy().pdcch, aggr_idx, rnti_type, dci_fmt_list);
|
||||
if (ss_candidates.empty()) {
|
||||
// Could not find space in PDCCH
|
||||
|
@ -437,15 +394,23 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant)
|
|||
}
|
||||
const srsran_search_space_t& ss = *ss_candidates[0];
|
||||
|
||||
// Verify if PUSCH allocation is valid
|
||||
ret = bwp_pusch_slot.puschs.is_grant_valid(ss.type, ul_grant);
|
||||
if (ret != alloc_result::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto pdcch_result = bwp_pdcch_slot.pdcchs.alloc_ul_pdcch(ss.id, aggr_idx, ue.cfg());
|
||||
if (pdcch_result.is_error()) {
|
||||
// Could not find space in PDCCH
|
||||
logger.debug("Could not find PDCCH space for rnti=0x%x PUSCH allocation", ue->rnti);
|
||||
return pdcch_result.error();
|
||||
}
|
||||
pdcch_ul_t* pdcch = pdcch_result.value();
|
||||
|
||||
// Allocation Successful
|
||||
pdcch_ul_t& pdcch = *pdcch_result.value();
|
||||
|
||||
// Allocate PUSCH
|
||||
pusch_t& pusch = bwp_pusch_slot.puschs.alloc_pusch_unchecked(ul_grant, pdcch.dci);
|
||||
|
||||
if (ue.h_ul->empty()) {
|
||||
int mcs = ue->fixed_pusch_mcs();
|
||||
|
@ -456,17 +421,15 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant)
|
|||
srsran_assert(success, "Failed to allocate UL HARQ retx");
|
||||
}
|
||||
|
||||
// Generate PDCCH
|
||||
fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss.id, pdcch->dci.ctx.location, pdcch->dci);
|
||||
pdcch->dci_cfg = ue->phy().get_dci_cfg();
|
||||
// Generate PUSCH
|
||||
bwp_pusch_slot.ul_prbs |= ul_grant;
|
||||
bwp_pusch_slot.ul.pusch.emplace_back();
|
||||
pusch_t& pusch = bwp_pusch_slot.ul.pusch.back();
|
||||
// Generate PDCCH content
|
||||
fill_ul_dci_ue_fields(ue, pdcch.dci);
|
||||
pdcch.dci_cfg = ue->phy().get_dci_cfg();
|
||||
|
||||
// Generate PUSCH content
|
||||
srsran_slot_cfg_t slot_cfg;
|
||||
slot_cfg.idx = ue.pusch_slot.to_uint();
|
||||
pusch.pid = ue.h_ul->pid;
|
||||
bool success = ue->phy().get_pusch_cfg(slot_cfg, pdcch->dci, pusch.sch);
|
||||
bool success = ue->phy().get_pusch_cfg(slot_cfg, pdcch.dci, pusch.sch);
|
||||
srsran_assert(success, "Error converting DCI to PUSCH grant");
|
||||
pusch.sch.grant.tb[0].softbuffer.rx = ue.h_ul->get_softbuffer().get();
|
||||
if (ue.h_ul->nof_retx() == 0) {
|
||||
|
@ -478,37 +441,12 @@ alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, prb_grant ul_grant)
|
|||
return alloc_result::success;
|
||||
}
|
||||
|
||||
alloc_result bwp_slot_allocator::verify_pdsch_space(bwp_slot_grid& pdsch_grid,
|
||||
bwp_slot_grid& pdcch_grid,
|
||||
bwp_slot_grid* uci_grid) const
|
||||
alloc_result bwp_slot_allocator::verify_uci_space(const 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()) {
|
||||
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()) {
|
||||
logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", pusch_grid.slot_idx);
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
if (pusch_grid.ul.pusch.full()) {
|
||||
logger.warning("SCHED: Maximum number of PUSCH allocations reached");
|
||||
return alloc_result::no_grant_space;
|
||||
}
|
||||
return alloc_result::success;
|
||||
}
|
||||
|
||||
|
@ -526,5 +464,20 @@ alloc_result bwp_slot_allocator::verify_ue_cfg(const ue_carrier_params_t& ue_cfg
|
|||
return alloc_result::success;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
prb_grant find_optimal_dl_grant(bwp_slot_allocator& slot_alloc, const slot_ue& ue, uint32_t ss_id)
|
||||
{
|
||||
static const srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; // TODO: Support more DCI formats
|
||||
|
||||
const bwp_slot_grid& sl_grid = slot_alloc.res_grid()[ue.pdsch_slot];
|
||||
|
||||
prb_bitmap used_prb_mask = sl_grid.pdschs.occupied_prbs(ss_id, dci_fmt);
|
||||
|
||||
prb_interval prb_interv = find_empty_interval_of_length(used_prb_mask, used_prb_mask.size(), 0);
|
||||
|
||||
return prb_interv;
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -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>
|
||||
void fill_dci_harq(const slot_ue& ue, DciDlOrUl& dci)
|
||||
{
|
||||
|
@ -70,25 +35,6 @@ void fill_dci_harq(const slot_ue& ue, DciDlOrUl& dci)
|
|||
dci.rv = rv_idx[h->nof_retx() % 4];
|
||||
}
|
||||
|
||||
void fill_dci_grant(const bwp_params_t& bwp_cfg, const prb_grant& grant, srsran_dci_ul_nr_t& dci)
|
||||
{
|
||||
dci.time_domain_assigment = 0;
|
||||
if (grant.is_alloc_type0()) {
|
||||
dci.freq_domain_assigment = grant.rbgs().to_uint64();
|
||||
} else {
|
||||
uint32_t nof_prb = bwp_cfg.nof_prb();
|
||||
dci.freq_domain_assigment = srsran_ra_nr_type1_riv(nof_prb, grant.prbs().start(), grant.prbs().length());
|
||||
}
|
||||
}
|
||||
|
||||
bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci)
|
||||
{
|
||||
dci.mcs = 5;
|
||||
// TODO: Fill
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& msg3_dci)
|
||||
{
|
||||
// Fill DCI context
|
||||
|
@ -103,18 +49,17 @@ bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul
|
|||
}
|
||||
|
||||
// Fill DCI content
|
||||
fill_dci_common(bwp_cfg, msg3_dci);
|
||||
fill_dci_from_cfg(bwp_cfg, msg3_dci);
|
||||
msg3_dci.time_domain_assigment = 0;
|
||||
uint32_t nof_prb = bwp_cfg.nof_prb();
|
||||
msg3_dci.freq_domain_assigment =
|
||||
srsran_ra_nr_type1_riv(nof_prb, ue.h_ul->prbs().prbs().start(), ue.h_ul->prbs().prbs().length());
|
||||
fill_dci_harq(ue, msg3_dci);
|
||||
fill_dci_grant(bwp_cfg, ue.h_ul->prbs(), msg3_dci);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fill_dl_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params_t& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_dl_nr_t& dci)
|
||||
void fill_dl_dci_ue_fields(const slot_ue& ue, srsran_dci_dl_nr_t& dci)
|
||||
{
|
||||
fill_dci_harq(ue, dci);
|
||||
if (dci.ctx.format == srsran_dci_format_nr_1_0) {
|
||||
|
@ -124,18 +69,9 @@ void fill_dl_dci_ue_fields(const slot_ue& ue,
|
|||
}
|
||||
}
|
||||
|
||||
void fill_ul_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params_t& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_ul_nr_t& dci)
|
||||
void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_ul_nr_t& dci)
|
||||
{
|
||||
bool ret = ue->phy().get_dci_ctx_pusch_rnti_c(ss_id, dci_pos, ue->rnti, dci.ctx);
|
||||
srsran_assert(ret, "Invalid DL DCI format");
|
||||
|
||||
fill_dci_common(bwp_cfg, dci);
|
||||
fill_dci_harq(ue, dci);
|
||||
fill_dci_grant(bwp_cfg, ue.h_ul->prbs(), dci);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_pdsch.h"
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_sch.h"
|
||||
#include "srsran/common/string_helpers.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
@ -56,7 +56,7 @@ alloc_result pdsch_allocator::is_grant_valid(uint32_t ss_id,
|
|||
|
||||
// No space in Scheduler PDSCH output list
|
||||
if (pdschs.full()) {
|
||||
log_alloc_failure(bwp_cfg.logger.warning, ss_id, "SearchSpace has not been configured.");
|
||||
log_alloc_failure(bwp_cfg.logger.warning, ss_id, "Maximum number of PDSCHs={} reached.", pdschs.size());
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ alloc_result pdsch_allocator::is_grant_valid(uint32_t ss_id,
|
|||
return alloc_result::invalid_grant_params;
|
||||
}
|
||||
|
||||
if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss_id)) {
|
||||
if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss->type)) {
|
||||
// In case of common SearchSpaces, the PRBs must be contiguous
|
||||
if (grant.is_alloc_type0()) {
|
||||
log_alloc_failure(bwp_cfg.logger.warning, ss_id, "AllocType0 not allowed in common SearchSpace.");
|
||||
|
@ -142,5 +142,120 @@ void pdsch_allocator::cancel_last_pdsch()
|
|||
pdschs.pop_back();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <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 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_) :
|
||||
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
|
||||
* @param ue_db map of "slot_ue"
|
||||
* @param rr_count starting index to select next UE
|
||||
* @param p callable that returns true if UE allocation was successful
|
||||
* @param p callable with signature "bool(slot_ue&)" that returns true if UE allocation was successful
|
||||
* @return true if a UE was allocated
|
||||
*/
|
||||
template <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)
|
||||
{
|
||||
// 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())) {
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})) {
|
||||
};
|
||||
if (round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), retx_ue_function)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Move on to new txs
|
||||
round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), [&slot_alloc](slot_ue& ue) {
|
||||
auto newtx_ue_function = [&slot_alloc](slot_ue& ue) {
|
||||
if (ue.dl_bytes > 0 and ue.h_dl != nullptr and ue.h_dl->empty()) {
|
||||
alloc_result res = slot_alloc.alloc_pdsch(ue, prb_interval{0, slot_alloc.cfg.cfg.rb_width});
|
||||
int ss_id = ue.find_ss_id(srsran_dci_format_nr_1_0);
|
||||
if (ss_id < 0) {
|
||||
return false;
|
||||
}
|
||||
prb_grant prbs = find_optimal_dl_grant(slot_alloc, ue, ss_id);
|
||||
alloc_result res = slot_alloc.alloc_pdsch(ue, ss_id, prbs);
|
||||
if (res == alloc_result::success) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
round_robin_apply(ue_db, slot_alloc.get_pdcch_tti().to_uint(), newtx_ue_function);
|
||||
}
|
||||
|
||||
void sched_nr_time_rr::sched_ul_users(slot_ue_map_t& ue_db, bwp_slot_allocator& slot_alloc)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_ue.h"
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_pdcch.h"
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_helpers.h"
|
||||
#include "srsran/common/string_helpers.h"
|
||||
#include "srsran/mac/mac_sch_pdu_nr.h"
|
||||
|
||||
|
@ -83,6 +83,30 @@ slot_ue::slot_ue(ue_carrier& ue_, slot_point slot_tx_, uint32_t dl_pending_bytes
|
|||
}
|
||||
}
|
||||
|
||||
int slot_ue::find_ss_id(srsran_dci_format_nr_t dci_fmt) const
|
||||
{
|
||||
static const uint32_t aggr_idx = 2; // TODO: Make it dynamic
|
||||
static const srsran_rnti_type_t rnti_type = srsran_rnti_type_c; // TODO: Use TC-RNTI for Msg4
|
||||
|
||||
auto active_ss_lst = view_active_search_spaces(cfg().phy().pdcch);
|
||||
|
||||
for (const srsran_search_space_t& ss : active_ss_lst) {
|
||||
// Prioritize UE-dedicated SearchSpaces
|
||||
if (ss.type == srsran_search_space_type_ue and ss.nof_candidates[aggr_idx] > 0 and
|
||||
contains_dci_format(ss, dci_fmt) and is_rnti_type_valid_in_search_space(rnti_type, ss.type)) {
|
||||
return ss.id;
|
||||
}
|
||||
}
|
||||
// Search Common SearchSpaces
|
||||
for (const srsran_search_space_t& ss : active_ss_lst) {
|
||||
if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss.type) and ss.nof_candidates[aggr_idx] > 0 and
|
||||
contains_dci_format(ss, dci_fmt) and is_rnti_type_valid_in_search_space(rnti_type, ss.type)) {
|
||||
return ss.id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ue_carrier::ue_carrier(uint16_t rnti_,
|
||||
|
|
|
@ -30,9 +30,9 @@ add_executable(sched_nr_pdcch_test sched_nr_pdcch_test.cc)
|
|||
target_link_libraries(sched_nr_pdcch_test srsgnb_mac sched_nr_test_suite srsran_common)
|
||||
add_nr_test(sched_nr_pdcch_test sched_nr_pdcch_test)
|
||||
|
||||
add_executable(sched_nr_pdsch_test sched_nr_pdsch_test.cc)
|
||||
target_link_libraries(sched_nr_pdsch_test srsgnb_mac sched_nr_test_suite srsran_common)
|
||||
add_nr_test(sched_nr_pdsch_test sched_nr_pdsch_test)
|
||||
add_executable(sched_nr_sch_test sched_nr_sch_test.cc)
|
||||
target_link_libraries(sched_nr_sch_test srsgnb_mac sched_nr_test_suite srsran_common)
|
||||
add_nr_test(sched_nr_sch_test sched_nr_sch_test)
|
||||
|
||||
add_executable(sched_nr_rar_test sched_nr_rar_test.cc)
|
||||
target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common)
|
||||
|
|
|
@ -123,7 +123,9 @@ inline sched_nr_interface::ue_cfg_t get_default_ue_cfg(
|
|||
|
||||
inline sched_nr_interface::cell_cfg_t get_default_sa_cell_cfg_common()
|
||||
{
|
||||
sched_nr_interface::cell_cfg_t cell_cfg = get_default_cell_cfg();
|
||||
srsran::phy_cfg_nr_default_t::reference_cfg_t ref;
|
||||
ref.duplex = srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_FDD;
|
||||
sched_nr_interface::cell_cfg_t cell_cfg = get_default_cell_cfg(srsran::phy_cfg_nr_default_t{ref});
|
||||
cell_cfg.bwps[0].pdcch.coreset_present[0] = true;
|
||||
cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(52);
|
||||
cell_cfg.bwps[0].pdcch.coreset[0].offset_rb = 1;
|
||||
|
|
|
@ -104,7 +104,7 @@ void test_single_prach()
|
|||
result = run_slot();
|
||||
if (bwpparams.slots[current_slot.slot_idx()].is_dl and
|
||||
bwpparams.slots[(current_slot + bwpparams.pusch_ra_list[0].msg3_delay).slot_idx()].is_ul) {
|
||||
TESTASSERT_EQ(result->dl.phy.pdcch_dl.size(), 1);
|
||||
TESTASSERT_EQ(1, result->dl.phy.pdcch_dl.size());
|
||||
const auto& pdcch = result->dl.phy.pdcch_dl[0];
|
||||
TESTASSERT_EQ(pdcch.dci.ctx.rnti, ra_rnti);
|
||||
TESTASSERT_EQ(pdcch.dci.ctx.rnti_type, srsran_rnti_type_ra);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "sched_nr_cfg_generators.h"
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_interface_utils.h"
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_pdsch.h"
|
||||
#include "srsgnb/hdr/stack/mac/sched_nr_sch.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
extern "C" {
|
||||
#include "srsran/phy/common/sliv.h"
|
||||
|
@ -80,7 +80,7 @@ void test_dci_freq_assignment(const bwp_params_t& bwp_params, prb_interval grant
|
|||
TESTASSERT(allocated_prbs == grant);
|
||||
}
|
||||
|
||||
void test_si_sched()
|
||||
void test_si()
|
||||
{
|
||||
srsran::test_delimit_logger delimiter{"Test PDSCH SI Allocation"};
|
||||
|
||||
|
@ -139,7 +139,7 @@ void test_si_sched()
|
|||
}
|
||||
}
|
||||
|
||||
void test_rar_sched()
|
||||
void test_rar()
|
||||
{
|
||||
srsran::test_delimit_logger delimiter{"Test PDSCH RAR Allocation"};
|
||||
static const uint32_t ss_id = 1;
|
||||
|
@ -197,7 +197,7 @@ void test_rar_sched()
|
|||
}
|
||||
}
|
||||
|
||||
void test_ue_sched()
|
||||
void test_ue_pdsch()
|
||||
{
|
||||
srsran::test_delimit_logger delimiter{"Test PDSCH UE Allocation"};
|
||||
|
||||
|
@ -266,7 +266,7 @@ void test_ue_sched()
|
|||
}
|
||||
}
|
||||
|
||||
void test_multi_sched()
|
||||
void test_multi_pdsch()
|
||||
{
|
||||
srsran::test_delimit_logger delimiter{"Test Multiple PDSCH Allocations"};
|
||||
|
||||
|
@ -354,6 +354,62 @@ void test_multi_sched()
|
|||
TESTASSERT_EQ(0, pdsch_sched.occupied_prbs(2, srsran_dci_format_nr_1_0).count());
|
||||
}
|
||||
|
||||
void test_multi_pusch()
|
||||
{
|
||||
srsran::test_delimit_logger delimiter{"Test Multiple PUSCH Allocations"};
|
||||
|
||||
// Create Cell and UE configs
|
||||
sched_nr_impl::cell_cfg_t cell_cfg = get_cell_cfg();
|
||||
sched_nr_impl::ue_cfg_t uecfg = get_ue_cfg(cell_cfg);
|
||||
sched_nr_interface::sched_args_t sched_args;
|
||||
bwp_params_t bwp_params{cell_cfg, sched_args, 0, 0};
|
||||
ue_carrier_params_t ue_cc{0x4601, bwp_params, uecfg};
|
||||
ue_carrier_params_t ue_cc2{0x4602, bwp_params, uecfg};
|
||||
|
||||
pusch_list_t puschs;
|
||||
pusch_alloc_result alloc_res;
|
||||
|
||||
pusch_allocator pusch_sched(bwp_params, 0, puschs);
|
||||
|
||||
pdcch_ul_t pdcch_ue1, pdcch_ue2;
|
||||
pdcch_ue1.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 1, srsran_rnti_type_c, 0x4601);
|
||||
pdcch_ue2.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 2, srsran_rnti_type_c, 0x4602);
|
||||
|
||||
// Allocate UE in common SearchSpace
|
||||
uint32_t ss_id = 1;
|
||||
pdcch_ul_t* pdcch = &pdcch_ue1;
|
||||
prb_bitmap used_prbs = pusch_sched.occupied_prbs();
|
||||
uint32_t ue_grant_size = 10;
|
||||
prb_interval ue_grant = find_empty_interval_of_length(used_prbs, ue_grant_size);
|
||||
TESTASSERT_EQ(alloc_result::success, pusch_sched.is_grant_valid(srsran_search_space_type_common_1, ue_grant));
|
||||
alloc_res = pusch_sched.alloc_pusch(pdcch->dci.ctx, ue_grant, pdcch->dci);
|
||||
TESTASSERT(alloc_res.has_value());
|
||||
prb_bitmap used_prbs_ue1 = pusch_sched.occupied_prbs();
|
||||
TESTASSERT_EQ(used_prbs_ue1.count(), used_prbs.count() + ue_grant.length());
|
||||
TESTASSERT_EQ(alloc_result::sch_collision,
|
||||
pusch_sched.is_grant_valid(srsran_search_space_type_common_1, ue_grant, false));
|
||||
|
||||
prb_bitmap last_prb_bitmap(used_prbs.size());
|
||||
last_prb_bitmap.fill(ue_grant.start(), ue_grant.stop());
|
||||
fmt::print("C-RNTI allocated in Common SearchSpace. Occupied PRBs:\n{:b} -> {:b}\n", last_prb_bitmap, used_prbs_ue1);
|
||||
|
||||
// Allocate UE in dedicated SearchSpace
|
||||
ss_id = 2;
|
||||
pdcch = &pdcch_ue2;
|
||||
used_prbs = pusch_sched.occupied_prbs();
|
||||
prb_interval ue2_grant = find_empty_interval_of_length(used_prbs, used_prbs.size());
|
||||
TESTASSERT_EQ(alloc_result::success, pusch_sched.is_grant_valid(srsran_search_space_type_ue, ue2_grant));
|
||||
alloc_res = pusch_sched.alloc_pusch(pdcch->dci.ctx, ue2_grant, pdcch->dci);
|
||||
TESTASSERT(alloc_res.has_value());
|
||||
prb_bitmap used_prbs_ue2 = pusch_sched.occupied_prbs();
|
||||
TESTASSERT_EQ(used_prbs_ue2.count(), used_prbs.count() + ue2_grant.length());
|
||||
TESTASSERT_EQ(alloc_result::sch_collision, pusch_sched.is_grant_valid(srsran_search_space_type_ue, ue2_grant, false));
|
||||
|
||||
last_prb_bitmap.reset();
|
||||
last_prb_bitmap.fill(ue2_grant.start(), ue2_grant.stop());
|
||||
fmt::print("C-RNTI allocated in Common SearchSpace. Occupied PRBs:\n{:b} -> {:b}\n", last_prb_bitmap, used_prbs_ue2);
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
int main()
|
||||
|
@ -368,8 +424,9 @@ int main()
|
|||
// Start the log backend.
|
||||
srslog::init();
|
||||
|
||||
srsenb::test_si_sched();
|
||||
srsenb::test_rar_sched();
|
||||
srsenb::test_ue_sched();
|
||||
srsenb::test_multi_sched();
|
||||
srsenb::test_si();
|
||||
srsenb::test_rar();
|
||||
srsenb::test_ue_pdsch();
|
||||
srsenb::test_multi_pdsch();
|
||||
srsenb::test_multi_pusch();
|
||||
}
|
Loading…
Reference in New Issue