diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h similarity index 81% rename from srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h rename to srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h index 278abc067..0262d2b71 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_SCHED_CQI_H -#define SRSRAN_SCHED_CQI_H +#ifndef SRSRAN_SCHED_DL_CQI_H +#define SRSRAN_SCHED_DL_CQI_H #include "srsenb/hdr/stack/mac/sched_common.h" #include "srsenb/hdr/stack/mac/sched_helpers.h" @@ -21,10 +21,16 @@ namespace srsenb { -class sched_cqi +/** + * Class that handles DL CQI state of a given {rnti,sector} + * - The cell bandwidth is divided into J parts. J = f(nof_cell_prbs) + * - UE reports wideband CQI every H.Np msec, where Np is the CQI period and H=JK + 1, where K is configured in RRC + * - Thus, for K==0, only wideband CQI is active + */ +class sched_dl_cqi { public: - sched_cqi(uint32_t cell_nof_prb_, uint32_t K_, float alpha = 0.1) : + sched_dl_cqi(uint32_t cell_nof_prb_, uint32_t K_, float alpha = 0.1) : cell_nof_prb(cell_nof_prb_), cell_nof_rbg(cell_nof_prb_to_rbg(cell_nof_prb_)), K(K_), @@ -35,12 +41,10 @@ public: 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)); + wb_cqi_avg = static_cast(cqi_value); } void cqi_sb_info(tti_point tti, uint32_t sb_index, uint32_t cqi_value) @@ -48,12 +52,12 @@ public: 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)); + bp_list[bp_idx].cqi_val = 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(); + subband_cqi[sb_index2] = bp_list[bp_idx].cqi_val; } } @@ -61,7 +65,7 @@ public: int get_rbg_grant_avg_cqi(rbg_interval interv) const { if (not subband_cqi_enabled()) { - return static_cast(wb_cqi_avg.value()); + return static_cast(wb_cqi_avg); } float cqi = 0; for (uint32_t rbg = interv.start(); rbg < interv.stop(); ++rbg) { @@ -74,7 +78,7 @@ public: int get_rbg_grant_avg_cqi(const rbgmask_t& mask) const { if (not subband_cqi_enabled()) { - return static_cast(wb_cqi_avg.value()); + return static_cast(wb_cqi_avg); } float cqi = 0; for (int rbg = mask.find_lowest(0, mask.size()); rbg != -1; rbg = mask.find_lowest(rbg + 1, mask.size())) { @@ -113,9 +117,10 @@ private: static const uint32_t max_nof_subbands = 13; static const uint32_t max_bandwidth_parts = 4; + /// TS 36.321, Table 7.2.2-2 static uint32_t nof_bandwidth_parts(uint32_t nof_prb) { - static const uint32_t nrb[] = {0, 1, 2, 3, 4}; + static const uint32_t nrb[] = {0, 2, 2, 3, 4, 4}; return nrb[srsran::lte_cell_nof_prb_to_index(nof_prb)]; } @@ -139,15 +144,15 @@ private: /// 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; + tti_point last_feedback_tti; + uint32_t last_cqi_subband_idx; + float cqi_val; explicit bandwidth_part_context(float alpha) : cqi_val(alpha), last_cqi_subband_idx(max_nof_subbands) {} }; - tti_point last_wb_tti; - srsran::exp_average_fast_start wb_cqi_avg; + tti_point last_wb_tti; + float wb_cqi_avg; srsran::bounded_vector bp_list; srsran::bounded_vector subband_cqi; @@ -155,4 +160,4 @@ private: } // namespace srsenb -#endif // SRSRAN_SCHED_CQI_H +#endif // SRSRAN_SCHED_DL_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 e2b27b128..03ea4adaa 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,7 +14,7 @@ #define SRSRAN_SCHED_UE_CELL_H #include "../sched_common.h" -#include "sched_cqi.h" +#include "sched_dl_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/sched_cqi_test.cc b/srsenb/test/mac/sched_cqi_test.cc index abe87ae3c..ce7cf0ae8 100644 --- a/srsenb/test/mac/sched_cqi_test.cc +++ b/srsenb/test/mac/sched_cqi_test.cc @@ -10,14 +10,15 @@ * */ -#include "srsenb/hdr/stack/mac/sched_ue_ctrl/sched_cqi.h" +#include "srsenb/hdr/stack/mac/sched_ue_ctrl/sched_dl_cqi.h" #include "srsran/common/test_common.h" namespace srsenb { void test_sched_cqi_one_subband_cqi() { - sched_cqi ue_cqi(50, 4); + // 50 PRBs, K=4 + sched_dl_cqi ue_cqi(50, 4); // J == 3, N == 9 TESTASSERT(ue_cqi.nof_bandwidth_parts() == 3); @@ -51,6 +52,34 @@ void test_sched_cqi_one_subband_cqi() } } +void test_sched_cqi_wideband_cqi() +{ + uint32_t nof_prb = 50; + uint32_t nof_rbgs = cell_nof_prb_to_rbg(nof_prb); + + sched_dl_cqi ue_cqi(nof_prb, 0); + + ue_cqi.cqi_wb_info(tti_point(0), 5); + + // TEST: all bandwidth has positive cqi. + for (uint32_t i = 0; i < nof_rbgs; ++i) { + TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(rbg_interval(i, i + 1)) == 5); + } + TESTASSERT(ue_cqi.get_rbg_grant_avg_cqi(rbg_interval(0, nof_rbgs)) == 5); + + // 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) == 5); + + // TEST: Get optimal RBG mask in terms of CQI + mask = ue_cqi.get_optim_rbg_mask(5); + TESTASSERT(mask.count() == 5); + for (uint32_t i = 0; i < 5; ++i) { + TESTASSERT(mask.test(i) > 0); + } +} + } // namespace srsenb int main(int argc, char** argv) @@ -58,6 +87,7 @@ int main(int argc, char** argv) srsran::test_init(argc, argv); srsenb::test_sched_cqi_one_subband_cqi(); + srsenb::test_sched_cqi_wideband_cqi(); return SRSRAN_SUCCESS; }