mirror of https://github.com/PentHertz/srsLTE.git
adt: create split optional span view to be used for C-array types
This commit is contained in:
parent
d616e46936
commit
e896ac49e8
|
@ -14,6 +14,7 @@
|
|||
#define SRSRAN_OPTIONAL_ARRAY_H
|
||||
|
||||
#include "optional.h"
|
||||
#include "span.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include <array>
|
||||
|
||||
|
@ -22,9 +23,9 @@ namespace srsran {
|
|||
namespace detail {
|
||||
|
||||
template <typename Vec>
|
||||
class base_optional_vector
|
||||
class base_optional_span
|
||||
{
|
||||
using base_t = base_optional_vector<Vec>;
|
||||
using base_t = base_optional_span<Vec>;
|
||||
using T = typename Vec::value_type::value_type;
|
||||
|
||||
protected:
|
||||
|
@ -67,7 +68,7 @@ protected:
|
|||
bool operator==(const It& other) const { return idx == other.idx and parent == other.parent; }
|
||||
bool operator!=(const It& other) const { return not(*this == other); }
|
||||
|
||||
protected:
|
||||
private:
|
||||
friend base_t;
|
||||
|
||||
base_t* parent = nullptr;
|
||||
|
@ -78,24 +79,10 @@ protected:
|
|||
Vec vec;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using iterator = iterator_impl<T>;
|
||||
using const_iterator = iterator_impl<const T>;
|
||||
|
||||
base_optional_vector() = default;
|
||||
base_optional_vector(const base_optional_vector&) = default;
|
||||
base_optional_vector(base_optional_vector&& other) noexcept : vec(std::move(other.vec)), nof_elems(other.nof_elems)
|
||||
{
|
||||
other.nof_elems = 0;
|
||||
}
|
||||
base_optional_vector& operator=(const base_optional_vector&) = default;
|
||||
base_optional_vector& operator =(base_optional_vector&& other) noexcept
|
||||
{
|
||||
vec = std::move(other.vec);
|
||||
nof_elems = other.nof_elems;
|
||||
nof_elems = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Find first position that is empty
|
||||
size_t find_first_empty(size_t start_guess = 0)
|
||||
{
|
||||
|
@ -112,22 +99,6 @@ public:
|
|||
|
||||
bool contains(size_t idx) const { return idx < vec.size() and vec[idx].has_value(); }
|
||||
|
||||
void erase(size_t idx)
|
||||
{
|
||||
if (contains(idx)) {
|
||||
nof_elems--;
|
||||
vec[idx].reset();
|
||||
}
|
||||
}
|
||||
void erase(iterator it) { erase(it.idx); }
|
||||
void clear()
|
||||
{
|
||||
nof_elems = 0;
|
||||
for (auto& e : *this) {
|
||||
e.reset();
|
||||
}
|
||||
}
|
||||
|
||||
T& operator[](size_t idx) { return *vec[idx]; }
|
||||
const T& operator[](size_t idx) const { return *vec[idx]; }
|
||||
|
||||
|
@ -138,6 +109,58 @@ public:
|
|||
iterator end() { return iterator{this, vec.size()}; }
|
||||
const_iterator begin() const { return const_iterator{this, 0}; }
|
||||
const_iterator end() const { return const_iterator{this, vec.size()}; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->nof_elems = 0;
|
||||
for (auto& e : *this) {
|
||||
e.reset();
|
||||
}
|
||||
}
|
||||
void erase(size_t idx)
|
||||
{
|
||||
srsran_assert(idx < this->vec.size(), "Out-of-bounds access to array: %zd>=%zd", idx, this->vec.size());
|
||||
if (this->contains(idx)) {
|
||||
this->nof_elems--;
|
||||
this->vec[idx].reset();
|
||||
}
|
||||
}
|
||||
void erase(iterator it) { erase(it.idx); }
|
||||
|
||||
template <typename U>
|
||||
void insert(size_t idx, U&& u)
|
||||
{
|
||||
srsran_assert(idx < this->vec.size(), "Out-of-bounds access to array: %zd>=%zd", idx, this->vec.size());
|
||||
this->nof_elems += this->contains(idx) ? 0 : 1;
|
||||
this->vec[idx] = std::forward<U>(u);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Vec>
|
||||
class base_optional_vector : public base_optional_span<Vec>
|
||||
{
|
||||
using base_t = base_optional_span<Vec>;
|
||||
|
||||
public:
|
||||
using value_type = typename base_optional_span<Vec>::value_type;
|
||||
using iterator = typename base_optional_span<Vec>::iterator;
|
||||
using const_iterator = typename base_optional_span<Vec>::const_iterator;
|
||||
|
||||
base_optional_vector() = default;
|
||||
base_optional_vector(const base_optional_vector&) = default;
|
||||
base_optional_vector(base_optional_vector&& other) noexcept : base_t::vec(std::move(other.vec)),
|
||||
base_t::nof_elems(other.nof_elems)
|
||||
{
|
||||
other.nof_elems = 0;
|
||||
}
|
||||
base_optional_vector& operator=(const base_optional_vector&) = default;
|
||||
base_optional_vector& operator =(base_optional_vector&& other) noexcept
|
||||
{
|
||||
this->vec = std::move(other.vec);
|
||||
this->nof_elems = other.nof_elems;
|
||||
this->nof_elems = 0;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -151,17 +174,7 @@ public:
|
|||
*/
|
||||
template <typename T, size_t N>
|
||||
class optional_array : public detail::base_optional_vector<std::array<optional<T>, N> >
|
||||
{
|
||||
using base_t = detail::base_optional_vector<std::array<optional<T>, N> >;
|
||||
|
||||
public:
|
||||
template <typename U>
|
||||
void insert(size_t idx, U&& u)
|
||||
{
|
||||
this->nof_elems += this->contains(idx) ? 0 : 1;
|
||||
this->vec[idx] = std::forward<U>(u);
|
||||
}
|
||||
};
|
||||
{};
|
||||
|
||||
/**
|
||||
* Contrarily to optional_array, this class may allocate and cause pointer/reference/iterator invalidation.
|
||||
|
@ -178,14 +191,206 @@ public:
|
|||
template <typename U>
|
||||
void insert(size_t idx, U&& u)
|
||||
{
|
||||
if (not this->contains(idx)) {
|
||||
this->nof_elems++;
|
||||
this->vec.resize(std::max(idx + 1, this->vec.size()));
|
||||
if (idx >= this->vec.size()) {
|
||||
this->vec.resize(idx + 1);
|
||||
}
|
||||
this->vec[idx] = std::forward<U>(u);
|
||||
base_t::insert(idx, std::forward<U>(u));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class optional_span : public detail::base_optional_span<srsran::span<optional<T> > >
|
||||
{
|
||||
using base_t = detail::base_optional_span<srsran::span<optional<T> > >;
|
||||
|
||||
public:
|
||||
template <size_t N>
|
||||
optional_span(const optional_array<T, N>& ar) : base_t::vec(ar)
|
||||
{}
|
||||
optional_span(const optional_vector<T>& ar) : base_t::vec(ar) {}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class base_split_optional_span
|
||||
{
|
||||
protected:
|
||||
using presence_type = typename std::conditional<std::is_const<T>::value, const bool, bool>::type;
|
||||
|
||||
T* ptr = nullptr;
|
||||
presence_type* present_ptr = nullptr;
|
||||
size_t len = 0;
|
||||
|
||||
template <typename Obj>
|
||||
class iterator_impl
|
||||
{
|
||||
using It = iterator_impl<Obj>;
|
||||
using Parent = typename std::
|
||||
conditional<std::is_const<Obj>::value, const base_split_optional_span<T>, base_split_optional_span<T> >::type;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = Obj;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = Obj*;
|
||||
using reference = Obj&;
|
||||
|
||||
iterator_impl() = default;
|
||||
iterator_impl(Parent* parent_, size_t idx_) : parent(parent_), idx(idx_)
|
||||
{
|
||||
if (idx < parent->len and not parent->contains(idx)) {
|
||||
++(*this);
|
||||
}
|
||||
}
|
||||
|
||||
It& operator++()
|
||||
{
|
||||
while (++idx < parent->len and not parent->contains(idx)) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
It& operator--()
|
||||
{
|
||||
while (--idx < parent->len and not parent->contains(idx)) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*() { return parent->operator[](idx); }
|
||||
pointer operator->() { return &parent->operator[](idx); }
|
||||
|
||||
bool operator==(const It& other) const { return idx == other.idx and parent == other.parent; }
|
||||
bool operator!=(const It& other) const { return not(*this == other); }
|
||||
|
||||
size_t get_idx() const { return idx; }
|
||||
|
||||
private:
|
||||
Parent* parent = nullptr;
|
||||
size_t idx = std::numeric_limits<size_t>::max();
|
||||
};
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using iterator = iterator_impl<T>;
|
||||
using const_iterator = iterator_impl<const T>;
|
||||
|
||||
constexpr base_split_optional_span() = default;
|
||||
template <std::size_t N>
|
||||
constexpr base_split_optional_span(value_type (&arr)[N], presence_type (&present)[N]) noexcept : ptr(arr),
|
||||
present_ptr(present),
|
||||
len(N)
|
||||
{}
|
||||
constexpr base_split_optional_span(value_type* arr, presence_type* present, size_t N) :
|
||||
ptr(arr), present_ptr(present), len(N)
|
||||
{}
|
||||
|
||||
bool contains(size_t idx) const { return idx < len and present_ptr[idx]; }
|
||||
bool empty() const
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (present_ptr[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
size_t c = 0;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
c += present_ptr[i] ? 1 : 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
size_t capacity() const { return len; }
|
||||
|
||||
const T& operator[](size_t idx) const { return ptr[idx]; }
|
||||
T& operator[](size_t idx) { return ptr[idx]; }
|
||||
const T& at(size_t idx) const
|
||||
{
|
||||
srsran_assert(contains(idx), "Access to inexistent element of index=%zd", idx);
|
||||
return ptr[idx];
|
||||
}
|
||||
T& at(size_t idx)
|
||||
{
|
||||
srsran_assert(this->contains(idx), "Access to inexistent element of index=%zd", idx);
|
||||
return this->ptr[idx];
|
||||
}
|
||||
|
||||
const_iterator begin() const { return const_iterator(this, 0); }
|
||||
const_iterator end() const { return const_iterator(this, len); }
|
||||
iterator begin() { return iterator(this, 0); }
|
||||
iterator end() { return iterator(this, this->len); }
|
||||
|
||||
// Find first position that is empty
|
||||
size_t find_first_empty(size_t start_guess = 0) { return begin().get_idx(); }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class split_optional_span : public detail::base_split_optional_span<T>
|
||||
{
|
||||
using base_t = detail::base_split_optional_span<T>;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using const_iterator = typename base_t::const_iterator;
|
||||
using iterator = typename base_t::iterator;
|
||||
|
||||
using base_t::base_t;
|
||||
|
||||
template <typename U>
|
||||
void insert(size_t idx, U&& u)
|
||||
{
|
||||
srsran_assert(idx < this->len, "Out-of-bounds access to array: %zd>=%zd", idx, this->len);
|
||||
this->present_ptr[idx] = true;
|
||||
this->ptr[idx] = std::forward<U>(u);
|
||||
}
|
||||
void erase(size_t idx)
|
||||
{
|
||||
srsran_assert(idx < this->len, "Out-of-bounds access to array: %zd>=%zd", idx, this->len);
|
||||
this->present_ptr[idx] = false;
|
||||
}
|
||||
void erase(iterator it) { erase(it.get_idx()); }
|
||||
void clear()
|
||||
{
|
||||
for (size_t i = 0; i < this->len; ++i) {
|
||||
this->present_ptr[i] = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
class split_optional_span<const U> : public detail::base_split_optional_span<const U>
|
||||
{
|
||||
using base_t = detail::base_split_optional_span<const U>;
|
||||
using presence_type = typename base_t::presence_type;
|
||||
|
||||
public:
|
||||
using value_type = const U;
|
||||
using const_iterator = typename base_t::const_iterator;
|
||||
|
||||
using base_t::base_t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
split_optional_span<T>
|
||||
make_optional_span(T* array,
|
||||
typename std::conditional<std::is_const<T>::value, const bool, bool>::type* present,
|
||||
size_t N)
|
||||
{
|
||||
return split_optional_span<T>(array, present, N);
|
||||
}
|
||||
template <typename T, size_t N>
|
||||
split_optional_span<T>
|
||||
make_optional_span(T (&array)[N],
|
||||
typename std::conditional<std::is_const<T>::value, const bool, bool>::type (&present)[N])
|
||||
{
|
||||
return split_optional_span<T>(array, present);
|
||||
}
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_OPTIONAL_ARRAY_H
|
||||
|
|
|
@ -69,6 +69,42 @@ void test_optional_vector()
|
|||
TESTASSERT(table1.size() == 1);
|
||||
}
|
||||
|
||||
void test_split_optional_span()
|
||||
{
|
||||
constexpr size_t L = 7;
|
||||
int some_list[L] = {};
|
||||
bool some_list_presence[L] = {};
|
||||
split_optional_span<int> view(some_list, some_list_presence, L);
|
||||
|
||||
TESTASSERT(view.size() == 0 and view.empty());
|
||||
TESTASSERT(view.begin() == view.end());
|
||||
TESTASSERT(not view.contains(0));
|
||||
TESTASSERT(view.find_first_empty() == L);
|
||||
|
||||
view.insert(1, 1);
|
||||
TESTASSERT(view.size() == 1 and not view.empty());
|
||||
TESTASSERT(view.begin() != view.end() and *view.begin() == 1);
|
||||
TESTASSERT(view.contains(1));
|
||||
TESTASSERT(view[1] == 1);
|
||||
TESTASSERT(view.find_first_empty() == 1);
|
||||
|
||||
view.insert(3, 3);
|
||||
TESTASSERT(view[3] == 3);
|
||||
size_t c = 0;
|
||||
for (auto& e : view) {
|
||||
TESTASSERT(c == 0 ? e == 1 : e == 3);
|
||||
c++;
|
||||
}
|
||||
TESTASSERT(view.size() == 2);
|
||||
|
||||
view.erase(view.begin());
|
||||
TESTASSERT(view.size() == 1);
|
||||
TESTASSERT(not view.contains(1) and view.contains(3));
|
||||
|
||||
view.clear();
|
||||
TESTASSERT(view.empty());
|
||||
}
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
int main(int argc, char** argv)
|
||||
|
@ -80,6 +116,7 @@ int main(int argc, char** argv)
|
|||
|
||||
srsran::test_optional_array();
|
||||
srsran::test_optional_vector();
|
||||
srsran::test_split_optional_span();
|
||||
|
||||
printf("Success\n");
|
||||
return SRSRAN_SUCCESS;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h"
|
||||
#include "srsran/adt/optional_array.h"
|
||||
extern "C" {
|
||||
#include "srsran/phy/phch/ra_ul_nr.h"
|
||||
}
|
||||
|
@ -95,40 +96,36 @@ bwp_ue_cfg::bwp_ue_cfg(uint16_t rnti_, const bwp_params& bwp_cfg_, const ue_cfg_
|
|||
{
|
||||
std::fill(ss_id_to_cce_idx.begin(), ss_id_to_cce_idx.end(), SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE);
|
||||
const auto& pdcch = phy().pdcch;
|
||||
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++i) {
|
||||
if (pdcch.search_space_present[i]) {
|
||||
const auto& ss = pdcch.search_space[i];
|
||||
srsran_assert(pdcch.coreset_present[ss.coreset_id],
|
||||
auto ss_view = srsran::make_optional_span(pdcch.search_space, pdcch.search_space_present);
|
||||
auto coreset_view = srsran::make_optional_span(pdcch.coreset, pdcch.coreset_present);
|
||||
for (const auto& ss : ss_view) {
|
||||
srsran_assert(coreset_view.contains(ss.coreset_id),
|
||||
"Invalid mapping search space id=%d to coreset id=%d",
|
||||
ss.id,
|
||||
ss.coreset_id);
|
||||
const auto& coreset = pdcch.coreset[ss.coreset_id];
|
||||
cce_positions_list.emplace_back();
|
||||
get_dci_locs(coreset, ss, rnti, cce_positions_list.back());
|
||||
get_dci_locs(coreset_view[ss.coreset_id], ss, rnti, cce_positions_list.back());
|
||||
ss_id_to_cce_idx[ss.id] = cce_positions_list.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_)
|
||||
{
|
||||
auto ss_view = srsran::make_optional_span(phy_cfg.pdcch.search_space, phy_cfg.pdcch.search_space_present);
|
||||
auto coreset_view = srsran::make_optional_span(phy_cfg.pdcch.coreset, phy_cfg.pdcch.coreset_present);
|
||||
cc_params.resize(carriers.size());
|
||||
for (uint32_t cc = 0; cc < cc_params.size(); ++cc) {
|
||||
cc_params[cc].bwps.resize(1);
|
||||
auto& bwp = cc_params[cc].bwps[0];
|
||||
for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) {
|
||||
if (phy_cfg.pdcch.search_space_present[ssid]) {
|
||||
auto& ss = phy_cfg.pdcch.search_space[ssid];
|
||||
for (auto& ss : ss_view) {
|
||||
bwp.ss_list[ss.id].emplace();
|
||||
bwp.ss_list[ss.id]->cfg = &ss;
|
||||
get_dci_locs(phy_cfg.pdcch.coreset[ss.coreset_id], ss, rnti, bwp.ss_list[ss.id]->cce_positions);
|
||||
}
|
||||
}
|
||||
for (uint32_t idx = 0; idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++idx) {
|
||||
if (phy_cfg.pdcch.coreset_present[idx]) {
|
||||
for (auto& coreset_cfg : coreset_view) {
|
||||
bwp.coresets.emplace_back();
|
||||
auto& coreset = bwp.coresets.back();
|
||||
coreset.cfg = &phy_cfg.pdcch.coreset[idx];
|
||||
coreset.cfg = &coreset_cfg;
|
||||
for (auto& ss : bwp.ss_list) {
|
||||
if (ss.has_value() and ss->cfg->coreset_id == coreset.cfg->id) {
|
||||
coreset.ss_list.push_back(ss->cfg->id);
|
||||
|
@ -136,7 +133,6 @@ ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
|
|
Loading…
Reference in New Issue