mirror of https://github.com/PentHertz/srsLTE.git
Integrated PUCCH decoding in gNb
This commit is contained in:
parent
3fe9176750
commit
e764a26136
|
@ -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,
|
* @brief Compute UCI configuration for the given slot from the pending PDSCH ACK resources, periodic CSI,
|
||||||
* periodic SR resources and so on.
|
* periodic SR resources and so on.
|
||||||
*/
|
*/
|
||||||
bool get_uci_cfg(const srsran_slot_cfg_t& slot_cfg,
|
bool get_pucch(const srsran_slot_cfg_t& slot_cfg,
|
||||||
const srsran_pdsch_ack_nr_t& pdsch_ack,
|
const srsran_pdsch_ack_nr_t& pdsch_ack,
|
||||||
srsran_uci_cfg_nr_t& uci_cfg) const;
|
srsran_pucch_nr_common_cfg_t& cfg,
|
||||||
|
srsran_uci_cfg_nr_t& uci_cfg,
|
||||||
|
srsran_pucch_nr_resource_t& resource) const;
|
||||||
};
|
};
|
||||||
} // namespace srsran
|
} // namespace srsran
|
||||||
|
|
||||||
|
|
|
@ -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,
|
const srsran_dci_dl_nr_t* dci_dl,
|
||||||
srsran_harq_ack_resource_t* pdsch_ack_resource);
|
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,
|
SRSRAN_API int srsran_harq_ack_pack(const srsran_harq_ack_cfg_hl_t* cfg,
|
||||||
const srsran_pdsch_ack_nr_t* ack_info,
|
const srsran_pdsch_ack_nr_t* ack_info,
|
||||||
srsran_uci_data_nr_t* uci_data);
|
srsran_uci_data_nr_t* uci_data);
|
||||||
|
|
|
@ -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;
|
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,
|
bool phy_cfg_nr_t::get_pucch(const srsran_slot_cfg_t& slot_cfg,
|
||||||
const srsran_pdsch_ack_nr_t& pdsch_ack,
|
const srsran_pdsch_ack_nr_t& ack_info,
|
||||||
srsran_uci_cfg_nr_t& uci_cfg) const
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ slot_worker::~slot_worker()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
srsran_gnb_dl_free(&gnb_dl);
|
srsran_gnb_dl_free(&gnb_dl);
|
||||||
|
srsran_gnb_ul_free(&gnb_ul);
|
||||||
}
|
}
|
||||||
|
|
||||||
cf_t* slot_worker::get_buffer_rx(uint32_t antenna_idx)
|
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;
|
std::array<char, 512> str;
|
||||||
srsran_uci_data_nr_t uci_data = {.cfg = pucch.uci_cfg, .value = uci_value};
|
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());
|
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
|
// Retrieve Scheduling for the current processing DL slot
|
||||||
stack_interface_phy_nr::dl_sched_t dl_sched = {};
|
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");
|
logger.error("Error retrieving DL scheduling");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ void sf_worker::work_imp()
|
||||||
for (uint32_t i = 0; i < (uint32_t)cc_workers.size(); i++) {
|
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(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
|
// Always call worker_end before returning
|
||||||
common.worker_end(this, true, tx_buffer, tx_time, true);
|
common.worker_end(this, true, tx_buffer, tx_time, true);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#ifndef SRSRAN_DUMMY_GNB_STACK_H
|
#ifndef SRSRAN_DUMMY_GNB_STACK_H
|
||||||
#define SRSRAN_DUMMY_GNB_STACK_H
|
#define SRSRAN_DUMMY_GNB_STACK_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <srsran/adt/circular_array.h>
|
#include <srsran/adt/circular_array.h>
|
||||||
#include <srsran/common/phy_cfg_nr.h>
|
#include <srsran/common/phy_cfg_nr.h>
|
||||||
#include <srsran/interfaces/gnb_interfaces.h>
|
#include <srsran/interfaces/gnb_interfaces.h>
|
||||||
|
@ -35,6 +36,49 @@ private:
|
||||||
srsran::phy_cfg_nr_t phy_cfg = {};
|
srsran::phy_cfg_nr_t phy_cfg = {};
|
||||||
bool valid = false;
|
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 {
|
struct dummy_harq_proc {
|
||||||
static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC;
|
static const uint32_t MAX_TB_SZ = SRSRAN_LDPC_MAX_LEN_CB * SRSRAN_SCH_NR_MAX_NOF_CB_LDPC;
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
|
@ -68,12 +112,14 @@ public:
|
||||||
uint32_t dl_start_rb = 0; ///< Start resource block
|
uint32_t dl_start_rb = 0; ///< Start resource block
|
||||||
uint32_t dl_length_rb = 0l; ///< Number of resource blocks
|
uint32_t dl_length_rb = 0l; ///< Number of resource blocks
|
||||||
uint32_t dl_time_res = 0; ///< PDSCH time resource
|
uint32_t dl_time_res = 0; ///< PDSCH time resource
|
||||||
|
std::string log_level = "debug";
|
||||||
};
|
};
|
||||||
|
|
||||||
gnb_dummy_stack(args_t args) :
|
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)
|
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);
|
random_gen = srsran_random_init(0x1234);
|
||||||
|
logger.set_level(srslog::str_to_basic_level(args.log_level));
|
||||||
|
|
||||||
// Select DCI locations
|
// Select DCI locations
|
||||||
for (uint32_t slot = 0; slot < SRSRAN_NOF_SF_X_FRAME; slot++) {
|
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
|
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
|
// 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)) {
|
if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) {
|
||||||
return SRSRAN_SUCCESS;
|
return SRSRAN_SUCCESS;
|
||||||
|
@ -159,6 +207,9 @@ public:
|
||||||
return SRSRAN_ERROR;
|
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
|
// Fill DCI fields
|
||||||
srsran_dci_dl_nr_t& dci = pdcch.dci;
|
srsran_dci_dl_nr_t& dci = pdcch.dci;
|
||||||
dci.freq_domain_assigment = dl_freq_res;
|
dci.freq_domain_assigment = dl_freq_res;
|
||||||
|
@ -167,10 +218,14 @@ public:
|
||||||
dci.rv = 0;
|
dci.rv = 0;
|
||||||
dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2;
|
dci.ndi = (slot_cfg.idx / SRSRAN_NOF_SF_X_FRAME) % 2;
|
||||||
dci.pid = slot_cfg.idx % SRSRAN_NOF_SF_X_FRAME;
|
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.tpc = 1;
|
||||||
dci.pucch_resource = 0;
|
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
|
// Create PDSCH configuration
|
||||||
if (not phy_cfg.get_pdsch_cfg(slot_cfg, dci, pdsch.sch)) {
|
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.pdcch_dl.push_back(pdcch);
|
||||||
dl_sched.pdsch.push_back(pdsch);
|
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;
|
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
|
#endif // SRSRAN_DUMMY_GNB_STACK_H
|
||||||
|
|
|
@ -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.pusch.typeA_pos = srsran_dmrs_sch_typeA_pos_2;
|
||||||
|
|
||||||
phy_cfg.tdd.pattern1.period_ms = 10;
|
phy_cfg.tdd.pattern1.period_ms = 10;
|
||||||
phy_cfg.tdd.pattern1.nof_dl_slots = 7;
|
phy_cfg.tdd.pattern1.nof_dl_slots = 5;
|
||||||
phy_cfg.tdd.pattern1.nof_dl_symbols = 6;
|
phy_cfg.tdd.pattern1.nof_dl_symbols = 0;
|
||||||
phy_cfg.tdd.pattern1.nof_ul_slots = 4;
|
phy_cfg.tdd.pattern1.nof_ul_slots = 5;
|
||||||
phy_cfg.tdd.pattern1.nof_ul_symbols = 4;
|
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.additional_pos = srsran_dmrs_sch_add_pos_1;
|
||||||
phy_cfg.pdsch.dmrs_typeA.present = true;
|
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[2] = 6;
|
||||||
phy_cfg.harq_ack.dl_data_to_ul_ack[3] = 5;
|
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[4] = 4;
|
||||||
phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 12;
|
phy_cfg.harq_ack.dl_data_to_ul_ack[5] = 4;
|
||||||
phy_cfg.harq_ack.dl_data_to_ul_ack[6] = 11;
|
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.harq_ack.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic;
|
||||||
|
|
||||||
phy_cfg.prach.freq_offset = 2;
|
phy_cfg.prach.freq_offset = 2;
|
||||||
|
@ -272,10 +273,10 @@ int main(int argc, char** argv)
|
||||||
// Parse test bench arguments
|
// Parse test bench arguments
|
||||||
test_bench::args_t args(argc, argv);
|
test_bench::args_t args(argc, argv);
|
||||||
args.gnb_args.log_id_preamble = "GNB/";
|
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.gnb_args.nof_phy_threads = 1;
|
||||||
args.ue_args.log.id_preamble = " UE/";
|
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.log.phy_hex_limit = 0;
|
||||||
args.ue_args.nof_phy_threads = 1;
|
args.ue_args.nof_phy_threads = 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue