sched,nr: creation of pool of softbuffers for NR. Now the sched NR harq manages the lifetime of the softbuffer and its forwarding to the PHY

master
Francisco Paisana 3 years ago
parent 1535e6b205
commit d9336bcd9e

@ -214,8 +214,9 @@ public:
}; };
struct pdsch_t { struct pdsch_t {
srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration
std::array<uint8_t*, SRSRAN_MAX_TB> data = {}; ///< Data pointer std::array<uint8_t*, SRSRAN_MAX_TB> data = {}; ///< Data pointer
std::array<srsran_softbuffer_tx_t, SRSRAN_MAX_TB> tx_softbuffer = {}; ///< HARQ-specific Softbuffer
}; };
struct ssb_t { struct ssb_t {

@ -0,0 +1,132 @@
/**
*
* \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_HARQ_SOFTBUFFER_H
#define SRSRAN_HARQ_SOFTBUFFER_H
#include "srsran/adt/pool/pool_interface.h"
#include "srsran/adt/span.h"
extern "C" {
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/fec/softbuffer.h"
}
namespace srsenb {
class tx_harq_softbuffer
{
public:
tx_harq_softbuffer() { bzero(&buffer, sizeof(buffer)); }
explicit tx_harq_softbuffer(uint32_t nof_prb_) { srsran_softbuffer_tx_init(&buffer, nof_prb_); }
tx_harq_softbuffer(const tx_harq_softbuffer&) = delete;
tx_harq_softbuffer(tx_harq_softbuffer&& other) noexcept
{
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
bzero(&other.buffer, sizeof(other.buffer));
}
tx_harq_softbuffer& operator=(const tx_harq_softbuffer&) = delete;
tx_harq_softbuffer& operator =(tx_harq_softbuffer&& other) noexcept
{
if (this != &other) {
destroy();
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
bzero(&other.buffer, sizeof(other.buffer));
}
return *this;
}
~tx_harq_softbuffer() { destroy(); }
void reset() { srsran_softbuffer_tx_reset(&buffer); }
srsran_softbuffer_tx_t& operator*() { return buffer; }
const srsran_softbuffer_tx_t& operator*() const { return buffer; }
srsran_softbuffer_tx_t* operator->() { return &buffer; }
const srsran_softbuffer_tx_t* operator->() const { return &buffer; }
srsran_softbuffer_tx_t* get() { return &buffer; }
const srsran_softbuffer_tx_t* get() const { return &buffer; }
private:
void destroy() { srsran_softbuffer_tx_free(&buffer); }
srsran_softbuffer_tx_t buffer;
};
class rx_harq_softbuffer
{
public:
rx_harq_softbuffer() { bzero(&buffer, sizeof(buffer)); }
explicit rx_harq_softbuffer(uint32_t nof_prb_) { srsran_softbuffer_rx_init(&buffer, nof_prb_); }
rx_harq_softbuffer(const rx_harq_softbuffer&) = delete;
rx_harq_softbuffer(rx_harq_softbuffer&& other) noexcept
{
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
bzero(&other.buffer, sizeof(other.buffer));
}
rx_harq_softbuffer& operator=(const rx_harq_softbuffer&) = delete;
rx_harq_softbuffer& operator =(rx_harq_softbuffer&& other) noexcept
{
if (this != &other) {
destroy();
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
bzero(&other.buffer, sizeof(other.buffer));
}
return *this;
}
~rx_harq_softbuffer() { destroy(); }
void reset() { srsran_softbuffer_rx_reset(&buffer); }
void reset(uint32_t tbs_bits) { srsran_softbuffer_rx_reset_tbs(&buffer, tbs_bits); }
srsran_softbuffer_rx_t& operator*() { return buffer; }
const srsran_softbuffer_rx_t& operator*() const { return buffer; }
srsran_softbuffer_rx_t* operator->() { return &buffer; }
const srsran_softbuffer_rx_t* operator->() const { return &buffer; }
srsran_softbuffer_rx_t* get() { return &buffer; }
const srsran_softbuffer_rx_t* get() const { return &buffer; }
private:
void destroy() { srsran_softbuffer_rx_free(&buffer); }
srsran_softbuffer_rx_t buffer;
};
class harq_softbuffer_pool
{
public:
harq_softbuffer_pool(const harq_softbuffer_pool&) = delete;
harq_softbuffer_pool(harq_softbuffer_pool&&) = delete;
harq_softbuffer_pool& operator=(const harq_softbuffer_pool&) = delete;
harq_softbuffer_pool& operator=(harq_softbuffer_pool&&) = delete;
void init_pool(uint32_t nof_prb, uint32_t batch_size = MAX_HARQ * 4, uint32_t thres = 0, uint32_t init_size = 0);
srsran::unique_pool_ptr<tx_harq_softbuffer> get_tx(uint32_t nof_prb);
srsran::unique_pool_ptr<rx_harq_softbuffer> get_rx(uint32_t nof_prb);
static harq_softbuffer_pool& get_instance()
{
static harq_softbuffer_pool pool;
return pool;
}
private:
const static uint32_t MAX_HARQ = 16;
harq_softbuffer_pool() = default;
std::array<std::unique_ptr<srsran::obj_pool_itf<tx_harq_softbuffer> >, SRSRAN_MAX_PRB_NR> tx_pool;
std::array<std::unique_ptr<srsran::obj_pool_itf<rx_harq_softbuffer> >, SRSRAN_MAX_PRB_NR> rx_pool;
};
} // namespace srsenb
#endif // SRSRAN_HARQ_SOFTBUFFER_H

@ -57,6 +57,8 @@ struct sched_cell_params {
std::vector<bwp_params> bwps; std::vector<bwp_params> bwps;
sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_); sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_);
uint32_t nof_prb() const { return cell_cfg.carrier.nof_prb; }
}; };
struct sched_params { struct sched_params {

@ -14,6 +14,7 @@
#define SRSRAN_SCHED_NR_HARQ_H #define SRSRAN_SCHED_NR_HARQ_H
#include "sched_nr_cfg.h" #include "sched_nr_cfg.h"
#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h"
#include "srsran/common/tti_point.h" #include "srsran/common/tti_point.h"
#include <array> #include <array>
@ -70,23 +71,55 @@ private:
std::array<tb_t, SCHED_NR_MAX_TB> tb; std::array<tb_t, SCHED_NR_MAX_TB> tb;
}; };
class dl_harq_proc : public harq_proc
{
public:
dl_harq_proc(uint32_t id_, uint32_t nprb) :
harq_proc(id_), softbuffer(harq_softbuffer_pool::get_instance().get_tx(nprb))
{}
tx_harq_softbuffer& get_softbuffer() { return *softbuffer; }
private:
srsran::unique_pool_ptr<tx_harq_softbuffer> softbuffer;
};
class ul_harq_proc : public harq_proc
{
public:
ul_harq_proc(uint32_t id_, uint32_t nprb) :
harq_proc(id_), softbuffer(harq_softbuffer_pool::get_instance().get_rx(nprb))
{}
rx_harq_softbuffer& get_softbuffer() { return *softbuffer; }
bool set_tbs(uint32_t tbs)
{
softbuffer->reset(tbs * 8u);
return harq_proc::set_tbs(tbs);
}
private:
srsran::unique_pool_ptr<rx_harq_softbuffer> softbuffer;
};
class harq_entity class harq_entity
{ {
public: public:
explicit harq_entity(uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ); explicit harq_entity(uint32_t nprb, uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ);
void new_tti(tti_point tti_rx_); void new_tti(tti_point tti_rx_);
void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); } void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); }
harq_proc* find_pending_dl_retx() dl_harq_proc* find_pending_dl_retx()
{ {
return find_dl([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); return find_dl([this](const dl_harq_proc& h) { return h.has_pending_retx(tti_rx); });
} }
harq_proc* find_pending_ul_retx() harq_proc* find_pending_ul_retx()
{ {
return find_ul([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); }); return find_ul([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); });
} }
harq_proc* find_empty_dl_harq() dl_harq_proc* find_empty_dl_harq()
{ {
return find_dl([](const harq_proc& h) { return h.empty(); }); return find_dl([](const harq_proc& h) { return h.empty(); });
} }
@ -97,7 +130,7 @@ public:
private: private:
template <typename Predicate> template <typename Predicate>
harq_proc* find_dl(Predicate p) dl_harq_proc* find_dl(Predicate p)
{ {
auto it = std::find_if(dl_harqs.begin(), dl_harqs.end(), p); auto it = std::find_if(dl_harqs.begin(), dl_harqs.end(), p);
return (it == dl_harqs.end()) ? nullptr : &(*it); return (it == dl_harqs.end()) ? nullptr : &(*it);
@ -109,9 +142,9 @@ private:
return (it == ul_harqs.end()) ? nullptr : &(*it); return (it == ul_harqs.end()) ? nullptr : &(*it);
} }
tti_point tti_rx; tti_point tti_rx;
std::vector<harq_proc> dl_harqs; std::vector<dl_harq_proc> dl_harqs;
std::vector<harq_proc> ul_harqs; std::vector<ul_harq_proc> ul_harqs;
}; };
} // namespace sched_nr_impl } // namespace sched_nr_impl

@ -68,7 +68,8 @@ public:
}; };
struct ue_cc_cfg_t { struct ue_cc_cfg_t {
bool active = false; bool active = false;
uint32_t cc = 0;
}; };
struct ue_cfg_t { struct ue_cfg_t {

@ -53,7 +53,7 @@ public:
tti_point uci_tti; tti_point uci_tti;
uint32_t dl_cqi; uint32_t dl_cqi;
uint32_t ul_cqi; uint32_t ul_cqi;
harq_proc* h_dl = nullptr; dl_harq_proc* h_dl = nullptr;
harq_proc* h_ul = nullptr; harq_proc* h_ul = nullptr;
private: private:

@ -7,6 +7,6 @@
# #
set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc
sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc sched_nr_rb.cc) sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc sched_nr_rb.cc harq_softbuffer.cc)
add_library(srsgnb_mac STATIC ${SOURCES}) add_library(srsgnb_mac STATIC ${SOURCES})

@ -0,0 +1,62 @@
/**
*
* \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/harq_softbuffer.h"
#include "srsran/adt/pool/obj_pool.h"
namespace srsenb {
void harq_softbuffer_pool::init_pool(uint32_t nof_prb, uint32_t batch_size, uint32_t thres, uint32_t init_size)
{
srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid nof prb=%d", nof_prb);
size_t idx = nof_prb - 1;
if (tx_pool[idx] != nullptr) {
return;
}
if (thres == 0) {
thres = batch_size;
}
if (init_size == 0) {
init_size = batch_size;
}
auto init_tx_softbuffers = [nof_prb](void* ptr) { new (ptr) tx_harq_softbuffer(nof_prb); };
auto recycle_tx_softbuffers = [](tx_harq_softbuffer& softbuffer) { softbuffer.reset(); };
tx_pool[idx].reset(new srsran::background_obj_pool<tx_harq_softbuffer>(
batch_size, thres, init_size, init_tx_softbuffers, recycle_tx_softbuffers));
auto init_rx_softbuffers = [nof_prb](void* ptr) { new (ptr) rx_harq_softbuffer(nof_prb); };
auto recycle_rx_softbuffers = [](rx_harq_softbuffer& softbuffer) { softbuffer.reset(); };
rx_pool[idx].reset(new srsran::background_obj_pool<rx_harq_softbuffer>(
batch_size, thres, init_size, init_rx_softbuffers, recycle_rx_softbuffers));
}
srsran::unique_pool_ptr<tx_harq_softbuffer> harq_softbuffer_pool::get_tx(uint32_t nof_prb)
{
srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid Nprb=%d", nof_prb);
size_t idx = nof_prb - 1;
if (tx_pool[idx] == nullptr) {
init_pool(nof_prb);
}
return tx_pool[idx]->make();
}
srsran::unique_pool_ptr<rx_harq_softbuffer> harq_softbuffer_pool::get_rx(uint32_t nof_prb)
{
srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid Nprb=%d", nof_prb);
size_t idx = nof_prb - 1;
if (rx_pool[idx] == nullptr) {
init_pool(nof_prb);
}
return rx_pool[idx]->make();
}
} // namespace srsenb

@ -11,6 +11,7 @@
*/ */
#include "srsenb/hdr/stack/mac/nr/sched_nr.h" #include "srsenb/hdr/stack/mac/nr/sched_nr.h"
#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h"
#include "srsran/common/thread_pool.h" #include "srsran/common/thread_pool.h"
@ -156,6 +157,7 @@ int sched_nr::cell_cfg(srsran::const_span<cell_cfg_t> cell_list)
pending_results.reset(new sched_result_manager(cell_list.size())); pending_results.reset(new sched_result_manager(cell_list.size()));
sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg)); sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg));
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -145,11 +145,16 @@ int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info)
bwp_ctxt::bwp_ctxt(const bwp_params& bwp_cfg) : cfg(&bwp_cfg), ra(bwp_cfg), grid(bwp_cfg) {} bwp_ctxt::bwp_ctxt(const bwp_params& bwp_cfg) : cfg(&bwp_cfg), ra(bwp_cfg), grid(bwp_cfg) {}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
serv_cell_ctxt::serv_cell_ctxt(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_) serv_cell_ctxt::serv_cell_ctxt(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_)
{ {
for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) { for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) {
bwps.emplace_back(cell_cfg_.bwps[bwp_id]); bwps.emplace_back(cell_cfg_.bwps[bwp_id]);
} }
// Pre-allocate HARQs in common pool of softbuffers
harq_softbuffer_pool::get_instance().init_pool(cfg->nof_prb());
} }
} // namespace sched_nr_impl } // namespace sched_nr_impl

@ -100,13 +100,14 @@ bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_)
return true; return true;
} }
harq_entity::harq_entity(uint32_t nof_harq_procs) harq_entity::harq_entity(uint32_t nprb, uint32_t nof_harq_procs)
{ {
// Create HARQs
dl_harqs.reserve(nof_harq_procs); dl_harqs.reserve(nof_harq_procs);
ul_harqs.reserve(nof_harq_procs); ul_harqs.reserve(nof_harq_procs);
for (uint32_t pid = 0; pid < nof_harq_procs; ++pid) { for (uint32_t pid = 0; pid < nof_harq_procs; ++pid) {
dl_harqs.emplace_back(pid); dl_harqs.emplace_back(pid, nprb);
ul_harqs.emplace_back(pid); ul_harqs.emplace_back(pid, nprb);
} }
} }

@ -191,6 +191,7 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr
} else { } else {
srsran_assert(pdsch.sch.grant.tb[0].tbs == (int)ue.h_dl->tbs(), "The TBS did not remain constant in retx"); srsran_assert(pdsch.sch.grant.tb[0].tbs == (int)ue.h_dl->tbs(), "The TBS did not remain constant in retx");
} }
pdsch.tx_softbuffer[0] = *ue.h_dl->get_softbuffer();
return alloc_result::success; return alloc_result::success;
} }

@ -23,7 +23,11 @@ slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_params& cell_params_) : ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_params& cell_params_) :
rnti(rnti_), cc(cell_params_.cc), bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_), cell_params(cell_params_) rnti(rnti_),
cc(cell_params_.cc),
bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_),
cell_params(cell_params_),
harq_ent(cell_params_.nof_prb())
{} {}
void ue_carrier::push_feedback(srsran::move_callback<void(ue_carrier&)> callback) void ue_carrier::push_feedback(srsran::move_callback<void(ue_carrier&)> callback)

@ -11,7 +11,7 @@
*/ */
#include "sched_nr_ue_ded_test_suite.h" #include "sched_nr_ue_ded_test_suite.h"
#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" #include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h"
#include "srsran/common/test_common.h" #include "srsran/common/test_common.h"
namespace srsenb { namespace srsenb {
@ -22,6 +22,7 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o
{ {
tti_point pdcch_tti = cc_out.tti; tti_point pdcch_tti = cc_out.tti;
const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->pdcch_dl; const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->pdcch_dl;
const pdsch_list_t& pdschs = cc_out.dl_cc_result->pdsch;
// Iterate over UE PDCCH allocations // Iterate over UE PDCCH allocations
for (const pdcch_dl_t& pdcch : pdcchs) { for (const pdcch_dl_t& pdcch : pdcchs) {
@ -49,6 +50,11 @@ void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_o
} }
TESTASSERT(ue.cc_list[cc_out.cc].pending_acks[(pdcch_tti + k1).to_uint()] % 4 == pdcch.dci.dai); TESTASSERT(ue.cc_list[cc_out.cc].pending_acks[(pdcch_tti + k1).to_uint()] % 4 == pdcch.dci.dai);
} }
for (const pdsch_t& pdsch : pdschs) {
TESTASSERT(pdsch.tx_softbuffer[0].buffer_b != nullptr);
TESTASSERT(pdsch.tx_softbuffer[0].max_cb > 0);
}
} }
} // namespace srsenb } // namespace srsenb

Loading…
Cancel
Save