From 653177ca7c2fcd9190dbea56f6ca022591c86006 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 4 May 2021 20:51:08 +0200 Subject: [PATCH] SRSUE: Refactored work_dl for NR. Added NZP-CSI-RS measurement --- srsue/hdr/phy/nr/cc_worker.h | 6 + srsue/hdr/phy/nr/state.h | 14 +- srsue/src/phy/nr/cc_worker.cc | 256 ++++++++++++++++++++-------------- 3 files changed, 168 insertions(+), 108 deletions(-) diff --git a/srsue/hdr/phy/nr/cc_worker.h b/srsue/hdr/phy/nr/cc_worker.h index 9ea44588e..4c95702f4 100644 --- a/srsue/hdr/phy/nr/cc_worker.h +++ b/srsue/hdr/phy/nr/cc_worker.h @@ -57,6 +57,12 @@ private: // Methods for DCI blind search void decode_pdcch_ul(); void decode_pdcch_dl(); + + // Method for decode PDSCH + bool decode_pdsch_dl(); + + // Method for measurements + bool measure(); }; } // namespace nr diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index 80cb79a1d..0cc50622d 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -57,6 +57,7 @@ private: mutable std::mutex metrics_mutex; /// CSI-RS measurements + std::mutex csi_measurements_mutex; std::array csi_measurements = {}; /** @@ -90,7 +91,7 @@ public: csi_measurements[0].K_csi_rs = 1; csi_measurements[0].nof_ports = 1; csi_measurements[1].K_csi_rs = 4; - csi_measurements[0].nof_ports = 1; + csi_measurements[1].nof_ports = 1; } /** @@ -422,6 +423,17 @@ public: // Reset all metrics reset_metrics_(); } + + void new_nzp_csi_rs_channel_measurement(const srsran_csi_measurements_t& new_measure, uint32_t resource_set_id) + { + std::lock_guard lock(csi_measurements_mutex); + + if (srsran_csi_new_nzp_csi_rs_measurement( + cfg.csi.csi_resources, csi_measurements.data(), &new_measure, resource_set_id) < SRSRAN_SUCCESS) { + ERROR("Error processing new NZP-CSI-RS"); + return; + } + } }; } // namespace nr } // namespace srsue diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 454a24378..e0025a0ec 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -192,135 +192,177 @@ void cc_worker::decode_pdcch_ul() } } -bool cc_worker::work_dl() +bool cc_worker::decode_pdsch_dl() { - // Do NOT process any DL if it is not configured - if (not configured) { - return true; + // Get DL grant for this TTI, if available + uint32_t pid = 0; + srsran_sch_cfg_nr_t pdsch_cfg = {}; + srsran_pdsch_ack_resource_nr_t ack_resource = {}; + if (not phy->get_dl_pending_grant(dl_slot_cfg.idx, pdsch_cfg, ack_resource, pid)) { + // Early return if no grant was available + return false; } + // Notify MAC about PDSCH grant + mac_interface_phy_nr::tb_action_dl_t dl_action = {}; + mac_interface_phy_nr::mac_nr_grant_dl_t mac_dl_grant = {}; + mac_dl_grant.rnti = pdsch_cfg.grant.rnti; + mac_dl_grant.pid = pid; + mac_dl_grant.rv = pdsch_cfg.grant.tb[0].rv; + mac_dl_grant.ndi = pdsch_cfg.grant.tb[0].ndi; + mac_dl_grant.tbs = pdsch_cfg.grant.tb[0].tbs / 8; + mac_dl_grant.tti = dl_slot_cfg.idx; + phy->stack->new_grant_dl(0, mac_dl_grant, &dl_action); + + // Abort if MAC says it doesn't need the TB + if (not dl_action.tb.enabled) { + // Force positive ACK + if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_c) { + phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, true); + } - // Check if it is a DL slot, if not skip - if (!srsran_tdd_nr_is_dl(&phy->cfg.tdd, 0, dl_slot_cfg.idx)) { + logger.info("Decoding not required. Skipping PDSCH. ack_tti_tx=%d", TTI_ADD(dl_slot_cfg.idx, ack_resource.k1)); return true; } - // Run FFT - srsran_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); + // Get data buffer + srsran::unique_byte_buffer_t data = srsran::make_byte_buffer(); + if (data == nullptr) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } + data->N_bytes = pdsch_cfg.grant.tb[0].tbs / 8U; - // Decode PDCCH DL first - decode_pdcch_dl(); + // Initialise PDSCH Result + srsran_pdsch_res_nr_t pdsch_res = {}; + pdsch_res.tb[0].payload = data->msg; + pdsch_cfg.grant.tb[0].softbuffer.rx = dl_action.tb.softbuffer; - // Decode PDCCH UL after - decode_pdcch_ul(); + // Decode actual PDSCH transmission + if (srsran_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, &pdsch_res) < SRSRAN_SUCCESS) { + ERROR("Error decoding PDSCH"); + return false; + } - // Get DL grant for this TTI, if available - uint32_t pid = 0; - srsran_sch_cfg_nr_t pdsch_cfg = {}; - srsran_pdsch_ack_resource_nr_t ack_resource = {}; - if (phy->get_dl_pending_grant(dl_slot_cfg.idx, pdsch_cfg, ack_resource, pid)) { - // Notify MAC about PDSCH grant - mac_interface_phy_nr::tb_action_dl_t dl_action = {}; - mac_interface_phy_nr::mac_nr_grant_dl_t mac_dl_grant = {}; - mac_dl_grant.rnti = pdsch_cfg.grant.rnti; - mac_dl_grant.pid = pid; - mac_dl_grant.rv = pdsch_cfg.grant.tb[0].rv; - mac_dl_grant.ndi = pdsch_cfg.grant.tb[0].ndi; - mac_dl_grant.tbs = pdsch_cfg.grant.tb[0].tbs / 8; - mac_dl_grant.tti = dl_slot_cfg.idx; - phy->stack->new_grant_dl(0, mac_dl_grant, &dl_action); - - // Abort if MAC says it doesn't need the TB - if (not dl_action.tb.enabled) { - // Force positive ACK - if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_c) { - phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, true); - } + // Logging + if (logger.info.enabled()) { + str_info_t str; + srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str.data(), (uint32_t)str.size()); - logger.info("Decoding not required. Skipping PDSCH. ack_tti_tx=%d", TTI_ADD(dl_slot_cfg.idx, ack_resource.k1)); - return true; + if (logger.debug.enabled()) { + str_extra_t str_extra; + srsran_sch_cfg_nr_info(&pdsch_cfg, str_extra.data(), (uint32_t)str_extra.size()); + logger.info(pdsch_res.tb[0].payload, + pdsch_cfg.grant.tb[0].tbs / 8, + "PDSCH: cc=%d pid=%d %s\n%s", + cc_idx, + pid, + str.data(), + str_extra.data()); + } else { + logger.info(pdsch_res.tb[0].payload, + pdsch_cfg.grant.tb[0].tbs / 8, + "PDSCH: cc=%d pid=%d %s ack_tti_tx=%d", + cc_idx, + pid, + str.data(), + TTI_ADD(dl_slot_cfg.idx, ack_resource.k1)); } + } - // Get data buffer - srsran::unique_byte_buffer_t data = srsran::make_byte_buffer(); - if (data == nullptr) { - logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); - return false; - } - data->N_bytes = pdsch_cfg.grant.tb[0].tbs / 8U; + // Enqueue PDSCH ACK information only if the RNTI is type C + if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_c) { + phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, pdsch_res.tb[0].crc); + } - // Initialise PDSCH Result - srsran_pdsch_res_nr_t pdsch_res = {}; - pdsch_res.tb[0].payload = data->msg; - pdsch_cfg.grant.tb[0].softbuffer.rx = dl_action.tb.softbuffer; + // Notify MAC about PDSCH decoding result + mac_interface_phy_nr::tb_action_dl_result_t mac_dl_result = {}; + mac_dl_result.ack = pdsch_res.tb[0].crc; + mac_dl_result.payload = mac_dl_result.ack ? std::move(data) : nullptr; // only pass data when successful + phy->stack->tb_decoded(cc_idx, mac_dl_grant, std::move(mac_dl_result)); - // Decode actual PDSCH transmission - if (srsran_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, &pdsch_res) < SRSRAN_SUCCESS) { - ERROR("Error decoding PDSCH"); - return false; - } + if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_ra) { + phy->rar_grant_tti = dl_slot_cfg.idx; + } - // Logging - if (logger.info.enabled()) { - str_info_t str; - srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str.data(), (uint32_t)str.size()); + if (pdsch_res.tb[0].crc) { + // Generate DL metrics + dl_metrics_t dl_m = {}; + dl_m.mcs = pdsch_cfg.grant.tb[0].mcs; + dl_m.fec_iters = pdsch_res.tb[0].avg_iter; + dl_m.evm = pdsch_res.evm[0]; + phy->set_dl_metrics(dl_m); + + // Generate Synch metrics + sync_metrics_t sync_m = {}; + sync_m.cfo = ue_dl.chest.cfo; + phy->set_sync_metrics(sync_m); + + // Generate channel metrics + ch_metrics_t ch_m = {}; + ch_m.n = ue_dl.chest.noise_estimate; + ch_m.sinr = ue_dl.chest.snr_db; + ch_m.rsrp = ue_dl.chest.rsrp_dbm; + ch_m.sync_err = ue_dl.chest.sync_error; + phy->set_channel_metrics(ch_m); + } - if (logger.debug.enabled()) { - str_extra_t str_extra; - srsran_sch_cfg_nr_info(&pdsch_cfg, str_extra.data(), (uint32_t)str_extra.size()); - logger.info(pdsch_res.tb[0].payload, - pdsch_cfg.grant.tb[0].tbs / 8, - "PDSCH: cc=%d pid=%d %s\n%s", - cc_idx, - pid, - str.data(), - str_extra.data()); - } else { - logger.info(pdsch_res.tb[0].payload, - pdsch_cfg.grant.tb[0].tbs / 8, - "PDSCH: cc=%d pid=%d %s ack_tti_tx=%d", - cc_idx, - pid, - str.data(), - TTI_ADD(dl_slot_cfg.idx, ack_resource.k1)); - } + return true; +} + +bool cc_worker::measure() +{ + // Iterate all NZP-CSI-RS and perform channel measurements + for (uint32_t resource_set_id = 0; resource_set_id < SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS; resource_set_id++) { + // Select NZP-CSI-RS set + const srsran_csi_rs_nzp_set_t& nzp_set = phy->cfg.pdsch.nzp_csi_rs_sets[resource_set_id]; + + srsran_csi_measurements_t measurements = {}; + int n = srsran_ue_dl_nr_csi_measure(&ue_dl, &dl_slot_cfg, &nzp_set, &measurements); + if (n < SRSRAN_SUCCESS) { + logger.error("Error measuring CSI-RS"); + return false; } - // Enqueue PDSCH ACK information only if the RNTI is type C - if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_c) { - phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, pdsch_res.tb[0].crc); + // Report new measurement to the PHY state + if (n > 0) { + phy->new_nzp_csi_rs_channel_measurement(measurements, resource_set_id); } + } - // Notify MAC about PDSCH decoding result - mac_interface_phy_nr::tb_action_dl_result_t mac_dl_result = {}; - mac_dl_result.ack = pdsch_res.tb[0].crc; - mac_dl_result.payload = mac_dl_result.ack ? std::move(data) : nullptr; // only pass data when successful - phy->stack->tb_decoded(cc_idx, mac_dl_grant, std::move(mac_dl_result)); + return true; +} - if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_ra) { - phy->rar_grant_tti = dl_slot_cfg.idx; - } +bool cc_worker::work_dl() +{ + // Do NOT process any DL if it is not configured + if (not configured) { + return true; + } - if (pdsch_res.tb[0].crc) { - // Generate DL metrics - dl_metrics_t dl_m = {}; - dl_m.mcs = pdsch_cfg.grant.tb[0].mcs; - dl_m.fec_iters = pdsch_res.tb[0].avg_iter; - dl_m.evm = pdsch_res.evm[0]; - phy->set_dl_metrics(dl_m); - - // Generate Synch metrics - sync_metrics_t sync_m = {}; - sync_m.cfo = ue_dl.chest.cfo; - phy->set_sync_metrics(sync_m); - - // Generate channel metrics - ch_metrics_t ch_m = {}; - ch_m.n = ue_dl.chest.noise_estimate; - ch_m.sinr = ue_dl.chest.snr_db; - ch_m.rsrp = ue_dl.chest.rsrp_dbm; - ch_m.sync_err = ue_dl.chest.sync_error; - phy->set_channel_metrics(ch_m); - } + // Check if it is a DL slot, if not skip + if (!srsran_tdd_nr_is_dl(&phy->cfg.tdd, 0, dl_slot_cfg.idx)) { + return true; + } + + // Run FFT + srsran_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); + + // Decode PDCCH DL first + decode_pdcch_dl(); + + // Decode PDCCH UL after + decode_pdcch_ul(); + + // Decode PDSCH + if (not decode_pdsch_dl()) { + logger.error("Error decoding PDSCH, aborting work DL"); + return false; + } + + // Measure CSI-RS + if (not measure()) { + logger.error("Error measuring CSI-RS, aborting work DL"); + return false; } return true;