Skip to content

Commit 4350ad4

Browse files
committed
sched: store list of resource_info in pucch_collision_manager
1 parent a0ebf93 commit 4350ad4

File tree

3 files changed

+202
-175
lines changed

3 files changed

+202
-175
lines changed

lib/scheduler/cell/resource_grid.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ struct grant_info {
5353
{
5454
}
5555

56+
bool operator==(const grant_info& other) const
57+
{
58+
return scs == other.scs and symbols == other.symbols and crbs == other.crbs;
59+
}
60+
bool operator!=(const grant_info& other) const { return not(*this == other); }
61+
5662
/// Checks whether this grant overlaps with another grant in time and frequency.
5763
bool overlaps(const grant_info& other) const
5864
{

lib/scheduler/pucch_scheduling/pucch_collision_manager.cpp

Lines changed: 132 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#include "pucch_collision_manager.h"
1212
#include "../support/pucch/pucch_default_resource.h"
13+
#include "srsran/adt/bounded_bitset.h"
14+
#include "srsran/adt/static_vector.h"
1315
#include "srsran/ran/pucch/pucch_configuration.h"
1416
#include "srsran/ran/pucch/pucch_constants.h"
1517
#include "srsran/ran/pucch/pucch_mapping.h"
@@ -19,160 +21,90 @@
1921

2022
using namespace srsran;
2123

22-
namespace {
23-
24-
/// Represents the time-frequency allocation of a PUCCH resource.
25-
struct time_freq_grants {
26-
prb_interval prbs1;
27-
ofdm_symbol_range symbols1;
28-
prb_interval prbs2;
29-
ofdm_symbol_range symbols2;
30-
31-
/// Constructor from a dedicated PUCCH resource.
32-
time_freq_grants(const pucch_resource& res)
33-
{
34-
unsigned nof_prbs = 1;
35-
if (const auto* format_2_3 = std::get_if<pucch_format_2_3_cfg>(&res.format_params)) {
36-
nof_prbs = format_2_3->nof_prbs;
37-
}
38-
39-
if (res.second_hop_prb.has_value()) {
40-
prbs1 = {res.starting_prb, res.starting_prb + nof_prbs};
41-
symbols1 = {res.starting_sym_idx, res.starting_sym_idx + res.nof_symbols / 2};
42-
prbs2 = {res.second_hop_prb.value(), res.second_hop_prb.value() + nof_prbs};
43-
symbols2 = {res.starting_sym_idx + res.nof_symbols / 2, res.starting_sym_idx + res.nof_symbols};
44-
} else {
45-
prbs1 = {res.starting_prb, res.starting_prb + nof_prbs};
46-
symbols1 = {res.starting_sym_idx, res.starting_sym_idx + res.nof_symbols};
47-
prbs2 = prb_interval();
48-
symbols2 = ofdm_symbol_range();
49-
}
50-
}
51-
52-
/// Constructor from a common PUCCH resource.
53-
time_freq_grants(const pucch_default_resource& res, unsigned r_pucch, unsigned size_ul_bwp)
54-
{
55-
// Compute PRB_first_hop and PRB_second_hop as per Section 9.2.1, TS 38.213.
56-
auto prbs = get_pucch_default_prb_index(r_pucch, res.rb_bwp_offset, res.cs_indexes.size(), size_ul_bwp);
57-
58-
prbs1 = {prbs.first, prbs.first + pucch_constants::FORMAT0_1_4_MAX_NPRB};
59-
symbols1 = {res.first_symbol_index, res.first_symbol_index + res.nof_symbols / 2};
60-
prbs2 = {prbs.second, prbs.second + pucch_constants::FORMAT0_1_4_MAX_NPRB};
61-
symbols2 = {res.first_symbol_index + res.nof_symbols / 2, res.first_symbol_index + res.nof_symbols};
62-
}
63-
64-
bool overlaps(const time_freq_grants& other) const
65-
{
66-
// Check overlap between this' first hop and other's first hop.
67-
bool ret = symbols1.overlaps(other.symbols1) and prbs1.overlaps(other.prbs1);
68-
// Check overlap between this' first hop and other's second hop.
69-
ret |= symbols1.overlaps(other.symbols2) and prbs1.overlaps(other.prbs2);
70-
// Check overlap between this' second hop and other's first hop.
71-
ret |= symbols2.overlaps(other.symbols1) and prbs2.overlaps(other.prbs1);
72-
// Check overlap between this' second hop and other's second hop.
73-
ret |= symbols2.overlaps(other.symbols2) and prbs2.overlaps(other.prbs2);
74-
return ret;
75-
}
76-
77-
bool operator==(const time_freq_grants& other) const
78-
{
79-
return symbols1 == other.symbols1 and prbs1 == other.prbs1 and symbols2 == other.symbols2 and prbs2 == other.prbs2;
80-
}
81-
82-
bool operator!=(const time_freq_grants& other) const { return not(*this == other); }
83-
};
84-
85-
/// Represents the relevant information of a PUCCH resource for collision checking.
86-
struct resource_info {
87-
/// Time-frequency grants of the resource.
88-
time_freq_grants grants;
89-
/// PUCCH format of the resource.
90-
pucch_format format;
91-
/// Multiplexing index of the resource. Resources with different multiplexing indices are orthogonal and do not
92-
/// collide. It is computed from different parameters depending on the format:
93-
/// - Format 0: initial cyclic shift.
94-
/// - Format 1: initial cyclic shift, time domain OCC index.
95-
/// - Format 2/3: not multiplexed (always 0).
96-
/// - Format 4: OCC index.
97-
unsigned multiplexing_index;
98-
99-
/// Constructor from a dedicated PUCCH resource.
100-
resource_info(const pucch_resource& res) : grants(res), format(res.format)
101-
{
102-
switch (res.format) {
103-
case pucch_format::FORMAT_0: {
104-
const auto& f0_params = std::get<pucch_format_0_cfg>(res.format_params);
105-
multiplexing_index = f0_params.initial_cyclic_shift;
106-
} break;
107-
case pucch_format::FORMAT_1: {
108-
// For PUCCH Format 1, two sequences are orthogonal unless both the initial cyclic shift and the time domain OCC
109-
// index are the same.
110-
const auto& f1_params = std::get<pucch_format_1_cfg>(res.format_params);
111-
multiplexing_index = f1_params.initial_cyclic_shift +
112-
f1_params.time_domain_occ * pucch_constants::format1_initial_cyclic_shift_range.length();
113-
} break;
114-
case pucch_format::FORMAT_4: {
115-
// For PUCCH Format 4, the OCC index is mapped to a cyclic shift value, as per Table 6.4.1.3.3.1-1, TS 38.211.
116-
// Thus, resources with different OCC indices will never collide, even if they have different OCC lengths.
117-
// Therefore, we can use the OCC index directly as the multiplexing index.
118-
const auto& f4_params = std::get<pucch_format_4_cfg>(res.format_params);
119-
multiplexing_index = static_cast<unsigned>(f4_params.occ_index);
120-
} break;
121-
default:
122-
// Non multiplexed formats.
123-
multiplexing_index = 0;
124-
break;
125-
}
126-
}
127-
128-
/// Constructor from a common PUCCH resource.
129-
resource_info(const pucch_default_resource& res, unsigned r_pucch, unsigned size_ul_bwp) :
130-
grants(res, r_pucch, size_ul_bwp),
131-
format(res.format),
132-
multiplexing_index(res.cs_indexes[get_pucch_default_cyclic_shift(r_pucch, res.cs_indexes.size())])
133-
{
134-
}
135-
};
136-
137-
/// \brief Represents a multiplexing region of PUCCH resources.
138-
/// Contains parameters that all resources in the region have in common.
139-
struct mux_region {
140-
/// Time-frequency grants of the region.
141-
time_freq_grants grants;
142-
/// PUCCH format of the region.
143-
pucch_format format;
144-
145-
/// Check if a a given resource belongs to this multiplexing region.
146-
bool does_resource_belong(const resource_info& res) const { return res.format == format and res.grants == grants; }
147-
};
148-
149-
} // namespace
150-
151-
/// Collects all PUCCH resources (common + dedicated) from the cell configuration.
152-
static static_vector<resource_info, pucch_collision_manager::max_nof_cell_resources>
153-
get_all_resources(const cell_configuration& cell_cfg)
24+
/// Constructs resource_info for a common PUCCH resource.
25+
static detail::resource_info
26+
make_common_resource_info(const pucch_default_resource& res, unsigned r_pucch, const bwp_configuration& bwp_cfg)
15427
{
155-
// Get the parameter N_bwp_size, which is the Initial UL BWP size in PRBs, as per TS 38.213, Section 9.2.1.
156-
const unsigned size_ul_bwp = cell_cfg.ul_cfg_common.init_ul_bwp.generic_params.crbs.length();
28+
// Compute PRB_first_hop and PRB_second_hop as per Section 9.2.1, TS 38.213.
29+
auto prbs = get_pucch_default_prb_index(r_pucch, res.rb_bwp_offset, res.cs_indexes.size(), bwp_cfg.crbs.length());
30+
31+
return detail::resource_info{
32+
.format = res.format,
33+
.multiplexing_index = res.cs_indexes[get_pucch_default_cyclic_shift(r_pucch, res.cs_indexes.size())],
34+
.grants = {
35+
.first_hop = grant_info(
36+
bwp_cfg.scs,
37+
{res.first_symbol_index, res.first_symbol_index + res.nof_symbols / 2},
38+
prb_to_crb(bwp_cfg, prb_interval::start_and_len(prbs.first, pucch_constants::FORMAT0_1_4_MAX_NPRB))),
39+
.second_hop = grant_info(
40+
bwp_cfg.scs,
41+
{res.first_symbol_index + res.nof_symbols / 2, res.first_symbol_index + res.nof_symbols},
42+
prb_to_crb(bwp_cfg, prb_interval::start_and_len(prbs.second, pucch_constants::FORMAT0_1_4_MAX_NPRB))),
43+
}};
44+
}
15745

158-
// Get PUCCH common resource config from Table 9.2.1-1, TS 38.213.
159-
const pucch_default_resource common_default_res = get_pucch_default_resource(
160-
cell_cfg.ul_cfg_common.init_ul_bwp.pucch_cfg_common->pucch_resource_common, size_ul_bwp);
46+
/// Constructs resource_info for a dedicated PUCCH resource.
47+
static detail::resource_info make_ded_resource_info(const pucch_resource& res, const bwp_configuration& bwp_cfg)
48+
{
49+
detail::resource_info info{.format = res.format};
50+
51+
// Compute multiplexing index.
52+
switch (res.format) {
53+
case pucch_format::FORMAT_0: {
54+
const auto& f0_params = std::get<pucch_format_0_cfg>(res.format_params);
55+
info.multiplexing_index = f0_params.initial_cyclic_shift;
56+
} break;
57+
case pucch_format::FORMAT_1: {
58+
// For PUCCH Format 1, two sequences are orthogonal unless both the initial cyclic shift and the time domain OCC
59+
// index are the same.
60+
const auto& f1_params = std::get<pucch_format_1_cfg>(res.format_params);
61+
info.multiplexing_index =
62+
f1_params.initial_cyclic_shift +
63+
f1_params.time_domain_occ * pucch_constants::format1_initial_cyclic_shift_range.length();
64+
} break;
65+
case pucch_format::FORMAT_4: {
66+
// For PUCCH Format 4, the OCC index is mapped to a cyclic shift value, as per Table 6.4.1.3.3.1-1, TS 38.211.
67+
// Thus, resources with different OCC indices will never collide, even if they have different OCC lengths.
68+
// Therefore, we can use the OCC index directly as the multiplexing index.
69+
const auto& f4_params = std::get<pucch_format_4_cfg>(res.format_params);
70+
info.multiplexing_index = static_cast<unsigned>(f4_params.occ_index);
71+
} break;
72+
default:
73+
// Non multiplexed formats.
74+
info.multiplexing_index = 0;
75+
break;
76+
}
16177

162-
// Collect all resources (common + dedicated).
163-
static_vector<resource_info, pucch_collision_manager::max_nof_cell_resources> all_resources;
164-
for (unsigned r_pucch = 0; r_pucch != pucch_collision_manager::nof_common_res; ++r_pucch) {
165-
all_resources.push_back(resource_info(common_default_res, r_pucch, size_ul_bwp));
78+
// Compute time-frequency grants.
79+
unsigned nof_prbs = 1;
80+
if (const auto* format_2_3 = std::get_if<pucch_format_2_3_cfg>(&res.format_params)) {
81+
nof_prbs = format_2_3->nof_prbs;
16682
}
167-
for (const auto& res : cell_cfg.ded_pucch_resources) {
168-
all_resources.push_back(resource_info(res));
83+
if (res.second_hop_prb.has_value()) {
84+
// Intra-slot frequency hopping.
85+
info.grants = {
86+
.first_hop = grant_info{bwp_cfg.scs,
87+
{res.starting_sym_idx, res.starting_sym_idx + res.nof_symbols / 2},
88+
prb_to_crb(bwp_cfg, prb_interval::start_and_len(res.starting_prb, nof_prbs))},
89+
.second_hop =
90+
grant_info{bwp_cfg.scs,
91+
{res.starting_sym_idx + res.nof_symbols / 2, res.starting_sym_idx + res.nof_symbols},
92+
prb_to_crb(bwp_cfg, prb_interval::start_and_len(res.second_hop_prb.value(), nof_prbs))}};
93+
} else {
94+
// No intra-slot frequency hopping.
95+
info.grants = {
96+
.first_hop = grant_info{bwp_cfg.scs,
97+
ofdm_symbol_range::start_and_len(res.starting_sym_idx, res.nof_symbols),
98+
prb_to_crb(bwp_cfg, prb_interval::start_and_len(res.starting_prb, nof_prbs))},
99+
.second_hop = std::nullopt,
100+
};
169101
}
170102

171-
return all_resources;
103+
return info;
172104
}
173105

174106
/// Checks if two PUCCH resources collide.
175-
static bool do_resources_collide(const resource_info& res1, const resource_info& res2)
107+
static bool do_resources_collide(const detail::resource_info& res1, const detail::resource_info& res2)
176108
{
177109
if (not res1.grants.overlaps(res2.grants)) {
178110
// Resources that do not overlap in time and frequency do not collide.
@@ -194,11 +126,31 @@ static bool do_resources_collide(const resource_info& res1, const resource_info&
194126
return res1.multiplexing_index == res2.multiplexing_index;
195127
}
196128

129+
namespace {
130+
131+
/// \brief Represents a multiplexing region of PUCCH resources.
132+
/// Contains parameters that all resources in the region have in common.
133+
struct mux_region {
134+
/// Time-frequency grants of the region.
135+
detail::pucch_grants grants;
136+
/// PUCCH format of the region.
137+
pucch_format format;
138+
139+
/// Check if a a given resource belongs to this multiplexing region.
140+
bool does_resource_belong(const detail::resource_info& res) const
141+
{
142+
return res.format == format and res.grants == grants;
143+
}
144+
};
145+
146+
} // namespace
147+
197148
pucch_collision_manager::pucch_collision_manager(const cell_configuration& cell_cfg_) :
198149
cell_cfg(cell_cfg_),
199-
collision_matrix(compute_collisions(cell_cfg)),
200-
mux_matrix(compute_mux_regions(cell_cfg)),
201-
slots_ctx({bounded_bitset<max_nof_cell_resources>(nof_common_res + cell_cfg.ded_pucch_resources.size())})
150+
resources(compute_resources(cell_cfg)),
151+
collision_matrix(compute_collisions(resources)),
152+
mux_matrix(compute_mux_regions(resources)),
153+
slots_ctx({bounded_bitset<max_nof_cell_resources>(resources.size())})
202154
{
203155
}
204156

@@ -307,23 +259,41 @@ void pucch_collision_manager::free_ded(slot_point sl, unsigned cell_res_id)
307259
ctx.current_state.reset(nof_common_res + cell_res_id);
308260
}
309261

310-
pucch_collision_manager::collision_matrix_t
311-
pucch_collision_manager::compute_collisions(const cell_configuration& cell_cfg)
262+
/// Collects all PUCCH resources (common + dedicated) from the cell configuration.
263+
pucch_collision_manager::cell_resources_t pucch_collision_manager::compute_resources(const cell_configuration& cell_cfg)
312264
{
313-
const unsigned nof_res = nof_common_res + cell_cfg.ded_pucch_resources.size();
314-
collision_matrix_t matrix(nof_res, bounded_bitset<max_nof_cell_resources>(nof_res));
265+
const auto& init_ul_bwp_cfg = cell_cfg.ul_cfg_common.init_ul_bwp.generic_params;
266+
267+
// Get PUCCH common resource config from Table 9.2.1-1, TS 38.213.
268+
// N_bwp_size is equal to the Initial UL BWP size in PRBs, as per TS 38.213, Section 9.2.1.
269+
const pucch_default_resource common_default_res = get_pucch_default_resource(
270+
cell_cfg.ul_cfg_common.init_ul_bwp.pucch_cfg_common->pucch_resource_common, init_ul_bwp_cfg.crbs.length());
315271

316272
// Collect all resources (common + dedicated).
317-
static_vector<resource_info, max_nof_cell_resources> all_resources = get_all_resources(cell_cfg);
273+
cell_resources_t all_resources;
274+
for (unsigned r_pucch = 0; r_pucch != nof_common_res; ++r_pucch) {
275+
all_resources.push_back(make_common_resource_info(common_default_res, r_pucch, init_ul_bwp_cfg));
276+
}
277+
for (const auto& res : cell_cfg.ded_pucch_resources) {
278+
all_resources.push_back(make_ded_resource_info(res, init_ul_bwp_cfg));
279+
}
280+
281+
return all_resources;
282+
}
283+
284+
pucch_collision_manager::collision_matrix_t
285+
pucch_collision_manager::compute_collisions(span<const detail::resource_info> resources)
286+
{
287+
collision_matrix_t matrix(resources.size(), bounded_bitset<max_nof_cell_resources>(resources.size()));
318288

319289
// Precompute the collision matrix.
320-
for (size_t i = 0; i != nof_res; ++i) {
290+
for (size_t i = 0; i != resources.size(); ++i) {
321291
// A resource always collides with itself.
322292
matrix[i].set(i);
323293

324294
// Note: The collision matrix is symmetric.
325-
for (size_t j = i + 1; j != nof_res; ++j) {
326-
if (do_resources_collide(all_resources[i], all_resources[j])) {
295+
for (size_t j = i + 1; j != resources.size(); ++j) {
296+
if (do_resources_collide(resources[i], resources[j])) {
327297
matrix[i].set(j);
328298
matrix[j].set(i);
329299
}
@@ -334,23 +304,17 @@ pucch_collision_manager::compute_collisions(const cell_configuration& cell_cfg)
334304
}
335305

336306
pucch_collision_manager::mux_regions_matrix_t
337-
pucch_collision_manager::compute_mux_regions(const cell_configuration& cell_cfg)
307+
pucch_collision_manager::compute_mux_regions(span<const detail::resource_info> resources)
338308
{
339-
unsigned nof_res = nof_common_res + cell_cfg.ded_pucch_resources.size();
340-
mux_regions_matrix_t mux_regions;
341-
342-
// Collect all resources (common + dedicated).
343-
static_vector<resource_info, max_nof_cell_resources> all_resources = get_all_resources(cell_cfg);
344-
345309
// Helper structure to keep track of multiplexing regions and their members.
346310
struct region_record {
347311
mux_region region;
348312
bounded_bitset<max_nof_cell_resources> members;
349313
};
350314
static_vector<region_record, max_nof_cell_resources> tmp_regions;
351315

352-
for (size_t i = 0; i != nof_res; ++i) {
353-
const auto& res = all_resources[i];
316+
for (size_t i = 0; i != resources.size(); ++i) {
317+
const auto& res = resources[i];
354318

355319
// Find if the resource belongs to an existing multiplexing region.
356320
auto* region_it = std::find_if(tmp_regions.begin(), tmp_regions.end(), [&res](const region_record& record) {
@@ -363,21 +327,21 @@ pucch_collision_manager::compute_mux_regions(const cell_configuration& cell_cfg)
363327
.grants = res.grants,
364328
.format = res.format,
365329
},
366-
bounded_bitset<max_nof_cell_resources>(nof_res)});
330+
bounded_bitset<max_nof_cell_resources>(resources.size())});
367331
}
368332

369333
// Add the resource to the multiplexing region.
370334
region_it->members.set(i);
371335
}
372336

373-
// Return only multiplexing regions with more than one resource.
337+
mux_regions_matrix_t mux_regions;
374338
for (const auto& record : tmp_regions) {
339+
// Return only multiplexing regions with more than one resource.
375340
if (record.members.count() < 2) {
376341
continue;
377342
}
378343

379344
mux_regions.push_back(record.members);
380345
}
381-
382346
return mux_regions;
383347
}

0 commit comments

Comments
 (0)