changed interval interface to disallow interval::stop < interval::start via an assertion

master
Francisco Paisana 4 years ago
parent 39b380c8e0
commit 8b174ce2f4

@ -22,6 +22,7 @@
#ifndef SRSLTE_INTERVAL_H
#define SRSLTE_INTERVAL_H
#include <cassert>
#include <string>
#include <type_traits>
@ -37,45 +38,71 @@ class interval
#endif
public:
T start;
T stop;
interval() : start_(T{}), stop_(T{}) {}
interval(T start_point, T stop_point) : start_(start_point), stop_(stop_point) { assert(start_ <= stop_); }
interval() : start(T{}), stop(T{}) {}
interval(T start_, T stop_) : start(start_), stop(stop_) {}
T start() const { return start_; }
T stop() const { return stop_; }
bool empty() const { return stop <= start; }
bool empty() const { return stop_ == start_; }
T length() const { return stop > start ? stop - start : 0; }
T length() const { return stop_ - start_; }
void set_length(T len) { stop = start + len; }
void inc_length(int n)
{
stop_ += n;
assert(stop_ >= start_);
}
void set_length(T len)
{
assert(len >= 0);
stop_ = start_ + len;
}
void set_start(T start_point)
{
assert(start_point <= stop_);
start_ = start_point;
}
void set_stop(T stop_point)
{
assert(start_ <= stop_point);
stop_ = stop_point;
}
void displace_by(int offset)
{
start += offset;
stop += offset;
start_ += offset;
stop_ += offset;
}
void displace_to(T start_point)
{
stop = start_point + length();
start = start_point;
stop_ = start_point + length();
start_ = start_point;
}
bool overlaps(interval other) const { return start < other.stop and other.start < stop; }
bool overlaps(interval other) const { return start_ < other.stop_ and other.start_ < stop_; }
bool contains(T point) const { return start <= point and point < stop; }
bool contains(T point) const { return start_ <= point and point < stop_; }
std::string to_string() const
{
std::string s = "[" + std::to_string(start) + "," + std::to_string(stop) + ")";
std::string s = "[" + std::to_string(start_) + "," + std::to_string(stop_) + ")";
return s;
}
private:
T start_;
T stop_;
};
template <typename T>
bool operator==(const interval<T>& lhs, const interval<T>& rhs)
{
return lhs.start == rhs.start and lhs.stop == rhs.stop;
return lhs.start() == rhs.start() and lhs.stop() == rhs.stop();
}
template <typename T>
@ -87,7 +114,7 @@ bool operator!=(const interval<T>& lhs, const interval<T>& rhs)
template <typename T>
bool operator<(const interval<T>& lhs, const interval<T>& rhs)
{
return lhs.start < rhs.start or (lhs.start == rhs.start and lhs.stop < rhs.stop);
return lhs.start() < rhs.start() or (lhs.start() == rhs.start() and lhs.stop() < rhs.stop());
}
//! Union of intervals
@ -97,7 +124,7 @@ interval<T> operator|(const interval<T>& lhs, const interval<T>& rhs)
if (not lhs.overlaps(rhs)) {
return interval<T>{};
}
return {std::min(lhs.start, rhs.start), std::max(lhs.stop, rhs.stop)};
return {std::min(lhs.start(), rhs.start()), std::max(lhs.stop(), rhs.stop())};
}
template <typename T>
@ -113,7 +140,7 @@ interval<T> operator&(const interval<T>& lhs, const interval<T>& rhs)
if (not lhs.overlaps(rhs)) {
return interval<T>{};
}
return interval<T>{std::max(lhs.start, rhs.start), std::min(lhs.stop, rhs.stop)};
return interval<T>{std::max(lhs.start(), rhs.start()), std::min(lhs.stop(), rhs.stop())};
}
template <typename T>

@ -26,9 +26,9 @@ int test_interval_init()
{
srslte::interval<int> I{}, I2{12, 15}, I3{12, 12};
TESTASSERT(I.empty() and I.start == 0 and I.stop == 0);
TESTASSERT(not I2.empty() and I2.start == 12 and I2.stop == 15);
TESTASSERT(I3.empty() and I3.start == 12 and I3.stop == 12);
TESTASSERT(I.empty() and I.start() == 0 and I.stop() == 0);
TESTASSERT(not I2.empty() and I2.start() == 12 and I2.stop() == 15);
TESTASSERT(I3.empty() and I3.start() == 12 and I3.stop() == 12);
return SRSLTE_SUCCESS;
}

@ -452,23 +452,22 @@ void sched_cell_params_t::regs_deleter::operator()(srslte_regs_t* 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.start, 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};
return prb_interval{rbgs.start() * P, rbgs.stop() * P};
}
prb_interval prb_interval::riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs)
{
prb_interval p;
if (nof_vrbs < 0) {
nof_vrbs = nof_prbs;
}
srslte_ra_type2_from_riv(riv, &p.stop, &p.start, nof_prbs, (uint32_t)nof_vrbs);
p.stop += p.start;
return p;
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 {

@ -444,9 +444,8 @@ alloc_outcome_t sf_grid_t::alloc_dl(uint32_t aggr_idx, alloc_type_t alloc_type,
//! Allocates CCEs and RBs for control allocs. It allocates RBs in a contiguous manner.
sf_grid_t::dl_ctrl_alloc_t sf_grid_t::alloc_dl_ctrl(uint32_t aggr_idx, alloc_type_t alloc_type)
{
rbg_interval range;
range.start = nof_rbgs - avail_rbg;
range.set_length((alloc_type == alloc_type_t::DL_RAR) ? rar_n_rbg : si_n_rbg);
rbg_interval range{nof_rbgs - avail_rbg,
nof_rbgs - avail_rbg + ((alloc_type == alloc_type_t::DL_RAR) ? rar_n_rbg : si_n_rbg)};
if (alloc_type != alloc_type_t::DL_RAR and alloc_type != alloc_type_t::DL_BC and
alloc_type != alloc_type_t::DL_PCCH) {
@ -454,13 +453,13 @@ sf_grid_t::dl_ctrl_alloc_t sf_grid_t::alloc_dl_ctrl(uint32_t aggr_idx, alloc_typ
return {alloc_outcome_t::ERROR, range};
}
// Setup range starting from left
if (range.stop > nof_rbgs) {
if (range.stop() > nof_rbgs) {
return {alloc_outcome_t::RB_COLLISION, range};
}
// allocate DCI and RBGs
rbgmask_t new_mask(dl_mask.size());
new_mask.fill(range.start, range.stop);
new_mask.fill(range.start(), range.stop());
return {alloc_dl(aggr_idx, alloc_type, new_mask), range};
}
@ -477,12 +476,12 @@ alloc_outcome_t sf_grid_t::alloc_dl_data(sched_ue* user, const rbgmask_t& user_m
alloc_outcome_t sf_grid_t::alloc_ul_data(sched_ue* user, prb_interval alloc, bool needs_pdcch)
{
if (alloc.stop > ul_mask.size()) {
if (alloc.stop() > ul_mask.size()) {
return alloc_outcome_t::ERROR;
}
prbmask_t newmask(ul_mask.size());
newmask.fill(alloc.start, alloc.stop);
newmask.fill(alloc.start(), alloc.stop());
if ((ul_mask & newmask).any()) {
return alloc_outcome_t::RB_COLLISION;
}
@ -539,12 +538,11 @@ bool sf_grid_t::find_ul_alloc(uint32_t L, prb_interval* alloc) const
alloc->displace_to(n);
}
if (not ul_mask.test(n)) {
alloc->stop++;
alloc->inc_length(1);
} else if (alloc->length() > 0) {
// avoid edges
if (n < 3) {
alloc->start = 0;
alloc->stop = 0;
*alloc = {};
} else {
break;
}
@ -556,7 +554,7 @@ bool sf_grid_t::find_ul_alloc(uint32_t L, prb_interval* alloc) const
// Make sure L is allowed by SC-FDMA modulation
while (!srslte_dft_precoding_valid_prb(alloc->length())) {
alloc->stop--;
alloc->inc_length(-1);
}
return alloc->length() == L;
}
@ -758,7 +756,7 @@ alloc_outcome_t sf_sched::alloc_dl_user(sched_ue* user, const rbgmask_t& user_ma
if (h.is_empty()) {
// It is newTx
rbg_interval r = user->get_required_dl_rbgs(ue_cc_idx);
if (r.start > user_mask.count()) {
if (r.start() > user_mask.count()) {
log_h->warning("The number of RBGs allocated to rnti=0x%x will force segmentation\n", user->get_rnti());
return alloc_outcome_t::NOF_RB_INVALID;
}
@ -890,8 +888,8 @@ void sf_sched::set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul
if (tbs <= (int)bc_alloc.req_bytes) {
log_h->warning("SCHED: Error SIB%d, rbgs=(%d,%d), dci=(%d,%d), len=%d\n",
bc_alloc.sib_idx + 1,
bc_alloc.rbg_range.start,
bc_alloc.rbg_range.stop,
bc_alloc.rbg_range.start(),
bc_alloc.rbg_range.stop(),
bc->dci.location.L,
bc->dci.location.ncce,
bc_alloc.req_bytes);
@ -905,8 +903,8 @@ void sf_sched::set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul
log_h->debug("SCHED: SIB%d, rbgs=(%d,%d), dci=(%d,%d), rv=%d, len=%d, period=%d, mcs=%d\n",
bc_alloc.sib_idx + 1,
bc_alloc.rbg_range.start,
bc_alloc.rbg_range.stop,
bc_alloc.rbg_range.start(),
bc_alloc.rbg_range.stop(),
bc->dci.location.L,
bc->dci.location.ncce,
bc_alloc.rv,
@ -1164,10 +1162,7 @@ void sf_sched::set_ul_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul
alloc_outcome_t sf_sched::alloc_msg3(sched_ue* user, const sched_interface::dl_sched_rar_grant_t& rargrant)
{
// Derive PRBs from allocated RAR grants
prb_interval msg3_alloc = {};
uint32_t L;
srslte_ra_type2_from_riv(rargrant.grant.rba, &L, &msg3_alloc.start, cc_cfg->nof_prb(), cc_cfg->nof_prb());
msg3_alloc.set_length(L);
prb_interval msg3_alloc = prb_interval::riv_to_prbs(rargrant.grant.rba, cc_cfg->nof_prb());
alloc_outcome_t ret = alloc_ul(user, msg3_alloc, sf_sched::ul_alloc_t::MSG3, rargrant.grant.trunc_mcs);
if (not ret) {
@ -1246,7 +1241,7 @@ int sf_sched::generate_format1a(prb_interval prb_range,
dci->alloc_type = SRSLTE_RA_ALLOC_TYPE2;
dci->type2_alloc.mode = srslte_ra_type2_t::SRSLTE_RA_TYPE2_LOC;
dci->type2_alloc.riv = srslte_ra_type2_to_riv(prb_range.length(), prb_range.start, cc_cfg->cfg.cell.nof_prb);
dci->type2_alloc.riv = srslte_ra_type2_to_riv(prb_range.length(), prb_range.start(), cc_cfg->cfg.cell.nof_prb);
dci->pid = 0;
dci->tb[0].mcs_idx = mcs;
dci->tb[0].rv = rv;

@ -132,9 +132,9 @@ dl_harq_proc* dl_metric_rr::allocate_user(sched_ue* user)
if (h != nullptr) {
// Allocate resources based on pending data
rbg_interval req_rbgs = user->get_required_dl_rbgs(cell_idx);
if (req_rbgs.start > 0) {
if (req_rbgs.stop() > 0) {
rbgmask_t newtx_mask(tti_alloc->get_dl_mask().size());
if (find_allocation(req_rbgs.start, req_rbgs.stop, &newtx_mask)) {
if (find_allocation(req_rbgs.start(), req_rbgs.stop(), &newtx_mask)) {
// some empty spaces were found
code = tti_alloc->alloc_dl_user(user, newtx_mask, h->get_id());
if (code == alloc_outcome_t::SUCCESS) {
@ -212,7 +212,7 @@ bool ul_metric_rr::find_allocation(uint32_t L, prb_interval* alloc)
alloc->displace_to(n);
}
if (not used_rb->test(n)) {
alloc->stop++;
alloc->inc_length(1);
} else if (alloc->length() > 0) {
// avoid edges
if (n < 3) {
@ -228,7 +228,7 @@ bool ul_metric_rr::find_allocation(uint32_t L, prb_interval* alloc)
// Make sure L is allowed by SC-FDMA modulation
while (!srslte_dft_precoding_valid_prb(alloc->length())) {
alloc->stop--;
alloc->inc_length(-1);
}
return alloc->length() == L;
}

@ -539,7 +539,7 @@ std::pair<int, int> sched_ue::compute_mcs_and_tbs(uint32_t ue_cc_i
// Use a higher MCS for the Msg4 to fit in the 6 PRB case
if (carriers[ue_cc_idx].fixed_mcs_dl < 0 or not carriers[ue_cc_idx].dl_cqi_rx) {
// Dynamic MCS
tbs_bytes = carriers[ue_cc_idx].alloc_tbs_dl(nof_alloc_prbs, nof_re, req_bytes.stop, &mcs);
tbs_bytes = carriers[ue_cc_idx].alloc_tbs_dl(nof_alloc_prbs, nof_re, req_bytes.stop(), &mcs);
} else {
// Fixed MCS
mcs = carriers[ue_cc_idx].fixed_mcs_dl;
@ -549,7 +549,7 @@ std::pair<int, int> sched_ue::compute_mcs_and_tbs(uint32_t ue_cc_i
// 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) {
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);
}
@ -722,7 +722,7 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data,
dci->rnti = rnti;
dci->format = SRSLTE_DCI_FORMAT0;
dci->ue_cc_idx = cc_idx;
dci->type2_alloc.riv = srslte_ra_type2_to_riv(alloc.length(), alloc.start, cell.nof_prb);
dci->type2_alloc.riv = srslte_ra_type2_to_riv(alloc.length(), alloc.start(), cell.nof_prb);
dci->tb.rv = sched_utils::get_rvidx(h->nof_retx(0));
if (!is_newtx && h->is_adaptive_retx()) {
dci->tb.mcs_idx = 28 + dci->tb.rv;
@ -801,17 +801,17 @@ rbg_interval sched_ue::get_required_dl_rbgs(uint32_t ue_cc_idx)
}
const auto* cellparams = carriers[ue_cc_idx].get_cell_cfg();
int pending_prbs =
carriers[ue_cc_idx].get_required_prb_dl(req_bytes.start, cellparams->sched_cfg->max_nof_ctrl_symbols);
carriers[ue_cc_idx].get_required_prb_dl(req_bytes.start(), cellparams->sched_cfg->max_nof_ctrl_symbols);
if (pending_prbs < 0) {
// Cannot fit allocation in given PRBs
log_h->error("SCHED: DL CQI=%d does now allow fitting %d non-segmentable DL tx bytes into the cell bandwidth. "
"Consider increasing initial CQI value.\n",
carriers[ue_cc_idx].dl_cqi,
req_bytes.start);
req_bytes.start());
return {cellparams->nof_prb(), cellparams->nof_prb()};
}
uint32_t min_pending_rbg = cellparams->prb_to_rbg(pending_prbs);
pending_prbs = carriers[ue_cc_idx].get_required_prb_dl(req_bytes.stop, cellparams->sched_cfg->max_nof_ctrl_symbols);
pending_prbs = carriers[ue_cc_idx].get_required_prb_dl(req_bytes.stop(), cellparams->sched_cfg->max_nof_ctrl_symbols);
pending_prbs = (pending_prbs < 0) ? cellparams->nof_prb() : pending_prbs;
uint32_t max_pending_rbg = cellparams->prb_to_rbg(pending_prbs);
return {min_pending_rbg, max_pending_rbg};

@ -65,15 +65,15 @@ int output_sched_tester::test_pusch_collisions(const tti_params_t&
ul_allocs.reset();
auto try_ul_fill = [&](prb_interval alloc, const char* ch_str, bool strict = true) {
CONDERROR(alloc.stop > nof_prb, "Allocated RBs %s out-of-bounds\n", alloc.to_string().c_str());
CONDERROR(alloc.stop() > nof_prb, "Allocated RBs %s out-of-bounds\n", alloc.to_string().c_str());
CONDERROR(alloc.empty(), "Allocations must have at least one PRB\n");
if (strict and ul_allocs.any(alloc.start, alloc.stop)) {
if (strict and ul_allocs.any(alloc.start(), alloc.stop())) {
TESTERROR("Collision Detected of %s alloc=%s and cumulative_mask=0x%s\n",
ch_str,
alloc.to_string().c_str(),
ul_allocs.to_hex().c_str());
}
ul_allocs.fill(alloc.start, alloc.stop, true);
ul_allocs.fill(alloc.start(), alloc.stop(), true);
return SRSLTE_SUCCESS;
};

Loading…
Cancel
Save