From 632f2dbddd04a9041e8e2eef5caf0cfca62f3e86 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 10 Dec 2021 18:24:28 +0000 Subject: [PATCH] nr,gnb,sched: changed pdsch_allocator interface and extended its respective unit tests --- lib/src/common/phy_cfg_nr_default.cc | 3 + srsgnb/hdr/stack/mac/sched_nr_cfg.h | 19 +- srsgnb/hdr/stack/mac/sched_nr_sch.h | 94 ++++++--- srsgnb/src/stack/mac/sched_nr_cfg.cc | 26 +-- .../src/stack/mac/sched_nr_grant_allocator.cc | 16 +- srsgnb/src/stack/mac/sched_nr_pdcch.cc | 2 +- srsgnb/src/stack/mac/sched_nr_sch.cc | 181 ++++++++++++++---- .../src/stack/mac/test/sched_nr_sch_test.cc | 104 +++++++--- 8 files changed, 322 insertions(+), 123 deletions(-) diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index e412b4684..2a4bfdada 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -172,6 +172,9 @@ void phy_cfg_nr_default_t::make_pdsch_default(srsran_sch_hl_cfg_nr_t& pdsch) pdsch.common_time_ra[0].sliv = srsran_ra_type2_to_riv(SRSRAN_NSYMB_PER_SLOT_NR - 1, 1, SRSRAN_NSYMB_PER_SLOT_NR); pdsch.nof_common_time_ra = 1; + // Set contiguous PRBs as default + pdsch.alloc = srsran_resource_alloc_type1; + // Setup PDSCH DMRS type A position pdsch.typeA_pos = srsran_dmrs_sch_typeA_pos_2; } diff --git a/srsgnb/hdr/stack/mac/sched_nr_cfg.h b/srsgnb/hdr/stack/mac/sched_nr_cfg.h index 6a1f85ae7..6e39c5e89 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_cfg.h +++ b/srsgnb/hdr/stack/mac/sched_nr_cfg.h @@ -94,15 +94,9 @@ struct bwp_params_t { bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); - uint32_t coreset_bw(uint32_t cs_id) const { return coresets[cs_id].bw; } - - const bwp_rb_bitmap& coreset_prb_limits(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const - { - if (used_common_prb_masks.contains(ss_id) and dci_fmt == srsran_dci_format_nr_1_0) { - return used_common_prb_masks[ss_id]; - } - return cached_empty_prb_mask; - } + prb_interval coreset_prb_range(uint32_t cs_id) const { return coresets[cs_id].prb_limits; } + prb_interval dci_fmt_1_0_prb_lims(uint32_t cs_id) const { return coresets[cs_id].dci_1_0_prb_limits; } + bwp_rb_bitmap dci_fmt_1_0_excluded_prbs(uint32_t cs_id) const { return coresets[cs_id].usable_common_ss_prb_mask; } const srsran_search_space_t* get_ss(uint32_t ss_id) const { @@ -110,10 +104,11 @@ struct bwp_params_t { } private: - bwp_rb_bitmap cached_empty_prb_mask; - srsran::optional_vector used_common_prb_masks; + bwp_rb_bitmap cached_empty_prb_mask; struct coreset_cached_params { - uint32_t bw = 0; + prb_interval prb_limits; + prb_interval dci_1_0_prb_limits; /// See TS 38.214, section 5.1.2.2 + bwp_rb_bitmap usable_common_ss_prb_mask; }; srsran::optional_vector coresets; }; diff --git a/srsgnb/hdr/stack/mac/sched_nr_sch.h b/srsgnb/hdr/stack/mac/sched_nr_sch.h index 9378257f9..9dd7d39a9 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_sch.h +++ b/srsgnb/hdr/stack/mac/sched_nr_sch.h @@ -28,47 +28,96 @@ public: pdsch_allocator(const bwp_params_t& cfg_, uint32_t sl_index, pdsch_list_t& pdsch_lst); /// Get available RBGs for allocation - rbg_bitmap occupied_rbgs(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const + rbg_bitmap occupied_rbgs() const { - return (dl_prbs | bwp_cfg.coreset_prb_limits(ss_id, dci_fmt)).rbgs(); + // Note: in case, RBGs are used, dci format is not 1_0 + return dl_prbs.rbgs(); } /// Get available PRBs for allocation prb_bitmap occupied_prbs(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const { - return (dl_prbs | bwp_cfg.coreset_prb_limits(ss_id, dci_fmt)).prbs(); + if (dci_fmt == srsran_dci_format_nr_1_0) { + const srsran_search_space_t* ss = bwp_cfg.get_ss(ss_id); + if (ss != nullptr and SRSRAN_SEARCH_SPACE_IS_COMMON(ss->type)) { + return (dl_prbs | bwp_cfg.dci_fmt_1_0_excluded_prbs(ss->coreset_id)).prbs(); + } + } + return dl_prbs.prbs(); } - /// 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(uint32_t ss_id, - srsran_dci_format_nr_t dci_fmt, - const prb_grant& grant, - ue_carrier_params_t* ue = nullptr) const; + /// Verifies if the input arguments are valid for an SI allocation and grant doesnt collide with other grants + alloc_result is_si_grant_valid(uint32_t ss_id, const prb_grant& grant) const; + + /// Verifies if the input arguments are valid for an RAR allocation and grant doesnt collide with other grants + alloc_result is_rar_grant_valid(const prb_grant& grant) const; + + /// Verifies if the input arguments are valid for an UE allocation and grant doesnt collide with other grants + alloc_result is_ue_grant_valid(const ue_carrier_params_t& ue, + uint32_t ss_id, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant) 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 + * @brief Tries to allocate UE PDSCH grant. Ensures that there are no collisions with other previous PDSCH allocations * @param ss_id[in] SearchSpaceId used for allocation + * @param dci_fmt[in] Chosen DL DCI format * @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 + * @param ue[in] UE carrier parameters + * @param dci[out] DCI where frequency_assignment and time_assignment get stored. + * @return pdsch_t* of allocated PDSCH in case of success. alloc_result error code in case of failure */ - pdsch_alloc_result - alloc_pdsch(const srsran_dci_ctx_t& dci_ctx, uint32_t ss_id, const prb_grant& grant, srsran_dci_dl_nr_t& dci); + pdsch_alloc_result alloc_ue_pdsch(uint32_t ss_id, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant, + const ue_carrier_params_t& ue, + srsran_dci_dl_nr_t& dci); + + /// Similar to alloc_ue_pdsch, but it doesn't verify if input parameters are valid + pdsch_t& alloc_ue_pdsch_unchecked(uint32_t ss_id, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant, + const ue_carrier_params_t& ue, + srsran_dci_dl_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. + * @brief Tries to allocate SI PDSCH grant. Ensures that there are no collisions with other previous PDSCH allocations + * @param ss_id[in] SearchSpaceId used for allocation + * @param grant[in] PRBs used for the grant + * @param dci[out] DCI where frequency_assignment and time_assignment get stored. + * @return pdsch_t* of allocated PDSCH in case of success. alloc_result error code in case of failure */ - pdsch_t& alloc_pdsch_unchecked(const srsran_dci_ctx_t& dci_ctx, const prb_grant& grant, srsran_dci_dl_nr_t& dci); + pdsch_alloc_result alloc_si_pdsch(uint32_t ss_id, const prb_grant& grant, srsran_dci_dl_nr_t& dci); + /// Similar to alloc_si_pdsch, but it doesn't verify if input parameters are valid + pdsch_t& alloc_si_pdsch_unchecked(uint32_t ss_id, const prb_grant& grant, srsran_dci_dl_nr_t& dci); + /** + * @brief Tries to allocate RAR PDSCH grant. Ensures that there are no collisions with other previous PDSCH + * allocations + * @param grant[in] PRBs used for the grant + * @param dci[out] DCI where frequency_assignment and time_assignment get stored. + * @return pdsch_t* of allocated PDSCH in case of success. alloc_result error code in case of failure + */ + pdsch_alloc_result alloc_rar_pdsch(const prb_grant& grant, srsran_dci_dl_nr_t& dci); + /// Similar to alloc_rar_pdsch, but it doesn't verify if input parameters are valid + pdsch_t& alloc_rar_pdsch_unchecked(const prb_grant& grant, srsran_dci_dl_nr_t& dci); + + /// Cancel last PDSCH allocation void cancel_last_pdsch(); + /// Clear all PDSCHs void reset(); private: + alloc_result is_grant_valid_common(srsran_search_space_type_t ss_type, + srsran_dci_format_nr_t dci_fmt, + uint32_t coreset_id, + const prb_grant& grant) const; + pdsch_t& alloc_pdsch_unchecked(uint32_t coreset_id, + srsran_search_space_type_t ss_type, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant, + srsran_dci_dl_nr_t& dci); + const bwp_params_t& bwp_cfg; uint32_t slot_idx = 0; @@ -96,12 +145,13 @@ public: /** * @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 ss_type[in] PDCCH chosen search space type * @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); + pusch_alloc_result + alloc_pusch(const srsran_search_space_type_t ss_type, 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 diff --git a/srsgnb/src/stack/mac/sched_nr_cfg.cc b/srsgnb/src/stack/mac/sched_nr_cfg.cc index 12c4b24c3..c1efdeed3 100644 --- a/srsgnb/src/stack/mac/sched_nr_cfg.cc +++ b/srsgnb/src/stack/mac/sched_nr_cfg.cc @@ -57,8 +57,20 @@ bwp_params_t::bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg for (const srsran_coreset_t& cs : view_active_coresets(cfg.pdcch)) { coresets.emplace(cs.id); - auto& cached_coreset = coresets[cs.id]; - cached_coreset.bw = srsran_coreset_get_bw(&cs); + uint32_t rb_start = srsran_coreset_start_rb(&cs); + coresets[cs.id].prb_limits = prb_interval{rb_start, rb_start + srsran_coreset_get_bw(&cs)}; + coresets[cs.id].usable_common_ss_prb_mask = cached_empty_prb_mask; + + // TS 38.214, 5.1.2.2 - For DCI format 1_0 and common search space, lowest RB of the CORESET is the RB index = 0 + coresets[cs.id].usable_common_ss_prb_mask |= prb_interval(0, rb_start); + coresets[cs.id].dci_1_0_prb_limits = prb_interval{rb_start, cfg.rb_width}; + + // TS 38.214, 5.1.2.2.2 - when DCI format 1_0, common search space and CORESET#0 is configured for the cell, + // RA type 1 allocs shall be within the CORESET#0 region + if (cfg.pdcch.coreset_present[0]) { + coresets[cs.id].dci_1_0_prb_limits = coresets[cs.id].prb_limits; + coresets[cs.id].usable_common_ss_prb_mask |= prb_interval(coresets[cs.id].prb_limits.stop(), cfg.rb_width); + } } // Derive params of individual slots @@ -116,16 +128,6 @@ bwp_params_t::bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg ss_cce_list[sl][agg_idx].resize(n); } } - - if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss.type)) { - used_common_prb_masks.emplace(ss_id, cached_empty_prb_mask); - uint32_t coreset_start = srsran_coreset_start_rb(&cfg.pdcch.coreset[ss.coreset_id]); - used_common_prb_masks[ss_id] |= prb_interval(0, coreset_start); - if (ss.coreset_id == 0) { - uint32_t coreset0_bw = srsran_coreset_get_bw(&cfg.pdcch.coreset[0]); - used_common_prb_masks[ss_id] |= prb_interval(coreset_start + coreset0_bw, cfg.rb_width); - } - } } } diff --git a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index e5547eb6d..de005ea7a 100644 --- a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -123,7 +123,7 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_slot]; // Verify there is space in PDSCH - alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(ss_id, dci_fmt, prbs); + alloc_result ret = bwp_pdcch_slot.pdschs.is_si_grant_valid(ss_id, prbs); if (ret != alloc_result::success) { return ret; } @@ -137,7 +137,7 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, 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); + pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_si_pdsch_unchecked(ss_id, prbs, pdcch.dci); // Generate DCI for SIB pdcch.dci_cfg.coreset0_bw = srsran_coreset_get_bw(&cfg.cfg.pdcch.coreset[0]); @@ -177,7 +177,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t bwp_slot_grid& bwp_msg3_slot = bwp_grid[msg3_slot]; // Verify there is space in PDSCH - alloc_result ret = bwp_pdcch_slot.pdschs.is_grant_valid(cfg.cfg.pdcch.ra_search_space.id, dci_fmt, interv); + alloc_result ret = bwp_pdcch_slot.pdschs.is_rar_grant_valid(interv); if (ret != alloc_result::success) { return ret; } @@ -219,7 +219,7 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t 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_rar_pdsch_unchecked(interv, pdcch.dci); // Generate DCI for RAR with given RA-RNTI pdcch.dci_cfg = slot_ues[pending_rachs[0].temp_crnti]->get_dci_cfg(); @@ -278,7 +278,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, uint32_t ss_id, const bwp_slot_grid& bwp_uci_slot = bwp_grid[ue.uci_slot]; // UCI : UL control info // 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_ue_grant_valid(ue.cfg(), ss_id, dci_fmt, dl_grant); if (ret != alloc_result::success) { return ret; } @@ -309,7 +309,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, uint32_t ss_id, const pdcch_dl_t& pdcch = *pdcch_result.value(); // Allocate PDSCH - pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_pdsch_unchecked(pdcch.dci.ctx, dl_grant, pdcch.dci); + pdsch_t& pdsch = bwp_pdcch_slot.pdschs.alloc_ue_pdsch_unchecked(ss_id, dci_fmt, dl_grant, ue.cfg(), pdcch.dci); // Allocate HARQ int mcs = ue->fixed_pdsch_mcs(); @@ -470,9 +470,7 @@ prb_grant find_optimal_dl_grant(bwp_slot_allocator& slot_alloc, const slot_ue& u { 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_bitmap used_prb_mask = slot_alloc.occupied_dl_prbs(ue.pdsch_slot, ss_id, dci_fmt); prb_interval prb_interv = find_empty_interval_of_length(used_prb_mask, used_prb_mask.size(), 0); diff --git a/srsgnb/src/stack/mac/sched_nr_pdcch.cc b/srsgnb/src/stack/mac/sched_nr_pdcch.cc index 33d7ba8ef..cb34f8dc5 100644 --- a/srsgnb/src/stack/mac/sched_nr_pdcch.cc +++ b/srsgnb/src/stack/mac/sched_nr_pdcch.cc @@ -45,7 +45,7 @@ void fill_dci_from_cfg(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] ? bwp_cfg.coreset_bw(0) : 0; + dci.coreset0_bw = bwp_cfg.cfg.pdcch.coreset_present[0] ? bwp_cfg.coreset_prb_range(0).length() : 0; } void fill_dci_from_cfg(const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& dci) diff --git a/srsgnb/src/stack/mac/sched_nr_sch.cc b/srsgnb/src/stack/mac/sched_nr_sch.cc index 2a9e937ca..ebe7bcb2c 100644 --- a/srsgnb/src/stack/mac/sched_nr_sch.cc +++ b/srsgnb/src/stack/mac/sched_nr_sch.cc @@ -17,7 +17,7 @@ namespace srsenb { namespace sched_nr_impl { template -void log_alloc_failure(srslog::log_channel& log_ch, uint32_t ss_id, const char* cause_fmt, Args&&... args) +void log_alloc_failure(srslog::log_channel& log_ch, const char* cause_fmt, Args&&... args) { if (not log_ch.enabled()) { return; @@ -25,7 +25,7 @@ void log_alloc_failure(srslog::log_channel& log_ch, uint32_t ss_id, const char* // Log allocation failure fmt::memory_buffer fmtbuf; - fmt::format_to(fmtbuf, "SCHED: Failure to allocate PDSCH in SS#{}. Cause: ", ss_id); + fmt::format_to(fmtbuf, "SCHED: Failure to allocate PDSCH. Cause: "); fmt::format_to(fmtbuf, cause_fmt, std::forward(args)...); log_ch("%s", srsran::to_c_str(fmtbuf)); } @@ -43,70 +43,168 @@ void pdsch_allocator::reset() dl_prbs.reset(); } -alloc_result pdsch_allocator::is_grant_valid(uint32_t ss_id, - srsran_dci_format_nr_t dci_fmt, - const prb_grant& grant, - ue_carrier_params_t* ue) const +alloc_result pdsch_allocator::is_grant_valid_common(srsran_search_space_type_t ss_type, + srsran_dci_format_nr_t dci_fmt, + uint32_t coreset_id, + const prb_grant& grant) const { // DL must be active in given slot if (not bwp_cfg.slots[slot_idx].is_dl) { - log_alloc_failure(bwp_cfg.logger.error, ss_id, "DL is disabled for slot={}", slot_idx); + log_alloc_failure(bwp_cfg.logger.error, "DL is disabled for slot={}", slot_idx); return alloc_result::no_sch_space; } // No space in Scheduler PDSCH output list if (pdschs.full()) { - log_alloc_failure(bwp_cfg.logger.warning, ss_id, "Maximum number of PDSCHs={} reached.", pdschs.size()); + log_alloc_failure(bwp_cfg.logger.warning, "Maximum number of PDSCHs={} reached.", pdschs.size()); return alloc_result::no_sch_space; } - // Verify SearchSpace validity - const srsran_search_space_t* ss = (ue == nullptr) ? bwp_cfg.get_ss(ss_id) : ue->get_ss(ss_id); - if (ss == nullptr) { - // Couldn't find SearchSpace - log_alloc_failure(bwp_cfg.logger.error, ss_id, "SearchSpace has not been configured."); + // TS 38.214, 5.1.2.2 - "The UE shall assume that when the scheduling grant is received with DCI format 1_0, then + // downlink resource allocation type 1 is used." + if (dci_fmt == srsran_dci_format_nr_1_0 and not grant.is_alloc_type1()) { + log_alloc_failure(bwp_cfg.logger.warning, "DL Resource Allocation type 1 must be used in case of DCI format 1_0."); return alloc_result::invalid_grant_params; } - 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."); - return alloc_result::invalid_grant_params; - } - + // TS 38.214 - 5.1.2.2 - For DCI format 1_0 and Common Search Space, the list of available PRBs is limited by the + // rb_start and bandwidth of the coreset + if (dci_fmt == srsran_dci_format_nr_1_0 and SRSRAN_SEARCH_SPACE_IS_COMMON(ss_type)) { // Grant PRBs do not collide with CORESET PRB limits (in case of common SearchSpace) - if (bwp_cfg.coreset_prb_limits(ss_id, dci_fmt).collides(grant)) { - bwp_cfg.logger.debug("SCHED: Provided RBG mask falls outside common CORESET PRB boundaries."); + if (bwp_cfg.dci_fmt_1_0_excluded_prbs(coreset_id).collides(grant)) { + log_alloc_failure( + bwp_cfg.logger.debug, "Provided PRB grant={:x} falls outside common CORESET PRB boundaries.", grant); return alloc_result::sch_collision; } } // Grant PRBs do not collide with previous PDSCH allocations if (dl_prbs.collides(grant)) { - bwp_cfg.logger.debug("SCHED: Provided RBG mask collides with allocation previously made."); + log_alloc_failure( + bwp_cfg.logger.debug, "Provided PRB grant={:x} collides with allocations previously made.", grant); return alloc_result::sch_collision; } return alloc_result::success; } -srsran::expected pdsch_allocator::alloc_pdsch(const srsran_dci_ctx_t& dci_ctx, - uint32_t ss_id, - const prb_grant& grant, - srsran_dci_dl_nr_t& dci) +alloc_result pdsch_allocator::is_si_grant_valid(uint32_t ss_id, const prb_grant& grant) const { - alloc_result code = is_grant_valid(ss_id, dci_ctx.format, grant); + // Verify SearchSpace validity + const srsran_search_space_t* ss = bwp_cfg.get_ss(ss_id); + if (ss == nullptr) { + // Couldn't find SearchSpace + log_alloc_failure(bwp_cfg.logger.error, "SearchSpace has not been configured."); + return alloc_result::invalid_grant_params; + } + return is_grant_valid_common(ss->type, srsran_dci_format_nr_1_0, ss->coreset_id, grant); +} + +alloc_result pdsch_allocator::is_rar_grant_valid(const prb_grant& grant) const +{ + srsran_sanity_check(bwp_cfg.cfg.pdcch.ra_search_space_present, + "Attempting RAR allocation in BWP with no raSearchSpace"); + return is_grant_valid_common(bwp_cfg.cfg.pdcch.ra_search_space.type, + srsran_dci_format_nr_1_0, + bwp_cfg.cfg.pdcch.ra_search_space.coreset_id, + grant); +} + +alloc_result pdsch_allocator::is_ue_grant_valid(const ue_carrier_params_t& ue, + uint32_t ss_id, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant) const +{ + const srsran_search_space_t* ss = ue.get_ss(ss_id); + if (ss == nullptr) { + // Couldn't find SearchSpace + log_alloc_failure(bwp_cfg.logger.error, "rnti=0x%x,SearchSpaceId={} has not been configured.", ue.rnti, ss_id); + return alloc_result::invalid_grant_params; + } + alloc_result alloc_result = is_grant_valid_common(ss->type, dci_fmt, ss->coreset_id, grant); + if (alloc_result != alloc_result::success) { + return alloc_result; + } + + // TS 38.214, 5.1.2.2 - "the UE shall use the downlink frequency resource allocation type as defined by the higher + // layer parameter resourceAllocation" + if (ue.phy().pdsch.alloc != srsran_resource_alloc_dynamic) { + if ((ue.phy().pdsch.alloc == srsran_resource_alloc_type0) != grant.is_alloc_type0()) { + log_alloc_failure(bwp_cfg.logger.warning, + "UE rnti=0x{:x} PDSCH RA configuration type {} doesn't match grant type", + ue.rnti, + grant.is_alloc_type0() ? 0 : 1); + return alloc_result::invalid_grant_params; + } + } + + return alloc_result::success; +} + +pdsch_alloc_result pdsch_allocator::alloc_si_pdsch(uint32_t ss_id, const prb_grant& grant, srsran_dci_dl_nr_t& dci) +{ + alloc_result code = is_si_grant_valid(ss_id, grant); if (code != alloc_result::success) { return code; } - - return {&alloc_pdsch_unchecked(dci_ctx, grant, dci)}; + return {&alloc_si_pdsch_unchecked(ss_id, grant, dci)}; } -pdsch_t& pdsch_allocator::alloc_pdsch_unchecked(const srsran_dci_ctx_t& dci_ctx, - const prb_grant& grant, - srsran_dci_dl_nr_t& out_dci) +pdsch_t& pdsch_allocator::alloc_si_pdsch_unchecked(uint32_t ss_id, const prb_grant& grant, srsran_dci_dl_nr_t& dci) +{ + // Verify SearchSpace validity + const srsran_search_space_t* ss = bwp_cfg.get_ss(ss_id); + srsran_sanity_check(ss != nullptr, "SearchSpace has not been configured"); + return alloc_pdsch_unchecked(ss->coreset_id, ss->type, srsran_dci_format_nr_1_0, grant, dci); +} + +pdsch_alloc_result pdsch_allocator::alloc_rar_pdsch(const prb_grant& grant, srsran_dci_dl_nr_t& dci) +{ + alloc_result code = is_rar_grant_valid(grant); + if (code != alloc_result::success) { + return code; + } + return {&alloc_rar_pdsch_unchecked(grant, dci)}; +} + +pdsch_t& pdsch_allocator::alloc_rar_pdsch_unchecked(const prb_grant& grant, srsran_dci_dl_nr_t& dci) +{ + // TS 38.213, 8.2 - "In response to a PRACH transmission, a UE attempts to detect a DCI format 1_0" + const static srsran_dci_format_nr_t dci_fmt = srsran_dci_format_nr_1_0; + + return alloc_pdsch_unchecked( + bwp_cfg.cfg.pdcch.ra_search_space.coreset_id, bwp_cfg.cfg.pdcch.ra_search_space.type, dci_fmt, grant, dci); +} + +pdsch_alloc_result pdsch_allocator::alloc_ue_pdsch(uint32_t ss_id, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant, + const ue_carrier_params_t& ue, + srsran_dci_dl_nr_t& dci) +{ + alloc_result code = is_ue_grant_valid(ue, ss_id, dci_fmt, grant); + if (code != alloc_result::success) { + return code; + } + return {&alloc_ue_pdsch_unchecked(ss_id, dci_fmt, grant, ue, dci)}; +} + +pdsch_t& pdsch_allocator::alloc_ue_pdsch_unchecked(uint32_t ss_id, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant, + const ue_carrier_params_t& ue, + srsran_dci_dl_nr_t& dci) +{ + const srsran_search_space_t* ss = ue.get_ss(ss_id); + srsran_sanity_check(ss != nullptr, "SearchSpace has not been configured"); + return alloc_pdsch_unchecked(ss->coreset_id, ss->type, dci_fmt, grant, dci); +} + +pdsch_t& pdsch_allocator::alloc_pdsch_unchecked(uint32_t coreset_id, + srsran_search_space_type_t ss_type, + srsran_dci_format_nr_t dci_fmt, + const prb_grant& grant, + srsran_dci_dl_nr_t& out_dci) { // Create new PDSCH entry in output PDSCH list pdschs.emplace_back(); @@ -121,12 +219,14 @@ pdsch_t& pdsch_allocator::alloc_pdsch_unchecked(const srsran_dci_ctx_t& dci_ctx, out_dci.freq_domain_assigment = grant.rbgs().to_uint64(); } else { uint32_t rb_start = grant.prbs().start(), nof_prb = bwp_cfg.nof_prb(); - if (SRSRAN_SEARCH_SPACE_IS_COMMON(dci_ctx.ss_type)) { - if (dci_ctx.format == srsran_dci_format_nr_1_0) { - rb_start -= dci_ctx.coreset_start_rb; + if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss_type)) { + prb_interval lims = bwp_cfg.coreset_prb_range(coreset_id); + if (dci_fmt == srsran_dci_format_nr_1_0) { + srsran_sanity_check(rb_start >= lims.start(), "Invalid PRB grant"); + rb_start -= lims.start(); } - if (dci_ctx.coreset_id == 0) { - nof_prb = bwp_cfg.coreset_bw(0); + if (coreset_id == 0) { + nof_prb = lims.length(); } } srsran_sanity_check(rb_start + grant.prbs().length() <= nof_prb, "Invalid PRB grant"); @@ -140,6 +240,7 @@ void pdsch_allocator::cancel_last_pdsch() { srsran_assert(not pdschs.empty(), "Trying to abort PDSCH allocation that does not exist"); pdschs.pop_back(); + // TODO: clear bitmap allocated RBs } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -220,9 +321,9 @@ pusch_allocator::is_grant_valid(srsran_search_space_type_t ss_type, const prb_gr } pusch_alloc_result -pusch_allocator::alloc_pusch(const srsran_dci_ctx_t& dci_ctx, const prb_grant& grant, srsran_dci_ul_nr_t& dci) +pusch_allocator::alloc_pusch(const srsran_search_space_type_t ss_type, const prb_grant& grant, srsran_dci_ul_nr_t& dci) { - alloc_result code = is_grant_valid(dci_ctx.ss_type, grant); + alloc_result code = is_grant_valid(ss_type, grant); if (code != alloc_result::success) { return code; } diff --git a/srsgnb/src/stack/mac/test/sched_nr_sch_test.cc b/srsgnb/src/stack/mac/test/sched_nr_sch_test.cc index 7728dfd48..d27f3d466 100644 --- a/srsgnb/src/stack/mac/test/sched_nr_sch_test.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_sch_test.cc @@ -65,8 +65,7 @@ void test_dci_freq_assignment(const bwp_params_t& bwp_params, prb_interval grant // Compute BWP PRB limits prb_interval lims{0, bwp_params.nof_prb()}; if (SRSRAN_SEARCH_SPACE_IS_COMMON(pdcch.dci.ctx.ss_type) and pdcch.dci.ctx.format == srsran_dci_format_nr_1_0) { - uint32_t s = pdcch.dci.ctx.coreset_start_rb; - lims = prb_interval{s, pdcch.dci.ctx.coreset_id == 0 ? s + bwp_params.coreset_bw(0) : bwp_params.nof_prb()}; + lims = bwp_params.dci_fmt_1_0_prb_lims(pdcch.dci.ctx.coreset_id); } // RB indexing should start from the first PRB of CORESET @@ -99,8 +98,8 @@ void test_si() pdcch_dl_t pdcch; pdcch.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, ss_id, srsran_rnti_type_si, SRSRAN_SIRNTI); - uint32_t min_prb = pdcch.dci.ctx.coreset_start_rb; - uint32_t max_prb = min_prb + bwp_params.coreset_bw(0); + uint32_t min_prb = bwp_params.dci_fmt_1_0_prb_lims(pdcch.dci.ctx.coreset_id).start(); + uint32_t max_prb = bwp_params.dci_fmt_1_0_prb_lims(pdcch.dci.ctx.coreset_id).stop(); std::array grant_list = { prb_interval{2, 4}, prb_interval{min_prb, max_prb}, prb_interval{0, bwp_params.nof_prb()}}; @@ -113,13 +112,13 @@ void test_si() bool success_expected = grant.start() >= min_prb and grant.stop() <= max_prb; - alloc_result check_ret = pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, grant); + alloc_result check_ret = pdsch_sched.is_si_grant_valid(ss_id, grant); prb_bitmap avail_prbs = pdsch_sched.occupied_prbs(ss_id, srsran_dci_format_nr_1_0); TESTASSERT_EQ((int)min_prb, avail_prbs.find_lowest(0, avail_prbs.size(), false)); TESTASSERT_EQ((int)max_prb, avail_prbs.find_lowest(min_prb, avail_prbs.size(), true)); printf("Attempt %d should be %ssuccessful\n", i, success_expected ? "" : "un"); - alloc_res = pdsch_sched.alloc_pdsch(pdcch.dci.ctx, ss_id, grant, pdcch.dci); + alloc_res = pdsch_sched.alloc_si_pdsch(ss_id, grant, pdcch.dci); if (success_expected) { // SIB1 allocation doesnt go outside CORESET#0 BW TESTASSERT(alloc_res.has_value()); @@ -157,8 +156,8 @@ void test_rar() pdcch_dl_t pdcch; pdcch.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, ss_id, srsran_rnti_type_ra, 0x2); - uint32_t min_prb = pdcch.dci.ctx.coreset_start_rb; - uint32_t max_prb = min_prb + bwp_params.coreset_bw(0); + uint32_t min_prb = bwp_params.dci_fmt_1_0_prb_lims(pdcch.dci.ctx.coreset_id).start(); + uint32_t max_prb = bwp_params.dci_fmt_1_0_prb_lims(pdcch.dci.ctx.coreset_id).stop(); std::array grant_list = { prb_interval{2, 4}, prb_interval{min_prb, max_prb}, prb_interval{0, bwp_params.nof_prb()}}; @@ -171,13 +170,13 @@ void test_rar() bool success_expected = grant.start() >= min_prb and grant.stop() <= max_prb; - alloc_result check_ret = pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, grant); + alloc_result check_ret = pdsch_sched.is_rar_grant_valid(grant); prb_bitmap avail_prbs = pdsch_sched.occupied_prbs(ss_id, srsran_dci_format_nr_1_0); TESTASSERT_EQ((int)min_prb, avail_prbs.find_lowest(0, avail_prbs.size(), false)); TESTASSERT_EQ((int)max_prb, avail_prbs.find_lowest(min_prb, avail_prbs.size(), true)); printf("Attempt %d should be %ssuccessful\n", i, success_expected ? "" : "un"); - alloc_res = pdsch_sched.alloc_pdsch(pdcch.dci.ctx, ss_id, grant, pdcch.dci); + alloc_res = pdsch_sched.alloc_rar_pdsch(grant, pdcch.dci); if (success_expected) { // SIB1 allocation doesnt go outside CORESET#0 BW TESTASSERT(alloc_res.has_value()); @@ -217,8 +216,7 @@ void test_ue_pdsch() pdcch_common.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 1, srsran_rnti_type_c, 0x4601); pdcch_ue.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 2, srsran_rnti_type_c, 0x4601); - prb_interval lims_common{pdcch_common.dci.ctx.coreset_start_rb, - pdcch_common.dci.ctx.coreset_start_rb + bwp_params.coreset_bw(0)}; + prb_interval lims_common = bwp_params.dci_fmt_1_0_prb_lims(pdcch_common.dci.ctx.coreset_id); prb_interval lims_ue{0, bwp_params.nof_prb()}; std::array, 4> grant_list = {std::make_pair(1, prb_interval{2, 4}), @@ -238,7 +236,7 @@ void test_ue_pdsch() bool success_expected = grant.start() >= lims.start() and grant.stop() <= lims.stop(); - alloc_result check_ret = pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, grant); + alloc_result check_ret = pdsch_sched.is_ue_grant_valid(ue_cc, ss_id, srsran_dci_format_nr_1_0, grant); prb_bitmap avail_prbs = pdsch_sched.occupied_prbs(ss_id, srsran_dci_format_nr_1_0); int pos = avail_prbs.find_lowest(0, avail_prbs.size(), false); TESTASSERT_EQ((int)lims.start(), pos); @@ -246,10 +244,10 @@ void test_ue_pdsch() TESTASSERT_EQ((int)lims.stop(), (pos < 0 ? (int)avail_prbs.size() : pos)); printf("Attempt %d should be %ssuccessful\n", i, success_expected ? "" : "un"); - alloc_res = pdsch_sched.alloc_pdsch(pdcch.dci.ctx, ss_id, grant, pdcch.dci); + alloc_res = pdsch_sched.alloc_ue_pdsch(ss_id, srsran_dci_format_nr_1_0, grant, ue_cc, pdcch.dci); + TESTASSERT(success_expected == alloc_res.has_value()); if (success_expected) { // SIB1 allocation doesnt go outside CORESET#0 BW - TESTASSERT(alloc_res.has_value()); TESTASSERT_EQ(1, pdschs.size()); TESTASSERT(&pdschs.back() == alloc_res.value()); TESTASSERT_EQ(0, pdcch.dci.time_domain_assigment); @@ -258,7 +256,6 @@ void test_ue_pdsch() test_dci_freq_assignment(bwp_params, grant, pdcch); } else { - TESTASSERT(alloc_res.is_error()); TESTASSERT(check_ret == alloc_res.error()); TESTASSERT_EQ(0, pdschs.size()); TESTASSERT(avail_prbs.any(grant.start(), grant.stop())); @@ -266,6 +263,55 @@ void test_ue_pdsch() } } +void test_pdsch_fail() +{ + srsran::test_delimit_logger delimiter{"Test PDSCH Allocation Failure"}; + + // 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}; + + pdsch_list_t pdschs; + pdsch_alloc_result alloc_res; + + pdsch_allocator pdsch_sched(bwp_params, 0, pdschs); + + pdcch_dl_t pdcch_common, pdcch_ue, pdcch_rar, pdcch_si, pdcch; + pdcch_si.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 0, srsran_rnti_type_si, SRSRAN_SIRNTI); + pdcch_rar.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 1, srsran_rnti_type_ra, 0x2); + pdcch_common.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 1, srsran_rnti_type_c, 0x4601); + pdcch_ue.dci.ctx = generate_dci_ctx(bwp_params.cfg.pdcch, 2, srsran_rnti_type_c, 0x4601); + + // Allocations of type 0 are not compatible with DCI format 1_0 + rbg_bitmap rbgs(bwp_params.N_rbg); + rbgs.set(1); + rbgs.set(3); + prb_grant grant_type0 = rbgs; + TESTASSERT_EQ(alloc_result::invalid_grant_params, pdsch_sched.alloc_si_pdsch(0, grant_type0, pdcch_si.dci).error()); + TESTASSERT_EQ(alloc_result::invalid_grant_params, pdsch_sched.alloc_rar_pdsch(grant_type0, pdcch_rar.dci).error()); + TESTASSERT_EQ(alloc_result::invalid_grant_params, + pdsch_sched.alloc_ue_pdsch(1, srsran_dci_format_nr_1_0, grant_type0, ue_cc, pdcch.dci).error()); + TESTASSERT_EQ(alloc_result::invalid_grant_params, + pdsch_sched.alloc_ue_pdsch(2, srsran_dci_format_nr_1_0, grant_type0, ue_cc, pdcch.dci).error()); + + // Resource Allocation type must be compatible with UE PDSCH configuration + TESTASSERT_EQ(alloc_result::invalid_grant_params, + pdsch_sched.alloc_ue_pdsch(2, srsran_dci_format_nr_1_1, grant_type0, ue_cc, pdcch.dci).error()); + + // Allocations of DCI format 1_0 should start from CORESET first RB and their BW should be limited by CORESET#0 BW + prb_grant grant_type1 = prb_interval{0, bwp_params.coreset_prb_range(0).stop()}; + TESTASSERT(pdsch_sched.alloc_ue_pdsch(1, srsran_dci_format_nr_1_0, grant_type1, ue_cc, pdcch.dci).is_error()); + grant_type1 = prb_interval{bwp_params.coreset_prb_range(0).start(), bwp_params.nof_prb()}; + TESTASSERT(pdsch_sched.alloc_ue_pdsch(1, srsran_dci_format_nr_1_0, grant_type1, ue_cc, pdcch.dci).is_error()); + TESTASSERT(pdsch_sched.alloc_ue_pdsch(2, srsran_dci_format_nr_1_0, grant_type1, ue_cc, pdcch.dci).has_value()); + + // PRB collisions are detected + TESTASSERT(pdsch_sched.alloc_ue_pdsch(2, srsran_dci_format_nr_1_0, prb_interval{5, 6}, ue_cc, pdcch.dci).is_error()); +} + void test_multi_pdsch() { srsran::test_delimit_logger delimiter{"Test Multiple PDSCH Allocations"}; @@ -297,13 +343,13 @@ void test_multi_pdsch() prb_bitmap sib_prbs = ~used_prbs; int first_prb = sib_prbs.find_lowest(0, sib_prbs.size(), true); prb_interval sib_grant{(uint32_t)first_prb, sib1_grant_size}; - TESTASSERT_EQ(alloc_result::success, pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, sib_grant)); - alloc_res = pdsch_sched.alloc_pdsch(pdcch->dci.ctx, ss_id, sib_grant, pdcch->dci); + TESTASSERT_EQ(alloc_result::success, pdsch_sched.is_si_grant_valid(ss_id, sib_grant)); + alloc_res = pdsch_sched.alloc_si_pdsch(ss_id, sib_grant, pdcch->dci); TESTASSERT(alloc_res.has_value()); test_dci_freq_assignment(bwp_params, sib_grant, *pdcch); prb_bitmap used_prbs_sib1 = pdsch_sched.occupied_prbs(ss_id, srsran_dci_format_nr_1_0); TESTASSERT_EQ(used_prbs_sib1.count(), used_prbs.count() + sib_grant.length()); - TESTASSERT_EQ(alloc_result::sch_collision, pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, sib_grant)); + TESTASSERT_EQ(alloc_result::sch_collision, pdsch_sched.is_si_grant_valid(ss_id, sib_grant)); prb_bitmap last_prb_bitmap(used_prbs.size()); last_prb_bitmap.fill(sib_grant.start(), sib_grant.stop()); @@ -316,13 +362,14 @@ void test_multi_pdsch() first_prb = ue_prbs.find_lowest(0, ue_prbs.size(), true); uint32_t ue_grant_size = 10; prb_interval ue_grant{(uint32_t)first_prb, ue_grant_size}; - TESTASSERT_EQ(alloc_result::success, pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, ue_grant)); - alloc_res = pdsch_sched.alloc_pdsch(pdcch->dci.ctx, ss_id, ue_grant, pdcch->dci); + TESTASSERT_EQ(alloc_result::success, pdsch_sched.is_ue_grant_valid(ue_cc, ss_id, srsran_dci_format_nr_1_0, ue_grant)); + alloc_res = pdsch_sched.alloc_ue_pdsch(ss_id, srsran_dci_format_nr_1_0, ue_grant, ue_cc, pdcch->dci); TESTASSERT(alloc_res.has_value()); test_dci_freq_assignment(bwp_params, ue_grant, *pdcch); prb_bitmap used_prbs_ue = pdsch_sched.occupied_prbs(ss_id, srsran_dci_format_nr_1_0); TESTASSERT_EQ(used_prbs_ue.count(), used_prbs_sib1.count() + ue_grant.length()); - TESTASSERT_EQ(alloc_result::sch_collision, pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, ue_grant)); + TESTASSERT_EQ(alloc_result::sch_collision, + pdsch_sched.is_ue_grant_valid(ue_cc, ss_id, srsran_dci_format_nr_1_0, ue_grant)); last_prb_bitmap.reset(); last_prb_bitmap.fill(ue_grant.start(), ue_grant.stop()); @@ -334,13 +381,15 @@ void test_multi_pdsch() used_prbs = pdsch_sched.occupied_prbs(ss_id, srsran_dci_format_nr_1_0); prb_interval ue_grant2 = find_empty_interval_of_length(used_prbs, used_prbs_ue.size(), 0); TESTASSERT_EQ(bwp_params.nof_prb(), ue_grant2.stop()); - TESTASSERT_EQ(alloc_result::success, pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, ue_grant2)); - alloc_res = pdsch_sched.alloc_pdsch(pdcch->dci.ctx, ss_id, ue_grant2, pdcch->dci); + TESTASSERT_EQ(alloc_result::success, + pdsch_sched.is_ue_grant_valid(ue_cc, ss_id, srsran_dci_format_nr_1_0, ue_grant2)); + alloc_res = pdsch_sched.alloc_ue_pdsch(ss_id, srsran_dci_format_nr_1_0, ue_grant2, ue_cc, pdcch->dci); TESTASSERT(alloc_res.has_value()); test_dci_freq_assignment(bwp_params, ue_grant2, *pdcch); prb_bitmap used_prbs_ue2 = pdsch_sched.occupied_prbs(ss_id, srsran_dci_format_nr_1_0); TESTASSERT_EQ(used_prbs_ue2.count(), used_prbs.count() + ue_grant2.length()); - TESTASSERT_EQ(alloc_result::sch_collision, pdsch_sched.is_grant_valid(ss_id, srsran_dci_format_nr_1_0, ue_grant2)); + TESTASSERT_EQ(alloc_result::sch_collision, + pdsch_sched.is_ue_grant_valid(ue_cc, ss_id, srsran_dci_format_nr_1_0, ue_grant2)); last_prb_bitmap.reset(); last_prb_bitmap.fill(ue_grant2.start(), ue_grant2.stop()); @@ -382,7 +431,7 @@ void test_multi_pusch() 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); + alloc_res = pusch_sched.alloc_pusch(pdcch->dci.ctx.ss_type, 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()); @@ -399,7 +448,7 @@ void test_multi_pusch() 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); + alloc_res = pusch_sched.alloc_pusch(pdcch->dci.ctx.ss_type, 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()); @@ -427,6 +476,7 @@ int main() srsenb::test_si(); srsenb::test_rar(); srsenb::test_ue_pdsch(); + srsenb::test_pdsch_fail(); srsenb::test_multi_pdsch(); srsenb::test_multi_pusch(); } \ No newline at end of file