From eeb8ad65711881e0cdb075bfc1b00d4337ea5971 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 27 Apr 2021 19:07:16 +0100 Subject: [PATCH] sched,feature - creation of sched_cqi class to manage the update of CQI in a subband CQI setting --- .../hdr/stack/mac/sched_ue_ctrl/sched_cqi.h | 131 ++++++++++++++++++ .../stack/mac/sched_ue_ctrl/sched_ue_cell.h | 1 + srsenb/test/mac/CMakeLists.txt | 4 + srsenb/test/mac/sched_cqi_test.cc | 56 ++++++++ 4 files changed, 192 insertions(+) create mode 100644 srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h create mode 100644 srsenb/test/mac/sched_cqi_test.cc diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h new file mode 100644 index 000000000..8fc257dee --- /dev/null +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h @@ -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(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(cqi_value)); + + // just cap all sub-bands in the same bandwidth part + srsran::interval 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(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(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 get_bp_sb_indexes(uint32_t bp_idx) const + { + return srsran::interval{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 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 wb_cqi_avg; + + srsran::bounded_vector bp_list; + srsran::bounded_vector subband_cqi; +}; + +} // namespace srsenb + +#endif // SRSRAN_SCHED_CQI_H diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h index cd1dc74f3..e2b27b128 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.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" diff --git a/srsenb/test/mac/CMakeLists.txt b/srsenb/test/mac/CMakeLists.txt index c7e721db2..40e5800b7 100644 --- a/srsenb/test/mac/CMakeLists.txt +++ b/srsenb/test/mac/CMakeLists.txt @@ -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) diff --git a/srsenb/test/mac/sched_cqi_test.cc b/srsenb/test/mac/sched_cqi_test.cc new file mode 100644 index 000000000..e7933e980 --- /dev/null +++ b/srsenb/test/mac/sched_cqi_test.cc @@ -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; +}