mirror of https://github.com/pvnis/srsRAN_4G.git
sched,nr: use PRBs instead of RBGs as the basic unit for PRB grants in the NR scheduler
parent
b81cbd1334
commit
d63ea00a5d
@ -0,0 +1,238 @@
|
||||
/**
|
||||
*
|
||||
* \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_NR_RB_H
|
||||
#define SRSRAN_SCHED_NR_RB_H
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h"
|
||||
#include "srsran/adt/bounded_bitset.h"
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
using prb_bitmap = srsran::bounded_bitset<SRSRAN_MAX_PRB_NR, true>;
|
||||
using rbg_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
|
||||
/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P
|
||||
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2);
|
||||
|
||||
/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs
|
||||
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2);
|
||||
|
||||
/// Struct to express a {min,...,max} range of PRBs
|
||||
struct prb_interval : public srsran::interval<uint32_t> {
|
||||
using interval::interval;
|
||||
};
|
||||
|
||||
struct prb_grant {
|
||||
prb_grant() = default;
|
||||
prb_grant(const prb_interval& other) noexcept : alloc_type_0(false), alloc(other) {}
|
||||
prb_grant(const rbg_bitmap& other) noexcept : alloc_type_0(true), alloc(other) {}
|
||||
prb_grant(const prb_grant& other) noexcept : alloc_type_0(other.alloc_type_0), alloc(other.alloc_type_0, other.alloc)
|
||||
{}
|
||||
prb_grant& operator=(const prb_grant& other) noexcept
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
if (other.alloc_type_0) {
|
||||
*this = other.rbgs();
|
||||
} else {
|
||||
*this = other.prbs();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
prb_grant& operator=(const prb_interval& prbs)
|
||||
{
|
||||
if (alloc_type_0) {
|
||||
alloc_type_0 = false;
|
||||
alloc.rbgs.~rbg_bitmap();
|
||||
new (&alloc.interv) prb_interval(prbs);
|
||||
} else {
|
||||
alloc.interv = alloc.interv;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
prb_grant& operator=(const rbg_bitmap& rbgs)
|
||||
{
|
||||
if (alloc_type_0) {
|
||||
alloc.rbgs = rbgs;
|
||||
} else {
|
||||
alloc_type_0 = true;
|
||||
alloc.interv.~prb_interval();
|
||||
new (&alloc.rbgs) rbg_bitmap(rbgs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~prb_grant()
|
||||
{
|
||||
if (is_alloc_type0()) {
|
||||
alloc.rbgs.~rbg_bitmap();
|
||||
} else {
|
||||
alloc.interv.~prb_interval();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_alloc_type0() const { return alloc_type_0; }
|
||||
bool is_alloc_type1() const { return not is_alloc_type0(); }
|
||||
const rbg_bitmap& rbgs() const
|
||||
{
|
||||
srsran_assert(is_alloc_type0(), "Invalid access to rbgs() field of grant with alloc type 1");
|
||||
return alloc.rbgs;
|
||||
}
|
||||
const prb_interval& prbs() const
|
||||
{
|
||||
srsran_assert(is_alloc_type1(), "Invalid access to prbs() field of grant with alloc type 0");
|
||||
return alloc.interv;
|
||||
}
|
||||
rbg_bitmap& rbgs()
|
||||
{
|
||||
srsran_assert(is_alloc_type0(), "Invalid access to rbgs() field of grant with alloc type 1");
|
||||
return alloc.rbgs;
|
||||
}
|
||||
prb_interval& prbs()
|
||||
{
|
||||
srsran_assert(is_alloc_type1(), "Invalid access to prbs() field of grant with alloc type 0");
|
||||
return alloc.interv;
|
||||
}
|
||||
|
||||
private:
|
||||
bool alloc_type_0 = false;
|
||||
union alloc_t {
|
||||
rbg_bitmap rbgs;
|
||||
prb_interval interv;
|
||||
|
||||
alloc_t() : interv(0, 0) {}
|
||||
explicit alloc_t(const prb_interval& prbs) : interv(prbs) {}
|
||||
explicit alloc_t(const rbg_bitmap& rbgs_) : rbgs(rbgs_) {}
|
||||
alloc_t(bool type0, const alloc_t& other)
|
||||
{
|
||||
if (type0) {
|
||||
new (&rbgs) rbg_bitmap(other.rbgs);
|
||||
} else {
|
||||
new (&interv) prb_interval(other.interv);
|
||||
}
|
||||
}
|
||||
} alloc;
|
||||
};
|
||||
|
||||
struct bwp_rb_bitmap {
|
||||
public:
|
||||
bwp_rb_bitmap() = default;
|
||||
bwp_rb_bitmap(uint32_t bwp_nof_prbs, uint32_t bwp_prb_start_, bool config1_or_2);
|
||||
|
||||
void reset()
|
||||
{
|
||||
prbs_.reset();
|
||||
rbgs_.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator|=(const T& grant)
|
||||
{
|
||||
add(grant);
|
||||
}
|
||||
|
||||
void add(const prb_interval& prbs)
|
||||
{
|
||||
prbs_.fill(prbs.start(), prbs.stop());
|
||||
add_prbs_to_rbgs(prbs);
|
||||
}
|
||||
void add(const prb_bitmap& grant)
|
||||
{
|
||||
prbs_ |= grant;
|
||||
add_prbs_to_rbgs(grant);
|
||||
}
|
||||
void add(const rbg_bitmap& grant)
|
||||
{
|
||||
rbgs_ |= grant;
|
||||
add_rbgs_to_prbs(grant);
|
||||
}
|
||||
void add(const prb_grant& grant)
|
||||
{
|
||||
if (grant.is_alloc_type0()) {
|
||||
add(grant.rbgs());
|
||||
} else {
|
||||
add(grant.prbs());
|
||||
}
|
||||
}
|
||||
bool collides(const prb_grant& grant) const
|
||||
{
|
||||
if (grant.is_alloc_type0()) {
|
||||
return (rbgs() & grant.rbgs()).any();
|
||||
}
|
||||
return prbs().any(grant.prbs().start(), grant.prbs().stop());
|
||||
}
|
||||
bool test(uint32_t prb_idx) { return prbs().test(prb_idx); }
|
||||
void set(uint32_t prb_idx)
|
||||
{
|
||||
prbs_.set(prb_idx);
|
||||
rbgs_.set(prb_to_rbg_idx(prb_idx));
|
||||
}
|
||||
|
||||
const prb_bitmap& prbs() const { return prbs_; }
|
||||
const rbg_bitmap& rbgs() const { return rbgs_; }
|
||||
uint32_t P() const { return P_; }
|
||||
uint32_t nof_prbs() const { return prbs_.size(); }
|
||||
uint32_t nof_rbgs() const { return rbgs_.size(); }
|
||||
|
||||
uint32_t prb_to_rbg_idx(uint32_t prb_idx) const;
|
||||
|
||||
private:
|
||||
prb_bitmap prbs_;
|
||||
rbg_bitmap rbgs_;
|
||||
uint32_t bwp_prb_start = 0;
|
||||
uint32_t P_ = 0;
|
||||
uint32_t Pnofbits = 0;
|
||||
uint32_t first_rbg_size = 0;
|
||||
|
||||
void add_prbs_to_rbgs(const prb_bitmap& grant);
|
||||
void add_prbs_to_rbgs(const prb_interval& grant);
|
||||
void add_rbgs_to_prbs(const rbg_bitmap& grant);
|
||||
};
|
||||
|
||||
inline prb_interval
|
||||
find_next_empty_interval(const prb_bitmap& mask, size_t start_prb_idx = 0, size_t last_prb_idx = SRSRAN_MAX_PRB_NR)
|
||||
{
|
||||
int rb_start = mask.find_lowest(start_prb_idx, std::min(mask.size(), last_prb_idx), false);
|
||||
if (rb_start != -1) {
|
||||
int rb_end = mask.find_lowest(rb_start + 1, std::min(mask.size(), last_prb_idx), true);
|
||||
return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? mask.size() : rb_end)};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
inline prb_interval find_empty_interval_of_length(const prb_bitmap& mask, size_t nof_prbs, uint32_t start_prb_idx = 0)
|
||||
{
|
||||
prb_interval max_interv;
|
||||
do {
|
||||
prb_interval interv = find_next_empty_interval(mask, start_prb_idx, mask.size());
|
||||
if (interv.empty()) {
|
||||
break;
|
||||
}
|
||||
if (interv.length() >= nof_prbs) {
|
||||
max_interv.set(interv.start(), interv.start() + nof_prbs);
|
||||
break;
|
||||
}
|
||||
if (interv.length() > max_interv.length()) {
|
||||
max_interv = interv;
|
||||
}
|
||||
start_prb_idx = interv.stop() + 1;
|
||||
} while (start_prb_idx < mask.size());
|
||||
return max_interv;
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_RB_H
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
*
|
||||
* \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/nr/sched_nr_rb.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P
|
||||
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2)
|
||||
{
|
||||
srsran_assert(bwp_nof_prb > 0 and bwp_nof_prb <= 275, "Invalid BWP size");
|
||||
if (bwp_nof_prb <= 36) {
|
||||
return config_1_or_2 ? 2 : 4;
|
||||
}
|
||||
if (bwp_nof_prb <= 72) {
|
||||
return config_1_or_2 ? 4 : 8;
|
||||
}
|
||||
if (bwp_nof_prb <= 144) {
|
||||
return config_1_or_2 ? 8 : 16;
|
||||
}
|
||||
return 16;
|
||||
}
|
||||
|
||||
/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs
|
||||
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2)
|
||||
{
|
||||
uint32_t P = get_P(bwp_nof_prb, config1_or_2);
|
||||
return srsran::ceil_div(bwp_nof_prb + (bwp_start % P), P);
|
||||
}
|
||||
|
||||
uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2, uint32_t rbg_idx)
|
||||
{
|
||||
uint32_t P = get_P(bwp_nof_prb, config1_or_2);
|
||||
uint32_t nof_rbgs = get_nof_rbgs(bwp_nof_prb, bwp_start, config1_or_2);
|
||||
if (rbg_idx == 0) {
|
||||
return P - (bwp_start % P);
|
||||
}
|
||||
if (rbg_idx == nof_rbgs - 1) {
|
||||
uint32_t ret = (bwp_start + bwp_nof_prb) % P;
|
||||
return ret > 0 ? ret : P;
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
bwp_rb_bitmap::bwp_rb_bitmap(uint32_t bwp_nof_prbs, uint32_t bwp_prb_start_, bool config1_or_2) :
|
||||
prbs_(bwp_nof_prbs),
|
||||
rbgs_(get_nof_rbgs(bwp_nof_prbs, bwp_prb_start_, config1_or_2)),
|
||||
bwp_prb_start(bwp_prb_start_),
|
||||
P_(get_P(bwp_nof_prbs, config1_or_2)),
|
||||
Pnofbits(log2(P_)),
|
||||
first_rbg_size(get_rbg_size(bwp_nof_prbs, bwp_prb_start_, config1_or_2, 0))
|
||||
{}
|
||||
|
||||
uint32_t bwp_rb_bitmap::prb_to_rbg_idx(uint32_t prb_idx) const
|
||||
{
|
||||
return ((prb_idx + P_ - first_rbg_size) >> Pnofbits);
|
||||
}
|
||||
|
||||
void bwp_rb_bitmap::add_prbs_to_rbgs(const prb_bitmap& grant)
|
||||
{
|
||||
int idx = 0;
|
||||
do {
|
||||
idx = grant.find_lowest(idx, grant.size(), true);
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t rbg_idx = prb_to_rbg_idx(idx);
|
||||
rbgs_.set(rbg_idx, true);
|
||||
idx++;
|
||||
} while (idx != (int)prbs_.size());
|
||||
}
|
||||
|
||||
void bwp_rb_bitmap::add_prbs_to_rbgs(const prb_interval& grant)
|
||||
{
|
||||
uint32_t rbg_start = prb_to_rbg_idx(grant.start());
|
||||
uint32_t rbg_stop = std::min(prb_to_rbg_idx(grant.stop() - 1) + 1u, (uint32_t)rbgs_.size());
|
||||
rbgs_.fill(rbg_start, rbg_stop);
|
||||
}
|
||||
|
||||
void bwp_rb_bitmap::add_rbgs_to_prbs(const rbg_bitmap& grant)
|
||||
{
|
||||
int idx = 0;
|
||||
do {
|
||||
idx = grant.find_lowest(idx, grant.size(), true);
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t prb_idx = (idx - 1) * P_ + first_rbg_size;
|
||||
uint32_t prb_end = std::min(prb_idx + ((idx == 0) ? first_rbg_size : P_), (uint32_t)prbs_.size());
|
||||
prbs_.fill(prb_idx, prb_end);
|
||||
idx++;
|
||||
} while (idx != (int)prbs_.size());
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
@ -0,0 +1,130 @@
|
||||
/**
|
||||
*
|
||||
* \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/nr/sched_nr_rb.h"
|
||||
#include "srsran/common/test_common.h"
|
||||
|
||||
using namespace srsenb;
|
||||
using namespace srsenb::sched_nr_impl;
|
||||
|
||||
void test_bwp_prb_grant()
|
||||
{
|
||||
// TEST: default ctor
|
||||
prb_grant grant;
|
||||
TESTASSERT(grant.is_alloc_type1());
|
||||
TESTASSERT(grant.prbs().length() == 0);
|
||||
|
||||
// TEST: assignment of RBGs
|
||||
rbg_bitmap rbgs(18);
|
||||
rbgs.set(1);
|
||||
grant = rbgs;
|
||||
TESTASSERT(grant.is_alloc_type0() and grant.rbgs().count() == 1);
|
||||
|
||||
// TEST: assignment of PRBs
|
||||
prb_interval prb_interv(2, 5);
|
||||
grant = prb_interv;
|
||||
TESTASSERT(grant.is_alloc_type1() and grant.prbs().length() == 3);
|
||||
|
||||
// TEST: non-default ctor
|
||||
prb_grant grant2(prb_interv), grant3(rbgs);
|
||||
TESTASSERT(grant2.is_alloc_type1() and grant2.prbs().length() == 3);
|
||||
TESTASSERT(grant3.is_alloc_type0() and grant3.rbgs().count() == 1);
|
||||
|
||||
// TEST: copy ctor
|
||||
prb_grant grant4(grant2), grant5(grant3);
|
||||
TESTASSERT(grant4.is_alloc_type1() and grant4.prbs().length() == 3);
|
||||
TESTASSERT(grant5.is_alloc_type0() and grant5.rbgs().count() == 1);
|
||||
|
||||
// TEST: copy assignment
|
||||
grant = grant3;
|
||||
TESTASSERT(grant.is_alloc_type0() and grant.rbgs().count() == 1);
|
||||
grant = grant2;
|
||||
TESTASSERT(grant.is_alloc_type1() and grant.prbs().length() == 3);
|
||||
}
|
||||
|
||||
void test_bwp_rb_bitmap()
|
||||
{
|
||||
bwp_rb_bitmap rb_bitmap(275, 0, true);
|
||||
|
||||
TESTASSERT(rb_bitmap.P() == 16);
|
||||
TESTASSERT(rb_bitmap.rbgs().none());
|
||||
TESTASSERT(rb_bitmap.prbs().none());
|
||||
TESTASSERT(rb_bitmap.prbs().size() == 275 and rb_bitmap.nof_prbs() == 275);
|
||||
TESTASSERT(rb_bitmap.rbgs().size() == 18 and rb_bitmap.nof_rbgs() == 18);
|
||||
|
||||
rb_bitmap.add(prb_interval{0, 1});
|
||||
TESTASSERT(rb_bitmap.prbs().count() == 1 and rb_bitmap.prbs().test(0));
|
||||
TESTASSERT(rb_bitmap.rbgs().count() == 1 and rb_bitmap.rbgs().test(0));
|
||||
rb_bitmap.add(prb_interval{2, 4});
|
||||
TESTASSERT(rb_bitmap.prbs().count() == 3 and rb_bitmap.prbs().test(2) and not rb_bitmap.prbs().test(1));
|
||||
TESTASSERT(rb_bitmap.rbgs().count() == 1 and rb_bitmap.rbgs().test(0));
|
||||
|
||||
prb_bitmap prbs(rb_bitmap.nof_prbs());
|
||||
prbs.set(1);
|
||||
prbs.set(2);
|
||||
prbs.set(15);
|
||||
rb_bitmap.add(prbs);
|
||||
TESTASSERT(rb_bitmap.prbs().count() == 5 and rb_bitmap.prbs().test(1) and rb_bitmap.prbs().test(15));
|
||||
TESTASSERT(rb_bitmap.rbgs().count() == 1 and rb_bitmap.rbgs().test(0));
|
||||
prbs.set(16);
|
||||
rb_bitmap |= prbs;
|
||||
TESTASSERT(rb_bitmap.prbs().count() == 6 and rb_bitmap.prbs().test(16));
|
||||
TESTASSERT(rb_bitmap.rbgs().count() == 2 and rb_bitmap.rbgs().test(1));
|
||||
|
||||
rbg_bitmap rbgs(rb_bitmap.nof_rbgs());
|
||||
rbgs.set(3);
|
||||
rbgs.set(17);
|
||||
rb_bitmap |= rbgs;
|
||||
TESTASSERT(rb_bitmap.prbs().count() == (6 + 16 + 3) and rb_bitmap.prbs().test(rb_bitmap.nof_prbs() - 1));
|
||||
TESTASSERT(rb_bitmap.rbgs().count() == 4 and rb_bitmap.rbgs().test(3) and rb_bitmap.rbgs().test(17));
|
||||
rbgs.set(0);
|
||||
rb_bitmap |= rbgs;
|
||||
TESTASSERT(rb_bitmap.prbs().count() == (16 + 1 + 16 + 3) and rb_bitmap.prbs().test(rb_bitmap.nof_prbs() - 1));
|
||||
TESTASSERT(rb_bitmap.rbgs().count() == 4 and rb_bitmap.rbgs().test(3) and rb_bitmap.rbgs().test(17));
|
||||
|
||||
// TEST: collides operator
|
||||
TESTASSERT(rb_bitmap.collides(rbgs));
|
||||
TESTASSERT(rb_bitmap.collides(prb_interval{0, 2}));
|
||||
}
|
||||
|
||||
void test_bwp_rb_bitmap_search()
|
||||
{
|
||||
bwp_rb_bitmap rb_bitmap(275, 0, true);
|
||||
|
||||
prb_interval prbs = find_empty_interval_of_length(rb_bitmap.prbs(), 5);
|
||||
TESTASSERT(prbs == prb_interval(0, 5));
|
||||
prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size());
|
||||
TESTASSERT(prbs == prb_interval(0, rb_bitmap.prbs().size()));
|
||||
|
||||
rb_bitmap |= prb_interval{1, 5};
|
||||
prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size());
|
||||
TESTASSERT(prbs == prb_interval(5, rb_bitmap.prbs().size()));
|
||||
|
||||
rb_bitmap |= prb_interval{16, 32};
|
||||
prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size());
|
||||
TESTASSERT(prbs == prb_interval(32, rb_bitmap.prbs().size()));
|
||||
|
||||
rb_bitmap |= prb_interval{270, 275};
|
||||
prbs = find_empty_interval_of_length(rb_bitmap.prbs(), rb_bitmap.prbs().size());
|
||||
TESTASSERT(prbs == prb_interval(32, 270));
|
||||
prbs = find_empty_interval_of_length(rb_bitmap.prbs(), 1);
|
||||
TESTASSERT(prbs == prb_interval(0, 1));
|
||||
prbs = find_empty_interval_of_length(rb_bitmap.prbs(), 5);
|
||||
TESTASSERT(prbs == prb_interval(5, 10));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_bwp_prb_grant();
|
||||
test_bwp_rb_bitmap();
|
||||
test_bwp_rb_bitmap_search();
|
||||
}
|
Loading…
Reference in New Issue