sched,feature - creation of sched_cqi class to manage the update of CQI in a subband CQI setting

master
Francisco 4 years ago committed by Francisco Paisana
parent f25dbea4de
commit eeb8ad6571

@ -0,0 +1,131 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_CQI_H
#define SRSRAN_SCHED_CQI_H
#include "srsenb/hdr/stack/mac/sched_common.h"
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srsran/adt/accumulators.h"
#include "srsran/common/common_lte.h"
#include "srsran/phy/phch/cqi.h"
namespace srsenb {
class sched_cqi
{
public:
sched_cqi(uint32_t cell_nof_prb_, uint32_t K_) :
cell_nof_prb(cell_nof_prb_),
cell_nof_rbg(cell_nof_prb_to_rbg(cell_nof_prb_)),
K(K_),
wb_cqi_avg(0.01),
bp_list(nof_bandwidth_parts(cell_nof_prb_)),
subband_cqi(srsran_cqi_hl_get_no_subbands(cell_nof_prb), 0)
{
srsran_assert(K <= 4, "K=%d outside of {0, 4}", K);
}
void new_tti(tti_point tti) {}
void cqi_wb_info(tti_point tti, uint32_t cqi_value)
{
last_wb_tti = tti;
wb_cqi_avg.push(static_cast<float>(cqi_value));
}
void cqi_sb_info(tti_point tti, uint32_t sb_index, uint32_t cqi_value)
{
uint32_t bp_idx = get_bp_index(sb_index);
bp_list[bp_idx].last_feedback_tti = tti;
bp_list[bp_idx].last_cqi_subband_idx = sb_index;
bp_list[bp_idx].cqi_val.push(static_cast<float>(cqi_value));
// just cap all sub-bands in the same bandwidth part
srsran::interval<uint32_t> interv = get_bp_sb_indexes(bp_idx);
for (uint32_t sb_index2 = interv.start(); sb_index2 < interv.stop(); ++sb_index2) {
subband_cqi[sb_index2] = bp_list[bp_idx].cqi_val.value();
}
}
int get_rbg_grant_avg_cqi(rbg_interval interv) const
{
float cqi = 0;
for (uint32_t rbg = interv.start(); rbg < interv.stop(); ++rbg) {
cqi += subband_cqi[rbg_to_sb_index(rbg)];
}
return static_cast<int>(cqi / interv.length());
}
int get_rbg_grant_avg_cqi(const rbgmask_t& mask) const
{
float cqi = 0;
for (int rbg = mask.find_lowest(0, mask.size()); rbg != -1; rbg = mask.find_lowest(rbg + 1, mask.size())) {
cqi += subband_cqi[rbg_to_sb_index(rbg)];
}
return static_cast<int>(cqi / mask.count());
}
/// TS 36.321, 7.2.2 - Parameter N
uint32_t nof_subbands() const { return subband_cqi.size(); }
/// TS 36.321, 7.2.2 - Parameter J
uint32_t nof_bandwidth_parts() const { return bp_list.size(); }
private:
static const uint32_t max_subband_size = 8;
static const uint32_t max_nof_subbands = 13;
static const uint32_t max_bandwidth_parts = 4;
static uint32_t nof_bandwidth_parts(uint32_t nof_prb)
{
static const uint32_t nrb[] = {0, 1, 2, 3, 4};
return nrb[srsran::lte_cell_nof_prb_to_index(nof_prb)];
}
uint32_t J() const { return nof_bandwidth_parts(); }
uint32_t N() const { return nof_subbands(); }
uint32_t get_bp_index(uint32_t sb_index) const { return sb_index * J() / N(); }
uint32_t get_sb_index(uint32_t prb_index) const { return prb_index * N() / cell_nof_prb; }
uint32_t rbg_to_sb_index(uint32_t rbg_index) const { return rbg_index * N() / cell_nof_rbg; }
srsran::interval<uint32_t> get_bp_sb_indexes(uint32_t bp_idx) const
{
return srsran::interval<uint32_t>{bp_idx * N() / J(), (bp_idx + 1) * N() / J()};
}
uint32_t cell_nof_prb;
uint32_t cell_nof_rbg;
uint32_t K; ///< set in RRC
/// context of bandwidth part
struct bandwidth_part_context {
tti_point last_feedback_tti;
uint32_t last_cqi_subband_idx;
srsran::exp_average_fast_start<float> cqi_val;
explicit bandwidth_part_context() : cqi_val(0), last_cqi_subband_idx(max_nof_subbands) {}
};
tti_point last_wb_tti;
srsran::exp_average_fast_start<float> wb_cqi_avg;
srsran::bounded_vector<bandwidth_part_context, max_bandwidth_parts> bp_list;
srsran::bounded_vector<float, max_nof_subbands> subband_cqi;
};
} // namespace srsenb
#endif // SRSRAN_SCHED_CQI_H

@ -14,6 +14,7 @@
#define SRSRAN_SCHED_UE_CELL_H
#include "../sched_common.h"
#include "sched_cqi.h"
#include "sched_harq.h"
#include "srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h"
#include "tpc.h"

@ -66,3 +66,7 @@ add_test(sched_ue_cell_test sched_ue_cell_test)
add_executable(sched_benchmark_test sched_benchmark.cc)
target_link_libraries(sched_benchmark_test srsran_common srsenb_mac srsran_mac sched_test_common)
add_test(sched_benchmark_test sched_benchmark_test)
add_executable(sched_cqi_test sched_cqi_test.cc)
target_link_libraries(sched_cqi_test srsran_common srsenb_mac srsran_mac sched_test_common)
add_test(sched_cqi_test sched_cqi_test)

@ -0,0 +1,56 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h"
#include "srsran/common/test_common.h"
namespace srsenb {
void test_sched_cqi_one_subband_cqi()
{
sched_cqi ue_cqi(50, 4);
// J == 3, N == 9
TESTASSERT(ue_cqi.nof_bandwidth_parts() == 3);
TESTASSERT(ue_cqi.nof_subbands() == 9);
// Ni = 0 -> cqi=5
ue_cqi.cqi_sb_info(tti_point(0), 0, 5);
// TEST: updated part has positive cqi. Non-updated cqi didn't change
TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(rbg_interval(0, 1)) == 5);
for (uint32_t i = 1; i < 5; ++i) {
TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(rbg_interval(i, i + 1)) > 0);
}
TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(rbg_interval(6, cell_nof_prb_to_rbg(50))) == 0);
// TEST: Check average cqi over a mask of RBGs
rbgmask_t mask(cell_nof_prb_to_rbg(50));
mask.fill(10, mask.size());
TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(mask) == 0);
mask.reset();
mask.set(1);
TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(mask) == 5);
mask.fill(0, mask.size());
TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(mask) > 0 and ue_cqi.get_rbg_grant_avg_cqi(mask) < 5);
}
} // namespace srsenb
int main(int argc, char** argv)
{
srsran::test_init(argc, argv);
srsenb::test_sched_cqi_one_subband_cqi();
return SRSRAN_SUCCESS;
}
Loading…
Cancel
Save