Skip to content

Commit 8f48456

Browse files
committed
du: add unittets for du srs res manager
Signed-off-by: Carlo Galiotto <[email protected]>
1 parent e2d31e8 commit 8f48456

File tree

6 files changed

+421
-82
lines changed

6 files changed

+421
-82
lines changed

include/srsran/du/du_cell_config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ struct srs_builder_params {
113113
/// \c Transmission comb number , as per TS 38.211, Section 6.4.1.4.2, or TS 38.331, "SRS-Resource".
114114
tx_comb_size tx_comb = tx_comb_size::n4;
115115
/// Defines the number of symbols per SRS resource.
116-
srs_nof_symbols nof_symbols = n1;
116+
srs_nof_symbols nof_symbols = srs_nof_symbols::n1;
117117
/// Defines the CS reuse factor for the SRS resources.
118118
/// \remark With 2 or 4 antenna ports, different cyclic shifts are used by the different antennas. This parameter
119119
/// defines how many UEs can be multiplexed in the same symbols and RBs by exploiting different cyclic shifts.

include/srsran/scheduler/config/cell_config_builder_params.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ struct cell_config_builder_params {
4848
std::optional<ssb_subcarrier_offset> k_ssb;
4949
/// Whether to enable CSI-RS in the cell.
5050
bool csi_rs_enabled = true;
51-
/// Defines whether the default SRS configuration has periodic vs aperiodic SRS.
52-
bool srs_periodic_enabled = false;
5351
/// Number of DL ports for the cell.
5452
unsigned nof_dl_ports = 1;
5553
/// \brief Minimum k1 value used in the generation of the UE "dl-DataToUl-Ack", as per TS38.213, 9.1.2.1.

lib/du/du_high/du_manager/ran_resource_management/du_srs_resource_manager.cpp

Lines changed: 86 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,42 @@
1515
using namespace srsran;
1616
using namespace srs_du;
1717

18+
// Helper that computes the SRS bandwidth parameter \f$C_{SRS}\f$ based on the number of UL RBs.
1819
static std::optional<unsigned> compute_srs_bw_param(unsigned nof_ul_rbs)
1920
{
20-
// Iterate over Table 6.4.1.4.3-1, TS 38.211, and find the first \f$C_{SRS}\f$ value that provides the
21-
// greatest \f$m_{SRS,0}\f$ such that it is less than or equal to number of UL RBs.
21+
// Iterate over Table 6.4.1.4.3-1, TS 38.211, and find the minimum \f$C_{SRS}\f$ value that maximizes \f$m_{SRS,0}\f$
22+
// under the constraint \f$m_{SRS,0}\f$ <= UL RBs.
2223

2324
// As per Table 6.4.1.4.3-1, TS 38.211, the maximum value of \f$C_{SRS}\f$ is 63.
2425
constexpr unsigned max_non_valid_c_srs = 64;
25-
constexpr uint8_t b_srs_0 = 0;
26-
for (uint8_t c_srs = 0; c_srs != max_non_valid_c_srs; c_srs++) {
26+
// As per Table 6.4.1.4.3-1, TS 38.211, we do not consider frequency hopping.
27+
constexpr uint8_t b_srs_0 = 0;
28+
// Defines the pair of C_SRS and m_SRS values.
29+
using pair_c_srs_m_srs = std::pair<unsigned, unsigned>;
30+
std::optional<pair_c_srs_m_srs> candidate_c_srs = std::nullopt;
31+
for (uint8_t c_srs = 0; c_srs != max_non_valid_c_srs; ++c_srs) {
2732
auto srs_params = srs_configuration_get(c_srs, b_srs_0);
28-
srsran_assert(srs_params.has_value(), "The SRS is not valid");
2933

30-
if (c_srs == 0 and srs_params.value().m_srs > nof_ul_rbs) {
31-
srsran_assertion_failure("C_SRS is not compatible with the number of UL RBs");
34+
if (not srs_params.has_value()) {
35+
srsran_assertion_failure("C_SRS is not compatible with the current BW configuration");
3236
return std::nullopt;
3337
}
34-
if (srs_params.value().m_srs == nof_ul_rbs) {
35-
return c_srs;
38+
39+
// If there is no candidate C_SRS value, we set the first valid C_SRS value as the candidate.
40+
if (not candidate_c_srs.has_value()) {
41+
candidate_c_srs = pair_c_srs_m_srs{c_srs, srs_params.value().m_srs};
42+
}
43+
// NOTE: the condition srs_params.value().m_srs > candidate_c_srs->second is used to find the minimum C_SRS value
44+
// that maximizes m_SRS.
45+
else if (srs_params.value().m_srs <= nof_ul_rbs and srs_params.value().m_srs > candidate_c_srs->second) {
46+
candidate_c_srs = pair_c_srs_m_srs{c_srs, srs_params.value().m_srs};
3647
}
48+
// If we reach this point, no need to keep looking for a valid C_SRS value.
3749
if (srs_params.value().m_srs > nof_ul_rbs) {
38-
return c_srs - 1;
50+
break;
3951
}
4052
}
41-
return max_non_valid_c_srs - 1;
53+
return candidate_c_srs.value().first;
4254
}
4355

4456
// Helper that returns the frequency shift value for the SRS; the value is computed in such a way that the SRS resources
@@ -62,53 +74,48 @@ static bool is_ul_slot(unsigned offset, const tdd_ul_dl_config_common& tdd_cfg)
6274

6375
static bool is_partually_ul_slot(unsigned offset, const tdd_ul_dl_config_common& tdd_cfg)
6476
{
65-
const unsigned slot_index = offset % (NOF_SUBFRAMES_PER_FRAME * get_nof_slots_per_subframe(tdd_cfg.ref_scs));
66-
return srsran::get_active_tdd_ul_symbols(tdd_cfg, slot_index, cyclic_prefix::NORMAL).length() != 0 and
67-
srsran::get_active_tdd_dl_symbols(tdd_cfg, slot_index, cyclic_prefix::NORMAL).length() !=
68-
NOF_OFDM_SYM_PER_SLOT_NORMAL_CP;
77+
const unsigned slot_index = offset % (NOF_SUBFRAMES_PER_FRAME * get_nof_slots_per_subframe(tdd_cfg.ref_scs));
78+
const unsigned nof_symbols = srsran::get_active_tdd_ul_symbols(tdd_cfg, slot_index, cyclic_prefix::NORMAL).length();
79+
return nof_symbols != 0 and nof_symbols != NOF_OFDM_SYM_PER_SLOT_NORMAL_CP;
6980
}
7081

71-
static bool srs_config_validator(const du_cell_config& cell_cfg)
82+
// Helper that updates the starting SRS config with user-defined parameters.
83+
static srs_config build_default_srs_cfg(const du_cell_config& default_cell_cfg)
7284
{
73-
if (not cell_cfg.ue_ded_serv_cell_cfg.ul_config.has_value()) {
74-
return false;
75-
}
76-
77-
if (cell_cfg.ue_ded_serv_cell_cfg.ul_config.value().init_ul_bwp.srs_cfg.has_value()) {
78-
return false;
79-
}
85+
srsran_assert(default_cell_cfg.ue_ded_serv_cell_cfg.ul_config.has_value() and
86+
default_cell_cfg.ue_ded_serv_cell_cfg.ul_config.value().init_ul_bwp.srs_cfg.has_value(),
87+
"DU cell config is not valid");
8088

81-
const auto& srs_cfg = cell_cfg.ue_ded_serv_cell_cfg.ul_config.value().init_ul_bwp.srs_cfg.value();
82-
if (srs_cfg.srs_res_set_list.size() != 1) {
83-
return false;
89+
// If the DU is not configured for periodic SRS, we don't need to update the SRS configuration.
90+
if (not default_cell_cfg.srs_cfg.srs_period.has_value()) {
91+
return default_cell_cfg.ue_ded_serv_cell_cfg.ul_config.value().init_ul_bwp.srs_cfg.value();
8492
}
8593

86-
if (not std::holds_alternative<srs_config::srs_resource_set::periodic_resource_type>(
87-
srs_cfg.srs_res_set_list.front().res_type)) {
88-
return false;
89-
}
90-
91-
if (srs_cfg.srs_res_set_list.front().srs_res_id_list.size() != 1 or
92-
srs_cfg.srs_res_set_list.front().srs_res_id_list.front() != static_cast<srs_config::srs_res_id>(0U)) {
93-
return false;
94-
}
94+
auto srs_cfg = default_cell_cfg.ue_ded_serv_cell_cfg.ul_config.value().init_ul_bwp.srs_cfg.value();
9595

96-
if (srs_cfg.srs_res_list.size() != 1 or
97-
srs_cfg.srs_res_list.front().id.ue_res_id != static_cast<srs_config::srs_res_id>(0U)) {
98-
return false;
99-
}
96+
srsran_assert(srs_cfg.srs_res_list.size() == 1 and srs_cfg.srs_res_set_list.size() == 1,
97+
"The SRS resource list and the SRS resource set list are expected to have a single element");
10098

101-
if (srs_cfg.srs_res_list.front().res_type != srs_resource_type::periodic) {
102-
return false;
103-
}
99+
srs_config::srs_resource& res = srs_cfg.srs_res_list.back();
100+
res.res_type = srs_resource_type::periodic;
101+
// Set offset to 0. The offset will be updated later on, when the UE is allocated the SRS resources.
102+
res.periodicity_and_offset.emplace(
103+
srs_config::srs_periodicity_and_offset{.period = default_cell_cfg.srs_cfg.srs_period.value(), .offset = 0});
104+
// Set the SRS resource ID to 0, as there is only 1 SRS resource per UE.
105+
res.id.ue_res_id = static_cast<srs_config::srs_res_id>(0U);
104106

105-
if (not srs_cfg.srs_res_list.front().periodicity_and_offset.has_value()) {
106-
return false;
107-
}
107+
srs_config::srs_resource_set& res_set = srs_cfg.srs_res_set_list.back();
108+
res_set.res_type.emplace<srs_config::srs_resource_set::periodic_resource_type>(
109+
srs_config::srs_resource_set::periodic_resource_type{});
110+
// Set the SRS resource set ID to 0, as there is only 1 SRS resource set per UE.
111+
res_set.id = static_cast<srs_config::srs_res_set_id>(0U);
108112

109-
return true;
113+
return srs_cfg;
110114
}
111115

116+
du_srs_policy_max_ul_th::cell_context::cell_context(const du_cell_config& cfg) :
117+
cell_cfg(cfg), default_srs_cfg(build_default_srs_cfg(cfg)){};
118+
112119
du_srs_policy_max_ul_th::du_srs_policy_max_ul_th(span<const du_cell_config> cell_cfg_list_) :
113120
cells(cell_cfg_list_.begin(), cell_cfg_list_.end())
114121
{
@@ -117,7 +124,6 @@ du_srs_policy_max_ul_th::du_srs_policy_max_ul_th(span<const du_cell_config> cell
117124
continue;
118125
}
119126

120-
srsran_assert(srs_config_validator(cell.cell_cfg), "The SRS configuration is not valid");
121127
std::optional<unsigned> c_srs =
122128
compute_srs_bw_param(cell.cell_cfg.ul_cfg_common.init_ul_bwp.generic_params.crbs.length()).value();
123129
srsran_assert(c_srs.has_value(), "SRS parameters didn't provide a valid C_SRS value");
@@ -130,19 +136,30 @@ du_srs_policy_max_ul_th::du_srs_policy_max_ul_th(span<const du_cell_config> cell
130136
// TODO: evaluate whether we need to consider the case of multiple cells.
131137
cell.cell_srs_res_list = generate_cell_srs_list(cell.cell_cfg);
132138

133-
const unsigned srs_period_slots = static_cast<unsigned>(cell.cell_cfg.srs_cfg.srs_period.value());
139+
const auto srs_period_slots = static_cast<unsigned>(cell.cell_cfg.srs_cfg.srs_period.value());
134140
cell.slot_resource_cnt.reserve(srs_period_slots);
141+
cell.srs_res_offset_free_list.reserve(du_srs_policy_max_ul_th::cell_context::max_nof_srs_res);
135142

136143
for (unsigned offset = 0; offset != srs_period_slots; ++offset) {
144+
// We don't generate more than the maximum number of SRS resources per cell.
145+
if (cell.srs_res_offset_free_list.size() >= du_srs_policy_max_ul_th::cell_context::max_nof_srs_res) {
146+
break;
147+
}
148+
137149
unsigned offset_res_cnt = 0U;
150+
// Verify whether the offset maps to a partially- or fully-UL slot.
151+
if (cell_cfg_list_[0].tdd_ul_dl_cfg_common.has_value() and
152+
not is_ul_slot(offset, cell_cfg_list_[0].tdd_ul_dl_cfg_common.value())) {
153+
cell.slot_resource_cnt.emplace_back(0U, offset_res_cnt);
154+
continue;
155+
}
156+
138157
for (auto& res : cell.cell_srs_res_list) {
139-
// Handle TDD and FDD configurations separately, as we treat partially-UL slots differently from fully-UL slots.
158+
// Handle TDD and FDD configurations separately, as we treat partially-UL slots differently from
159+
// fully-UL slots.
140160
if (cell_cfg_list_[0].tdd_ul_dl_cfg_common.has_value()) {
141-
// Verify whether the offset maps to a partially- or fully-UL slot.
142-
if (not is_ul_slot(offset, cell_cfg_list_[0].tdd_ul_dl_cfg_common.value())) {
143-
continue;
144-
}
145-
// For partially-UL slots, we need to check if the SRS can be placed in the UL symbols of the slot.
161+
// For partially-UL slots, we need to check if the SRS can be placed in the UL symbols of the
162+
// slot.
146163
if (is_partually_ul_slot(offset, cell_cfg_list_[0].tdd_ul_dl_cfg_common.value())) {
147164
// TODO: Fix check for pattern 2.
148165
if (res.symbols.start() < NOF_OFDM_SYM_PER_SLOT_NORMAL_CP -
@@ -184,12 +201,10 @@ bool du_srs_policy_max_ul_th::alloc_resources(cell_group_config& cell_grp_cfg)
184201
return true;
185202
}
186203

187-
// The UE SRS configuration is taken from a base configuration, saved in the GNB. The details that are UE specific
188-
// will be added later on in this function.
204+
// The UE SRS configuration is taken from a base configuration, saved in the GNB. The details that are
205+
// UE specific will be added later on in this function.
189206
cell_grp_cfg.cells[0].serv_cell_cfg.ul_config->init_ul_bwp.srs_cfg.emplace(
190-
cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index]
191-
.cell_cfg.ue_ded_serv_cell_cfg.ul_config.value()
192-
.init_ul_bwp.srs_cfg.value());
207+
cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].default_srs_cfg);
193208
srs_config& ue_srs_cfg = cell_grp_cfg.cells[0].serv_cell_cfg.ul_config->init_ul_bwp.srs_cfg.value();
194209
auto& free_srs_list = cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].srs_res_offset_free_list;
195210

@@ -220,14 +235,20 @@ bool du_srs_policy_max_ul_th::alloc_resources(cell_group_config& cell_grp_cfg)
220235
only_ue_srs_res.id.cell_res_id = du_res.cell_res_id;
221236
only_ue_srs_res.id.ue_res_id = static_cast<srs_config::srs_res_id>(0U);
222237
only_ue_srs_res.periodicity_and_offset.value().offset = srs_offset;
238+
only_ue_srs_res.tx_comb.size = cells[0].cell_cfg.srs_cfg.tx_comb;
223239
only_ue_srs_res.tx_comb.tx_comb_offset = du_res.tx_comb_offset.to_uint();
240+
only_ue_srs_res.tx_comb.tx_comb_cyclic_shift = du_res.cs;
224241
only_ue_srs_res.freq_domain_pos = du_res.freq_dom_position;
225242
only_ue_srs_res.res_mapping.start_pos = NOF_OFDM_SYM_PER_SLOT_NORMAL_CP - du_res.symbols.start() - 1;
226243
only_ue_srs_res.res_mapping.nof_symb = static_cast<srs_nof_symbols>(du_res.symbols.length());
227244
only_ue_srs_res.sequence_id = du_res.sequence_id;
228245

229246
// Update the SRS configuration with the parameters that are common to the cell.
230247
only_ue_srs_res.freq_hop.c_srs = cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].srs_common_params.c_srs;
248+
// We assume that the frequency hopping is disabled and that the SRS occupies all possible RBs within the BWP. Refer
249+
// to Section 6.4.1.4.3, TS 38.211.
250+
only_ue_srs_res.freq_hop.b_srs = 0U;
251+
only_ue_srs_res.freq_hop.b_hop = 0U;
231252
only_ue_srs_res.freq_domain_shift =
232253
cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].srs_common_params.freq_shift;
233254

@@ -249,7 +270,8 @@ du_srs_policy_max_ul_th::cell_context::find_optimal_ue_srs_resource()
249270
// The weights assigned here can be set to any value, as long as:
250271
// - symbol_weight_base is greater than 0;
251272
// - reuse_slot_discount less than symbol_weight_base;
252-
// - max_weight is > symbol_weight_base * (srs_builder_params::max_nof_symbols / srs_builder_params::nof_symbols).
273+
// - max_weight is > symbol_weight_base * (srs_builder_params::max_nof_symbols /
274+
// srs_builder_params::nof_symbols).
253275
static constexpr unsigned max_weight = 100U;
254276
static constexpr unsigned symbol_weight_base = 10U;
255277

@@ -270,8 +292,9 @@ du_srs_policy_max_ul_th::cell_context::find_optimal_ue_srs_resource()
270292
const unsigned symb_weight =
271293
(NOF_OFDM_SYM_PER_SLOT_NORMAL_CP - srs_res_cfg_it->symbols.start()) * symbol_weight_base;
272294

273-
// We consider a discount if the offset is already used but not full; this way, we give an incentive to the SRS
274-
// resources not to be allocated on a new slot, to avoid taking PUSCH symbols on a new slot.
295+
// We consider a discount if the offset is already used but not full; this way, we give an incentive
296+
// to the SRS resources not to be allocated on a new slot, to avoid taking PUSCH symbols on a new
297+
// slot.
275298
const unsigned reuse_slot_discount = offset_used_not_full(srs_res.second) ? symbol_weight_base / 2U : 0U;
276299

277300
return symb_weight - reuse_slot_discount;
@@ -299,7 +322,7 @@ void du_srs_policy_max_ul_th::dealloc_resources(cell_group_config& cell_grp_cfg)
299322

300323
for (const auto& srs_res : ue_srs_cfg.srs_res_list) {
301324
const unsigned offset_to_deallocate = srs_res.periodicity_and_offset.value().offset;
302-
free_srs_list.push_back({srs_res.id.cell_res_id, offset_to_deallocate});
325+
free_srs_list.emplace_back(srs_res.id.cell_res_id, offset_to_deallocate);
303326

304327
// Update the used_not_full slot vector.
305328
srsran_assert(cells[0].slot_resource_cnt[offset_to_deallocate].first != 0, "The offset is expected to be non-zero");

lib/du/du_high/du_manager/ran_resource_management/du_srs_resource_manager.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include "srs_resource_generator.h"
1414
#include "srsran/adt/optional.h"
1515
#include "srsran/du/du_cell_config.h"
16-
#include "srsran/ran/srs/srs_configuration.h"
16+
#include "srsran/ran/srs/srs_bandwidth_configuration.h"
1717

1818
namespace srsran {
1919
namespace srs_du {
@@ -51,7 +51,7 @@ class du_srs_policy_max_ul_th : public du_srs_resource_manager
5151

5252
private:
5353
struct cell_context {
54-
cell_context(const du_cell_config& cfg) : cell_cfg(cfg){};
54+
cell_context(const du_cell_config& cfg);
5555

5656
using pair_res_id_offset = std::pair<unsigned, unsigned>;
5757

@@ -82,8 +82,15 @@ class du_srs_policy_max_ul_th : public du_srs_resource_manager
8282

8383
using pair_cnt_max = std::pair<unsigned, const unsigned>;
8484

85+
// Maximum number of SRS resources that can be generated in a cell.
86+
// [Implementation-defined] We assume each UE has one and only one resource.
87+
static const unsigned max_nof_srs_res = MAX_NOF_DU_UES;
88+
// We need to save an object with the cell configuration parameters (not a reference), as this config is a modified
89+
// version of the default cell config.
8590
const du_cell_config& cell_cfg;
86-
srs_cell_common srs_common_params;
91+
// Default SRS configuration for the cell.
92+
const srs_config default_srs_cfg;
93+
srs_cell_common srs_common_params;
8794
// List of all SRS resources available to the cell; these resources can be allocated over to different UEs over
8895
// different offsets.
8996
std::vector<du_srs_resource> cell_srs_res_list;

lib/scheduler/config/serving_cell_config_factory.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -497,26 +497,18 @@ srs_config srsran::config_helpers::make_default_srs_config(const cell_config_bui
497497
res.freq_hop.b_srs = 0;
498498
res.freq_hop.b_hop = 0;
499499
res.grp_or_seq_hop = srs_group_or_sequence_hopping::neither;
500-
if (params.srs_periodic_enabled) {
501-
res.res_type = srs_resource_type::periodic;
502-
res.periodicity_and_offset.emplace(
503-
srs_config::srs_periodicity_and_offset{.period = srs_periodicity::sl40, .offset = 0});
504-
} else {
505-
res.res_type = srs_resource_type::aperiodic;
506-
}
500+
res.res_type = srs_resource_type::aperiodic;
501+
507502
res.sequence_id = params.pci;
508503

509504
cfg.srs_res_set_list.emplace_back();
510505
// TODO: Verify correctness of the config based on what we support.
511506
srs_config::srs_resource_set& res_set = cfg.srs_res_set_list.back();
512507
res_set.id = static_cast<srs_config::srs_res_set_id>(0);
513508
res_set.srs_res_id_list.emplace_back(static_cast<srs_config::srs_res_id>(0));
514-
if (params.srs_periodic_enabled) {
515-
res_set.res_type = srs_config::srs_resource_set::periodic_resource_type{};
516-
} else {
517-
res_set.res_type =
518-
srs_config::srs_resource_set::aperiodic_resource_type{.aperiodic_srs_res_trigger = 1, .slot_offset = 7};
519-
}
509+
res_set.res_type =
510+
srs_config::srs_resource_set::aperiodic_resource_type{.aperiodic_srs_res_trigger = 1, .slot_offset = 7};
511+
520512
res_set.srs_res_set_usage = srs_config::srs_resource_set::usage::codebook;
521513
res_set.p0 = -84;
522514
res_set.pathloss_ref_rs = static_cast<ssb_id_t>(0);

0 commit comments

Comments
 (0)