SRSUE: Refactored work_dl for NR. Added NZP-CSI-RS measurement

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent e68c822505
commit 653177ca7c

@ -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

@ -57,6 +57,7 @@ private:
mutable std::mutex metrics_mutex;
/// CSI-RS measurements
std::mutex csi_measurements_mutex;
std::array<srsran_csi_measurements_t, SRSRAN_CSI_MAX_NOF_RESOURCES> 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<std::mutex> 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

@ -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;

Loading…
Cancel
Save