Integrated PUCCH decoding in gNb

This commit is contained in:
Xavier Arteaga 2021-06-29 18:41:37 +02:00 committed by Xavier Arteaga
parent 3fe9176750
commit e764a26136
7 changed files with 132 additions and 20 deletions

View File

@ -127,9 +127,11 @@ struct phy_cfg_nr_t {
* @brief Compute UCI configuration for the given slot from the pending PDSCH ACK resources, periodic CSI,
* periodic SR resources and so on.
*/
bool get_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
const srsran_pdsch_ack_nr_t& pdsch_ack,
srsran_uci_cfg_nr_t& uci_cfg) const;
bool get_pucch(const srsran_slot_cfg_t& slot_cfg,
const srsran_pdsch_ack_nr_t& pdsch_ack,
srsran_pucch_nr_common_cfg_t& cfg,
srsran_uci_cfg_nr_t& uci_cfg,
srsran_pucch_nr_resource_t& resource) const;
};
} // namespace srsran

View File

@ -21,6 +21,10 @@ SRSRAN_API int srsran_harq_ack_resource(const srsran_harq_ack_cfg_hl_t* cfg,
const srsran_dci_dl_nr_t* dci_dl,
srsran_harq_ack_resource_t* pdsch_ack_resource);
SRSRAN_API int srsran_harq_ack_gen_uci_cfg(const srsran_harq_ack_cfg_hl_t* cfg,
const srsran_pdsch_ack_nr_t* ack_info,
srsran_uci_cfg_nr_t* uci_cfg);
SRSRAN_API int srsran_harq_ack_pack(const srsran_harq_ack_cfg_hl_t* cfg,
const srsran_pdsch_ack_nr_t* ack_info,
srsran_uci_data_nr_t* uci_data);

View File

@ -280,12 +280,22 @@ bool phy_cfg_nr_t::get_pdsch_ack_resource(const srsran_dci_dl_nr_t& dci_dl,
return srsran_harq_ack_resource(&harq_ack, &dci_dl, &ack_resource) == SRSRAN_SUCCESS;
}
bool phy_cfg_nr_t::get_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
const srsran_pdsch_ack_nr_t& pdsch_ack,
srsran_uci_cfg_nr_t& uci_cfg) const
bool phy_cfg_nr_t::get_pucch(const srsran_slot_cfg_t& slot_cfg,
const srsran_pdsch_ack_nr_t& ack_info,
srsran_pucch_nr_common_cfg_t& cfg,
srsran_uci_cfg_nr_t& uci_cfg,
srsran_pucch_nr_resource_t& resource) const
{
// TBD
// ...
// Generate configuration for HARQ feedback
if (srsran_harq_ack_gen_uci_cfg(&harq_ack, &ack_info, &uci_cfg) < SRSRAN_SUCCESS) {
return false;
}
// Select PUCCH resource
if (srsran_ra_ul_nr_pucch_resource(&pucch, &uci_cfg, &resource) < SRSRAN_SUCCESS) {
ERROR("Selecting PUCCH resource");
return false;
}
return true;
}

View File

@ -109,6 +109,7 @@ slot_worker::~slot_worker()
}
}
srsran_gnb_dl_free(&gnb_dl);
srsran_gnb_ul_free(&gnb_ul);
}
cf_t* slot_worker::get_buffer_rx(uint32_t antenna_idx)
@ -169,6 +170,8 @@ bool slot_worker::work_ul()
std::array<char, 512> str;
srsran_uci_data_nr_t uci_data = {.cfg = pucch.uci_cfg, .value = uci_value};
srsran_gnb_ul_pucch_info(&gnb_ul, &pucch.resource, &uci_data, str.data(), (uint32_t)str.size());
logger.info("PUCCH: %s", str.data());
}
}
@ -184,7 +187,7 @@ bool slot_worker::work_dl()
{
// Retrieve Scheduling for the current processing DL slot
stack_interface_phy_nr::dl_sched_t dl_sched = {};
if (stack.get_dl_sched(ul_slot_cfg, dl_sched) < SRSRAN_SUCCESS) {
if (stack.get_dl_sched(dl_slot_cfg, dl_sched) < SRSRAN_SUCCESS) {
logger.error("Error retrieving DL scheduling");
return false;
}

View File

@ -116,6 +116,7 @@ void sf_worker::work_imp()
for (uint32_t i = 0; i < (uint32_t)cc_workers.size(); i++) {
tx_buffer.set(i, cc_workers[i]->get_tx_buffer(0));
}
tx_buffer.set_nof_samples(SRSRAN_SF_LEN_PRB_NR(phy_state.cfg.carrier.nof_prb));
// Always call worker_end before returning
common.worker_end(this, true, tx_buffer, tx_time, true);

View File

@ -13,6 +13,7 @@
#ifndef SRSRAN_DUMMY_GNB_STACK_H
#define SRSRAN_DUMMY_GNB_STACK_H
#include <mutex>
#include <srsran/adt/circular_array.h>
#include <srsran/common/phy_cfg_nr.h>
#include <srsran/interfaces/gnb_interfaces.h>
@ -35,6 +36,49 @@ private:
srsran::phy_cfg_nr_t phy_cfg = {};
bool valid = false;
// HARQ feedback
class pending_ack_t
{
private:
std::mutex mutex;
srsran_pdsch_ack_nr_t ack = {};
public:
void push_ack(srsran_harq_ack_resource_t& ack_resource)
{
// Prepare ACK information
srsran_harq_ack_m_t ack_m = {};
ack_m.resource = ack_resource;
ack_m.present = true;
std::unique_lock<std::mutex> lock(mutex);
ack.nof_cc = 1;
srsran_harq_ack_insert_m(&ack, &ack_m);
}
srsran_pdsch_ack_nr_t get_ack()
{
std::unique_lock<std::mutex> lock(mutex);
return ack;
}
uint32_t get_dai()
{
std::unique_lock<std::mutex> lock(mutex);
return ack.cc[0].M % 4;
}
void reset()
{
std::unique_lock<std::mutex> lock(mutex);
ack = {};
}
};
srsran::circular_array<pending_ack_t, TTIMOD_SZ> pending_ack;
struct dummy_harq_proc {
static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC;
std::vector<uint8_t> data;
@ -68,12 +112,14 @@ public:
uint32_t dl_start_rb = 0; ///< Start resource block
uint32_t dl_length_rb = 0l; ///< Number of resource blocks
uint32_t dl_time_res = 0; ///< PDSCH time resource
std::string log_level = "debug";
};
gnb_dummy_stack(args_t args) :
mcs(args.mcs), rnti(args.rnti), dl_time_res(args.dl_time_res), phy_cfg(args.phy_cfg), ss_id(args.ss_id)
{
random_gen = srsran_random_init(0x1234);
logger.set_level(srslog::str_to_basic_level(args.log_level));
// Select DCI locations
for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) {
@ -135,6 +181,8 @@ public:
int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override
{
logger.set_context(slot_cfg.idx);
// Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip
if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) {
return SRSRAN_SUCCESS;
@ -159,6 +207,9 @@ public:
return SRSRAN_ERROR;
}
uint32_t harq_feedback = dl_data_to_ul_ack[slot_cfg.idx];
uint32_t harq_ack_slot_idx = TTI_ADD(slot_cfg.idx, harq_feedback);
// Fill DCI fields
srsran_dci_dl_nr_t& dci = pdcch.dci;
dci.freq_domain_assigment = dl_freq_res;
@ -167,10 +218,14 @@ public:
dci.rv = 0;
dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2;
dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME;
dci.dai = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME;
dci.dai = pending_ack[harq_ack_slot_idx].get_dai();
dci.tpc = 1;
dci.pucch_resource = 0;
dci.harq_feedback = dl_data_to_ul_ack[TTI_TX(slot_cfg.idx)];
if (dci.ctx.format == srsran_dci_format_nr_1_0) {
dci.harq_feedback = dl_data_to_ul_ack[slot_cfg.idx] - 1;
} else {
dci.harq_feedback = slot_cfg.idx;
}
// Create PDSCH configuration
if (not phy_cfg.get_pdsch_cfg(slot_cfg, dci, pdsch.sch)) {
@ -191,10 +246,46 @@ public:
dl_sched.pdcch_dl.push_back(pdcch);
dl_sched.pdsch.push_back(pdsch);
// Generate PDSCH HARQ Feedback
srsran_harq_ack_resource_t ack_resource = {};
if (not phy_cfg.get_pdsch_ack_resource(dci, ack_resource)) {
logger.error("Error getting ack resource");
return SRSRAN_ERROR;
}
// Calculate PUCCH slot and push resource
pending_ack[harq_ack_slot_idx].push_ack(ack_resource);
return SRSRAN_SUCCESS;
}
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override { return 0; }
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override
{
logger.set_context(slot_cfg.idx);
srsran_pdsch_ack_nr_t ack = pending_ack[slot_cfg.idx].get_ack();
pending_ack[slot_cfg.idx].reset();
if (ack.nof_cc > 0) {
mac_interface_phy_nr::pucch_t pucch = {};
if (logger.debug.enabled()) {
std::array<char, 512> str = {};
if (srsran_harq_ack_info(&ack, str.data(), (uint32_t)str.size()) > 0) {
logger.debug("HARQ feedback:\n%s", str.data());
}
}
if (not phy_cfg.get_pucch(slot_cfg, ack, pucch.pucch_cfg, pucch.uci_cfg, pucch.resource)) {
logger.error("Error getting UCI CFG");
return SRSRAN_ERROR;
}
ul_sched.pucch.push_back(pucch);
}
return 0;
}
};
#endif // SRSRAN_DUMMY_GNB_STACK_H

View File

@ -108,10 +108,10 @@ test_bench::args_t::args_t(int argc, char** argv)
phy_cfg.pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2;
phy_cfg.tdd.pattern1.period_ms = 10;
phy_cfg.tdd.pattern1.nof_dl_slots = 7;
phy_cfg.tdd.pattern1.nof_dl_symbols = 6;
phy_cfg.tdd.pattern1.nof_ul_slots = 4;
phy_cfg.tdd.pattern1.nof_ul_symbols = 4;
phy_cfg.tdd.pattern1.nof_dl_slots = 5;
phy_cfg.tdd.pattern1.nof_dl_symbols = 0;
phy_cfg.tdd.pattern1.nof_ul_slots = 5;
phy_cfg.tdd.pattern1.nof_ul_symbols = 0;
phy_cfg.pdsch.dmrs_typeA.additional_pos = srsran_dmrs_sch_add_pos_1;
phy_cfg.pdsch.dmrs_typeA.present = true;
@ -206,8 +206,9 @@ test_bench::args_t::args_t(int argc, char** argv)
phy_cfg.harq_ack.dl_data_to_ul_ack[2] = 6;
phy_cfg.harq_ack.dl_data_to_ul_ack[3] = 5;
phy_cfg.harq_ack.dl_data_to_ul_ack[4] = 4;
phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 12;
phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 11;
phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 4;
phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 4;
phy_cfg.harq_ack.dl_data_to_ul_ack[7] = 4;
phy_cfg.harq_ack.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic;
phy_cfg.prach.freq_offset = 2;
@ -272,10 +273,10 @@ int main(int argc, char** argv)
// Parse test bench arguments
test_bench::args_t args(argc, argv);
args.gnb_args.log_id_preamble = "GNB/";
args.gnb_args.log_level = "warning";
args.gnb_args.log_level = "info";
args.gnb_args.nof_phy_threads = 1;
args.ue_args.log.id_preamble = " UE/";
args.ue_args.log.phy_level = "warning";
args.ue_args.log.phy_level = "info";
args.ue_args.log.phy_hex_limit = 0;
args.ue_args.nof_phy_threads = 1;