created class that implements the scheduler transmit power control and PHR handling

master
Francisco 4 years ago committed by Andre Puschmann
parent 788ed5ce70
commit 5865df39d1

@ -0,0 +1,134 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 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 SRSLTE_ACCUMULATORS_H
#define SRSLTE_ACCUMULATORS_H
#include <cstdint>
#include <limits>
#include <vector>
namespace srslte {
template <typename T>
struct rolling_average {
void push(T sample)
{
avg_ += (sample - avg_) / (count_ + 1);
++count_;
}
T value() const { return count_ == 0 ? 0 : avg_; }
uint32_t count() const { return count_; }
private:
T avg_ = 0;
uint32_t count_ = 0;
};
template <typename T>
struct exp_average_fast_start {
exp_average_fast_start(T alpha_, uint32_t start_size = 100) : alpha(alpha_), nof_left(start_size) {}
void push(T sample)
{
if (nof_left-- > 0) {
avg_ += (sample - avg_) / (count + 1);
count++;
} else {
avg_ = (1 - alpha) * avg_ + alpha * sample;
}
}
T value() const { return count == 0 ? 0 : avg_; }
private:
T avg_ = 0;
uint32_t count = 0;
uint32_t nof_left;
T alpha;
};
namespace detail {
template <typename T>
struct sliding_window {
sliding_window(uint32_t N, T val) : window(N, val) {}
void push(T sample)
{
window[next_idx++] = sample;
if (next_idx >= window.size()) {
next_idx -= window.size();
}
}
size_t size() const { return window.size(); }
T& operator[](size_t i) { return window[i]; }
const T& operator[](size_t i) const { return window[i]; }
std::vector<T> window;
size_t next_idx = 0;
};
} // namespace detail
template <typename T>
struct sliding_sum {
sliding_sum(uint32_t N) : window(N, 0) {}
void push(T sample) { window.push(sample); }
T value() const
{
T ret = 0;
for (size_t i = 0; i < window.size(); ++i) {
ret += window[i];
}
return ret;
}
size_t size() const { return window.size(); }
private:
detail::sliding_window<T> window;
};
template <typename T>
struct sliding_average {
sliding_average(uint32_t N) : window(N, 0) {}
void push(T sample) { window.push(sample); }
T value() const { return window.value() / window.size(); }
private:
sliding_sum<T> window;
};
template <typename T>
struct null_sliding_average {
null_sliding_average(uint32_t N, T null_val = std::numeric_limits<T>::max()) :
null_value_(null_val), window(N, null_val)
{}
void push(T sample) { window.push(sample); }
void push_hole() { window.push(null_value_); }
T value() const
{
T ret = 0;
for (size_t i = 0; i < window.size(); ++i) {
if (window[i] != null_value_) {
ret += window[i];
}
}
return ret;
}
T null_value() const { return null_value_; }
private:
T null_value_;
detail::sliding_window<T> window;
};
} // namespace srslte
#endif // SRSLTE_ACCUMULATORS_H

@ -65,6 +65,7 @@ public:
/* pusch configuration */
srslte_pusch_hopping_cfg_t pusch_hopping_cfg;
float target_ul_sinr;
/* prach configuration */
uint32_t prach_config;
@ -282,11 +283,11 @@ public:
virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) = 0;
/* UL information */
virtual int ul_crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, bool crc) = 0;
virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0;
virtual int ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) = 0;
virtual int ul_phr(uint16_t rnti, int phr) = 0;
virtual int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code) = 0;
virtual int ul_crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, bool crc) = 0;
virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0;
virtual int ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) = 0;
virtual int ul_phr(uint16_t rnti, uint32_t enb_cc_idx, int phr) = 0;
virtual int ul_snr_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code) = 0;
/* Run Scheduler for this tti */
virtual int dl_sched(uint32_t tti, uint32_t enb_cc_idx, dl_sched_res_t& sched_result) = 0;

@ -88,8 +88,8 @@ public:
int ul_crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, bool crc) final;
int ul_sr_info(uint32_t tti, uint16_t rnti) override;
int ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) final;
int ul_phr(uint16_t rnti, int phr) final;
int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code) final;
int ul_phr(uint16_t rnti, uint32_t enb_cc_idx, int phr) final;
int ul_snr_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code) final;
int dl_sched(uint32_t tti, uint32_t enb_cc_idx, dl_sched_res_t& sched_result) final;
int ul_sched(uint32_t tti, uint32_t enb_cc_idx, ul_sched_res_t& sched_result) final;
@ -97,8 +97,6 @@ public:
/* Custom functions
*/
void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) final;
void tpc_inc(uint16_t rnti);
void tpc_dec(uint16_t rnti);
std::array<int, SRSLTE_MAX_CARRIERS> get_enb_ue_cc_map(uint16_t rnti) final;
std::array<bool, SRSLTE_MAX_CARRIERS> get_scell_activation_mask(uint16_t rnti) final;
int ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) final;

@ -19,7 +19,8 @@
#include <vector>
#include "sched_harq.h"
#include "sched_lch.h"
#include "sched_ue_ctrl/sched_lch.h"
#include "sched_ue_ctrl/tpc.h"
#include <bitset>
#include <deque>
@ -67,6 +68,7 @@ struct cc_sched_ue {
uint32_t max_mcs_dl = 28, max_mcs_ul = 28;
uint32_t max_aggr_level = 3;
int fixed_mcs_ul = 0, fixed_mcs_dl = 0;
tpc tpc_fsm;
// Allowed DCI locations per per CFI and per subframe
std::array<std::array<sched_dci_cce_t, 10>, 3> dci_locations = {};
@ -115,10 +117,10 @@ public:
void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue);
void ul_buffer_state(uint8_t lcg_id, uint32_t bsr);
void ul_phr(int phr);
void ul_phr(uint32_t enb_cc_idx, int phr);
void mac_buffer_state(uint32_t ce_code, uint32_t nof_cmds);
void set_ul_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code);
void set_ul_snr(tti_point tti_rx, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code);
void set_dl_ri(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t ri);
void set_dl_pmi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t ri);
void set_dl_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi);
@ -129,9 +131,6 @@ public:
* Custom functions
*******************************************************/
void tpc_inc();
void tpc_dec();
const dl_harq_proc& get_dl_harq(uint32_t idx, uint32_t cc_idx) const;
uint16_t get_rnti() const { return rnti; }
std::pair<bool, uint32_t> get_active_cell_index(uint32_t enb_cc_idx) const;
@ -252,15 +251,10 @@ private:
bool sr = false;
lch_ue_manager lch_handler;
int power_headroom = 0;
uint32_t cqi_request_tti = 0;
uint16_t rnti = 0;
uint32_t max_msg3retx = 0;
/* User State */
int next_tpc_pusch = 0;
int next_tpc_pucch = 0;
bool phy_config_dedicated_enabled = false;
tti_point current_tti;

@ -0,0 +1,123 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 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 SRSLTE_TPC_H
#define SRSLTE_TPC_H
#include "srslte/adt/accumulators.h"
#include "srslte/common/common.h"
namespace srsenb {
/**
* Class to handle TPC Commands sent to the UE.
* The TPC value sent to the UE in each DCI is a result of:
* - the difference between the target SINR and the windowed average of past UE UL SNR estimates
* - subtracted by the sum of TPC values sent in the last TX_UL_DELAY milliseconds (i.e. 8ms), which the UE hasn't yet
* applied
*/
class tpc
{
static constexpr size_t SNR_WINDOW_SIZE_MS = 8;
public:
tpc(float target_snr_dB_ = -1.0) :
target_snr_dB(target_snr_dB_),
pusch_tpc_values(FDD_HARQ_DELAY_DL_MS + FDD_HARQ_DELAY_UL_MS),
pucch_tpc_values(FDD_HARQ_DELAY_DL_MS + FDD_HARQ_DELAY_UL_MS),
snr_avg(SNR_WINDOW_SIZE_MS)
{
pending_snr = snr_avg.null_value();
}
void set_cfg(float target_snr_dB_) { target_snr_dB = target_snr_dB_; }
void set_snr(float snr) { pending_snr = snr; }
void set_phr(int phr_)
{
last_phr = phr_;
// compute and cache the max nof UL PRBs that avoids overflowing PHR
max_prbs_cached = 1;
for (int nof_prbs = 100; nof_prbs >= 0; --nof_prbs) {
if (last_phr >= 10 * log10(nof_prbs)) {
max_prbs_cached = last_phr;
break;
}
}
}
void new_tti()
{
if (target_snr_dB < 0) {
return;
}
// Enqueue PUSCH/PUCCH TPC sent in last TTI (zero for both Delta_PUSCH/Delta_PUCCH=0 and TPC not sent)
pusch_tpc_values.push(pending_pusch_tpc);
pending_pusch_tpc = 0;
pusch_tpc_values.push(pending_pucch_tpc);
pending_pucch_tpc = 0;
// Enqueue pending SNR measurement
snr_avg.push(pending_snr);
pending_snr = snr_avg.null_value();
}
/**
* Called during DCI format0 encoding to set TPC command
* @return accumulated TPC value {-3, -1, 0, 1, 3}
*/
int8_t encode_pusch_tpc()
{
if (target_snr_dB < 0) {
return 0;
}
float diff = target_snr_dB - snr_avg.value();
diff -= pusch_tpc_values.value();
int8_t ret = 0;
if (diff > 1) {
ret = diff > 3 ? 3 : 1;
} else if (diff <= -1) {
ret = -1;
}
pending_pusch_tpc = ret;
return ret;
}
int8_t encode_pucch_tpc()
{
float diff = target_snr_dB - snr_avg.value();
diff -= pucch_tpc_values.value();
int8_t ret = 0;
if (diff > 1) {
ret = diff > 3 ? 3 : 1;
} else if (diff <= -1) {
ret = -1;
}
pending_pucch_tpc = ret;
return ret;
}
uint32_t max_ul_prbs() const { return max_prbs_cached; }
private:
float target_snr_dB;
srslte::null_sliding_average<float> snr_avg;
srslte::sliding_sum<int> pusch_tpc_values, pucch_tpc_values;
uint32_t max_prbs_cached = 100;
int last_phr = 0;
int pending_pusch_tpc = 0, pending_pucch_tpc = 0;
float pending_snr = 0;
};
} // namespace srsenb
#endif // SRSLTE_TPC_H

@ -54,7 +54,8 @@ public:
void start_ta() { ta_fsm.start(); };
uint32_t set_ta_us(float ta_us) { return ta_fsm.push_value(ta_us); };
uint32_t tick_ta_fsm() { return ta_fsm.tick(); };
void tic();
uint8_t* generate_pdu(uint32_t ue_cc_idx,
uint32_t harq_pid,

@ -9,7 +9,7 @@
add_subdirectory(schedulers)
set(SOURCES mac.cc ue.cc sched.cc sched_carrier.cc sched_grid.cc sched_harq.cc sched_ue.cc
sched_lch.cc sched_interface_helpers.cc)
sched_ue_ctrl/sched_lch.cc sched_interface_helpers.cc)
add_library(srsenb_mac STATIC ${SOURCES} $<TARGET_OBJECTS:mac_schedulers>)
if(ENABLE_5GNR)

@ -391,8 +391,7 @@ int mac::snr_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, float snr
return SRSLTE_ERROR;
}
uint32_t cqi = srslte_cqi_from_snr(snr);
return scheduler.ul_cqi_info(tti_rx, rnti, enb_cc_idx, cqi, 0);
return scheduler.ul_snr_info(tti_rx, rnti, enb_cc_idx, snr, 0);
}
int mac::ta_info(uint32_t tti, uint16_t rnti, float ta_us)
@ -843,12 +842,9 @@ int mac::get_ul_sched(uint32_t tti_tx_ul, ul_sched_list_t& ul_sched_res_list)
log_h->step(TTI_SUB(tti_tx_ul, FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS));
// Execute TA FSM
// Execute UE FSMs (e.g. TA)
for (auto& ue : ue_db) {
uint32_t nof_ta_count = ue.second->tick_ta_fsm();
if (nof_ta_count) {
scheduler.dl_mac_buffer_state(ue.first, (uint32_t)srslte::dl_sch_lcid::TA_CMD, nof_ta_count);
}
ue.second->tic();
}
for (uint32_t enb_cc_idx = 0; enb_cc_idx < cell_config.size(); enb_cc_idx++) {

@ -313,9 +313,9 @@ int sched::dl_rach_info(uint32_t enb_cc_idx, dl_sched_rar_info_t rar_info)
return carrier_schedulers[enb_cc_idx]->dl_rach_info(rar_info);
}
int sched::ul_cqi_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code)
int sched::ul_snr_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code)
{
return ue_db_access(rnti, [&](sched_ue& ue) { ue.set_ul_cqi(tti_point{tti_rx}, enb_cc_idx, cqi, ul_ch_code); });
return ue_db_access(rnti, [&](sched_ue& ue) { ue.set_ul_snr(tti_point{tti_rx}, enb_cc_idx, snr, ul_ch_code); });
}
int sched::ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr)
@ -328,10 +328,10 @@ int sched::ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes)
return ue_db_access(rnti, [lcid, bytes](sched_ue& ue) { ue.ul_buffer_add(lcid, bytes); });
}
int sched::ul_phr(uint16_t rnti, int phr)
int sched::ul_phr(uint16_t rnti, uint32_t enb_cc_idx, int phr)
{
return ue_db_access(
rnti, [phr](sched_ue& ue) { ue.ul_phr(phr); }, __PRETTY_FUNCTION__);
rnti, [enb_cc_idx, phr](sched_ue& ue) { ue.ul_phr(enb_cc_idx, phr); }, __PRETTY_FUNCTION__);
}
int sched::ul_sr_info(uint32_t tti, uint16_t rnti)
@ -346,18 +346,6 @@ void sched::set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs)
carrier_schedulers[0]->set_dl_tti_mask(tti_mask, nof_sfs);
}
void sched::tpc_inc(uint16_t rnti)
{
ue_db_access(
rnti, [](sched_ue& ue) { ue.tpc_inc(); }, __PRETTY_FUNCTION__);
}
void sched::tpc_dec(uint16_t rnti)
{
ue_db_access(
rnti, [](sched_ue& ue) { ue.tpc_dec(); }, __PRETTY_FUNCTION__);
}
std::array<int, SRSLTE_MAX_CARRIERS> sched::get_enb_ue_cc_map(uint16_t rnti)
{
std::array<int, SRSLTE_MAX_CARRIERS> ret{};

@ -211,8 +211,6 @@ void sched_ue::reset()
{
cfg = {};
sr = false;
next_tpc_pusch = 1;
next_tpc_pucch = 1;
phy_config_dedicated_enabled = false;
cqi_request_tti = 0;
carriers.clear();
@ -229,6 +227,7 @@ void sched_ue::new_subframe(tti_point tti_rx, uint32_t enb_cc_idx)
current_tti = tti_rx;
lch_handler.new_tti();
}
carriers.at(enb_ue_cc_idx_map[enb_cc_idx]).tpc_fsm.new_tti();
}
/// sanity check the UE CC configuration
@ -296,9 +295,9 @@ void sched_ue::ul_buffer_add(uint8_t lcid, uint32_t bytes)
lch_handler.ul_buffer_add(lcid, bytes);
}
void sched_ue::ul_phr(int phr)
void sched_ue::ul_phr(uint32_t enb_cc_idx, int phr)
{
power_headroom = phr;
carriers[enb_ue_cc_idx_map[enb_cc_idx]].tpc_fsm.set_phr(phr);
}
void sched_ue::dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue)
@ -465,33 +464,18 @@ void sched_ue::set_dl_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi)
}
}
void sched_ue::set_ul_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code)
void sched_ue::set_ul_snr(tti_point tti_rx, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code)
{
cc_sched_ue* c = find_ue_carrier(enb_cc_idx);
if (c != nullptr and c->cc_state() != cc_st::idle) {
c->ul_cqi = cqi;
c->tpc_fsm.set_snr(snr);
c->ul_cqi = srslte_cqi_from_snr(snr);
c->ul_cqi_tti_rx = tti_rx;
} else {
log_h->warning("Received SNR info for invalid cell index %d\n", enb_cc_idx);
}
}
void sched_ue::tpc_inc()
{
if (power_headroom > 0) {
next_tpc_pusch = 3;
next_tpc_pucch = 3;
}
log_h->info("SCHED: Set TCP=%d for rnti=0x%x\n", next_tpc_pucch, rnti);
}
void sched_ue::tpc_dec()
{
next_tpc_pusch = 0;
next_tpc_pucch = 0;
log_h->info("SCHED: Set TCP=%d for rnti=0x%x\n", next_tpc_pucch, rnti);
}
/*******************************************************
*
* Functions used to generate DCI grants
@ -613,8 +597,7 @@ int sched_ue::generate_format1(uint32_t pid,
dci->tb[0].rv = sched_utils::get_rvidx(h->nof_retx(0));
dci->tb[0].ndi = h->get_ndi(0);
dci->tpc_pucch = (uint8_t)next_tpc_pucch;
next_tpc_pucch = 1;
dci->tpc_pucch = carriers[ue_cc_idx].tpc_fsm.encode_pucch_tpc();
data->tbs[0] = (uint32_t)tbs;
data->tbs[1] = 0;
}
@ -742,8 +725,7 @@ int sched_ue::generate_format2a(uint32_t pid,
dci->rnti = rnti;
dci->ue_cc_idx = ue_cc_idx;
dci->pid = h->get_id();
dci->tpc_pucch = (uint8_t)next_tpc_pucch;
next_tpc_pucch = 1;
dci->tpc_pucch = carriers[ue_cc_idx].tpc_fsm.encode_pucch_tpc();
int ret = data->tbs[0] + data->tbs[1];
return ret;
@ -850,8 +832,7 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data,
dci->tb.ndi = h->get_ndi(0);
dci->cqi_request = cqi_request;
dci->freq_hop_fl = srslte_dci_ul_t::SRSLTE_RA_PUSCH_HOP_DISABLED;
dci->tpc_pusch = next_tpc_pusch;
next_tpc_pusch = 1;
dci->tpc_pusch = carriers[ue_cc_idx].tpc_fsm.encode_pusch_tpc();
dci->type2_alloc.riv = srslte_ra_type2_to_riv(alloc.length(), alloc.start(), cell.nof_prb);
@ -1328,7 +1309,8 @@ cc_sched_ue::cc_sched_ue(const sched_interface::ue_cfg_t& cfg_,
log_h(srslte::logmap::get("MAC ")),
ue_cc_idx(ue_cc_idx_),
last_tti(current_tti),
harq_ent(SCHED_MAX_HARQ_PROC, SCHED_MAX_HARQ_PROC)
harq_ent(SCHED_MAX_HARQ_PROC, SCHED_MAX_HARQ_PROC),
tpc_fsm(cell_cfg_.cfg.target_ul_sinr)
{
dl_cqi_rx = false;
dl_cqi = (ue_cc_idx == 0) ? cell_params->cfg.initial_dl_cqi : 0;
@ -1530,8 +1512,9 @@ uint32_t cc_sched_ue::get_required_prb_ul(uint32_t req_bytes)
// find nof prbs that lead to a tbs just above req_bytes
int target_tbs = req_bytes + 4;
std::tuple<uint32_t, int, uint32_t, int> ret = false_position_method(
1u, cell_params->nof_prb(), target_tbs, compute_tbs_approx, [](int y) { return y == SRSLTE_ERROR; });
uint32_t max_prbs = std::min(tpc_fsm.max_ul_prbs(), cell_params->nof_prb());
std::tuple<uint32_t, int, uint32_t, int> ret =
false_position_method(1u, max_prbs, target_tbs, compute_tbs_approx, [](int y) { return y == SRSLTE_ERROR; });
uint32_t req_prbs = std::get<2>(ret);
while (!srslte_dft_precoding_valid_prb(req_prbs) && req_prbs < cell_params->nof_prb()) {
req_prbs++;

@ -10,7 +10,7 @@
*
*/
#include "srsenb/hdr/stack/mac/sched_lch.h"
#include "srsenb/hdr/stack/mac/sched_ue_ctrl/sched_lch.h"
#include "srsenb/hdr/stack/mac/sched_common.h"
#include "srslte/common/log_helper.h"

@ -347,7 +347,8 @@ bool ue::process_ce(srslte::sch_subh* subh)
switch (subh->ul_sch_ce_type()) {
case srslte::ul_sch_lcid::PHR_REPORT:
phr = subh->get_phr();
sched->ul_phr(rnti, (int)phr);
// TODO: Add enb_cc_idx
sched->ul_phr(rnti, 0, (int)phr);
metrics_phr(phr);
break;
case srslte::ul_sch_lcid::CRNTI:
@ -585,4 +586,13 @@ void ue::metrics_cnt()
metrics.nof_tti++;
}
void ue::tic()
{
// Check for pending TA commands
uint32_t nof_ta_count = ta_fsm.tick();
if (nof_ta_count) {
sched->dl_mac_buffer_state(rnti, (uint32_t)srslte::dl_sch_lcid::TA_CMD, nof_ta_count);
}
}
} // namespace srsenb

@ -91,8 +91,8 @@ int ue_ctxt_test::new_tti(sched* sched_ptr, srslte::tti_point tti_rx)
for (auto& cc : active_ccs) {
sched_ptr->dl_cqi_info(
tti_rx.to_uint(), rnti, cc.enb_cc_idx, std::uniform_int_distribution<uint32_t>{5, 24}(get_rand_gen()));
sched_ptr->ul_cqi_info(
tti_rx.to_uint(), rnti, cc.enb_cc_idx, std::uniform_int_distribution<uint32_t>{5, 24}(get_rand_gen()), 0);
sched_ptr->ul_snr_info(
tti_rx.to_uint(), rnti, cc.enb_cc_idx, std::uniform_int_distribution<uint32_t>{5, 40}(get_rand_gen()), 0);
}
}

Loading…
Cancel
Save