sched,nr: add RAR scheduler inspired in LTE one

This commit is contained in:
Francisco Paisana 2021-07-06 18:16:04 +01:00
parent 4f0b954cde
commit 2db8b8d876
15 changed files with 456 additions and 94 deletions

View File

@ -27,7 +27,8 @@ namespace srsenb {
namespace sched_nr_impl {
class sched_worker_manager;
}
class cell_sched;
} // namespace sched_nr_impl
class ue_event_manager;
class sched_result_manager;
@ -66,6 +67,9 @@ private:
// management of Sched Result buffering
std::unique_ptr<sched_result_manager> pending_results;
// management of cell resources
std::vector<std::unique_ptr<sched_nr_impl::cell_sched> > cells;
};
} // namespace srsenb

View File

@ -0,0 +1,79 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_BWP_H
#define SRSRAN_SCHED_NR_BWP_H
#include "sched_nr_cfg.h"
#include "sched_nr_rb_grid.h"
#include "srsran/adt/pool/cached_alloc.h"
namespace srsenb {
namespace sched_nr_impl {
using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t;
struct pending_rar_t {
uint16_t ra_rnti = 0;
tti_point prach_tti;
srsran::bounded_vector<dl_sched_rar_info_t, sched_interface::MAX_RAR_LIST> msg3_grant;
};
/// RAR/Msg3 scheduler
class ra_sched
{
public:
explicit ra_sched(const sched_cell_params& cell_cfg_);
int dl_rach_info(const dl_sched_rar_info_t& rar_info);
void run_slot(bwp_slot_allocator& slot_grid);
size_t empty() const { return pending_rars.empty(); }
private:
alloc_result
allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc);
const sched_cell_params* cell_cfg = nullptr;
srslog::basic_logger& logger;
srsran::deque<pending_rar_t> pending_rars;
};
class bwp_sched
{
public:
explicit bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_);
const sched_cell_params* cell_cfg;
const uint32_t bwp_id;
// channel-specific schedulers
ra_sched ra;
// Pending allocations
bwp_res_grid grid;
};
class cell_sched
{
public:
srsran::bounded_vector<bwp_sched, SCHED_NR_MAX_BWP_PER_CELL> bwps;
explicit cell_sched(const sched_cell_params& cell_cfg_);
const sched_cell_params* cfg;
};
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_BWP_H

View File

@ -33,6 +33,7 @@ using pucch_list_t = sched_nr_interface::pucch_list_t;
using sched_cfg_t = sched_nr_interface::sched_cfg_t;
using cell_cfg_t = sched_nr_interface::cell_cfg_t;
using bwp_cfg_t = sched_nr_interface::bwp_cfg_t;
struct sched_cell_params {
const uint32_t cc;
@ -49,8 +50,51 @@ struct sched_params {
explicit sched_params(const sched_cfg_t& sched_cfg_);
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using rbgmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using pdcchmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using rbgmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using pdcch_cce_pos_list = srsran::bounded_vector<uint32_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>;
using bwp_cce_pos_list = std::array<std::array<pdcch_cce_pos_list, MAX_NOF_AGGR_LEVELS>, SRSRAN_NOF_SF_X_FRAME>;
void get_dci_locs(const srsran_coreset_t& coreset,
const srsran_search_space_t& search_space,
uint16_t rnti,
bwp_cce_pos_list& cce_locs);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using ue_cfg_t = sched_nr_interface::ue_cfg_t;
using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t;
class ue_cfg_extended : public ue_cfg_t
{
public:
struct search_space_params {
srsran_search_space_t* cfg = nullptr;
};
struct coreset_params {
srsran_coreset_t* cfg = nullptr;
std::vector<search_space_params*> ss_list;
bwp_cce_pos_list cce_positions;
};
struct bwp_params {
std::vector<search_space_params> search_spaces;
std::vector<coreset_params> coresets;
};
struct cc_params {
srsran::bounded_vector<bwp_params, SCHED_NR_MAX_BWP_PER_CELL> bwps;
};
uint16_t rnti;
std::vector<cc_params> cc_params;
ue_cfg_extended() = default;
explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg);
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct resource_guard {
public:
@ -92,44 +136,6 @@ private:
bool flag = false;
};
using pdcch_cce_pos_list = srsran::bounded_vector<uint32_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>;
using bwp_cce_pos_list = std::array<std::array<pdcch_cce_pos_list, MAX_NOF_AGGR_LEVELS>, SRSRAN_NOF_SF_X_FRAME>;
void get_dci_locs(const srsran_coreset_t& coreset,
const srsran_search_space_t& search_space,
uint16_t rnti,
bwp_cce_pos_list& cce_locs);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using ue_cfg_t = sched_nr_interface::ue_cfg_t;
using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t;
class ue_cfg_extended : public ue_cfg_t
{
public:
struct search_space_params {
srsran_search_space_t* cfg = nullptr;
};
struct coreset_params {
srsran_coreset_t* cfg = nullptr;
std::vector<search_space_params*> ss_list;
bwp_cce_pos_list cce_positions;
};
struct bwp_params {
std::vector<search_space_params> search_spaces;
std::vector<coreset_params> coresets;
};
struct cc_params {
srsran::bounded_vector<bwp_params, SCHED_NR_MAX_BWP_PER_CELL> bwps;
};
uint16_t rnti;
std::vector<cc_params> cc_params;
ue_cfg_extended() = default;
explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg);
};
} // namespace sched_nr_impl
} // namespace srsenb

View File

@ -26,7 +26,7 @@ namespace srsenb {
const static size_t SCHED_NR_MAX_CARRIERS = 4;
const static uint16_t SCHED_NR_INVALID_RNTI = 0;
const static size_t SCHED_NR_MAX_NOF_RBGS = 25;
const static size_t SCHED_NR_MAX_NOF_RBGS = 17;
const static size_t SCHED_NR_MAX_TB = 1;
const static size_t SCHED_NR_MAX_HARQ = 16;
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2;
@ -52,14 +52,17 @@ public:
using pusch_td_res_alloc_list = srsran::bounded_vector<pusch_td_res_alloc, MAX_GRANTS>;
struct bwp_cfg_t {
uint32_t bwp_id = 1;
uint32_t start_rb = 0;
uint32_t rb_width = 100;
uint32_t bwp_id = 1;
uint32_t start_rb = 0;
uint32_t rb_width = 100;
srsran_sch_hl_cfg_nr_t pdsch = {};
srsran_sch_hl_cfg_nr_t pusch = {};
std::array<srsran::optional<srsran_coreset_t>, SRSRAN_UE_DL_NR_MAX_NOF_CORESET> coresets;
};
struct cell_cfg_t {
uint32_t rar_window_size;
uint32_t nof_prb = 100;
uint32_t nof_rbg = 25;
srsran_tdd_config_nr_t tdd = {};
@ -82,6 +85,16 @@ public:
srsran::phy_cfg_nr_t phy_cfg = {};
};
////// RACH //////
struct dl_sched_rar_info_t {
uint32_t preamble_idx;
uint32_t ta_cmd;
uint16_t temp_crnti;
uint32_t msg3_size;
uint32_t prach_tti;
};
///// Sched Result /////
using dl_sched_t = mac_interface_phy_nr::dl_sched_t;

View File

@ -25,7 +25,7 @@ namespace sched_nr_impl {
using coreset_bitmap = srsran::bounded_bitset<SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE * SRSRAN_CORESET_DURATION_MAX, true>;
enum class pdcch_grant_type_t { sib, dl_data, ul_data };
enum class pdcch_grant_type_t { sib, rar, dl_data, ul_data };
class slot_ue;

View File

@ -10,8 +10,8 @@
*
*/
#ifndef SRSRAN_SCHED_NR_PHY_HELPERS_H
#define SRSRAN_SCHED_NR_PHY_HELPERS_H
#ifndef SRSRAN_SCHED_NR_PHY_H
#define SRSRAN_SCHED_NR_PHY_H
#include "sched_nr_cfg.h"
@ -21,6 +21,16 @@ namespace sched_nr_impl {
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2);
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2);
using pdsch_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using pusch_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using rbg_interval = srsran::interval<uint32_t>;
rbg_interval find_empty_rbg_interval(const pdsch_bitmap& bitmap, uint32_t max_nof_rbgs);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci);
class slot_ue;
void fill_dci_ue_cfg(const slot_ue& ue,
const rbgmask_t& rbgmask,
@ -44,4 +54,4 @@ pucch_resource_grant find_pucch_resource(const slot_ue& ue, const rbgmask_t& rbg
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_PHY_HELPERS_H
#endif // SRSRAN_SCHED_NR_PHY_H

View File

@ -17,13 +17,15 @@
#include "lib/include/srsran/adt/circular_array.h"
#include "sched_nr_interface.h"
#include "sched_nr_pdcch.h"
#include "sched_nr_phy.h"
#include "sched_nr_ue.h"
namespace srsenb {
namespace sched_nr_impl {
using pdsch_bitmap = srsran::bounded_bitset<25, true>;
using pusch_bitmap = srsran::bounded_bitset<25, true>;
struct pending_rar_t;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const static size_t MAX_CORESET_PER_BWP = 3;
using slot_coreset_list = srsran::bounded_vector<coreset_region, MAX_CORESET_PER_BWP>;
@ -54,35 +56,35 @@ struct bwp_res_grid {
const sched_cell_params& cell_params() const { return *cell_cfg; }
const bwp_cfg_t& bwp_cfg() const { return cell_cfg->cell_cfg.bwps[id() - 1]; }
private:
uint32_t bwp_id;
const sched_cell_params* cell_cfg = nullptr;
private:
uint32_t bwp_id;
srsran::bounded_vector<bwp_slot_grid, TTIMOD_SZ> slots;
};
struct cell_res_grid {
const sched_cell_params* cell_cfg = nullptr;
srsran::bounded_vector<bwp_res_grid, SCHED_NR_MAX_BWP_PER_CELL> bwps;
explicit cell_res_grid(const sched_cell_params& cell_cfg);
};
class slot_bwp_sched
class bwp_slot_allocator
{
public:
explicit slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_);
explicit bwp_slot_allocator(bwp_res_grid& bwp_grid_);
void new_slot(tti_point pdcch_tti_) { pdcch_tti = pdcch_tti_; }
alloc_result alloc_rar(uint32_t aggr_idx, const pending_rar_t& rar, rbg_interval interv, uint32_t max_nof_grants);
alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask);
alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask);
tti_point get_pdcch_tti() const { return pdcch_tti; }
const bwp_res_grid& res_grid() const { return bwp_grid; }
const sched_cell_params& cfg;
private:
srslog::basic_logger& logger;
bwp_res_grid& bwp_grid;
tti_point tti_rx;
tti_point pdcch_tti;
};
} // namespace sched_nr_impl

View File

@ -13,6 +13,7 @@
#ifndef SRSRAN_SCHED_NR_WORKER_H
#define SRSRAN_SCHED_NR_WORKER_H
#include "sched_nr_bwp.h"
#include "sched_nr_cfg.h"
#include "sched_nr_rb_grid.h"
#include "sched_nr_ue.h"
@ -32,9 +33,7 @@ using ul_sched_t = sched_nr_interface::ul_sched_t;
class slot_cc_worker
{
public:
explicit slot_cc_worker(const sched_cell_params& cell_params, cell_res_grid& phy_grid) :
cfg(cell_params), res_grid(0, phy_grid)
{}
explicit slot_cc_worker(cell_sched& sched);
void start(tti_point tti_rx_, ue_map_t& ue_db_);
void run();
@ -46,9 +45,10 @@ private:
void alloc_ul_ues();
const sched_cell_params& cfg;
cell_sched& cell;
tti_point tti_rx;
slot_bwp_sched res_grid;
tti_point tti_rx;
bwp_slot_allocator bwp_alloc;
srsran::static_circular_map<uint16_t, slot_ue, SCHED_NR_MAX_USERS> slot_ues;
};
@ -80,9 +80,9 @@ private:
ue_map_t& ue_db;
std::mutex ue_db_mutex;
std::vector<std::unique_ptr<slot_worker_ctxt> > slot_ctxts;
std::vector<std::unique_ptr<slot_worker_ctxt> > slot_worker_ctxts;
srsran::bounded_vector<cell_res_grid, SCHED_NR_MAX_CARRIERS> cell_grid_list;
srsran::bounded_vector<cell_sched, SCHED_NR_MAX_CARRIERS> cell_grid_list;
slot_worker_ctxt& get_sf(tti_point tti_rx);
};

View File

@ -6,6 +6,7 @@
# the distribution.
#
set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy_helpers.cc)
set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc
sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_phy.cc sched_nr_bwp.cc)
add_library(srsgnb_mac STATIC ${SOURCES})

View File

@ -11,6 +11,7 @@
*/
#include "srsenb/hdr/stack/mac/nr/sched_nr.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h"
#include "srsran/common/thread_pool.h"

View File

@ -0,0 +1,157 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h"
#include "srsran/common/standard_streams.h"
#include "srsran/common/string_helpers.h"
namespace srsenb {
namespace sched_nr_impl {
ra_sched::ra_sched(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_), logger(srslog::fetch_basic_logger("MAC"))
{}
alloc_result
ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc)
{
const uint32_t rar_aggr_level = 2;
auto& pdsch_bitmap = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_rbgs;
alloc_result ret = alloc_result::other_cause;
for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) {
ret = alloc_result::invalid_coderate;
for (uint32_t nrbg = 1; nrbg < cell_cfg->cell_cfg.nof_rbg and ret == alloc_result::invalid_coderate; ++nrbg) {
rbg_interval rbg_interv = find_empty_rbg_interval(pdsch_bitmap, nrbg);
if (rbg_interv.length() == nrbg) {
ret = slot_grid.alloc_rar(rar_aggr_level, rar, rbg_interv, nof_grants_alloc);
} else {
ret = alloc_result::no_sch_space;
}
}
// If allocation was not successful because there were not enough RBGs, try allocating fewer Msg3 grants
if (ret != alloc_result::invalid_coderate and ret != alloc_result::no_sch_space) {
break;
}
}
if (ret != alloc_result::success) {
logger.info("SCHED: RAR allocation for L=%d was postponed. Cause=%s", rar_aggr_level, to_string(ret));
}
return ret;
}
void ra_sched::run_slot(bwp_slot_allocator& slot_grid)
{
static const uint32_t PRACH_RAR_OFFSET = 3;
tti_point pdcch_tti = slot_grid.get_pdcch_tti();
for (auto it = pending_rars.begin(); it != pending_rars.end();) {
pending_rar_t& rar = *it;
// In case of RAR outside RAR window:
// - if window has passed, discard RAR
// - if window hasn't started, stop loop, as RARs are ordered by TTI
tti_interval rar_window{rar.prach_tti + PRACH_RAR_OFFSET,
rar.prach_tti + PRACH_RAR_OFFSET + cell_cfg->cell_cfg.rar_window_size};
if (not rar_window.contains(pdcch_tti)) {
if (pdcch_tti >= rar_window.stop()) {
fmt::memory_buffer str_buffer;
fmt::format_to(str_buffer,
"SCHED: Could not transmit RAR within the window (RA={}, Window={}, RAR={}",
rar.prach_tti,
rar_window,
pdcch_tti);
srsran::console("%s\n", srsran::to_c_str(str_buffer));
logger.warning("%s", srsran::to_c_str(str_buffer));
it = pending_rars.erase(it);
continue;
}
return;
}
// Try to schedule DCI + RBGs for RAR Grant
uint32_t nof_rar_allocs = 0;
alloc_result ret = allocate_pending_rar(slot_grid, rar, nof_rar_allocs);
if (ret == alloc_result::success) {
// If RAR allocation was successful:
// - in case all Msg3 grants were allocated, remove pending RAR, and continue with following RAR
// - otherwise, erase only Msg3 grants that were allocated, and stop iteration
if (nof_rar_allocs == rar.msg3_grant.size()) {
it = pending_rars.erase(it);
} else {
std::copy(rar.msg3_grant.begin() + nof_rar_allocs, rar.msg3_grant.end(), rar.msg3_grant.begin());
rar.msg3_grant.resize(rar.msg3_grant.size() - nof_rar_allocs);
break;
}
} else {
// If RAR allocation was not successful:
// - in case of unavailable PDCCH space, try next pending RAR allocation
// - otherwise, stop iteration
if (ret != alloc_result::no_cch_space) {
break;
}
++it;
}
}
}
int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info)
{
logger.info("SCHED: New PRACH tti=%d, preamble=%d, temp_crnti=0x%x, ta_cmd=%d, msg3_size=%d",
rar_info.prach_tti,
rar_info.preamble_idx,
rar_info.temp_crnti,
rar_info.ta_cmd,
rar_info.msg3_size);
// RA-RNTI = 1 + t_id + f_id
// t_id = index of first subframe specified by PRACH (0<=t_id<10)
// f_id = index of the PRACH within subframe, in ascending order of freq domain (0<=f_id<6) (for FDD, f_id=0)
uint16_t ra_rnti = 1 + (uint16_t)(rar_info.prach_tti % 10u);
// find pending rar with same RA-RNTI
for (pending_rar_t& r : pending_rars) {
if (r.prach_tti.to_uint() == rar_info.prach_tti and ra_rnti == r.ra_rnti) {
if (r.msg3_grant.size() >= sched_interface::MAX_RAR_LIST) {
logger.warning("PRACH ignored, as the the maximum number of RAR grants per tti has been reached");
return SRSRAN_ERROR;
}
r.msg3_grant.push_back(rar_info);
return SRSRAN_SUCCESS;
}
}
// create new RAR
pending_rar_t p;
p.ra_rnti = ra_rnti;
p.prach_tti = tti_point{rar_info.prach_tti};
p.msg3_grant.push_back(rar_info);
pending_rars.push_back(p);
return SRSRAN_SUCCESS;
}
bwp_sched::bwp_sched(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) :
cell_cfg(&cell_cfg_), bwp_id(bwp_id_), ra(cell_cfg_), grid(cell_cfg_, bwp_id_)
{}
cell_sched::cell_sched(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_)
{
for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) {
bwps.emplace_back(cell_cfg_, bwp_id);
}
}
} // namespace sched_nr_impl
} // namespace srsenb

View File

@ -11,6 +11,7 @@
*/
#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h"
namespace srsenb {
namespace sched_nr_impl {

View File

@ -10,7 +10,7 @@
*
*/
#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h"
@ -82,6 +82,38 @@ int bitmap_to_riv(const rbgmask_t& bitmap, uint32_t cell_nof_prb)
return srsran_ra_nr_type1_riv(cell_nof_prb, interv.start(), interv.length());
}
rbg_interval find_empty_rbg_interval(const pdsch_bitmap& in_mask, uint32_t max_size)
{
rbg_interval max_interv;
for (size_t n = 0; n < in_mask.size();) {
int pos = in_mask.find_lowest(n, in_mask.size(), false);
if (pos < 0) {
break;
}
size_t max_pos = std::min(in_mask.size(), (size_t)pos + max_size);
int pos2 = in_mask.find_lowest(pos + 1, max_pos, true);
rbg_interval interv(pos, pos2 < 0 ? max_pos : pos2);
if (interv.length() >= max_size) {
return interv;
}
if (interv.length() > max_interv.length()) {
max_interv = interv;
}
n = interv.stop();
}
return max_interv;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool fill_dci_rar(rbg_interval rbginterv, const sched_cell_params& cell, srsran_dci_dl_nr_t& dci)
{
dci.mcs = 5;
return true;
}
template <typename DciDlOrUl>
void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cell_params& cc_cfg, DciDlOrUl& dci)
{

View File

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_phy.h"
namespace srsenb {
namespace sched_nr_impl {
@ -49,20 +49,68 @@ bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_)
}
}
cell_res_grid::cell_res_grid(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_)
{
for (uint32_t bwp_id = 0; bwp_id < cell_cfg->cell_cfg.bwps.size(); ++bwp_id) {
bwps.emplace_back(cell_cfg_, bwp_id);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
slot_bwp_sched::slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_) :
logger(srslog::fetch_basic_logger("MAC")), cfg(*phy_grid_.cell_cfg), bwp_grid(phy_grid_.bwps[bwp_id])
bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) :
logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cell_cfg), bwp_grid(bwp_grid_)
{}
alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask)
alloc_result bwp_slot_allocator::alloc_rar(uint32_t aggr_idx,
const srsenb::sched_nr_impl::pending_rar_t& rar,
srsenb::sched_nr_impl::rbg_interval interv,
uint32_t nof_grants)
{
static const uint32_t msg3_nof_prbs = 3;
bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_tti];
bwp_slot_grid& bwp_msg3_slot = bwp_grid[pdcch_tti + 4];
if (bwp_pdcch_slot.dl_pdcchs.full()) {
logger.warning("SCHED: Maximum number of DL allocations reached");
return alloc_result::no_grant_space;
}
// Check DL RB collision
rbgmask_t& pdsch_mask = bwp_pdcch_slot.dl_rbgs;
rbgmask_t dl_mask(pdsch_mask.size());
dl_mask.fill(interv.start(), interv.stop());
if ((pdsch_mask & dl_mask).any()) {
logger.debug("SCHED: Provided RBG mask collides with allocation previously made.");
return alloc_result::sch_collision;
}
// Check Msg3 RB collision
uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants;
uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.bwp_cfg().rb_width, false));
rbg_interval msg3_rbgs = find_empty_rbg_interval(bwp_msg3_slot.ul_rbgs, total_ul_nof_rbgs);
if (msg3_rbgs.length() < total_ul_nof_rbgs) {
logger.debug("SCHED: No space in PUSCH for Msg3.");
return alloc_result::sch_collision;
}
// Find PDCCH position
const uint32_t coreset_id = 0;
if (not bwp_pdcch_slot.coresets[coreset_id].alloc_dci(pdcch_grant_type_t::rar, aggr_idx, nullptr)) {
// Could not find space in PDCCH
logger.debug("SCHED: No space in PDCCH for DL tx.");
return alloc_result::no_cch_space;
}
// Generate DCI for RAR
pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back();
if (not fill_dci_rar(interv, bwp_grid.cell_params(), pdcch.dci)) {
// Cancel on-going PDCCH allocation
bwp_pdcch_slot.coresets[coreset_id].rem_last_dci();
return alloc_result::invalid_coderate;
}
// RAR allocation successful.
bwp_pdcch_slot.dl_rbgs.fill(interv.start(), interv.stop());
return alloc_result::success;
}
alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask)
{
if (ue.h_dl == nullptr) {
logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti);
@ -121,7 +169,7 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask)
return alloc_result::success;
}
alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask)
alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask)
{
if (ue.h_ul == nullptr) {
logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti);

View File

@ -15,6 +15,10 @@
namespace srsenb {
namespace sched_nr_impl {
slot_cc_worker::slot_cc_worker(cell_sched& cc_sched) :
cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid)
{}
/// Called at the beginning of TTI in a locked context, to reserve available UE resources
void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db)
{
@ -34,15 +38,18 @@ void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db)
}
// UE acquired successfully for scheduling in this {tti, cc}
}
tti_rx = tti_rx_;
}
void slot_cc_worker::run()
{
srsran_assert(running(), "scheduler worker::run() called for non-active worker");
// Prioritize PDCCH scheduling for DL and UL data in a RoundRobin fashion
bwp_alloc.new_slot(tti_rx + TX_ENB_DELAY);
// Allocate pending RARs
cell.bwps[0].ra.run_slot(bwp_alloc);
// Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion
if ((tti_rx.to_uint() & 0x1u) == 0) {
alloc_dl_ues();
alloc_ul_ues();
@ -74,8 +81,9 @@ void slot_cc_worker::alloc_dl_ues()
rbgmask_t dlmask(cfg.cell_cfg.nof_rbg);
dlmask.fill(0, dlmask.size(), true);
res_grid.alloc_pdsch(ue, dlmask);
bwp_alloc.alloc_pdsch(ue, dlmask);
}
void slot_cc_worker::alloc_ul_ues()
{
if (slot_ues.empty()) {
@ -88,7 +96,7 @@ void slot_cc_worker::alloc_ul_ues()
rbgmask_t ulmask(cfg.cell_cfg.nof_rbg);
ulmask.fill(0, ulmask.size(), true);
res_grid.alloc_pusch(ue, ulmask);
bwp_alloc.alloc_pusch(ue, ulmask);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -100,12 +108,12 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params&
}
// Note: For now, we only allow parallelism at the sector level
slot_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes);
slot_worker_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes);
for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) {
slot_ctxts[i].reset(new slot_worker_ctxt());
slot_ctxts[i]->workers.reserve(cfg.cells.size());
slot_worker_ctxts[i].reset(new slot_worker_ctxt());
slot_worker_ctxts[i]->workers.reserve(cfg.cells.size());
for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) {
slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], cell_grid_list[cc]);
slot_worker_ctxts[i]->workers.emplace_back(cell_grid_list[cc]);
}
}
}
@ -114,7 +122,7 @@ sched_worker_manager::~sched_worker_manager() = default;
sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx)
{
return *slot_ctxts[tti_rx.to_uint() % slot_ctxts.size()];
return *slot_worker_ctxts[tti_rx.to_uint() % slot_worker_ctxts.size()];
}
void sched_worker_manager::start_slot(tti_point tti_rx, srsran::move_callback<void()> process_feedback)
@ -189,7 +197,7 @@ void sched_worker_manager::release_slot(tti_point tti_rx_)
bool sched_worker_manager::get_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res)
{
auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0][pdcch_tti];
auto& pdcch_bwp_slot = cell_grid_list[cc].bwps[0].grid[pdcch_tti];
dl_res.pdcch_dl = pdcch_bwp_slot.dl_pdcchs;
dl_res.pdcch_ul = pdcch_bwp_slot.ul_pdcchs;