Skip to content

Commit ad74312

Browse files
carlo-galcodebot
authored andcommitted
sched: fix pusch allocation on slots with SRS
Signed-off-by: Carlo Galiotto <[email protected]>
1 parent c4e7cee commit ad74312

File tree

9 files changed

+164
-86
lines changed

9 files changed

+164
-86
lines changed

lib/scheduler/slicing/inter_slice_scheduler.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ void inter_slice_scheduler::slot_indication(slot_point slot_tx, const cell_resou
136136
span<const pusch_time_domain_resource_allocation> pusch_time_domain_list =
137137
cell_cfg.ul_cfg_common.init_ul_bwp.pusch_cfg_common.value().pusch_td_alloc_list;
138138
for (const auto& slice : slices) {
139+
std::optional<unsigned> allocated_k2;
139140
for (const unsigned pusch_td_res_idx : slot_ring[slot_tx.count() % slot_ring.size()].valid_pusch_td_list) {
140141
unsigned pusch_delay = pusch_time_domain_list[pusch_td_res_idx].k2 + cell_cfg.ntn_cs_koffset;
141142
const cell_slot_resource_allocator& pusch_alloc = res_grid[pusch_delay];
@@ -147,6 +148,12 @@ void inter_slice_scheduler::slot_indication(slot_point slot_tx, const cell_resou
147148
continue;
148149
}
149150

151+
if (allocated_k2.has_value() and allocated_k2.value() == pusch_time_domain_list[pusch_td_res_idx].k2) {
152+
// There is already a slice candidate for the same k2. Adding another candidate for the same k2 and different
153+
// symbols would result in repeating the same slice candidates several times.
154+
continue;
155+
}
156+
150157
const crb_bitmap pusch_used_crbs =
151158
pusch_alloc.ul_res_grid.used_crbs(cell_cfg.ul_cfg_common.init_ul_bwp.generic_params.scs,
152159
cell_cfg.ul_cfg_common.init_ul_bwp.generic_params.crbs,
@@ -169,6 +176,7 @@ void inter_slice_scheduler::slot_indication(slot_point slot_tx, const cell_resou
169176
rb_lims = {pusch_rb_count, slice.inst.cfg.rbs.max()};
170177
}
171178
const auto prio = slice.get_prio(false, slot_tx, pusch_slot, rb_lims.stop());
179+
allocated_k2.emplace(pusch_time_domain_list[pusch_td_res_idx].k2);
172180
ul_prio_queue.push(slice_candidate_context{slice.inst.id, prio, rb_lims, pusch_slot});
173181
}
174182
}
@@ -230,7 +238,7 @@ void inter_slice_scheduler::add_impl(ue& u)
230238
}
231239
}
232240

233-
ue* inter_slice_scheduler::fetch_ue_to_update(du_ue_index_t ue_idx)
241+
ue* inter_slice_scheduler::fetch_ue_to_update(du_ue_index_t ue_idx) const
234242
{
235243
if (not ues.contains(ue_idx)) {
236244
// UE should be added to the repository at this stage.
@@ -410,8 +418,8 @@ inter_slice_scheduler::priority_type inter_slice_scheduler::ran_slice_sched_cont
410418
prio = (prio << delay_prio_bitsize) + delay_prio;
411419

412420
// 5. Round-robin across slices with the same slice and delay priorities.
413-
float rbs_per_slot = is_dl ? inst.average_pdsch_rbs_per_slot() : inst.average_pusch_rbs_per_slot();
414-
const priority_type rr_prio = rr_bitmask - std::min((unsigned)std::round(rbs_per_slot), rr_bitmask);
421+
const float rbs_per_slot = is_dl ? inst.average_pdsch_rbs_per_slot() : inst.average_pusch_rbs_per_slot();
422+
const priority_type rr_prio = rr_bitmask - std::min(static_cast<unsigned>(std::round(rbs_per_slot)), rr_bitmask);
415423
prio = (prio << rr_bitsize) + rr_prio;
416424

417425
// Add one bit to differentiate from skip priority.

lib/scheduler/slicing/inter_slice_scheduler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class inter_slice_scheduler
4545

4646
size_t nof_slices() const { return slices.size(); }
4747
const slice_rrm_policy_config& slice_config(ran_slice_id_t id) const { return slices[id.value()].inst.cfg; }
48-
scheduler_policy& get_policy(ran_slice_id_t id) { return *slices[id.value()].policy; }
48+
scheduler_policy& get_policy(ran_slice_id_t id) const { return *slices[id.value()].policy; }
4949

5050
void handle_slice_reconfiguration_request(const du_cell_slice_reconfig_request& slice_reconf_req);
5151

@@ -131,7 +131,7 @@ class inter_slice_scheduler
131131
ran_slice_instance& get_slice(const logical_channel_config& lc_cfg);
132132

133133
// Fetch UE if it is in a state to be added/reconfigured.
134-
ue* fetch_ue_to_update(du_ue_index_t ue_idx);
134+
ue* fetch_ue_to_update(du_ue_index_t ue_idx) const;
135135

136136
void add_impl(ue& u);
137137

lib/scheduler/ue_scheduling/grant_params_selector.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ static std::optional<ul_sched_context> get_ul_sched_context(const slice_ue&
338338
slot_point pusch_slot,
339339
unsigned uci_nof_harq_bits,
340340
const ul_harq_process_handle* h_ul,
341-
unsigned pending_bytes)
341+
unsigned pending_bytes,
342+
ofdm_symbol_range allowed_symbols)
342343
{
343344
const ue_cell& ue_cc = u.get_cc();
344345

@@ -347,9 +348,10 @@ static std::optional<ul_sched_context> get_ul_sched_context(const slice_ue&
347348
return std::nullopt;
348349
}
349350

350-
const ue_cell_configuration& ue_cell_cfg = ue_cc.cfg();
351-
const cell_configuration& cell_cfg = ue_cell_cfg.cell_cfg_common;
352-
unsigned slot_nof_symbols = cell_cfg.get_nof_ul_symbol_per_slot(pusch_slot);
351+
const ue_cell_configuration& ue_cell_cfg = ue_cc.cfg();
352+
const cell_configuration& cell_cfg = ue_cell_cfg.cell_cfg_common;
353+
// If the slot has SRS allocated, take the min between the symbols per slots and available symbols in that slot.
354+
unsigned slot_nof_symbols = std::min(cell_cfg.get_nof_ul_symbol_per_slot(pusch_slot), allowed_symbols.length());
353355

354356
// TODO: Support more search spaces.
355357
static constexpr search_space_id ue_ded_ss_id = to_search_space_id(2);
@@ -380,7 +382,7 @@ static std::optional<ul_sched_context> get_ul_sched_context(const slice_ue&
380382
for (unsigned pusch_td_index = 0, e = ss.pusch_time_domain_list.size(); pusch_td_index != e; ++pusch_td_index) {
381383
const pusch_time_domain_resource_allocation& pusch_td_res = ss.pusch_time_domain_list[pusch_td_index];
382384

383-
// Check that k2 matches the chosen PUSCH slot
385+
// Check that k2 matches the chosen PUSCH slot.
384386
if (pdcch_slot + pusch_td_res.k2 + cell_cfg.ntn_cs_koffset != pusch_slot) {
385387
continue;
386388
}
@@ -398,6 +400,12 @@ static std::optional<ul_sched_context> get_ul_sched_context(const slice_ue&
398400
continue;
399401
}
400402

403+
// Make sure the PUSCH time resource symbols fit within the UL symbols available in this slot; this is to avoid
404+
// allocating the PUSCH over SRS resource symbols, if any.
405+
if (not allowed_symbols.contains(pusch_td_res.symbols)) {
406+
continue;
407+
}
408+
401409
// Compute recommended number of layers, MCS and PRBs.
402410
sch_mcs_index mcs;
403411
pusch_config_params pusch_cfg;
@@ -452,22 +460,24 @@ static std::optional<ul_sched_context> get_ul_sched_context(const slice_ue&
452460
return std::nullopt;
453461
}
454462

455-
std::optional<ul_sched_context> sched_helper::get_newtx_ul_sched_context(const slice_ue& u,
456-
slot_point pdcch_slot,
457-
slot_point pusch_slot,
458-
unsigned uci_nof_harq_bits,
459-
unsigned pending_bytes)
463+
std::optional<ul_sched_context> sched_helper::get_newtx_ul_sched_context(const slice_ue& u,
464+
slot_point pdcch_slot,
465+
slot_point pusch_slot,
466+
unsigned uci_nof_harq_bits,
467+
unsigned pending_bytes,
468+
ofdm_symbol_range allowed_symbols)
460469
{
461-
return get_ul_sched_context(u, pdcch_slot, pusch_slot, uci_nof_harq_bits, nullptr, pending_bytes);
470+
return get_ul_sched_context(u, pdcch_slot, pusch_slot, uci_nof_harq_bits, nullptr, pending_bytes, allowed_symbols);
462471
}
463472

464473
std::optional<ul_sched_context> sched_helper::get_retx_ul_sched_context(const slice_ue& u,
465474
slot_point pdcch_slot,
466475
slot_point pusch_slot,
467476
unsigned uci_nof_harq_bits,
468-
const ul_harq_process_handle& h_ul)
477+
const ul_harq_process_handle& h_ul,
478+
ofdm_symbol_range allowed_symbols)
469479
{
470-
return get_ul_sched_context(u, pdcch_slot, pusch_slot, uci_nof_harq_bits, &h_ul, 0);
480+
return get_ul_sched_context(u, pdcch_slot, pusch_slot, uci_nof_harq_bits, &h_ul, 0, allowed_symbols);
471481
}
472482

473483
static vrb_interval

lib/scheduler/ue_scheduling/grant_params_selector.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,20 @@ struct ul_sched_context {
7777
};
7878

7979
/// Retrieve recommended PDCCH and PUSCH parameters for a newTx UL grant.
80-
std::optional<ul_sched_context> get_newtx_ul_sched_context(const slice_ue& u,
81-
slot_point pdcch_slot,
82-
slot_point pusch_slot,
83-
unsigned uci_nof_harq_bits,
84-
unsigned pending_bytes);
80+
std::optional<ul_sched_context> get_newtx_ul_sched_context(const slice_ue& u,
81+
slot_point pdcch_slot,
82+
slot_point pusch_slot,
83+
unsigned uci_nof_harq_bits,
84+
unsigned pending_bytes,
85+
ofdm_symbol_range allowed_symbols);
8586

8687
/// Retrieve recommended PDCCH and PUSCH parameters for a reTx UL grant.
8788
std::optional<ul_sched_context> get_retx_ul_sched_context(const slice_ue& u,
8889
slot_point pdcch_slot,
8990
slot_point pusch_slot,
9091
unsigned uci_nof_harq_bits,
91-
const ul_harq_process_handle& h_ul);
92+
const ul_harq_process_handle& h_ul,
93+
ofdm_symbol_range allowed_symbols);
9294

9395
/// Select UL VRBs to allocate for a newTx.
9496
vrb_interval compute_newtx_ul_vrbs(const ul_sched_context& decision_ctxt,

lib/scheduler/ue_scheduling/intra_slice_scheduler.cpp

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

lib/scheduler/ue_scheduling/intra_slice_scheduler.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,16 @@ class intra_slice_scheduler
100100
scheduler_policy& ul_policy,
101101
unsigned max_ue_grants_to_alloc);
102102

103-
unsigned max_pdschs_to_alloc(const dl_ran_slice_candidate& slice);
103+
unsigned max_pdschs_to_alloc(const dl_ran_slice_candidate& slice) const;
104104

105-
unsigned max_puschs_to_alloc(const ul_ran_slice_candidate& slice);
105+
unsigned max_puschs_to_alloc(const ul_ran_slice_candidate& slice) const;
106106

107107
// Called when bitmap of used VRBs needs to be recalculated.
108108
void update_used_dl_vrbs(const dl_ran_slice_candidate& slice);
109109
void update_used_ul_vrbs(const ul_ran_slice_candidate& slice);
110110

111+
void update_min_srs_symbol();
112+
111113
const scheduler_ue_expert_config& expert_cfg;
112114
const cell_resource_allocator& cell_alloc;
113115
cell_metrics_handler& cell_metrics;
@@ -140,6 +142,8 @@ class intra_slice_scheduler
140142
vrb_bitmap used_dl_vrbs;
141143
bool enable_pdsch_interleaving = false;
142144
vrb_bitmap used_ul_vrbs;
145+
// Minimum symbol index used for SRS resources within this slot.
146+
unsigned min_srs_symbol = 0;
143147

144148
// Grants being built for the current slice.
145149
std::vector<ue_cell_grid_allocator::dl_newtx_grant_builder> pending_dl_newtxs;

0 commit comments

Comments
 (0)