@@ -147,7 +147,7 @@ intra_slice_scheduler::intra_slice_scheduler(const scheduler_ue_expert_config& e
147147 pending_ul_newtxs.reserve (MAX_UE_PDUS_PER_SLOT);
148148
149149 // Pre-reserve memory for slice context.
150- const unsigned max_expected_ran_slices = 8 ;
150+ constexpr unsigned max_expected_ran_slices = 8 ;
151151 slice_ctxt_list.reserve (max_expected_ran_slices);
152152}
153153
@@ -201,6 +201,7 @@ void intra_slice_scheduler::ul_sched(ul_ran_slice_candidate slice, scheduler_pol
201201
202202 if (slice.get_slot_tx () != pusch_slot) {
203203 pusch_slot = slice.get_slot_tx ();
204+ update_min_srs_symbol ();
204205 update_used_ul_vrbs (slice);
205206 }
206207
@@ -243,7 +244,7 @@ static std::pair<unsigned, unsigned> get_max_grants_and_rb_grant_size(span<const
243244 return std::make_pair (0 , 0 );
244245 }
245246
246- // Determine how many UE grants to allocate in the slot (assuming full buffer). As an heuristic, we divide the number
247+ // Determine how many UE grants to allocate in the slot (assuming full buffer). As a heuristic, we divide the number
247248 // of candidates by 4 and set 8 as the maximum number of UEs to be scheduled per slot, assuming full buffer. This
248249 // heuristic is a result of a tradeoff between minimizing latency and ensuring we don't deplete the PDCCH resources.
249250 static constexpr unsigned MAX_UE_GRANT_PER_SLOT = 8 ;
@@ -351,7 +352,10 @@ unsigned intra_slice_scheduler::schedule_ul_retx_candidates(ul_ran_slice_candida
351352 }
352353
353354 // Allocate PDCCH and PUSCH.
354- auto result = ue_alloc.allocate_ul_grant (ue_retx_ul_grant_request{u, pusch_slot, h, used_ul_vrbs});
355+ // NOTE: the symbols passed to the grant are the symbols that are available for PUSCH and for which the used VRBs
356+ // have been computed.
357+ auto result = ue_alloc.allocate_ul_grant (
358+ ue_retx_ul_grant_request{u, pusch_slot, h, used_ul_vrbs, ofdm_symbol_range{0 , min_srs_symbol}});
355359 if (not result.has_value () and result.error () == alloc_status::skip_slot) {
356360 // Received signal to stop allocations in the slot.
357361 break ;
@@ -456,7 +460,7 @@ unsigned intra_slice_scheduler::schedule_dl_newtx_candidates(dl_ran_slice_candid
456460 for (const auto & ue_candidate : newtx_candidates) {
457461 if (pucch_grant_limit_exceeded) {
458462 // The PUCCH is likely saturated and there is no space for new PUCCHs.
459- // As an heuristic, we only allocate DL grants to UEs which already have a PUCCH or a PUSCH in a future slot that
463+ // As a heuristic, we only allocate DL grants to UEs which already have a PUCCH or a PUSCH in a future slot that
460464 // can likely accommodate more HARQ-ACK bits.
461465 if (not (ue_candidate.ue_cc ->harqs .last_ack_slot ().valid () and
462466 ue_candidate.ue_cc ->harqs .last_ack_slot () > pdsch_slot) and
@@ -586,8 +590,10 @@ unsigned intra_slice_scheduler::schedule_ul_newtx_candidates(ul_ran_slice_candid
586590 unsigned rb_count = 0 ;
587591 for (const auto & ue_candidate : newtx_candidates) {
588592 // Create UL grant builder.
589- auto result =
590- ue_alloc.allocate_ul_grant (ue_newtx_ul_grant_request{*ue_candidate.ue , pusch_slot, ue_candidate.pending_bytes });
593+ // NOTE: the symbols passed to the grant are the symbols that are available for PUSCH and for which the used VRBs
594+ // have been computed.
595+ auto result = ue_alloc.allocate_ul_grant (ue_newtx_ul_grant_request{
596+ *ue_candidate.ue , pusch_slot, ue_candidate.pending_bytes , ofdm_symbol_range{0 , min_srs_symbol}});
591597
592598 if (result.has_value ()) {
593599 // Allocation was successful. Move grant builder to list of pending newTx grants.
@@ -656,7 +662,7 @@ unsigned intra_slice_scheduler::schedule_ul_newtx_candidates(ul_ran_slice_candid
656662 // Update slice state.
657663 slice.store_grant (nof_rbs_alloc);
658664 rb_count += nof_rbs_alloc;
659- rbs_missing = ( max_grant_size - nof_rbs_alloc) ;
665+ rbs_missing = max_grant_size - nof_rbs_alloc;
660666 }
661667
662668 // Clear grant builders.
@@ -747,7 +753,7 @@ std::optional<ue_newtx_candidate> intra_slice_scheduler::create_newtx_ul_candida
747753 return ue_newtx_candidate{&u, &ue_cc, pending_bytes, forbid_sched_priority};
748754}
749755
750- unsigned intra_slice_scheduler::max_pdschs_to_alloc (const dl_ran_slice_candidate& slice)
756+ unsigned intra_slice_scheduler::max_pdschs_to_alloc (const dl_ran_slice_candidate& slice) const
751757{
752758 // We cannot allocate more than the number of UEs available.
753759 int pdschs_to_alloc = slice.get_slice_ues ().size ();
@@ -784,7 +790,7 @@ unsigned intra_slice_scheduler::max_pdschs_to_alloc(const dl_ran_slice_candidate
784790 return std::max (pdschs_to_alloc, 0 );
785791}
786792
787- unsigned intra_slice_scheduler::max_puschs_to_alloc (const ul_ran_slice_candidate& slice)
793+ unsigned intra_slice_scheduler::max_puschs_to_alloc (const ul_ran_slice_candidate& slice) const
788794{
789795 if (not cell_alloc.cfg .is_ul_enabled (slice.get_slot_tx ())) {
790796 return 0 ;
@@ -882,10 +888,40 @@ void intra_slice_scheduler::update_used_ul_vrbs(const ul_ran_slice_candidate& sl
882888
883889 // (Implementation-defined) We use the common PUSCH TD resources as a reference for the computation of RBs unavailable
884890 // for PDSCH. This assumes that these resources are not colliding with SRS.
885- const auto & init_ul_bwp = cell_alloc.cfg .ul_cfg_common .init_ul_bwp ;
886- const ofdm_symbol_range& symbols_to_check = init_ul_bwp.pusch_cfg_common ->pusch_td_alloc_list [0 ].symbols ;
891+ const auto & init_ul_bwp = cell_alloc.cfg .ul_cfg_common .init_ul_bwp ;
892+ srsran_assert (slice.get_slot_tx () - cell_alloc[0 ].slot > 0 , " PUSCH slot cannot precede its corresponding PDCCH slot" );
893+ const unsigned slice_candidate_k2 = slice.get_slot_tx () - cell_alloc[0 ].slot ;
894+ ofdm_symbol_range symbols_to_check = {0 , 0 };
895+ // Find the max symbols such that symbols.stop() <= min_srs_symbol;
896+ for (auto & td_res : init_ul_bwp.pusch_cfg_common ->pusch_td_alloc_list ) {
897+ // We can choose only the symbols for the same k2.
898+ if (td_res.k2 < slice_candidate_k2) {
899+ continue ;
900+ }
901+ if (td_res.k2 == slice_candidate_k2) {
902+ if (td_res.symbols .stop () <= min_srs_symbol and td_res.symbols .stop () > symbols_to_check.stop ())
903+ symbols_to_check = td_res.symbols ;
904+ }
905+ if (td_res.k2 > slice_candidate_k2) {
906+ break ;
907+ }
908+ }
909+
910+ if (symbols_to_check.empty ()) {
911+ logger.debug (
912+ " No symbols available for PUSCH allocation on slot={} for slice_id={}" , pusch_slot, slice.id ().value ());
913+ }
887914
888915 used_ul_vrbs = cell_alloc[pusch_slot]
889916 .ul_res_grid .used_prbs (init_ul_bwp.generic_params .scs , ul_crb_lims, symbols_to_check)
890917 .convert_to <vrb_bitmap>();
891918}
919+
920+ void intra_slice_scheduler::update_min_srs_symbol ()
921+ {
922+ // Reset to max symbol index before looking for the min.
923+ min_srs_symbol = NOF_OFDM_SYM_PER_SLOT_NORMAL_CP;
924+ for (const auto & srs : cell_alloc[pusch_slot - pdcch_slot].result .ul .srss ) {
925+ min_srs_symbol = std::min (static_cast <unsigned >(srs.symbols .start ()), min_srs_symbol);
926+ }
927+ }
0 commit comments