From e764a26136caba84d982be7137ab0ad40b1dbb0b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 29 Jun 2021 18:41:37 +0200 Subject: [PATCH] Integrated PUCCH decoding in gNb --- lib/include/srsran/common/phy_cfg_nr.h | 8 ++- lib/include/srsran/phy/phch/harq_ack.h | 4 ++ lib/src/common/phy_cfg_nr.cc | 20 ++++-- srsenb/src/phy/nr/slot_worker.cc | 5 +- srsue/src/phy/nr/sf_worker.cc | 1 + test/phy/dummy_gnb_stack.h | 97 +++++++++++++++++++++++++- test/phy/nr_dl_flood.cc | 17 ++--- 7 files changed, 132 insertions(+), 20 deletions(-) diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index c29c90f11..c61dc245d 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -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 diff --git a/lib/include/srsran/phy/phch/harq_ack.h b/lib/include/srsran/phy/phch/harq_ack.h index e926ae606..bba7719ac 100644 --- a/lib/include/srsran/phy/phch/harq_ack.h +++ b/lib/include/srsran/phy/phch/harq_ack.h @@ -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); diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc index 471a6ea62..729839084 100644 --- a/lib/src/common/phy_cfg_nr.cc +++ b/lib/src/common/phy_cfg_nr.cc @@ -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; } diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index ee4ec1755..bd89652ba 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -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 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; } diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index b761c0c8a..99436f87c 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -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); diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 155d1cb7c..5705d78ee 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_DUMMY_GNB_STACK_H #define SRSRAN_DUMMY_GNB_STACK_H +#include #include #include #include @@ -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 lock(mutex); + + ack.nof_cc = 1; + + srsran_harq_ack_insert_m(&ack, &ack_m); + } + + srsran_pdsch_ack_nr_t get_ack() + { + std::unique_lock lock(mutex); + + return ack; + } + uint32_t get_dai() + { + std::unique_lock lock(mutex); + return ack.cc[0].M % 4; + } + + void reset() + { + std::unique_lock lock(mutex); + + ack = {}; + } + }; + srsran::circular_array 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 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 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 diff --git a/test/phy/nr_dl_flood.cc b/test/phy/nr_dl_flood.cc index a6428b553..56bb8e87f 100644 --- a/test/phy/nr_dl_flood.cc +++ b/test/phy/nr_dl_flood.cc @@ -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;