move sched params and sched helper methods to sched_helpers.h/cc files. Removed place in the scheduler where the mcs is increased forcefully to avoid segmentation

This commit is contained in:
Francisco 2020-12-07 18:15:06 +00:00 committed by Andre Puschmann
parent 920e15c1a5
commit b4861bc59a
13 changed files with 365 additions and 413 deletions

View File

@ -26,28 +26,6 @@
namespace srsenb {
namespace sched_utils {
inline bool is_in_tti_interval(uint32_t tti, uint32_t tti1, uint32_t tti2)
{
tti %= 10240;
tti1 %= 10240;
tti2 %= 10240;
if (tti1 <= tti2) {
return tti >= tti1 and tti <= tti2;
}
return tti >= tti1 or tti <= tti2;
}
} // namespace sched_utils
/* Caution: User addition (ue_cfg) and removal (ue_rem) are not thread-safe
* Rest of operations are thread-safe
*
* The subclass sched_ue is thread-safe so that access to shared variables like buffer states
* from scheduler thread and other threads is protected for each individual user.
*/
class sched : public sched_interface
{
public:

View File

@ -35,7 +35,7 @@ struct sched_dci_cce_t {
uint32_t nof_loc[4]; ///< Number of possible CCE locations for each aggregation level index
};
//! structs to bundle together all the sched arguments, and share them with all the sched sub-components
/// structs to bundle together all the sched arguments, and share them with all the sched sub-components
class sched_cell_params_t
{
struct regs_deleter {
@ -86,47 +86,6 @@ struct prb_interval : public srslte::interval<uint32_t> {
static prb_interval riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs = -1);
};
/***********************
* Helper Functions
**********************/
namespace sched_utils {
inline uint32_t aggr_level(uint32_t aggr_idx)
{
return 1u << aggr_idx;
}
//! Obtain rvidx from nof retxs. This value is stored in DCI
inline uint32_t get_rvidx(uint32_t retx_idx)
{
const static uint32_t rv_idx[4] = {0, 2, 3, 1};
return rv_idx[retx_idx % 4];
}
//! Obtain nof retxs from rvidx.
inline uint32_t get_nof_retx(uint32_t rv_idx)
{
const static uint32_t nof_retxs[4] = {0, 3, 1, 2};
return nof_retxs[rv_idx % 4];
}
/**
* Generate possible CCE locations a user can use to allocate DCIs
* @param regs Regs data for the given cell configuration
* @param location Result of the CCE location computation.
* @param cfi Number of control symbols used for the PDCCH
* @param sf_idx subframe index specific to the tx TTI (relevant only for data and RAR transmissions)
* @param rnti identity of the user (invalid RNTI for RAR and BC transmissions)
*/
void generate_cce_location(srslte_regs_t* regs,
sched_dci_cce_t* location,
uint32_t cfi,
uint32_t sf_idx = 0,
uint16_t rnti = SRSLTE_INVALID_RNTI);
} // namespace sched_utils
} // namespace srsenb
#endif // SRSLTE_SCHED_COMMON_H

View File

@ -0,0 +1,59 @@
/**
*
* \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_SCHED_HELPERS_H
#define SRSLTE_SCHED_HELPERS_H
#include "srsenb/hdr/stack/mac/sched_common.h"
#include "srslte/common/logmap.h"
#include "srslte/interfaces/sched_interface.h"
namespace srsenb {
inline uint32_t aggr_level(uint32_t aggr_idx)
{
return 1u << aggr_idx;
}
/// Obtain rvidx from nof retxs. This value is stored in DCI
inline uint32_t get_rvidx(uint32_t retx_idx)
{
const static uint32_t rv_idx[4] = {0, 2, 3, 1};
return rv_idx[retx_idx % 4];
}
/// Obtain nof retxs from rvidx.
inline uint32_t get_nof_retx(uint32_t rv_idx)
{
const static uint32_t nof_retxs[4] = {0, 3, 1, 2};
return nof_retxs[rv_idx % 4];
}
void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result);
/**
* Generate possible CCE locations a user can use to allocate DCIs
* @param regs Regs data for the given cell configuration
* @param location Result of the CCE location computation.
* @param cfi Number of control symbols used for the PDCCH
* @param sf_idx subframe index specific to the tx TTI (relevant only for data and RAR transmissions)
* @param rnti identity of the user (invalid RNTI for RAR and BC transmissions)
*/
void generate_cce_location(srslte_regs_t* regs,
sched_dci_cce_t* location,
uint32_t cfi,
uint32_t sf_idx = 0,
uint16_t rnti = SRSLTE_INVALID_RNTI);
} // namespace srsenb
#endif // SRSLTE_SCHED_HELPERS_H

View File

@ -1,25 +0,0 @@
/**
*
* \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_SCHED_INTERFACE_HELPERS_H
#define SRSLTE_SCHED_INTERFACE_HELPERS_H
#include "srslte/common/logmap.h"
#include "srslte/interfaces/sched_interface.h"
namespace srsenb {
void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result);
}
#endif // SRSLTE_SCHED_INTERFACE_HELPERS_H

View File

@ -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_ue_ctrl/sched_lch.cc sched_interface_helpers.cc)
sched_ue_ctrl/sched_lch.cc sched_helpers.cc)
add_library(srsenb_mac STATIC ${SOURCES} $<TARGET_OBJECTS:mac_schedulers>)
if(ENABLE_5GNR)

View File

@ -15,6 +15,7 @@
#include "srsenb/hdr/stack/mac/sched.h"
#include "srsenb/hdr/stack/mac/sched_carrier.h"
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srslte/common/logmap.h"
#include "srslte/srslte.h"
@ -25,103 +26,6 @@ using srslte::tti_point;
namespace srsenb {
namespace sched_utils {
uint32_t tti_subtract(uint32_t tti1, uint32_t tti2)
{
return TTI_SUB(tti1, tti2);
}
uint32_t max_tti(uint32_t tti1, uint32_t tti2)
{
return ((tti1 - tti2) > 10240 / 2) ? SRSLTE_MIN(tti1, tti2) : SRSLTE_MAX(tti1, tti2);
}
} // namespace sched_utils
/*******************************************************
* Sched Params
*******************************************************/
bool sched_cell_params_t::set_cfg(uint32_t enb_cc_idx_,
const sched_interface::cell_cfg_t& cfg_,
const sched_interface::sched_args_t& sched_args)
{
enb_cc_idx = enb_cc_idx_;
cfg = cfg_;
sched_cfg = &sched_args;
// Basic cell config checks
if (cfg.si_window_ms == 0) {
Error("SCHED: Invalid si-window length 0 ms\n");
return false;
}
bool invalid_prach;
if (cfg.cell.nof_prb == 6) {
// PUCCH has to allow space for Msg3
if (cfg.nrb_pucch > 1) {
Console("Invalid PUCCH configuration: nrb_pucch=%d does not allow space for Msg3 transmission..\n",
cfg.nrb_pucch);
return false;
}
// PRACH has to fit within the PUSCH+PUCCH space
invalid_prach = cfg.prach_freq_offset + 6 > cfg.cell.nof_prb;
} else {
// PRACH has to fit within the PUSCH space
invalid_prach = (cfg.prach_freq_offset + 6) > (cfg.cell.nof_prb - cfg.nrb_pucch) or
((int)cfg.prach_freq_offset < cfg.nrb_pucch);
}
if (invalid_prach) {
Error("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset);
Console("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset);
return false;
}
// Set derived sched parameters
// init regs
regs.reset(new srslte_regs_t{});
if (srslte_regs_init(regs.get(), cfg.cell) != SRSLTE_SUCCESS) {
Error("Getting DCI locations\n");
return false;
}
// Compute Common locations for DCI for each CFI
for (uint32_t cfix = 0; cfix < pdcch_grid_t::MAX_CFI; cfix++) {
sched_utils::generate_cce_location(regs.get(), &common_locations[cfix], cfix + 1);
}
if (common_locations[sched_cfg->max_nof_ctrl_symbols - 1].nof_loc[2] == 0) {
Error("SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n",
sched_cfg->max_nof_ctrl_symbols);
Console("SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n",
sched_cfg->max_nof_ctrl_symbols);
return false;
}
// Compute UE locations for RA-RNTI
for (uint32_t cfi = 0; cfi < 3; cfi++) {
for (uint32_t sf_idx = 0; sf_idx < 10; sf_idx++) {
sched_utils::generate_cce_location(regs.get(), &rar_locations[cfi][sf_idx], cfi + 1, sf_idx);
}
}
// precompute nof cces in PDCCH for each CFI
for (uint32_t cfix = 0; cfix < nof_cce_table.size(); ++cfix) {
int ret = srslte_regs_pdcch_ncce(regs.get(), cfix + 1);
if (ret < 0) {
Error("SCHED: Failed to calculate the number of CCEs in the PDCCH\n");
return false;
}
nof_cce_table[cfix] = (uint32_t)ret;
}
P = srslte_ra_type0_P(cfg.cell.nof_prb);
nof_rbgs = srslte::ceil_div(cfg.cell.nof_prb, P);
return true;
}
/*******************************************************
*
* Initialization and sched configuration functions
@ -470,87 +374,4 @@ int sched::ue_db_access(uint16_t rnti, Func f, const char* func_name)
return SRSLTE_SUCCESS;
}
/*******************************************************
*
* Helper functions and common data types
*
*******************************************************/
void sched_cell_params_t::regs_deleter::operator()(srslte_regs_t* p)
{
if (p != nullptr) {
srslte_regs_free(p);
delete p;
}
}
rbg_interval rbg_interval::prbs_to_rbgs(const prb_interval& prbs, uint32_t P)
{
return rbg_interval{srslte::ceil_div(prbs.start(), P), srslte::ceil_div(prbs.stop(), P)};
}
prb_interval prb_interval::rbgs_to_prbs(const rbg_interval& rbgs, uint32_t P)
{
return prb_interval{rbgs.start() * P, rbgs.stop() * P};
}
rbg_interval rbg_interval::rbgmask_to_rbgs(const rbgmask_t& mask)
{
int rb_start = -1;
for (uint32_t i = 0; i < mask.size(); i++) {
if (rb_start == -1) {
if (mask.test(i)) {
rb_start = i;
}
} else {
if (!mask.test(i)) {
return rbg_interval(rb_start, i);
}
}
}
if (rb_start != -1) {
return rbg_interval(rb_start, mask.size());
} else {
return rbg_interval();
}
}
prb_interval prb_interval::riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs)
{
if (nof_vrbs < 0) {
nof_vrbs = nof_prbs;
}
uint32_t rb_start, l_crb;
srslte_ra_type2_from_riv(riv, &l_crb, &rb_start, nof_prbs, (uint32_t)nof_vrbs);
return {rb_start, rb_start + l_crb};
}
namespace sched_utils {
void generate_cce_location(srslte_regs_t* regs_,
sched_dci_cce_t* location,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti)
{
*location = {};
srslte_dci_location_t loc[64];
uint32_t nloc = 0;
if (rnti == 0) {
nloc = srslte_pdcch_common_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64);
} else {
nloc = srslte_pdcch_ue_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64, sf_idx, rnti);
}
// Save to different format
for (uint32_t i = 0; i < nloc; i++) {
uint32_t l = loc[i].L;
location->cce_start[l][location->nof_loc[l]] = loc[i].ncce;
location->nof_loc[l]++;
}
}
} // namespace sched_utils
} // namespace srsenb

View File

@ -11,7 +11,7 @@
*/
#include "srsenb/hdr/stack/mac/sched_carrier.h"
#include "srsenb/hdr/stack/mac/sched_interface_helpers.h"
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srsenb/hdr/stack/mac/schedulers/sched_time_pf.h"
#include "srsenb/hdr/stack/mac/schedulers/sched_time_rr.h"
#include "srslte/common/logmap.h"

View File

@ -12,9 +12,9 @@
#include "srsenb/hdr/stack/mac/sched_grid.h"
#include "srsenb/hdr/stack/mac/sched.h"
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srslte/common/log_helper.h"
#include "srslte/common/logmap.h"
#include <srslte/interfaces/sched_interface.h>
using srslte::tti_point;
@ -649,7 +649,7 @@ sf_sched::ctrl_code_t sf_sched::alloc_dl_ctrl(uint32_t aggr_lvl, uint32_t tbs_by
alloc_outcome_t sf_sched::alloc_bc(uint32_t aggr_lvl, uint32_t sib_idx, uint32_t sib_ntx)
{
uint32_t sib_len = cc_cfg->cfg.sibs[sib_idx].len;
uint32_t rv = sched_utils::get_rvidx(sib_ntx);
uint32_t rv = get_rvidx(sib_ntx);
ctrl_code_t ret = alloc_dl_ctrl(aggr_lvl, sib_len, SRSLTE_SIRNTI);
if (not ret.first) {
Warning("SCHED: Could not allocate SIB=%d, L=%d, len=%d, cause=%s\n",

View File

@ -0,0 +1,283 @@
/**
*
* \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.
*
*/
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srslte/mac/pdu.h"
#include "srslte/srslog/bundled/fmt/format.h"
#include <array>
#define Info(fmt, ...) srslte::logmap::get("MAC")->error(fmt, ##__VA_ARGS__)
#define Error(fmt, ...) srslte::logmap::get("MAC")->error(fmt, ##__VA_ARGS__)
namespace srsenb {
using dl_sched_res_t = sched_interface::dl_sched_res_t;
using dl_sched_data_t = sched_interface::dl_sched_data_t;
using custom_mem_buffer = fmt::basic_memory_buffer<char, 1024>;
const char* to_string_short(srslte_dci_format_t dcifmt)
{
switch (dcifmt) {
case SRSLTE_DCI_FORMAT0:
return "0";
case SRSLTE_DCI_FORMAT1:
return "1";
case SRSLTE_DCI_FORMAT1A:
return "1A";
case SRSLTE_DCI_FORMAT1B:
return "1B";
case SRSLTE_DCI_FORMAT2:
return "2";
case SRSLTE_DCI_FORMAT2A:
return "2A";
case SRSLTE_DCI_FORMAT2B:
return "2B";
default:
return "unknown";
}
}
void fill_dl_cc_result_info(custom_mem_buffer& strbuf, const dl_sched_data_t& data)
{
uint32_t first_ce = sched_interface::MAX_RLC_PDU_LIST;
for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) {
if (srslte::is_mac_ce(static_cast<srslte::dl_sch_lcid>(data.pdu[i]->lcid))) {
first_ce = i;
break;
}
}
if (first_ce == sched_interface::MAX_RLC_PDU_LIST) {
return;
}
const char* prefix = strbuf.size() > 0 ? " | " : "";
fmt::format_to(strbuf, "{}rnti={:0x}: [", prefix, data.dci.rnti);
bool ces_found = false;
for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) {
const auto& pdu = data.pdu[0][i];
prefix = (ces_found) ? " | " : "";
srslte::dl_sch_lcid lcid = static_cast<srslte::dl_sch_lcid>(pdu.lcid);
if (srslte::is_mac_ce(lcid)) {
fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid));
ces_found = true;
}
}
fmt::format_to(strbuf, "]");
}
void fill_dl_cc_result_debug(custom_mem_buffer& strbuf, const dl_sched_data_t& data)
{
if (data.nof_pdu_elems[0] == 0 and data.nof_pdu_elems[1] == 0) {
return;
}
fmt::format_to(strbuf,
" > rnti={:0x}, tbs={}, f={}, mcs={}: [",
data.dci.rnti,
data.tbs[0],
to_string_short(data.dci.format),
data.dci.tb[0].mcs_idx);
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; ++tb) {
for (uint32_t i = 0; i < data.nof_pdu_elems[tb]; ++i) {
const auto& pdu = data.pdu[tb][i];
const char* prefix = (i == 0) ? "" : " | ";
srslte::dl_sch_lcid lcid = static_cast<srslte::dl_sch_lcid>(pdu.lcid);
if (srslte::is_mac_ce(lcid)) {
fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid));
} else {
fmt::format_to(strbuf, "{}MAC SDU lcid={}, tb={}, len={} B", prefix, pdu.lcid, tb, pdu.nbytes);
}
}
}
fmt::format_to(strbuf, "]\n");
}
void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result)
{
if (log_h->get_level() < srslte::LOG_LEVEL_INFO) {
return;
}
custom_mem_buffer strbuf;
for (uint32_t i = 0; i < result.nof_data_elems; ++i) {
const dl_sched_data_t& data = result.data[i];
if (log_h->get_level() == srslte::LOG_LEVEL_INFO) {
fill_dl_cc_result_info(strbuf, data);
} else if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) {
fill_dl_cc_result_debug(strbuf, data);
}
}
if (strbuf.size() != 0) {
if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) {
log_h->debug("SCHED: MAC LCID allocs cc=%d:\n%s", enb_cc_idx, fmt::to_string(strbuf).c_str());
} else {
log_h->info("SCHED: MAC CE allocs cc=%d: %s", enb_cc_idx, fmt::to_string(strbuf).c_str());
}
}
}
rbg_interval rbg_interval::prbs_to_rbgs(const prb_interval& prbs, uint32_t P)
{
return rbg_interval{srslte::ceil_div(prbs.start(), P), srslte::ceil_div(prbs.stop(), P)};
}
prb_interval prb_interval::rbgs_to_prbs(const rbg_interval& rbgs, uint32_t P)
{
return prb_interval{rbgs.start() * P, rbgs.stop() * P};
}
rbg_interval rbg_interval::rbgmask_to_rbgs(const rbgmask_t& mask)
{
int rb_start = -1;
for (uint32_t i = 0; i < mask.size(); i++) {
if (rb_start == -1) {
if (mask.test(i)) {
rb_start = i;
}
} else {
if (!mask.test(i)) {
return rbg_interval(rb_start, i);
}
}
}
if (rb_start != -1) {
return rbg_interval(rb_start, mask.size());
} else {
return rbg_interval();
}
}
prb_interval prb_interval::riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs)
{
if (nof_vrbs < 0) {
nof_vrbs = nof_prbs;
}
uint32_t rb_start, l_crb;
srslte_ra_type2_from_riv(riv, &l_crb, &rb_start, nof_prbs, (uint32_t)nof_vrbs);
return {rb_start, rb_start + l_crb};
}
/*******************************************************
* Sched Params
*******************************************************/
void sched_cell_params_t::regs_deleter::operator()(srslte_regs_t* p)
{
if (p != nullptr) {
srslte_regs_free(p);
delete p;
}
}
bool sched_cell_params_t::set_cfg(uint32_t enb_cc_idx_,
const sched_interface::cell_cfg_t& cfg_,
const sched_interface::sched_args_t& sched_args)
{
enb_cc_idx = enb_cc_idx_;
cfg = cfg_;
sched_cfg = &sched_args;
// Basic cell config checks
if (cfg.si_window_ms == 0) {
Error("SCHED: Invalid si-window length 0 ms\n");
return false;
}
bool invalid_prach;
if (cfg.cell.nof_prb == 6) {
// PUCCH has to allow space for Msg3
if (cfg.nrb_pucch > 1) {
srslte::console("Invalid PUCCH configuration: nrb_pucch=%d does not allow space for Msg3 transmission..\n",
cfg.nrb_pucch);
return false;
}
// PRACH has to fit within the PUSCH+PUCCH space
invalid_prach = cfg.prach_freq_offset + 6 > cfg.cell.nof_prb;
} else {
// PRACH has to fit within the PUSCH space
invalid_prach = (cfg.prach_freq_offset + 6) > (cfg.cell.nof_prb - cfg.nrb_pucch) or
((int)cfg.prach_freq_offset < cfg.nrb_pucch);
}
if (invalid_prach) {
Error("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n", cfg.prach_freq_offset);
srslte::console("Invalid PRACH configuration: frequency offset=%d outside bandwidth limits\n",
cfg.prach_freq_offset);
return false;
}
// Set derived sched parameters
// init regs
regs.reset(new srslte_regs_t{});
if (srslte_regs_init(regs.get(), cfg.cell) != SRSLTE_SUCCESS) {
Error("Getting DCI locations\n");
return false;
}
// Compute Common locations for DCI for each CFI
for (uint32_t cfix = 0; cfix < SRSLTE_NOF_CFI; cfix++) {
generate_cce_location(regs.get(), &common_locations[cfix], cfix + 1);
}
if (common_locations[sched_cfg->max_nof_ctrl_symbols - 1].nof_loc[2] == 0) {
Error("SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n",
sched_cfg->max_nof_ctrl_symbols);
srslte::console(
"SCHED: Current cfi=%d is not valid for broadcast (check scheduler.max_nof_ctrl_symbols in conf file).\n",
sched_cfg->max_nof_ctrl_symbols);
return false;
}
// Compute UE locations for RA-RNTI
for (uint32_t cfi = 0; cfi < 3; cfi++) {
for (uint32_t sf_idx = 0; sf_idx < 10; sf_idx++) {
generate_cce_location(regs.get(), &rar_locations[cfi][sf_idx], cfi + 1, sf_idx);
}
}
// precompute nof cces in PDCCH for each CFI
for (uint32_t cfix = 0; cfix < nof_cce_table.size(); ++cfix) {
int ret = srslte_regs_pdcch_ncce(regs.get(), cfix + 1);
if (ret < 0) {
Error("SCHED: Failed to calculate the number of CCEs in the PDCCH\n");
return false;
}
nof_cce_table[cfix] = (uint32_t)ret;
}
P = srslte_ra_type0_P(cfg.cell.nof_prb);
nof_rbgs = srslte::ceil_div(cfg.cell.nof_prb, P);
return true;
}
void generate_cce_location(srslte_regs_t* regs_,
sched_dci_cce_t* location,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti)
{
*location = {};
srslte_dci_location_t loc[64];
uint32_t nloc = 0;
if (rnti == 0) {
nloc = srslte_pdcch_common_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64);
} else {
nloc = srslte_pdcch_ue_locations_ncce(srslte_regs_pdcch_ncce(regs_, cfi), loc, 64, sf_idx, rnti);
}
// Save to different format
for (uint32_t i = 0; i < nloc; i++) {
uint32_t l = loc[i].L;
location->cce_start[l][location->nof_loc[l]] = loc[i].ncce;
location->nof_loc[l]++;
}
}
} // namespace srsenb

View File

@ -1,122 +0,0 @@
/**
*
* \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.
*
*/
#include "srsenb/hdr/stack/mac/sched_interface_helpers.h"
#include "srslte/mac/pdu.h"
#include "srslte/srslog/bundled/fmt/format.h"
#include <array>
namespace srsenb {
using dl_sched_res_t = sched_interface::dl_sched_res_t;
using dl_sched_data_t = sched_interface::dl_sched_data_t;
using custom_mem_buffer = fmt::basic_memory_buffer<char, 1024>;
const char* to_string_short(srslte_dci_format_t dcifmt)
{
switch (dcifmt) {
case SRSLTE_DCI_FORMAT0:
return "0";
case SRSLTE_DCI_FORMAT1:
return "1";
case SRSLTE_DCI_FORMAT1A:
return "1A";
case SRSLTE_DCI_FORMAT1B:
return "1B";
case SRSLTE_DCI_FORMAT2:
return "2";
case SRSLTE_DCI_FORMAT2A:
return "2A";
case SRSLTE_DCI_FORMAT2B:
return "2B";
default:
return "unknown";
}
}
void fill_dl_cc_result_info(custom_mem_buffer& strbuf, const dl_sched_data_t& data)
{
uint32_t first_ce = sched_interface::MAX_RLC_PDU_LIST;
for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) {
if (srslte::is_mac_ce(static_cast<srslte::dl_sch_lcid>(data.pdu[i]->lcid))) {
first_ce = i;
break;
}
}
if (first_ce == sched_interface::MAX_RLC_PDU_LIST) {
return;
}
const char* prefix = strbuf.size() > 0 ? " | " : "";
fmt::format_to(strbuf, "{}rnti={:0x}: [", prefix, data.dci.rnti);
bool ces_found = false;
for (uint32_t i = 0; i < data.nof_pdu_elems[0]; ++i) {
const auto& pdu = data.pdu[0][i];
prefix = (ces_found) ? " | " : "";
srslte::dl_sch_lcid lcid = static_cast<srslte::dl_sch_lcid>(pdu.lcid);
if (srslte::is_mac_ce(lcid)) {
fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid));
ces_found = true;
}
}
fmt::format_to(strbuf, "]");
}
void fill_dl_cc_result_debug(custom_mem_buffer& strbuf, const dl_sched_data_t& data)
{
if (data.nof_pdu_elems[0] == 0 and data.nof_pdu_elems[1] == 0) {
return;
}
fmt::format_to(strbuf,
" > rnti={:0x}, tbs={}, f={}, mcs={}: [",
data.dci.rnti,
data.tbs[0],
to_string_short(data.dci.format),
data.dci.tb[0].mcs_idx);
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; ++tb) {
for (uint32_t i = 0; i < data.nof_pdu_elems[tb]; ++i) {
const auto& pdu = data.pdu[tb][i];
const char* prefix = (i == 0) ? "" : " | ";
srslte::dl_sch_lcid lcid = static_cast<srslte::dl_sch_lcid>(pdu.lcid);
if (srslte::is_mac_ce(lcid)) {
fmt::format_to(strbuf, "{}MAC CE \"{}\"", prefix, srslte::to_string_short(lcid));
} else {
fmt::format_to(strbuf, "{}MAC SDU lcid={}, tb={}, len={} B", prefix, pdu.lcid, tb, pdu.nbytes);
}
}
}
fmt::format_to(strbuf, "]\n");
}
void log_dl_cc_results(srslte::log_ref log_h, uint32_t enb_cc_idx, const sched_interface::dl_sched_res_t& result)
{
if (log_h->get_level() < srslte::LOG_LEVEL_INFO) {
return;
}
custom_mem_buffer strbuf;
for (uint32_t i = 0; i < result.nof_data_elems; ++i) {
const dl_sched_data_t& data = result.data[i];
if (log_h->get_level() == srslte::LOG_LEVEL_INFO) {
fill_dl_cc_result_info(strbuf, data);
} else if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) {
fill_dl_cc_result_debug(strbuf, data);
}
}
if (strbuf.size() != 0) {
if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) {
log_h->debug("SCHED: MAC LCID allocs cc=%d:\n%s", enb_cc_idx, fmt::to_string(strbuf).c_str());
} else {
log_h->info("SCHED: MAC CE allocs cc=%d: %s", enb_cc_idx, fmt::to_string(strbuf).c_str());
}
}
}
} // namespace srsenb

View File

@ -13,6 +13,7 @@
#include <string.h>
#include "srsenb/hdr/stack/mac/sched.h"
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srsenb/hdr/stack/mac/sched_ue.h"
#include "srslte/common/log_helper.h"
#include "srslte/common/logmap.h"
@ -31,7 +32,7 @@ namespace srsenb {
namespace sched_utils {
//! Obtains TB size *in bytes* for a given MCS and N_{PRB}
/// Obtains TB size *in bytes* for a given MCS and nof allocated prbs
uint32_t get_tbs_bytes(uint32_t mcs, uint32_t nof_alloc_prb, bool use_tbs_index_alt, bool is_ul)
{
int tbs_idx = srslte_ra_tbs_idx_from_mcs(mcs, use_tbs_index_alt, is_ul);
@ -574,7 +575,7 @@ int sched_ue::generate_format1(uint32_t pid,
SRSLTE_MIN(sched_utils::count_prb_per_tb(*carriers[ue_cc_idx].get_cell_cfg(), user_mask), cell.nof_prb);
uint32_t RB_start = prb_int.start();
dci->type2_alloc.riv = srslte_ra_type2_to_riv(L_crb, RB_start, cell.nof_prb);
dci->format = SRSLTE_DCI_FORMAT1A;
dci->format = SRSLTE_DCI_FORMAT1A;
if (prb_int.length() != P * user_mask.count()) {
// This happens if Type0 was using distributed allocation
Warning("SCHED: Can't use distributed RA due to DCI size ambiguity\n");
@ -599,7 +600,7 @@ int sched_ue::generate_format1(uint32_t pid,
dci->pid = h->get_id();
dci->ue_cc_idx = ue_cc_idx;
dci->tb[0].mcs_idx = (uint32_t)mcs;
dci->tb[0].rv = sched_utils::get_rvidx(h->nof_retx(0));
dci->tb[0].rv = get_rvidx(h->nof_retx(0));
dci->tb[0].ndi = h->get_ndi(0);
dci->tpc_pucch = carriers[ue_cc_idx].tpc_fsm.encode_pucch_tpc();
@ -647,11 +648,8 @@ std::pair<int, int> sched_ue::compute_mcs_and_tbs(uint32_t ue_cc_i
(uint32_t)carriers[ue_cc_idx].fixed_mcs_dl, nof_alloc_prbs, cfg.use_tbs_index_alt, false);
}
// If the number of prbs is not sufficient to fit minimum required bytes, increase the mcs
// NOTE: this may happen during ConRes CE tx when DL-CQI is still not available
while (tbs_bytes > 0 and (uint32_t) tbs_bytes < req_bytes.start() and mcs < 28) {
mcs++;
tbs_bytes = sched_utils::get_tbs_bytes((uint32_t)mcs, nof_alloc_prbs, cfg.use_tbs_index_alt, false);
if (tbs_bytes > 0 and (uint32_t) tbs_bytes < req_bytes.start() and mcs < 28) {
log_h->warning("SCHED: Could not get PRB allocation that avoids MAC CE or RLC SBR0 PDU segmentation\n");
}
return {mcs, tbs_bytes};
@ -712,7 +710,7 @@ int sched_ue::generate_format2a(uint32_t pid,
/* Fill DCI TB dedicated fields */
if (tbs > 0 && tb_en[tb]) {
dci->tb[tb].mcs_idx = (uint32_t)mcs;
dci->tb[tb].rv = sched_utils::get_rvidx(h->nof_retx(tb));
dci->tb[tb].rv = get_rvidx(h->nof_retx(tb));
if (!SRSLTE_DCI_IS_TB_EN(dci->tb[tb])) {
dci->tb[tb].rv = 2;
}
@ -855,7 +853,7 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data,
alloc.set(alloc.start(), alloc.start() + 4);
}
} else if (tbs > 0) {
dci->tb.rv = sched_utils::get_rvidx(h->nof_retx(0));
dci->tb.rv = get_rvidx(h->nof_retx(0));
if (!is_newtx && data->needs_pdcch) {
dci->tb.mcs_idx = 28 + dci->tb.rv;
} else {
@ -1330,7 +1328,7 @@ cc_sched_ue::cc_sched_ue(const sched_interface::ue_cfg_t& cfg_,
// Generate allowed CCE locations
for (int cfi = 0; cfi < 3; cfi++) {
for (int sf_idx = 0; sf_idx < 10; sf_idx++) {
sched_utils::generate_cce_location(cell_params->regs.get(), &dci_locations[cfi][sf_idx], cfi + 1, sf_idx, rnti);
generate_cce_location(cell_params->regs.get(), &dci_locations[cfi][sf_idx], cfi + 1, sf_idx, rnti);
}
}
}

View File

@ -12,6 +12,7 @@
#include "sched_test_common.h"
#include "srsenb/hdr/stack/mac/sched.h"
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srsenb/hdr/stack/upper/common_enb.h"
#include "srslte/mac/pdu.h"
@ -211,7 +212,7 @@ int ue_ctxt_test::schedule_acks(cc_result result)
ack_data.tb = 0;
ack_data.pid = data.dci.pid;
ack_data.ue_cc_idx = data.dci.ue_cc_idx;
uint32_t nof_retx = sched_utils::get_nof_retx(data.dci.tb[0].rv); // 0..3
uint32_t nof_retx = srsenb::get_nof_retx(data.dci.tb[0].rv); // 0..3
ack_data.ack = randf() < sim_cfg.prob_dl_ack_mask[nof_retx % sim_cfg.prob_dl_ack_mask.size()];
pending_dl_acks.push(ack_data);
@ -230,7 +231,7 @@ int ue_ctxt_test::schedule_acks(cc_result result)
ack_data.ue_cc_idx = pusch.dci.ue_cc_idx;
ack_data.tb = 0;
ack_data.pid = to_tx_ul(current_tti_rx).to_uint() % (FDD_HARQ_DELAY_DL_MS + FDD_HARQ_DELAY_UL_MS);
uint32_t nof_retx = sched_utils::get_nof_retx(pusch.dci.tb.rv); // 0..3
uint32_t nof_retx = srsenb::get_nof_retx(pusch.dci.tb.rv); // 0..3
ack_data.ack = randf() < sim_cfg.prob_ul_ack_mask[nof_retx % sim_cfg.prob_ul_ack_mask.size()];
pending_ul_acks.push(ack_data);

View File

@ -12,6 +12,7 @@
#include "sched_ue_ded_test_suite.h"
#include "lib/include/srslte/mac/pdu.h"
#include "srsenb/hdr/stack/mac/sched_helpers.h"
#include "srslte/common/test_common.h"
namespace srsenb {
@ -72,14 +73,14 @@ int test_pdsch_grant(const sim_enb_ctxt_t& enb_ctxt,
// TEST: DCI is consistent with current UE DL harq state
auto& h = ue_ctxt.cc_list[pdsch.dci.ue_cc_idx].dl_harqs[pdsch.dci.pid];
uint32_t nof_retx = sched_utils::get_nof_retx(pdsch.dci.tb[0].rv); // 0..3
uint32_t nof_retx = get_nof_retx(pdsch.dci.tb[0].rv); // 0..3
if (h.nof_txs == 0 or h.ndi != pdsch.dci.tb[0].ndi) {
// It is newtx
CONDERROR(nof_retx != 0, "Invalid rv index for new tx\n");
CONDERROR(h.active, "DL newtx for already active DL harq pid=%d\n", h.pid);
} else {
// it is retx
CONDERROR(sched_utils::get_rvidx(h.nof_retxs + 1) != (uint32_t)pdsch.dci.tb[0].rv, "Invalid rv index for retx\n");
CONDERROR(get_rvidx(h.nof_retxs + 1) != (uint32_t)pdsch.dci.tb[0].rv, "Invalid rv index for retx\n");
CONDERROR(not h.active, "retx for inactive dl harq pid=%d\n", h.pid);
CONDERROR(to_tx_dl_ack(h.last_tti_rx) > tti_rx, "harq pid=%d reused too soon\n", h.pid);
CONDERROR(h.nof_retxs + 1 > ue_ctxt.ue_cfg.maxharq_tx,
@ -184,7 +185,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t&
CONDERROR(pusch_ptr->dci.ue_cc_idx != (uint32_t)ue_cc_idx, "Inconsistent enb_cc_idx -> ue_cc_idx mapping\n");
// TEST: DCI is consistent with current UE UL harq state
uint32_t nof_retx = sched_utils::get_nof_retx(pusch_ptr->dci.tb.rv); // 0..3
uint32_t nof_retx = get_nof_retx(pusch_ptr->dci.tb.rv); // 0..3
if (h.nof_txs == 0 or h.ndi != pusch_ptr->dci.tb.ndi) {
// newtx
@ -204,8 +205,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t&
CONDERROR(pusch_ptr->dci.type2_alloc.riv != h.riv, "Non-adaptive retx must keep the same riv\n");
}
}
CONDERROR(sched_utils::get_rvidx(h.nof_retxs + 1) != (uint32_t)pusch_ptr->dci.tb.rv,
"Invalid rv index for retx\n");
CONDERROR(get_rvidx(h.nof_retxs + 1) != (uint32_t)pusch_ptr->dci.tb.rv, "Invalid rv index for retx\n");
CONDERROR(h.tbs != pusch_ptr->tbs, "TBS changed during HARQ retx\n");
CONDERROR(to_tx_ul(h.last_tti_rx) > sf_out.tti_rx, "UL harq pid=%d was reused too soon\n", h.pid);
}