Skip to content

Commit 9eab216

Browse files
committed
du: first version of DU SRS resource manager
Signed-off-by: Carlo Galiotto <[email protected]>
1 parent 2817c88 commit 9eab216

File tree

7 files changed

+355
-121
lines changed

7 files changed

+355
-121
lines changed

lib/du/du_high/du_manager/ran_resource_management/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_library(du_resource_manager
1010
du_bearer_resource_manager.cpp
1111
du_pucch_resource_manager.cpp
1212
du_ran_resource_manager_impl.cpp
13+
du_srs_resource_manager.cpp
1314
pucch_resource_generator.cpp
1415
srs_resource_generator.cpp
1516
ue_capability_manager.cpp)

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ du_ran_resource_manager_impl::du_ran_resource_manager_impl(span<const du_cell_co
4747
logger(srslog::fetch_basic_logger("DU-MNG")),
4848
test_cfg(test_cfg_),
4949
pucch_res_mng(cell_cfg_list, scheduler_cfg.ue.max_pucchs_per_slot),
50-
bearer_res_mng(srb_config, qos_config, logger)
50+
bearer_res_mng(srb_config, qos_config, logger),
51+
srs_res_mng(std::make_unique<du_srs_policy_max_ul_th>(cell_cfg_list))
5152
{
5253
}
5354

@@ -164,7 +165,7 @@ error_type<std::string> du_ran_resource_manager_impl::allocate_cell_resources(du
164165
ue_res.cell_group.pcg_cfg.pdsch_harq_codebook = pdsch_harq_ack_codebook::dynamic;
165166

166167
if (not pucch_res_mng.alloc_resources(ue_res.cell_group)) {
167-
// Deallocate dedicated Search Spaces.
168+
// Deallocate previously allocated SRS + dedicated Search Spaces.
168169
ue_res.cell_group.cells[0].serv_cell_cfg.init_dl_bwp.pdcch_cfg->search_spaces.clear();
169170
return make_unexpected(fmt::format("Unable to allocate dedicated PUCCH resources for cell={}", cell_index));
170171
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "du_bearer_resource_manager.h"
1414
#include "du_pucch_resource_manager.h"
1515
#include "du_ran_resource_manager.h"
16+
#include "du_srs_resource_manager.h"
1617
#include "ue_capability_manager.h"
1718
#include "srsran/ran/qos/five_qi.h"
1819

@@ -107,6 +108,8 @@ class du_ran_resource_manager_impl : public du_ran_resource_manager
107108

108109
/// Allocator of UE bearer resources.
109110
du_bearer_resource_manager bearer_res_mng;
111+
112+
std::unique_ptr<du_srs_resource_manager> srs_res_mng;
110113
};
111114

112115
} // namespace srs_du
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*
2+
*
3+
* Copyright 2021-2024 Software Radio Systems Limited
4+
*
5+
* By using this file, you agree to the terms and conditions set
6+
* forth in the LICENSE file which can be found at the top level of
7+
* the distribution.
8+
*
9+
*/
10+
11+
#include "du_srs_resource_manager.h"
12+
#include "du_ue_resource_config.h"
13+
#include "srsran/ran/srs/srs_bandwidth_configuration.h"
14+
15+
using namespace srsran;
16+
using namespace srs_du;
17+
18+
static std::optional<unsigned> compute_srs_bw_param(unsigned nof_ul_rbs)
19+
{
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.
22+
23+
// As per Table 6.4.1.4.3-1, TS 38.211, the maximum value of \f$C_{SRS}\f$ is 63.
24+
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++) {
27+
auto srs_params = srs_configuration_get(c_srs, b_srs_0);
28+
srsran_assert(srs_params.has_value(), "The SRS is not valid");
29+
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");
32+
return std::nullopt;
33+
}
34+
if (srs_params.value().m_srs == nof_ul_rbs) {
35+
return c_srs;
36+
}
37+
if (srs_params.value().m_srs > nof_ul_rbs) {
38+
return c_srs - 1;
39+
}
40+
}
41+
return max_non_valid_c_srs - 1;
42+
}
43+
44+
// Helper that returns the frequency shift value for the SRS; the value is computed in such a way that the SRS resources
45+
// are placed at the center of the band.
46+
static unsigned compute_freq_shift(unsigned c_srs, unsigned nof_ul_rbs)
47+
{
48+
// As per Section 6.4.1.4.3, the parameter \f$C_{SRS}\f$ = 0 provides the bandwidth of the SRS resources.
49+
constexpr uint8_t b_srs_0 = 0;
50+
std::optional<srsran::srs_configuration> srs_params = srs_configuration_get(c_srs, b_srs_0);
51+
srsran_sanity_check(srs_params.has_value() and nof_ul_rbs >= srs_params.value().m_srs,
52+
"The SRS configuration is not valid");
53+
54+
return (nof_ul_rbs - srs_params.value().m_srs) / 2;
55+
}
56+
57+
static bool is_ul_slot(unsigned offset, const tdd_ul_dl_config_common& tdd_cfg)
58+
{
59+
const unsigned slot_index = offset % (NOF_SUBFRAMES_PER_FRAME * get_nof_slots_per_subframe(tdd_cfg.ref_scs));
60+
return srsran::get_active_tdd_ul_symbols(tdd_cfg, slot_index, cyclic_prefix::NORMAL).length() != 0;
61+
}
62+
63+
static bool is_partually_ul_slot(unsigned offset, const tdd_ul_dl_config_common& tdd_cfg)
64+
{
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;
69+
}
70+
71+
du_srs_policy_max_ul_th::du_srs_policy_max_ul_th(span<const du_cell_config> cell_cfg_list_) :
72+
cells(cell_cfg_list_.begin(), cell_cfg_list_.end())
73+
{
74+
for (auto& cell : cells) {
75+
std::optional<unsigned> c_srs =
76+
compute_srs_bw_param(cell.cell_cfg.ul_cfg_common.init_ul_bwp.generic_params.crbs.length()).value();
77+
srsran_assert(c_srs.has_value(), "SRS parameters didn't provide a valid C_SRS value");
78+
cell.srs_common_params.c_srs = c_srs.value();
79+
std::optional<unsigned> freq_shift =
80+
compute_freq_shift(c_srs.value(), cell.cell_cfg.ul_cfg_common.init_ul_bwp.generic_params.crbs.length());
81+
srsran_assert(freq_shift.has_value(), "SRS parameters didn't provide a valid freq_shift value");
82+
cell.srs_common_params.freq_shift = freq_shift.value();
83+
84+
cell.cell_srs_res_list = generate_cell_srs_list(cell.cell_cfg);
85+
86+
const unsigned srs_period_slots = static_cast<unsigned>(cell.cell_cfg.srs_cfg.srs_period.value());
87+
cell.slot_resource_cnt.reserve(srs_period_slots);
88+
89+
for (unsigned offset = 0; offset != srs_period_slots; ++offset) {
90+
unsigned offset_res_cnt = 0U;
91+
for (auto& res : cell.cell_srs_res_list) {
92+
// Handle TDD and FDD configurations separately, as we treat partially-UL slots differently from fully-UL slots.
93+
if (cell_cfg_list_[0].tdd_ul_dl_cfg_common.has_value()) {
94+
// Verify whether the offset maps to a partially- or fully-UL slot.
95+
if (not is_ul_slot(offset, cell_cfg_list_[0].tdd_ul_dl_cfg_common.value())) {
96+
continue;
97+
}
98+
// For partially-UL slots, we need to check if the SRS can be placed in the UL symbols of the slot.
99+
if (is_partually_ul_slot(offset, cell_cfg_list_[0].tdd_ul_dl_cfg_common.value())) {
100+
// TODO: Fix check for pattern 2.
101+
if (res.symbols.start() < NOF_OFDM_SYM_PER_SLOT_NORMAL_CP -
102+
cell_cfg_list_[0].tdd_ul_dl_cfg_common.value().pattern1.nof_ul_symbols) {
103+
continue;
104+
}
105+
}
106+
// This is the fully-UL slot case: check if the SRS can be placed in the UL symbols of the slot.
107+
else if (res.symbols.start() <
108+
NOF_OFDM_SYM_PER_SLOT_NORMAL_CP - cell.cell_cfg.srs_cfg.max_nof_symbols.to_uint()) {
109+
continue;
110+
}
111+
}
112+
// FDD case.
113+
else {
114+
if (res.symbols.start() < NOF_OFDM_SYM_PER_SLOT_NORMAL_CP - cell.cell_cfg.srs_cfg.max_nof_symbols.to_uint()) {
115+
continue;
116+
}
117+
}
118+
cell.srs_res_offset_free_list.push_back({res.cell_res_id, offset});
119+
++offset_res_cnt;
120+
}
121+
cell.slot_resource_cnt.push_back({0U, offset_res_cnt});
122+
}
123+
}
124+
}
125+
126+
bool du_srs_policy_max_ul_th::alloc_resources(cell_group_config& cell_grp_cfg)
127+
{
128+
// Allocation of SR PUCCH offset.
129+
cell_grp_cfg.cells[0].serv_cell_cfg.ul_config->init_ul_bwp.srs_cfg.emplace(
130+
cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].default_srs_cfg);
131+
srs_config& ue_srs_cfg = cell_grp_cfg.cells[0].serv_cell_cfg.ul_config->init_ul_bwp.srs_cfg.value();
132+
auto& free_srs_list = cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].srs_res_offset_free_list;
133+
134+
// Verify where there are SRS resources to allocate a new UE.
135+
if (free_srs_list.empty()) {
136+
return false;
137+
}
138+
139+
// Find the best resource ID and offset for this UE.
140+
auto srs_res_id_offset = cells[0].find_optimal_ue_srs_resource();
141+
142+
if (srs_res_id_offset == free_srs_list.end()) {
143+
return false;
144+
}
145+
146+
const auto& du_res_it = cells[0].get_du_srs_res_cfg(srs_res_id_offset->first);
147+
148+
if (du_res_it == cells[0].cell_srs_res_list.end()) {
149+
return false;
150+
}
151+
152+
const auto& du_res = *du_res_it;
153+
154+
// Update the SRS configuration with the parameters that are specific to this resource and for this UE.
155+
auto& only_ue_srs_res = ue_srs_cfg.srs_res_list.front();
156+
const unsigned srs_offset = srs_res_id_offset->second;
157+
// NOTE: given that there is only 1 SRS resource per UE, we can assume that the SRS resource ID is 0.
158+
only_ue_srs_res.id.cell_res_id = du_res.cell_res_id;
159+
only_ue_srs_res.id.ue_res_id = static_cast<srs_config::srs_res_id>(0U);
160+
only_ue_srs_res.periodicity_and_offset.value().offset = srs_offset;
161+
only_ue_srs_res.tx_comb.tx_comb_offset = du_res.tx_comb_offset.to_uint();
162+
only_ue_srs_res.freq_domain_pos = du_res.freq_dom_position;
163+
only_ue_srs_res.res_mapping.start_pos = NOF_OFDM_SYM_PER_SLOT_NORMAL_CP - du_res.symbols.start() - 1;
164+
only_ue_srs_res.res_mapping.nof_symb = static_cast<srs_nof_symbols>(du_res.symbols.length());
165+
only_ue_srs_res.sequence_id = du_res.sequence_id;
166+
167+
// Update the SRS configuration with the parameters that are common to the cell.
168+
only_ue_srs_res.freq_hop.c_srs = cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].srs_common_params.c_srs;
169+
only_ue_srs_res.freq_domain_shift =
170+
cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].srs_common_params.freq_shift;
171+
172+
// Update the SRS resource set with the SRS id.
173+
ue_srs_cfg.srs_res_set_list.front().srs_res_id_list.front() = only_ue_srs_res.id.ue_res_id;
174+
175+
// Remove the allocated SRS resource from the free list.
176+
free_srs_list.erase(srs_res_id_offset);
177+
178+
// Update the used_not_full slot vector.
179+
++cells[0].slot_resource_cnt[srs_offset].first;
180+
181+
return true;
182+
}
183+
184+
std::vector<std::pair<unsigned, unsigned>>::const_iterator
185+
du_srs_policy_max_ul_th::cell_context::find_optimal_ue_srs_resource()
186+
{
187+
// The weights assigned here can be set to any value, as long as:
188+
// - symbol_weight_base is greater than 0;
189+
// - reuse_slot_discount less than symbol_weight_base;
190+
// - max_weight is > symbol_weight_base * (srs_builder_params::max_nof_symbols / srs_builder_params::nof_symbols).
191+
static constexpr unsigned max_weight = 100U;
192+
static constexpr unsigned symbol_weight_base = 10U;
193+
194+
const auto weight_function = [&](const pair_res_id_offset& srs_res) {
195+
if (cell_cfg.tdd_ul_dl_cfg_common.has_value() and
196+
is_partually_ul_slot(srs_res.second, cell_cfg.tdd_ul_dl_cfg_common.value())) {
197+
return 0U;
198+
}
199+
200+
// SRS res config.
201+
const auto srs_res_cfg_it = get_du_srs_res_cfg(srs_res.first);
202+
203+
if (srs_res_cfg_it == cell_srs_res_list.end()) {
204+
return max_weight;
205+
}
206+
207+
// Give priority to the last symbols within a slot. This reduces the space used for the SRS in a slot.
208+
const unsigned symb_weight =
209+
(NOF_OFDM_SYM_PER_SLOT_NORMAL_CP - srs_res_cfg_it->symbols.start()) * symbol_weight_base;
210+
211+
// We consider a discount if the offset is already used but not full; this way, we give an incentive to the SRS
212+
// resources not to be allocated on a new slot, to avoid taking PUSCH symbols on a new slot.
213+
const unsigned reuse_slot_discount = offset_used_not_full(srs_res.second) ? symbol_weight_base / 2U : 0U;
214+
215+
return symb_weight - reuse_slot_discount;
216+
};
217+
218+
auto optimal_res_it = std::min_element(
219+
srs_res_offset_free_list.begin(),
220+
srs_res_offset_free_list.end(),
221+
[&weight_function](const std::pair<unsigned, unsigned>& lhs, const std::pair<unsigned, unsigned>& rhs) {
222+
return weight_function(lhs) < weight_function(rhs);
223+
});
224+
225+
return optimal_res_it;
226+
}
227+
228+
void du_srs_policy_max_ul_th::dealloc_resources(cell_group_config& cell_grp_cfg)
229+
{
230+
if (not cell_grp_cfg.cells[0].serv_cell_cfg.ul_config->init_ul_bwp.srs_cfg.has_value()) {
231+
return;
232+
}
233+
234+
const auto& ue_srs_cfg = cell_grp_cfg.cells[0].serv_cell_cfg.ul_config->init_ul_bwp.srs_cfg.value();
235+
auto& free_srs_list = cells[cell_grp_cfg.cells[0].serv_cell_cfg.cell_index].srs_res_offset_free_list;
236+
237+
for (const auto& srs_res : ue_srs_cfg.srs_res_list) {
238+
const unsigned offset_to_deallocate = srs_res.periodicity_and_offset.value().offset;
239+
free_srs_list.push_back({srs_res.id.cell_res_id, offset_to_deallocate});
240+
241+
// Update the used_not_full slot vector.
242+
srsran_assert(cells[0].slot_resource_cnt[offset_to_deallocate].first != 0, "The offset is expected to be non-zero");
243+
--cells[0].slot_resource_cnt[offset_to_deallocate].first;
244+
}
245+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
*
3+
* Copyright 2021-2024 Software Radio Systems Limited
4+
*
5+
* By using this file, you agree to the terms and conditions set
6+
* forth in the LICENSE file which can be found at the top level of
7+
* the distribution.
8+
*
9+
*/
10+
11+
#pragma once
12+
13+
#include "srs_resource_generator.h"
14+
#include "srsran/adt/optional.h"
15+
#include "srsran/du/du_cell_config.h"
16+
#include "srsran/ran/srs/srs_configuration.h"
17+
18+
namespace srsran {
19+
namespace srs_du {
20+
21+
struct cell_group_config;
22+
23+
/// This abstract class defines the methods that the DU SRS resource manager must implement. The implementation of this
24+
/// class defines different policies for the SRS allocation.
25+
class du_srs_resource_manager
26+
{
27+
public:
28+
virtual ~du_srs_resource_manager() = default;
29+
30+
/// \brief Allocate SRS resources for a given UE. The resources are stored in the UE's cell group config.
31+
/// The function allocates the UE the resources from a common pool.
32+
/// \return true if allocation was successful.
33+
virtual bool alloc_resources(cell_group_config& cell_grp_cfg) = 0;
34+
35+
/// \brief Deallocate the SRS resources for a given UE and return the used resource to the common pool.
36+
virtual void dealloc_resources(cell_group_config& cell_grp_cfg) = 0;
37+
};
38+
39+
/// This class implements the MAX UL throughput policy for the SRS allocation. The SRS resources are allocated to
40+
/// minimize the number of slots that contains the SRS resources; furthermore, within a given slot, the SRS resources
41+
/// are allocated to minimize the number of symbols that are used for SRS. The drawback of this policy is that it can
42+
/// increase the inter slot SRS interference among different UEs.
43+
class du_srs_policy_max_ul_th : public du_srs_resource_manager
44+
{
45+
public:
46+
explicit du_srs_policy_max_ul_th(span<const du_cell_config> cell_cfg_list_);
47+
48+
bool alloc_resources(cell_group_config& cell_grp_cfg) override;
49+
50+
void dealloc_resources(cell_group_config& cell_grp_cfg) override;
51+
52+
private:
53+
struct cell_context {
54+
cell_context(const du_cell_config& cfg) :
55+
cell_cfg(cfg), default_srs_cfg(cfg.ue_ded_serv_cell_cfg.ul_config.value().init_ul_bwp.srs_cfg.value()){};
56+
57+
using pair_res_id_offset = std::pair<unsigned, unsigned>;
58+
59+
// Returns the DU SRS resource with the given cell resource ID from the cell list of resources.
60+
std::vector<du_srs_resource>::const_iterator get_du_srs_res_cfg(unsigned cell_res_id)
61+
{
62+
return std::find_if(cell_srs_res_list.begin(),
63+
cell_srs_res_list.end(),
64+
[cell_res_id](const du_srs_resource& res) { return res.cell_res_id == cell_res_id; });
65+
}
66+
67+
// Returns the best SRS resource ID and offset for this UE, according to the policy defined in this class.
68+
std::vector<pair_res_id_offset>::const_iterator find_optimal_ue_srs_resource();
69+
70+
// Check if this SRS offset has already some SRS resources allocated, but can still host more.
71+
bool offset_used_not_full(unsigned offset) const
72+
{
73+
srsran_assert(offset < slot_resource_cnt.size(), "Offset out of range");
74+
return slot_resource_cnt[offset].first != 0 and
75+
slot_resource_cnt[offset].first < slot_resource_cnt[offset].second;
76+
}
77+
78+
// Parameters that are common to all cell SRS resources.
79+
struct srs_cell_common {
80+
unsigned c_srs;
81+
unsigned freq_shift;
82+
};
83+
84+
using pair_cnt_max = std::pair<unsigned, const unsigned>;
85+
86+
const du_cell_config& cell_cfg;
87+
const srs_config default_srs_cfg;
88+
srs_cell_common srs_common_params;
89+
// List of all SRS resources available to the cell; these resources can be allocated over to different UEs over
90+
// different offsets.
91+
std::vector<du_srs_resource> cell_srs_res_list;
92+
// List of SRS resource ID and offset that can be allocated to the cell's UEs.
93+
std::vector<pair_res_id_offset> srs_res_offset_free_list;
94+
// Counter of how many SRS resources (current counter, max_counter) that can be allocated in the same slot (offset).
95+
std::vector<pair_cnt_max> slot_resource_cnt;
96+
};
97+
98+
// Contains the resources for the different cells of the DU.
99+
static_vector<cell_context, MAX_NOF_DU_CELLS> cells;
100+
};
101+
102+
} // namespace srs_du
103+
} // namespace srsran

0 commit comments

Comments
 (0)