Skip to content

Commit 6d78857

Browse files
herlesupreethcodebot
authored andcommitted
sched: track PUSCH grant allocation on a per PUSCH slot basis in a slice
1 parent 045edb4 commit 6d78857

File tree

9 files changed

+160
-72
lines changed

9 files changed

+160
-72
lines changed

lib/scheduler/slicing/ran_slice_candidate.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ template <bool IsDl>
2020
class common_ran_slice_candidate
2121
{
2222
public:
23-
common_ran_slice_candidate(ran_slice_instance& instance_, unsigned max_rbs_ = 0) :
24-
inst(&instance_), max_rbs(max_rbs_ == 0 ? inst->cfg.max_prb : max_rbs_)
23+
common_ran_slice_candidate(ran_slice_instance& instance_, slot_point slot_tx_, unsigned max_rbs_ = 0) :
24+
inst(&instance_), max_rbs(max_rbs_ == 0 ? inst->cfg.max_prb : max_rbs_), slot_tx(slot_tx_)
2525
{
2626
}
2727

@@ -40,7 +40,7 @@ class common_ran_slice_candidate
4040
if constexpr (IsDl) {
4141
inst->store_pdsch_grant(nof_rbs);
4242
} else {
43-
inst->store_pusch_grant(nof_rbs);
43+
inst->store_pusch_grant(nof_rbs, slot_tx);
4444
}
4545
}
4646

@@ -50,12 +50,16 @@ class common_ran_slice_candidate
5050
if constexpr (IsDl) {
5151
return max_rbs < inst->pdsch_rb_count ? 0 : max_rbs - inst->pdsch_rb_count;
5252
}
53-
return max_rbs < inst->pusch_rb_count ? 0 : max_rbs - inst->pusch_rb_count;
53+
return max_rbs < inst->pusch_rb_count_per_slot[slot_tx.to_uint()]
54+
? 0
55+
: max_rbs - inst->pusch_rb_count_per_slot[slot_tx.to_uint()];
5456
}
5557

5658
protected:
5759
ran_slice_instance* inst = nullptr;
5860
unsigned max_rbs = 0;
61+
/// Slot at which PUSCH/PDSCH needs to be scheduled for this slice candidate.
62+
slot_point slot_tx;
5963
};
6064

6165
} // namespace detail

lib/scheduler/slicing/ran_slice_instance.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ ran_slice_instance::ran_slice_instance(ran_slice_id_t id_,
1717
const slice_rrm_policy_config& cfg_) :
1818
id(id_), cell_cfg(&cell_cfg_), cfg(cfg_)
1919
{
20+
std::fill(pusch_rb_count_per_slot.begin(), pusch_rb_count_per_slot.end(), 0);
2021
}
2122

22-
void ran_slice_instance::slot_indication()
23+
void ran_slice_instance::slot_indication(slot_point slot_tx)
2324
{
2425
pdsch_rb_count = 0;
25-
pusch_rb_count = 0;
26+
// Clear RB count in previous slots.
27+
for (unsigned count = 0; count < nof_slots_to_clear; ++count) {
28+
pusch_rb_count_per_slot[(slot_tx - 1 - count).to_uint()] = 0;
29+
}
2630
}
2731

2832
void ran_slice_instance::rem_logical_channel(du_ue_index_t ue_idx, lcid_t lcid)

lib/scheduler/slicing/ran_slice_instance.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#pragma once
1212

13+
#include "../../scheduler/cell/resource_grid.h"
1314
#include "../config/cell_configuration.h"
1415
#include "../ue_scheduling/ue_repository.h"
1516
#include "ran_slice_id.h"
@@ -21,18 +22,25 @@ namespace srsran {
2122
/// This class stores all the internal information relative to a RAN slice instantiation.
2223
class ran_slice_instance
2324
{
25+
/// Number of slots for which allocated PUSCH grant is maintained.
26+
static const size_t RING_ALLOCATOR_SIZE =
27+
get_allocator_ring_size_gt_min(SCHEDULER_MAX_K2 + NTN_CELL_SPECIFIC_KOFFSET_MAX);
28+
2429
public:
2530
ran_slice_instance(ran_slice_id_t id_, const cell_configuration& cell_cfg_, const slice_rrm_policy_config& cfg_);
2631

27-
void slot_indication();
32+
void slot_indication(slot_point slot_tx);
2833

2934
bool active() const { return not slice_ues.empty(); }
3035

3136
/// Save PDSCH grant.
3237
void store_pdsch_grant(unsigned crbs) { pdsch_rb_count += crbs; }
3338

3439
/// Save PUSCH grant.
35-
void store_pusch_grant(unsigned crbs) { pusch_rb_count += crbs; }
40+
void store_pusch_grant(unsigned crbs, slot_point pusch_slot)
41+
{
42+
pusch_rb_count_per_slot[pusch_slot.to_uint()] += crbs;
43+
}
3644

3745
/// Determine if at least one bearer of the given UE is currently managed by this slice.
3846
bool contains(du_ue_index_t ue_idx) const
@@ -65,8 +73,14 @@ class ran_slice_instance
6573

6674
/// Counter of how many RBs have been scheduled for PDSCH in the current slot for this slice.
6775
unsigned pdsch_rb_count = 0;
68-
/// Counter of how many RBs have been scheduled for PUSCH in the current slot for this slice.
69-
unsigned pusch_rb_count = 0;
76+
/// Ring of counters of how many RBs have been scheduled for PUSCH in a particular slot for this slice.
77+
circular_array<unsigned, RING_ALLOCATOR_SIZE> pusch_rb_count_per_slot;
78+
79+
/// Nof. of previous slots in which RB count needs to be cleared in \c pusch_rb_count_per_slot upon receiving slot
80+
/// indication.
81+
/// \remark This is needed since slot_indication() is called only over DL slots.
82+
unsigned nof_slots_to_clear =
83+
cell_cfg->tdd_cfg_common.has_value() ? nof_slots_per_tdd_period(*cell_cfg->tdd_cfg_common) : 1;
7084

7185
private:
7286
slice_ue_repository slice_ues;

lib/scheduler/slicing/slice_scheduler.cpp

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "slice_scheduler.h"
1212
#include "../policy/scheduler_policy_factory.h"
13+
#include "../support/pusch/pusch_td_resource_indices.h"
1314
#include "srsran/srslog/srslog.h"
1415

1516
using namespace srsran;
@@ -41,24 +42,48 @@ slice_scheduler::slice_scheduler(const cell_configuration& cell_cfg_, ue_reposit
4142
slices.back().policy = create_scheduler_strategy(slice_scheduler_ue_expert_cfg);
4243
++id_count;
4344
}
45+
46+
// NOTE: Below derivation assumes that only pusch-ConfigCommon includes pusch-TimeDomainAllocationList.
47+
// NOTE: [Implementation-defined] In case of FDD, we use only single value of k2.
48+
unsigned nof_slots = cell_cfg.is_tdd() ? nof_slots_per_tdd_period(*cell_cfg.tdd_cfg_common) : 1;
49+
valid_pusch_td_list_per_slot.resize(nof_slots);
50+
for (unsigned slot_period_idx = 0, e = nof_slots; slot_period_idx != e; ++slot_period_idx) {
51+
slot_point pdcch_slot{to_numerology_value(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs), slot_period_idx};
52+
if (cell_cfg.is_dl_enabled(pdcch_slot)) {
53+
// TODO: Revisit when PUSCH time domain resource list is also defined in UE dedicated configuration.
54+
valid_pusch_td_list_per_slot[slot_period_idx] = get_pusch_td_resource_indices(cell_cfg, pdcch_slot);
55+
}
56+
}
4457
}
4558

46-
void slice_scheduler::slot_indication()
59+
void slice_scheduler::slot_indication(slot_point slot_tx)
4760
{
4861
slot_count++;
4962

5063
// Update the context of each slice.
5164
for (auto& slice : slices) {
52-
slice.inst.slot_indication();
65+
slice.inst.slot_indication(slot_tx);
5366
}
5467

68+
// TODO: Update slices (store_grant()) with already allocated grant in the previous slots.
69+
5570
// Recompute the priority queues.
5671
dl_prio_queue.clear();
5772
ul_prio_queue.clear();
5873
for (const auto& slice : slices) {
5974
unsigned max_rbs = slice.inst.cfg.min_prb > 0 ? slice.inst.cfg.min_prb : slice.inst.cfg.max_prb;
60-
dl_prio_queue.push(slice_candidate_context{slice.inst.id, slice.get_prio(true, slot_count, false), {0, max_rbs}});
61-
ul_prio_queue.push(slice_candidate_context{slice.inst.id, slice.get_prio(false, slot_count, false), {0, max_rbs}});
75+
dl_prio_queue.push(slice_candidate_context{
76+
slice.inst.id, slice.get_prio(true, slot_count, false, slot_tx), {0, max_rbs}, slot_tx});
77+
78+
// TODO: Revisit when PUSCH time domain resource list is also defined in UE dedicated configuration.
79+
span<const pusch_time_domain_resource_allocation> pusch_time_domain_list =
80+
cell_cfg.ul_cfg_common.init_ul_bwp.pusch_cfg_common.value().pusch_td_alloc_list;
81+
for (const unsigned pusch_td_res_idx :
82+
valid_pusch_td_list_per_slot[slot_tx.to_uint() % valid_pusch_td_list_per_slot.size()]) {
83+
slot_point pusch_slot = slot_tx + pusch_time_domain_list[pusch_td_res_idx].k2;
84+
ul_prio_queue.push(slice_candidate_context{
85+
slice.inst.id, slice.get_prio(false, slot_count, false, pusch_slot), {0, max_rbs}, pusch_slot});
86+
}
6287
}
6388
}
6489

@@ -189,9 +214,11 @@ slice_scheduler::get_next_candidate()
189214
while (not prio_queue.empty()) {
190215
ran_slice_sched_context& chosen_slice = slices[prio_queue.top().id.value()];
191216
interval<unsigned> rb_lims = prio_queue.top().rb_lims;
217+
slot_point slot_tx = prio_queue.top().slot_tx;
192218
prio_queue.pop();
193219

194-
unsigned rb_count = IsDownlink ? chosen_slice.inst.pdsch_rb_count : chosen_slice.inst.pusch_rb_count;
220+
unsigned rb_count =
221+
IsDownlink ? chosen_slice.inst.pdsch_rb_count : chosen_slice.inst.pusch_rb_count_per_slot[slot_tx.to_uint()];
195222
if (not rb_lims.contains(rb_count)) {
196223
// The slice has been scheduled in this slot with a number of RBs that is not within the limits for this
197224
// candidate. This could happen, for instance, if the scheduler could not schedule all RBs of a candidate
@@ -204,17 +231,17 @@ slice_scheduler::get_next_candidate()
204231
if (cfg.min_prb != cfg.max_prb and rb_lims.stop() == cfg.min_prb) {
205232
// For the special case when minRB ratio>0, the first candidate for this slice was bounded between {0, minRB}.
206233
// We re-add the slice as a candidate, this time, with RB bounds {minRB, maxRB}.
207-
priority_type prio = chosen_slice.get_prio(true, slot_count, true);
208-
prio_queue.push(slice_candidate_context{chosen_slice.inst.id, prio, {cfg.min_prb, cfg.max_prb}});
234+
priority_type prio = chosen_slice.get_prio(IsDownlink, slot_count, true, slot_tx);
235+
prio_queue.push(slice_candidate_context{chosen_slice.inst.id, prio, {cfg.min_prb, cfg.max_prb}, slot_tx});
209236
}
210237

211238
// Save current slot count.
212239
unsigned& count_to_set = IsDownlink ? chosen_slice.last_dl_slot : chosen_slice.last_ul_slot;
213240
count_to_set = slot_count;
214241

215242
// Return the candidate.
216-
return std::conditional_t<IsDownlink, dl_ran_slice_candidate, ul_ran_slice_candidate>{chosen_slice.inst,
217-
rb_lims.stop()};
243+
return std::conditional_t<IsDownlink, dl_ran_slice_candidate, ul_ran_slice_candidate>{
244+
chosen_slice.inst, slot_tx, rb_lims.stop()};
218245
}
219246
return std::nullopt;
220247
}
@@ -231,7 +258,8 @@ std::optional<ul_ran_slice_candidate> slice_scheduler::get_next_ul_candidate()
231258

232259
slice_scheduler::priority_type slice_scheduler::ran_slice_sched_context::get_prio(bool is_dl,
233260
slot_count_type current_slot_count,
234-
bool slice_resched) const
261+
bool slice_resched,
262+
slot_point slot_tx) const
235263
{
236264
// Note: The positive integer representing the priority of a slice consists of a concatenation of three priority
237265
// values:
@@ -248,7 +276,7 @@ slice_scheduler::priority_type slice_scheduler::ran_slice_sched_context::get_pri
248276
constexpr static priority_type delay_bitsize = 8U;
249277
constexpr static priority_type rr_bitsize = 8U;
250278

251-
unsigned rb_count = is_dl ? inst.pdsch_rb_count : inst.pusch_rb_count;
279+
unsigned rb_count = is_dl ? inst.pdsch_rb_count : inst.pusch_rb_count_per_slot[slot_tx.to_uint()];
252280
if (not inst.active() or rb_count >= inst.cfg.max_prb) {
253281
// If the slice is not in a state to be scheduled in this slot, return skip priority level.
254282
return skip_prio;

lib/scheduler/slicing/slice_scheduler.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class slice_scheduler
2828
slice_scheduler(const cell_configuration& cell_cfg_, ue_repository& ues_);
2929

3030
/// Reset the state of the slices.
31-
void slot_indication();
31+
void slot_indication(slot_point slot_tx);
3232

3333
/// Update the state of the slice with the provided UE configs.
3434
void add_ue(du_ue_index_t ue_idx);
@@ -66,16 +66,19 @@ class slice_scheduler
6666
}
6767

6868
/// Determines the slice candidate priority.
69-
priority_type get_prio(bool is_dl, slot_count_type current_slot_count, bool slice_resched) const;
69+
priority_type
70+
get_prio(bool is_dl, slot_count_type current_slot_count, bool slice_resched, slot_point slot_tx) const;
7071
};
7172

7273
struct slice_candidate_context {
7374
ran_slice_id_t id;
7475
priority_type prio;
7576
interval<unsigned> rb_lims;
77+
/// Slot at which PUSCH/PDSCH needs to be scheduled for this slice candidate.
78+
slot_point slot_tx;
7679

77-
slice_candidate_context(ran_slice_id_t id_, priority_type prio_, interval<unsigned> rb_lims_) :
78-
id(id_), prio(prio_), rb_lims(rb_lims_)
80+
slice_candidate_context(ran_slice_id_t id_, priority_type prio_, interval<unsigned> rb_lims_, slot_point slot_tx_) :
81+
id(id_), prio(prio_), rb_lims(rb_lims_), slot_tx(slot_tx_)
7982
{
8083
}
8184

@@ -122,6 +125,10 @@ class slice_scheduler
122125

123126
ue_repository& ues;
124127

128+
/// Vector circularly indexed by slot with the list of applicable PUSCH time domain resources per slot.
129+
/// NOTE: The list would be empty for UL slots.
130+
std::vector<static_vector<unsigned, pusch_constants::MAX_NOF_PUSCH_TD_RES_ALLOCS>> valid_pusch_td_list_per_slot;
131+
125132
std::vector<ran_slice_sched_context> slices;
126133

127134
// Queue of slice candidates sorted by priority.

lib/scheduler/support/pusch/pusch_td_resource_indices.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ compute_pusch_td_resource_indices(span<const pusch_time_domain_resource_allocati
2222
{
2323
// Compute list of PUSCH time domain resource index list relevant for the PUSCH slot.
2424
static_vector<unsigned, pusch_constants::MAX_NOF_PUSCH_TD_RES_ALLOCS> pusch_td_res_index_list;
25+
if (pusch_time_domain_list.empty()) {
26+
return pusch_td_res_index_list;
27+
}
28+
// [Implementation-defined] Default PUSCH time domain resource index to use if no valid PUSCH time domain resource is
29+
// found.
30+
const unsigned default_pusch_td_res_index = 0;
2531

2632
std::optional<unsigned> nof_full_ul_slots = std::nullopt;
2733
std::optional<unsigned> nof_full_dl_slots = std::nullopt;
@@ -53,6 +59,10 @@ compute_pusch_td_resource_indices(span<const pusch_time_domain_resource_allocati
5359
}
5460
}
5561

62+
if (pusch_td_res_index_list.empty()) {
63+
pusch_td_res_index_list.push_back(default_pusch_td_res_index);
64+
}
65+
5666
return pusch_td_res_index_list;
5767
}
5868

lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void ue_scheduler_impl::run_sched_strategy(slot_point slot_tx, du_cell_index_t c
4848
}
4949

5050
// Update slice context and compute slice priorities.
51-
cells[cell_index]->slice_sched.slot_indication();
51+
cells[cell_index]->slice_sched.slot_indication(slot_tx);
5252

5353
// Perform round-robin prioritization of UL and DL scheduling. This gives unfair preference to DL over UL. This is
5454
// done to avoid the issue of sending wrong DAI value in DCI format 0_1 to UE while the PDSCH is allocated

tests/unittests/scheduler/policy/scheduler_policy_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class base_scheduler_policy_test
6767
logger.set_context(next_slot.sfn(), next_slot.slot_index());
6868

6969
grid_alloc.slot_indication(next_slot);
70-
slice_sched.slot_indication();
70+
slice_sched.slot_indication(next_slot);
7171

7272
res_grid.slot_indication(next_slot);
7373
pdcch_alloc.slot_indication(next_slot);

0 commit comments

Comments
 (0)