implement TDD DL vs UL slot activation

This commit is contained in:
Francisco Paisana 2021-07-01 16:36:49 +01:00
parent f87f898641
commit bcc374c2cd
9 changed files with 170 additions and 72 deletions

View File

@ -26,12 +26,10 @@ 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_PDSCH_DATA = 16;
const static size_t SCHED_NR_MAX_NOF_RBGS = 25;
const static size_t SCHED_NR_MAX_UL_ALLOCS = 16;
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 = 1;
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2;
class sched_nr_interface
{
@ -39,17 +37,19 @@ public:
using pdcch_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
using rbg_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
static const size_t MAX_GRANTS = mac_interface_phy_nr::MAX_GRANTS;
///// Configuration /////
struct pdsch_td_res_alloc {
uint8_t k0 = 0; // 0..32
uint8_t k1 = 4; // 0..32
};
using pdsch_td_res_alloc_list = srsran::bounded_vector<pdsch_td_res_alloc, SCHED_NR_MAX_UL_ALLOCS>;
using pdsch_td_res_alloc_list = srsran::bounded_vector<pdsch_td_res_alloc, MAX_GRANTS>;
struct pusch_td_res_alloc {
uint8_t k2 = 4; // 0..32
};
using pusch_td_res_alloc_list = srsran::bounded_vector<pusch_td_res_alloc, SCHED_NR_MAX_UL_ALLOCS>;
using pusch_td_res_alloc_list = srsran::bounded_vector<pusch_td_res_alloc, MAX_GRANTS>;
struct bwp_cfg_t {
uint32_t bwp_id = 1;
@ -62,6 +62,7 @@ public:
struct cell_cfg_t {
uint32_t nof_prb = 100;
uint32_t nof_rbg = 25;
srsran_tdd_config_nr_t tdd = {};
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1};
};
@ -83,8 +84,6 @@ public:
///// Sched Result /////
const static int MAX_GRANTS = 64;
using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t;
using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t;
using pdcch_dl_list_t = srsran::bounded_vector<pdcch_dl_t, MAX_GRANTS>;
@ -93,7 +92,7 @@ public:
struct pdsch_t {
srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration
};
using pdsch_list_t = srsran::bounded_vector<pdsch_t, SCHED_NR_MAX_PDSCH_DATA>;
using pdsch_list_t = srsran::bounded_vector<pdsch_t, MAX_GRANTS>;
struct dl_tti_request_t {
tti_point pdsch_tti;
@ -104,11 +103,11 @@ public:
struct pusch_t {
srsran_sch_cfg_nr_t sch = {}; ///< PUSCH configuration
};
using pusch_list_t = srsran::bounded_vector<pusch_t, SCHED_NR_MAX_PDSCH_DATA>;
using pusch_list_t = srsran::bounded_vector<pusch_t, MAX_GRANTS>;
struct ul_tti_request_t {
tti_point pusch_tti;
srsran::bounded_vector<pusch_t, SCHED_NR_MAX_UL_ALLOCS> pusch;
tti_point pusch_tti;
srsran::bounded_vector<pusch_t, MAX_GRANTS> pusch;
};
struct tti_request_t {

View File

@ -21,15 +21,23 @@ 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);
void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant);
class slot_ue;
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci);
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci);
void fill_sch_ue(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_sch_cfg_nr_t& sch);
void fill_dci_ue_cfg(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_dci_dl_nr_t& dci);
void fill_dci_ue_cfg(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_dci_ul_nr_t& dci);
void fill_pdsch_ue(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_sch_cfg_nr_t& sch);
void fill_pusch_ue(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_sch_cfg_nr_t& sch);
} // namespace sched_nr_impl
} // namespace srsenb

View File

@ -36,15 +36,17 @@ const static size_t MAX_CORESET_PER_BWP = 3;
using slot_coreset_list = srsran::bounded_vector<coreset_region, MAX_CORESET_PER_BWP>;
struct bwp_slot_grid {
uint32_t bwp_id;
pdcch_dl_list_t pdcch_dl_list;
pdcch_ul_list_t pdcch_ul_list;
slot_coreset_list coresets;
pdsch_bitmap dl_rbgs;
pdsch_list_t pdsch_grants;
pusch_bitmap ul_rbgs;
pusch_list pusch_grants;
srsran::bounded_vector<pucch_t, SCHED_NR_MAX_PDSCH_DATA> pucch_grants;
uint32_t bwp_id;
uint32_t slot_idx;
bool is_dl, is_ul;
pdcch_dl_list_t pdcch_dl_list;
pdcch_ul_list_t pdcch_ul_list;
slot_coreset_list coresets;
pdsch_bitmap dl_rbgs;
pdsch_list_t pdsch_grants;
pusch_bitmap ul_rbgs;
pusch_list pusch_grants;
srsran::bounded_vector<pucch_t, MAX_GRANTS> pucch_grants;
bwp_slot_grid() = default;
explicit bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_);

View File

@ -92,7 +92,7 @@ private:
class ue_carrier
{
public:
ue_carrier(uint16_t rnti, uint32_t cc, const ue_cfg_t& cfg);
ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const sched_cell_params& cell_params_);
slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_extended& cfg);
void push_feedback(srsran::move_callback<void(ue_carrier&)> callback);
@ -106,7 +106,8 @@ public:
harq_entity harq_ent;
private:
const ue_cfg_t* cfg = nullptr;
const ue_cfg_t* cfg = nullptr;
const sched_cell_params& cell_params;
resource_guard busy;
tti_point last_tti_rx;
@ -117,7 +118,7 @@ private:
class ue
{
public:
ue(uint16_t rnti, const ue_cfg_t& cfg);
ue(uint16_t rnti, const ue_cfg_t& cfg, const sched_params& sched_cfg_);
slot_ue try_reserve(tti_point tti_rx, uint32_t cc);
@ -128,7 +129,8 @@ public:
std::array<std::unique_ptr<ue_carrier>, SCHED_NR_MAX_CARRIERS> carriers;
private:
const uint16_t rnti;
const uint16_t rnti;
const sched_params& sched_cfg;
bool pending_sr = false;

View File

@ -107,7 +107,7 @@ void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg)
void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg)
{
if (not ue_db.contains(rnti)) {
ue_db.insert(rnti, std::unique_ptr<ue>(new ue{rnti, uecfg}));
ue_db.insert(rnti, std::unique_ptr<ue>(new ue{rnti, uecfg, cfg}));
} else {
ue_db[rnti]->set_cfg(uecfg);
}

View File

@ -53,27 +53,45 @@ uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_
return P;
}
void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant)
void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran::span<bool> prbs)
{
uint32_t count = 0;
grant.nof_prb = bwp_nof_prb;
for (uint32_t rbg = 0; rbg < bitmap.size(); ++rbg) {
bool val = bitmap.test(rbg);
uint32_t rbg_size = get_rbg_size(bwp_nof_prb, 0, true, rbg);
for (uint32_t prb = count; prb < count + rbg_size; ++prb) {
grant.prb_idx[prb] = val;
for (uint32_t prb_idx = count; prb_idx < count + rbg_size; ++prb_idx) {
prbs[prb_idx] = val;
}
}
}
template <typename DciDlOrUl>
void fill_dci_common(const slot_ue& ue, DciDlOrUl& dci)
srsran::interval<uint32_t> find_first_interval(const rbgmask_t& mask)
{
dci.bwp_id = ue.bwp_id;
dci.cc_id = ue.cc;
dci.ctx.rnti = ue.rnti;
dci.ctx.rnti_type = srsran_rnti_type_c;
dci.tpc = 1;
int rb_start = mask.find_lowest(0, mask.size());
if (rb_start != -1) {
int rb_end = mask.find_lowest(rb_start + 1, mask.size(), false);
return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? mask.size() : rb_end)};
}
return {};
}
int bitmap_to_riv(const rbgmask_t& bitmap, uint32_t cell_nof_prb)
{
srsran::interval<uint32_t> interv = find_first_interval(bitmap);
srsran_assert(interv.length() == bitmap.count(), "Trying to acquire riv for non-contiguous bitmap");
return srsran_ra_nr_type1_riv(cell_nof_prb, interv.start(), interv.length());
}
template <typename DciDlOrUl>
void fill_dci_common(const slot_ue& ue, const rbgmask_t& bitmap, const sched_cell_params& cc_cfg, DciDlOrUl& dci)
{
// Note: PDCCH DCI position already filled at this point
dci.bwp_id = ue.bwp_id;
dci.cc_id = ue.cc;
dci.freq_domain_assigment = bitmap_to_riv(bitmap, cc_cfg.cell_cfg.nof_prb);
dci.ctx.rnti = ue.rnti;
dci.ctx.rnti_type = srsran_rnti_type_c;
dci.tpc = 1;
// harq
harq_proc* h = std::is_same<DciDlOrUl, srsran_dci_dl_nr_t>::value ? ue.h_dl : ue.h_ul;
dci.pid = h->pid;
@ -81,22 +99,51 @@ void fill_dci_common(const slot_ue& ue, DciDlOrUl& dci)
dci.mcs = h->mcs();
}
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci)
void fill_dci_ue_cfg(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_dci_dl_nr_t& dci)
{
fill_dci_common(ue, dci);
fill_dci_common(ue, rbgmask, cc_cfg, dci);
}
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci)
void fill_dci_ue_cfg(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_dci_ul_nr_t& dci)
{
fill_dci_common(ue, dci);
fill_dci_common(ue, rbgmask, cc_cfg, dci);
}
void fill_sch_ue(const slot_ue& ue, const rbgmask_t& rbgmask, const sched_cell_params& cc_cfg, srsran_sch_cfg_nr_t& sch)
void fill_sch_ue_common(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_sch_cfg_nr_t& sch)
{
sch.grant.rnti_type = srsran_rnti_type_c;
sch.grant.rnti = ue.rnti;
sch.grant.nof_layers = 1;
bitmap_to_prb_array(rbgmask, cc_cfg.cell_cfg.nof_prb, sch.grant);
sch.grant.nof_prb = cc_cfg.cell_cfg.nof_prb;
}
void fill_pdsch_ue(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_sch_cfg_nr_t& sch)
{
fill_sch_ue_common(ue, rbgmask, cc_cfg, sch);
sch.grant.k = ue.cc_cfg->pdsch_res_list[0].k0;
sch.grant.dci_format = srsran_dci_format_nr_1_0;
}
void fill_pusch_ue(const slot_ue& ue,
const rbgmask_t& rbgmask,
const sched_cell_params& cc_cfg,
srsran_sch_cfg_nr_t& sch)
{
fill_sch_ue_common(ue, rbgmask, cc_cfg, sch);
sch.grant.k = ue.cc_cfg->pusch_res_list[0].k2;
sch.grant.dci_format = srsran_dci_format_nr_0_1;
}
} // namespace sched_nr_impl

View File

@ -18,8 +18,15 @@ namespace sched_nr_impl {
using pusch_t = sched_nr_interface::pusch_t;
#define NUMEROLOGY_IDX 0
bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) :
dl_rbgs(cell_params.cell_cfg.nof_rbg), ul_rbgs(cell_params.cell_cfg.nof_rbg), bwp_id(bwp_id_)
dl_rbgs(cell_params.cell_cfg.nof_rbg),
ul_rbgs(cell_params.cell_cfg.nof_rbg),
bwp_id(bwp_id_),
slot_idx(slot_idx_),
is_dl(srsran_tdd_nr_is_dl(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)),
is_ul(srsran_tdd_nr_is_ul(&cell_params.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_))
{
const uint32_t coreset_id = 1; // Note: for now only one coreset per BWP supported
coresets.emplace_back(cell_params.cell_cfg.bwps[0], coreset_id, slot_idx_, pdcch_dl_list, pdcch_ul_list);
@ -64,12 +71,17 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask)
logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti);
return alloc_result::no_rnti_opportunity;
}
pdsch_list_t& pdsch_grants = bwp_grid[ue.pdsch_tti].pdsch_grants;
bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_tti];
if (not bwp_pdsch_slot.is_dl) {
logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch_slot.slot_idx);
return alloc_result::no_sch_space;
}
pdsch_list_t& pdsch_grants = bwp_pdsch_slot.pdsch_grants;
if (pdsch_grants.full()) {
logger.warning("SCHED: Maximum number of DL allocations reached");
return alloc_result::no_grant_space;
}
rbgmask_t& pdsch_mask = bwp_grid[ue.pdsch_tti].dl_rbgs;
rbgmask_t& pdsch_mask = bwp_pdsch_slot.dl_rbgs;
if ((pdsch_mask & dl_mask).any()) {
return alloc_result::sch_collision;
}
@ -92,9 +104,9 @@ alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask)
// Allocation Successful
pdcch_dl_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_dl_list.back();
fill_dci_ue_cfg(ue, pdcch.dci);
fill_dci_ue_cfg(ue, dl_mask, bwp_grid.cell_params(), pdcch.dci);
pdsch_grants.emplace_back();
fill_sch_ue(ue, dl_mask, bwp_grid.cell_params(), pdsch_grants.back().sch);
fill_pdsch_ue(ue, dl_mask, bwp_grid.cell_params(), pdsch_grants.back().sch);
pdsch_mask |= dl_mask;
return alloc_result::success;
@ -106,12 +118,17 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask)
logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti);
return alloc_result::no_rnti_opportunity;
}
pusch_list& pusch_grants = bwp_grid[ue.pusch_tti].pusch_grants;
auto& bwp_pusch_slot = bwp_grid[ue.pusch_tti];
if (not bwp_pusch_slot.is_ul) {
logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", bwp_pusch_slot.slot_idx);
return alloc_result::no_sch_space;
}
pusch_list& pusch_grants = bwp_pusch_slot.pusch_grants;
if (pusch_grants.full()) {
logger.warning("SCHED: Maximum number of UL allocations reached");
return alloc_result::no_grant_space;
}
rbgmask_t& pusch_mask = bwp_grid[ue.pusch_tti].ul_rbgs;
rbgmask_t& pusch_mask = bwp_pusch_slot.ul_rbgs;
if ((pusch_mask & ul_mask).any()) {
return alloc_result::sch_collision;
}
@ -134,9 +151,9 @@ alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask)
// Allocation Successful
pdcch_ul_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_ul_list.back();
fill_dci_ue_cfg(ue, pdcch.dci);
fill_dci_ue_cfg(ue, ul_mask, bwp_grid.cell_params(), pdcch.dci);
pusch_grants.emplace_back();
fill_sch_ue(ue, ul_mask, bwp_grid.cell_params(), pusch_grants.back().sch);
fill_pusch_ue(ue, ul_mask, bwp_grid.cell_params(), pusch_grants.back().sch);
pusch_mask |= ul_mask;
return alloc_result::success;

View File

@ -52,7 +52,9 @@ slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const ue_cfg_t& uecfg_) : rnti(rnti_), cc(cc_), cfg(&uecfg_) {}
ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_params& cell_params_) :
rnti(rnti_), cc(cell_params_.cc), cfg(&uecfg_), cell_params(cell_params_)
{}
void ue_carrier::push_feedback(srsran::move_callback<void(ue_carrier&)> callback)
{
@ -91,13 +93,21 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_)
sfu.uci_tti = sfu.pdsch_tti + sfu.cc_cfg->pdsch_res_list[0].k1;
sfu.dl_cqi = dl_cqi;
sfu.ul_cqi = ul_cqi;
sfu.h_dl = harq_ent.find_pending_dl_retx();
if (sfu.h_dl == nullptr) {
sfu.h_dl = harq_ent.find_empty_dl_harq();
const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd;
if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_tti.sf_idx())) {
// If DL enabled
sfu.h_dl = harq_ent.find_pending_dl_retx();
if (sfu.h_dl == nullptr) {
sfu.h_dl = harq_ent.find_empty_dl_harq();
}
}
sfu.h_ul = harq_ent.find_pending_ul_retx();
if (sfu.h_ul == nullptr) {
sfu.h_ul = harq_ent.find_empty_ul_harq();
if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_tti.sf_idx())) {
// If UL enabled
sfu.h_ul = harq_ent.find_pending_ul_retx();
if (sfu.h_ul == nullptr) {
sfu.h_ul = harq_ent.find_empty_ul_harq();
}
}
if (sfu.h_dl == nullptr and sfu.h_ul == nullptr) {
@ -110,12 +120,12 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ue::ue(uint16_t rnti_, const ue_cfg_t& cfg) : rnti(rnti_)
ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : rnti(rnti_), sched_cfg(sched_cfg_)
{
ue_cfgs[0] = ue_cfg_extended(rnti, cfg);
for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) {
if (cfg.carriers[cc].active) {
carriers[cc].reset(new ue_carrier(rnti, cc, cfg));
carriers[cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[cc]));
}
}
}

View File

@ -20,7 +20,7 @@ namespace srsenb {
srsran_coreset_t get_default_coreset()
{
srsran_coreset_t coreset{};
coreset.id = 1;
coreset.id = 0;
coreset.duration = 1;
coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle;
for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; ++i) {
@ -33,8 +33,19 @@ sched_nr_interface::cell_cfg_t get_default_cell_cfg()
{
sched_nr_interface::cell_cfg_t cell_cfg{};
cell_cfg.bwps.resize(1);
cell_cfg.tdd.pattern1.period_ms = 10;
cell_cfg.tdd.pattern1.nof_dl_slots = 6;
cell_cfg.tdd.pattern1.nof_dl_symbols = 0;
cell_cfg.tdd.pattern1.nof_ul_slots = 4;
cell_cfg.tdd.pattern1.nof_ul_symbols = 0;
// Disable pattern 2
cell_cfg.tdd.pattern2.period_ms = 0;
cell_cfg.bwps.resize(2);
cell_cfg.bwps[0].coresets[0].emplace(get_default_coreset());
cell_cfg.bwps[0].coresets[1].emplace(get_default_coreset());
cell_cfg.bwps[0].coresets[1].value().id = 1;
return cell_cfg;
}
std::vector<sched_nr_interface::cell_cfg_t> get_default_cells_cfg(uint32_t nof_sectors)
@ -56,6 +67,7 @@ sched_nr_interface::ue_cfg_t get_default_ue_cfg(uint32_t nof_cc)
}
uecfg.phy_cfg.pdcch.coreset_present[0] = true;
uecfg.phy_cfg.pdcch.coreset[0] = get_default_coreset();
uecfg.phy_cfg.pdcch.coreset[0].id = 1;
uecfg.phy_cfg.pdcch.search_space_present[0] = true;
auto& ss = uecfg.phy_cfg.pdcch.search_space[0];
@ -139,12 +151,13 @@ void sched_nr_cfg_serialized_test()
sched_nr_cc_output_res_t out{tti, cc, &res.dl_res, &res.ul_res};
sched_tester.update(out);
tasks.finish_task(res);
TESTASSERT(res.dl_res.pdschs.size() == 1);
TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (tti + TX_ENB_DELAY).sf_idx()) or
res.dl_res.pdschs.size() == 1);
}
}
tasks.print_results();
TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors));
TESTASSERT(tasks.pdsch_count == (int)(max_nof_ttis * nof_sectors * 0.6));
}
void sched_nr_cfg_parallel_cc_test()