From fe8727050b67c4d2e836c5d3afebd1d3370cc330 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Tue, 13 Apr 2021 22:27:04 +0200 Subject: [PATCH 01/46] Added new rrc_nr to phy flattening functions and fixes --- lib/include/srsran/asn1/rrc_nr_utils.h | 4 + .../srsran/phy/ch_estimation/csi_rs_cfg.h | 2 + lib/include/srsran/phy/common/phy_common_nr.h | 1 - lib/src/asn1/rrc_nr_utils.cc | 337 +++++++++++++++++- lib/test/asn1/rrc_nr_utils_test.cc | 126 ++++++- srsue/hdr/stack/rrc/rrc_nr.h | 6 +- srsue/src/stack/rrc/rrc_nr.cc | 93 ++++- 7 files changed, 560 insertions(+), 9 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 6f101550f..025b68ce1 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -48,6 +48,8 @@ struct sched_request_res_cfg_s; struct dmrs_ul_cfg_s; struct beta_offsets_s; struct uci_on_pusch_s; +struct zp_csi_rs_res_s; +struct nzp_csi_rs_res_s; } // namespace rrc_nr } // namespace asn1 @@ -88,6 +90,8 @@ bool make_phy_dmrs_additional_pos(const asn1::rrc_nr::dmrs_ul_cfg_s& dmrs_ul_cfg bool make_phy_beta_offsets(const asn1::rrc_nr::beta_offsets_s& beta_offsets, srsran_beta_offsets_t* srsran_beta_offsets); bool make_phy_pusch_scaling(const asn1::rrc_nr::uci_on_pusch_s& uci_on_pusch, float* scaling); +bool make_phy_zp_csi_rs_resource(const asn1::rrc_nr::zp_csi_rs_res_s & zp_csi_rs_res, srsran_csi_rs_zp_resource_t* zp_csi_rs_resource); +bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s & nzp_csi_rs_res, srsran_csi_rs_nzp_resource_t* csi_rs_nzp_resource); /*************************** * MAC Config **************************/ diff --git a/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h b/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h index de52f62bc..3da47d268 100644 --- a/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h +++ b/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h @@ -94,6 +94,7 @@ typedef struct SRSRAN_API { * @brief Contains TS 38.331 NZP-CSI-RS-Resource flattened configuration */ typedef struct SRSRAN_API { + uint32_t id; srsran_csi_rs_resource_mapping_t resource_mapping; ///< CSI-RS time/frequency mapping float power_control_offset; ///< -8..15 dB float power_control_offset_ss; ///< -3, 0, 3, 6 dB @@ -114,6 +115,7 @@ typedef struct SRSRAN_API { * @brief Contains TS 38.331 ZP-CSI-RS-Resource flattened configuration */ typedef struct { + uint32_t id; srsran_csi_rs_resource_mapping_t resource_mapping; ///< CSI-RS time/frequency mapping srsran_csi_rs_period_and_offset_t periodicity; } srsran_csi_rs_zp_resource_t; diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 51fef7e2d..46f7b0476 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -310,7 +310,6 @@ typedef struct SRSRAN_API { */ typedef struct SRSRAN_API { uint32_t id; - uint32_t coreset_id; srsran_coreset_mapping_type_t mapping_type; uint32_t duration; bool freq_resources[SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE]; diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 66d7ef932..21d6a3d9f 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -564,8 +564,7 @@ bool make_phy_csi_report(const csi_report_cfg_s& csi_report_cfg, bool make_phy_coreset_cfg(const ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* in_srsran_coreset) { srsran_coreset_t srsran_coreset = {}; - srsran_coreset.coreset_id = ctrl_res_set.ctrl_res_set_id; - + srsran_coreset.id = ctrl_res_set.ctrl_res_set_id; switch (ctrl_res_set.precoder_granularity) { case ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle: srsran_coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; @@ -576,6 +575,18 @@ bool make_phy_coreset_cfg(const ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* asn1::log_warning("Invalid option for precoder_granularity %s", ctrl_res_set.precoder_granularity.to_string()); return false; }; + + switch (ctrl_res_set.cce_reg_map_type.type()) { + case ctrl_res_set_s::cce_reg_map_type_c_::types_opts::options::interleaved: + srsran_coreset.mapping_type = srsran_coreset_mapping_type_interleaved; + break; + case ctrl_res_set_s::cce_reg_map_type_c_::types_opts::options::non_interleaved: + srsran_coreset.mapping_type = srsran_coreset_mapping_type_non_interleaved; + break; + default: + asn1::log_warning("Invalid option for cce_reg_map_type: %s", ctrl_res_set.cce_reg_map_type.type().to_string()); + return false; + } srsran_coreset.duration = ctrl_res_set.dur; for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { srsran_coreset.freq_resources[i] = ctrl_res_set.freq_domain_res.get(SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE - 1 - i); @@ -828,6 +839,328 @@ bool make_phy_pusch_scaling(const uci_on_pusch_s& uci_on_pusch, float* in_scalin return true; } +bool make_phy_zp_csi_rs_resource(const asn1::rrc_nr::zp_csi_rs_res_s& zp_csi_rs_res, + srsran_csi_rs_zp_resource_t* out_zp_csi_rs_resource) +{ + srsran_csi_rs_zp_resource_t zp_csi_rs_resource; + zp_csi_rs_resource.id = zp_csi_rs_res.zp_csi_rs_res_id; + switch (zp_csi_rs_res.res_map.freq_domain_alloc.type()) { + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row1: + zp_csi_rs_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1; + for (uint32_t i = 0; i < zp_csi_rs_res.res_map.freq_domain_alloc.row1().length(); i++) { + zp_csi_rs_resource.resource_mapping.frequency_domain_alloc[i] = + zp_csi_rs_res.res_map.freq_domain_alloc.row1().get(zp_csi_rs_res.res_map.freq_domain_alloc.row1().length() - + 1 - i); + } + break; + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row2: + zp_csi_rs_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_2; + for (uint32_t i = 0; i < zp_csi_rs_res.res_map.freq_domain_alloc.row2().length(); i++) { + zp_csi_rs_resource.resource_mapping.frequency_domain_alloc[i] = + zp_csi_rs_res.res_map.freq_domain_alloc.row2().get(zp_csi_rs_res.res_map.freq_domain_alloc.row2().length() - + 1 - i); + } + break; + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row4: + zp_csi_rs_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_4; + for (uint32_t i = 0; i < zp_csi_rs_res.res_map.freq_domain_alloc.row4().length(); i++) { + zp_csi_rs_resource.resource_mapping.frequency_domain_alloc[i] = + zp_csi_rs_res.res_map.freq_domain_alloc.row4().get(zp_csi_rs_res.res_map.freq_domain_alloc.row4().length() - + 1 - i); + } + break; + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::other: + zp_csi_rs_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_other; + break; + default: + asn1::log_warning("Invalid option for freq_domain_alloc %s", + zp_csi_rs_res.res_map.freq_domain_alloc.type().to_string()); + return false; + } + zp_csi_rs_resource.resource_mapping.nof_ports = zp_csi_rs_res.res_map.nrof_ports.to_number(); + zp_csi_rs_resource.resource_mapping.first_symbol_idx = zp_csi_rs_res.res_map.first_ofdm_symbol_in_time_domain; + + switch (zp_csi_rs_res.res_map.cdm_type) { + case csi_rs_res_map_s::cdm_type_opts::options::no_cdm: + zp_csi_rs_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_nocdm; + break; + case csi_rs_res_map_s::cdm_type_opts::options::fd_cdm2: + zp_csi_rs_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_fd_cdm2; + break; + case csi_rs_res_map_s::cdm_type_opts::options::cdm4_fd2_td2: + zp_csi_rs_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_cdm4_fd2_td2; + break; + case csi_rs_res_map_s::cdm_type_opts::options::cdm8_fd2_td4: + zp_csi_rs_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_cdm8_fd2_td4; + break; + default: + asn1::log_warning("Invalid option for cdm_type %s", zp_csi_rs_res.res_map.cdm_type.to_string()); + return false; + } + + switch (zp_csi_rs_res.res_map.density.type()) { + case csi_rs_res_map_s::density_c_::types_opts::options::dot5: + switch (zp_csi_rs_res.res_map.density.dot5()) { + case csi_rs_res_map_s::density_c_::dot5_opts::options::even_prbs: + zp_csi_rs_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_dot5_even; + break; + case csi_rs_res_map_s::density_c_::dot5_opts::options::odd_prbs: + zp_csi_rs_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_dot5_odd; + break; + default: + asn1::log_warning("Invalid option for dot5 %s", zp_csi_rs_res.res_map.density.dot5().to_string()); + return false; + } + break; + case csi_rs_res_map_s::density_c_::types_opts::options::one: + zp_csi_rs_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_one; + break; + case csi_rs_res_map_s::density_c_::types_opts::options::three: + zp_csi_rs_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three; + break; + case csi_rs_res_map_s::density_c_::types_opts::options::spare: + zp_csi_rs_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_spare; + break; + default: + asn1::log_warning("Invalid option for density %s", zp_csi_rs_res.res_map.density.type().to_string()); + return false; + } + zp_csi_rs_resource.resource_mapping.freq_band.nof_rb = zp_csi_rs_res.res_map.freq_band.nrof_rbs; + zp_csi_rs_resource.resource_mapping.freq_band.start_rb = zp_csi_rs_res.res_map.freq_band.start_rb; + if(zp_csi_rs_res.periodicity_and_offset_present){ + switch (zp_csi_rs_res.periodicity_and_offset.type()) + { + case csi_res_periodicity_and_offset_c::types_opts::options::slots4: + zp_csi_rs_resource.periodicity.period = 4; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots4(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots5: + zp_csi_rs_resource.periodicity.period = 5; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots5(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots8: + zp_csi_rs_resource.periodicity.period = 8; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots8(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots10: + zp_csi_rs_resource.periodicity.period = 10; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots10(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots16: + zp_csi_rs_resource.periodicity.period = 16; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots16(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots20: + zp_csi_rs_resource.periodicity.period = 20; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots20(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots32: + zp_csi_rs_resource.periodicity.period = 32; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots32(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots40: + zp_csi_rs_resource.periodicity.period = 40; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots40(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots64: + zp_csi_rs_resource.periodicity.period = 64; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots64(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots80: + zp_csi_rs_resource.periodicity.period = 80; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots80(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots160: + zp_csi_rs_resource.periodicity.period = 160; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots160(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots320: + zp_csi_rs_resource.periodicity.period = 320; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots320(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots640: + zp_csi_rs_resource.periodicity.period = 640; + zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots640(); + break; + default: + asn1::log_warning("Invalid option for periodicity_and_offset %s", + zp_csi_rs_res.periodicity_and_offset.type().to_string()); + return false; + } + } else { + asn1::log_warning("Option periodicity_and_offset not present"); + return false; + } + + *out_zp_csi_rs_resource = zp_csi_rs_resource; + return true; +} + +bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nzp_csi_rs_res, + srsran_csi_rs_nzp_resource_t* out_csi_rs_nzp_resource) +{ + srsran_csi_rs_nzp_resource_t csi_rs_nzp_resource; + csi_rs_nzp_resource.id = asn1_nzp_csi_rs_res.nzp_csi_rs_res_id; + switch (asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.type()) { + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row1: + csi_rs_nzp_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1; + for (uint32_t i = 0; i < asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row1().length(); i++) { + csi_rs_nzp_resource.resource_mapping.frequency_domain_alloc[i] = + asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row1().get(asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row1().length() - + 1 - i); + } + break; + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row2: + csi_rs_nzp_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_2; + for (uint32_t i = 0; i < asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row2().length(); i++) { + csi_rs_nzp_resource.resource_mapping.frequency_domain_alloc[i] = + asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row2().get(asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row2().length() - + 1 - i); + } + break; + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row4: + csi_rs_nzp_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_4; + for (uint32_t i = 0; i < asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row4().length(); i++) { + csi_rs_nzp_resource.resource_mapping.frequency_domain_alloc[i] = + asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row4().get(asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row4().length() - + 1 - i); + } + break; + case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::other: + csi_rs_nzp_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_other; + break; + default: + asn1::log_warning("Invalid option for freq_domain_alloc %s", + asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.type().to_string()); + return false; + } + + csi_rs_nzp_resource.resource_mapping.nof_ports = asn1_nzp_csi_rs_res.res_map.nrof_ports.to_number(); + csi_rs_nzp_resource.resource_mapping.first_symbol_idx = asn1_nzp_csi_rs_res.res_map.first_ofdm_symbol_in_time_domain; + + switch (asn1_nzp_csi_rs_res.res_map.cdm_type) { + case csi_rs_res_map_s::cdm_type_opts::options::no_cdm: + csi_rs_nzp_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_nocdm; + break; + case csi_rs_res_map_s::cdm_type_opts::options::fd_cdm2: + csi_rs_nzp_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_fd_cdm2; + break; + case csi_rs_res_map_s::cdm_type_opts::options::cdm4_fd2_td2: + csi_rs_nzp_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_cdm4_fd2_td2; + break; + case csi_rs_res_map_s::cdm_type_opts::options::cdm8_fd2_td4: + csi_rs_nzp_resource.resource_mapping.cdm = srsran_csi_rs_cdm_t::srsran_csi_rs_cdm_cdm8_fd2_td4; + break; + default: + asn1::log_warning("Invalid option for cdm_type %s", asn1_nzp_csi_rs_res.res_map.cdm_type.to_string()); + return false; + } + + switch (asn1_nzp_csi_rs_res.res_map.density.type()) { + case csi_rs_res_map_s::density_c_::types_opts::options::dot5: + switch (asn1_nzp_csi_rs_res.res_map.density.dot5()) { + case csi_rs_res_map_s::density_c_::dot5_opts::options::even_prbs: + csi_rs_nzp_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_dot5_even; + break; + case csi_rs_res_map_s::density_c_::dot5_opts::options::odd_prbs: + csi_rs_nzp_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_dot5_odd; + break; + default: + asn1::log_warning("Invalid option for dot5 %s", asn1_nzp_csi_rs_res.res_map.density.dot5().to_string()); + return false; + } + break; + case csi_rs_res_map_s::density_c_::types_opts::options::one: + csi_rs_nzp_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_one; + break; + case csi_rs_res_map_s::density_c_::types_opts::options::three: + csi_rs_nzp_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three; + break; + case csi_rs_res_map_s::density_c_::types_opts::options::spare: + csi_rs_nzp_resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_spare; + break; + default: + asn1::log_warning("Invalid option for density %s", asn1_nzp_csi_rs_res.res_map.density.type().to_string()); + return false; + } + csi_rs_nzp_resource.resource_mapping.freq_band.nof_rb = asn1_nzp_csi_rs_res.res_map.freq_band.nrof_rbs; + csi_rs_nzp_resource.resource_mapping.freq_band.start_rb = asn1_nzp_csi_rs_res.res_map.freq_band.start_rb; + + csi_rs_nzp_resource.power_control_offset = asn1_nzp_csi_rs_res.pwr_ctrl_offset; + if (asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss_present) { + csi_rs_nzp_resource.power_control_offset_ss = asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss.to_number(); + } + + if(asn1_nzp_csi_rs_res.periodicity_and_offset_present){ + switch (asn1_nzp_csi_rs_res.periodicity_and_offset.type()) + { + case csi_res_periodicity_and_offset_c::types_opts::options::slots4: + csi_rs_nzp_resource.periodicity.period = 4; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots4(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots5: + csi_rs_nzp_resource.periodicity.period = 5; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots5(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots8: + csi_rs_nzp_resource.periodicity.period = 8; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots8(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots10: + csi_rs_nzp_resource.periodicity.period = 10; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots10(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots16: + csi_rs_nzp_resource.periodicity.period = 16; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots16(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots20: + csi_rs_nzp_resource.periodicity.period = 20; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots20(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots32: + csi_rs_nzp_resource.periodicity.period = 32; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots32(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots40: + csi_rs_nzp_resource.periodicity.period = 40; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots40(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots64: + csi_rs_nzp_resource.periodicity.period = 64; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots64(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots80: + csi_rs_nzp_resource.periodicity.period = 80; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots80(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots160: + csi_rs_nzp_resource.periodicity.period = 160; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots160(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots320: + csi_rs_nzp_resource.periodicity.period = 320; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots320(); + break; + case csi_res_periodicity_and_offset_c::types_opts::options::slots640: + csi_rs_nzp_resource.periodicity.period = 640; + csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots640(); + break; + default: + asn1::log_warning("Invalid option for periodicity_and_offset %s", + asn1_nzp_csi_rs_res.periodicity_and_offset.type().to_string()); + return false; + } + } else { + asn1::log_warning("Option periodicity_and_offset not present"); + return false; + } + + csi_rs_nzp_resource.scrambling_id = asn1_nzp_csi_rs_res.scrambling_id; + + *out_csi_rs_nzp_resource = csi_rs_nzp_resource; + return true; +} } // namespace srsran namespace srsenb { diff --git a/lib/test/asn1/rrc_nr_utils_test.cc b/lib/test/asn1/rrc_nr_utils_test.cc index 6ca70f121..50bae6a7f 100644 --- a/lib/test/asn1/rrc_nr_utils_test.cc +++ b/lib/test/asn1/rrc_nr_utils_test.cc @@ -126,7 +126,7 @@ int make_phy_coreset_cfg_test() srsran_coreset_t srsran_coreset; TESTASSERT(make_phy_coreset_cfg(ctrl_res_set, &srsran_coreset) == true); - TESTASSERT(srsran_coreset.coreset_id == 1); + TESTASSERT(srsran_coreset.id == 1); TESTASSERT(srsran_coreset.precoder_granularity == srsran_coreset_precoder_granularity_reg_bundle); TESTASSERT(srsran_coreset.duration == 1); TESTASSERT(srsran_coreset.mapping_type == srsran_coreset_mapping_type_non_interleaved); @@ -546,6 +546,127 @@ int make_phy_pusch_scaling_test() return SRSRAN_SUCCESS; } +int make_phy_zp_csi_rs_resource_test() +{ + srsran_csi_rs_zp_resource_t zp_csi_rs_resource0 = {}; + // Item 0 + // ZP-CSI-RS-Resource + // zp-CSI-RS-ResourceId: 0 + // resourceMapping + // frequencyDomainAllocation: row4 (2) + // row4: 80 [bit length 3, 5 LSB pad bits, 100. .... + // decimal value 4] + // nrofPorts: p4 (2) + // firstOFDMSymbolInTimeDomain: 8 + // cdm-Type: fd-CDM2 (1) + // density: one (1) + // one: NULL + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // periodicityAndOffset: slots80 (9) + // slots80: 1 + + asn1::rrc_nr::zp_csi_rs_res_s zp_csi_rs_res0; + zp_csi_rs_res0.res_map.freq_domain_alloc.set_row4(); + zp_csi_rs_res0.res_map.freq_domain_alloc.row4().from_string("100"); + zp_csi_rs_res0.res_map.nrof_ports = csi_rs_res_map_s::nrof_ports_opts::options::p4; + zp_csi_rs_res0.res_map.first_ofdm_symbol_in_time_domain = 8; + zp_csi_rs_res0.res_map.cdm_type = csi_rs_res_map_s::cdm_type_opts::options::fd_cdm2; + zp_csi_rs_res0.res_map.density.set_one(); + zp_csi_rs_res0.res_map.freq_band.start_rb = 0; + zp_csi_rs_res0.res_map.freq_band.nrof_rbs = 52; + zp_csi_rs_res0.periodicity_and_offset_present = true; + zp_csi_rs_res0.periodicity_and_offset.set_slots80() = 1; + + TESTASSERT(make_phy_zp_csi_rs_resource(zp_csi_rs_res0, &zp_csi_rs_resource0) == true); + + TESTASSERT(zp_csi_rs_resource0.resource_mapping.row == srsran_csi_rs_resource_mapping_row_4); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[0] == true); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[1] == false); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[2] == false); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.nof_ports == 4); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.first_symbol_idx == 8); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.cdm == srsran_csi_rs_cdm_fd_cdm2); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.density == srsran_csi_rs_resource_mapping_density_one); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.freq_band.start_rb == 0); + TESTASSERT(zp_csi_rs_resource0.resource_mapping.freq_band.nof_rb == 52); + TESTASSERT(zp_csi_rs_resource0.periodicity.period == 80); + TESTASSERT(zp_csi_rs_resource0.periodicity.offset == 1); + return SRSRAN_SUCCESS; +} + +int make_phy_nzp_csi_rs_resource_test() +{ + // nzp-CSI-RS-ResourceToAddModList: 5 items + // Item 0 + // NZP-CSI-RS-Resource + // nzp-CSI-RS-ResourceId: 0 + // resourceMapping + // frequencyDomainAllocation: row2 (1) + // row2: 8000 [bit length 12, 4 LSB pad bits, 1000 0000 0000 .... decimal value 2048] + // nrofPorts: p1 (0) + // firstOFDMSymbolInTimeDomain: 4 + // cdm-Type: noCDM (0) + // density: one (1) + // one: NULL + // freqBand + // startingRB: 0 + // nrofRBs: 52 + // powerControlOffset: 0dB + // powerControlOffsetSS: db0 (1) + // scramblingID: 0 + // periodicityAndOffset: slots80 (9) + // slots80: 1 + // qcl-InfoPeriodicCSI-RS: 0 + asn1::rrc_nr::nzp_csi_rs_res_s nzp_csi_rs_res; + nzp_csi_rs_res.nzp_csi_rs_res_id = 0; + nzp_csi_rs_res.res_map.freq_domain_alloc.set_row2(); + nzp_csi_rs_res.res_map.freq_domain_alloc.row2().from_string("100000000000"); + nzp_csi_rs_res.res_map.nrof_ports = csi_rs_res_map_s::nrof_ports_opts::options::p1; + nzp_csi_rs_res.res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_rs_res.res_map.cdm_type = csi_rs_res_map_s::cdm_type_opts::options::no_cdm; + nzp_csi_rs_res.res_map.density.set_one(); + nzp_csi_rs_res.res_map.freq_band.start_rb = 0; + nzp_csi_rs_res.res_map.freq_band.nrof_rbs = 52; + nzp_csi_rs_res.pwr_ctrl_offset = 0; + nzp_csi_rs_res.pwr_ctrl_offset_ss_present = true; + nzp_csi_rs_res.pwr_ctrl_offset_ss = nzp_csi_rs_res_s::pwr_ctrl_offset_ss_opts::options::db0; + nzp_csi_rs_res.scrambling_id = 0; + nzp_csi_rs_res.periodicity_and_offset_present = true; + nzp_csi_rs_res.periodicity_and_offset.set_slots80() = 1; + + srsran_csi_rs_nzp_resource_t nzp_resource_0; + TESTASSERT(make_phy_nzp_csi_rs_resource(nzp_csi_rs_res, &nzp_resource_0) == true); + + TESTASSERT(nzp_resource_0.resource_mapping.row == srsran_csi_rs_resource_mapping_row_2); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[0] == true); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[1] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[2] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[3] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[4] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[5] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[6] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[7] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[8] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[9] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[10] == false); + TESTASSERT(nzp_resource_0.resource_mapping.frequency_domain_alloc[11] == false); + TESTASSERT(nzp_resource_0.resource_mapping.nof_ports == 1); + TESTASSERT(nzp_resource_0.resource_mapping.first_symbol_idx == 4); + TESTASSERT(nzp_resource_0.resource_mapping.cdm == srsran_csi_rs_cdm_nocdm); + TESTASSERT(nzp_resource_0.resource_mapping.density == srsran_csi_rs_resource_mapping_density_one); + TESTASSERT(nzp_resource_0.resource_mapping.freq_band.start_rb == 0); + TESTASSERT(nzp_resource_0.resource_mapping.freq_band.nof_rb == 52); + TESTASSERT(nzp_resource_0.power_control_offset == 0); + TESTASSERT(nzp_resource_0.power_control_offset_ss == 0); + TESTASSERT(nzp_resource_0.scrambling_id == 0); + TESTASSERT(nzp_resource_0.periodicity.period == 80); + TESTASSERT(nzp_resource_0.periodicity.offset == 1); + + return SRSRAN_SUCCESS; +} + int main() { auto& asn1_logger = srslog::fetch_basic_logger("ASN1", false); @@ -572,7 +693,8 @@ int main() TESTASSERT(make_phy_dmrs_additional_pos_test() == SRSRAN_SUCCESS); TESTASSERT(make_phy_beta_offsets_test() == SRSRAN_SUCCESS); TESTASSERT(make_phy_pusch_scaling_test() == SRSRAN_SUCCESS); - + TESTASSERT(make_phy_zp_csi_rs_resource_test() == SRSRAN_SUCCESS); + TESTASSERT(make_phy_nzp_csi_rs_resource_test() == SRSRAN_SUCCESS); srslog::flush(); printf("Success\n"); diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index bd9220baf..82edb843c 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -188,8 +188,10 @@ private: std::map drb_eps_bearer_id; // Map of drb id to eps_bearer_id // temporary maps for building the pucch nr resources - std::map res_list; - std::map res_list_present; + std::map res_list; + std::map res_list_present; + std::map csi_rs_zp_res; + std::map csi_rs_nzp_res; bool apply_cell_group_cfg(const asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg); bool apply_radio_bearer_cfg(const asn1::rrc_nr::radio_bearer_cfg_s& radio_bearer_cfg); diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 288d8462d..e2aed6574 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -578,11 +578,61 @@ bool rrc_nr::apply_sp_cell_init_dl_pdcch(const asn1::rrc_nr::pdcch_cfg_s& pdcch_ logger.warning("Option search_spaces_to_add_mod_list not present"); return false; } + if (pdcch_cfg.ctrl_res_set_to_add_mod_list_present) { + for (uint32_t i = 0; i < pdcch_cfg.ctrl_res_set_to_add_mod_list.size(); i++) { + srsran_coreset_t coreset; + if (make_phy_coreset_cfg(pdcch_cfg.ctrl_res_set_to_add_mod_list[i], &coreset) == true) { + phy_cfg.pdcch.coreset[coreset.id] = coreset; + phy_cfg.pdcch.coreset_present[coreset.id] = true; + } else { + logger.warning("Warning while building coreset structure"); + return false; + } + } + } else { + logger.warning("Option ctrl_res_set_to_add_mod_list not present"); + } return true; } bool rrc_nr::apply_sp_cell_init_dl_pdsch(const asn1::rrc_nr::pdsch_cfg_s& pdsch_cfg) { + if (pdsch_cfg.zp_csi_rs_res_to_add_mod_list_present) { + for (uint32_t i = 0; i < pdsch_cfg.zp_csi_rs_res_to_add_mod_list.size(); i++) { + srsran_csi_rs_zp_resource_t zp_csi_rs_resource; + if (make_phy_zp_csi_rs_resource(pdsch_cfg.zp_csi_rs_res_to_add_mod_list[i], &zp_csi_rs_resource) == true) { + // temporally store csi_rs_zp_res + csi_rs_zp_res[zp_csi_rs_resource.id] = zp_csi_rs_resource; + } else { + logger.warning("Warning while building zp_csi_rs resource"); + return false; + } + } + } else { + logger.warning("Option zp_csi_rs_res_to_add_mod_list not present"); + return false; + } + + if (pdsch_cfg.p_zp_csi_rs_res_set_present) { + if (pdsch_cfg.p_zp_csi_rs_res_set.type() == setup_release_c::types_opts::setup) { + for (uint32_t i = 0; i < pdsch_cfg.p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.size(); i++) { + uint8_t res = pdsch_cfg.p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list[i]; + // use temporally stored values to assign + if (csi_rs_zp_res.find(res) == csi_rs_zp_res.end()) { + logger.warning("Can not find p_zp_csi_rs_res in temporally stored csi_rs_zp_res"); + return false; + } + phy_cfg.pdsch.p_zp_csi_rs_set.data[i] = csi_rs_zp_res[res]; + phy_cfg.pdsch.p_zp_csi_rs_set.count += 1; + } + } else { + logger.warning("Option p_zp_csi_rs_res_set not of type setup"); + return false; + } + } else { + logger.warning("Option p_zp_csi_rs_res_set not present"); + return false; + } return true; } @@ -627,6 +677,45 @@ bool rrc_nr::apply_csi_meas_cfg(const asn1::rrc_nr::csi_meas_cfg_s& csi_meas_cfg logger.warning("Option csi_report_cfg_to_add_mod_list not present"); return false; } + + if (csi_meas_cfg.nzp_csi_rs_res_to_add_mod_list_present) { + for (uint32_t i = 0; i < csi_meas_cfg.nzp_csi_rs_res_to_add_mod_list.size(); i++) { + srsran_csi_rs_nzp_resource_t csi_rs_nzp_resource; + if (make_phy_nzp_csi_rs_resource(csi_meas_cfg.nzp_csi_rs_res_to_add_mod_list[i], &csi_rs_nzp_resource) == true) { + // temporally store csi_rs_zp_res + csi_rs_nzp_res[csi_rs_nzp_resource.id] = csi_rs_nzp_resource; + } else { + logger.warning("Warning while building phy_nzp_csi_rs resource"); + return false; + } + } + } else { + logger.warning("Option nzp_csi_rs_res_to_add_mod_list not present"); + return false; + } + + if (csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list_present) { + for (uint32_t i = 0; i < csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list.size(); i++) { + uint8_t set_id = csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list[i].nzp_csi_res_set_id; + for (uint32_t j = 0; j < csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list[i].nzp_csi_rs_res.size(); j++) { + uint8_t res = csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list[i].nzp_csi_rs_res[j]; + // use temporally stored values to assign + if (csi_rs_nzp_res.find(res) == csi_rs_nzp_res.end()) { + logger.warning("Can not find p_zp_csi_rs_res in temporally stored csi_rs_zp_res"); + return false; + } + phy_cfg.pdsch.nzp_csi_rs_sets[set_id].data[i] = csi_rs_nzp_res[res]; + phy_cfg.pdsch.nzp_csi_rs_sets[set_id].count += 1; + } + if (csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list[i].trs_info_present) { + phy_cfg.pdsch.nzp_csi_rs_sets[set_id].trs_info = true; + } + } + } else { + logger.warning("Option p_zp_csi_rs_res_set not present"); + return false; + } + return true; } @@ -640,8 +729,8 @@ bool rrc_nr::apply_dl_common_cfg(const asn1::rrc_nr::dl_cfg_common_s& dl_cfg_com if (pdcch_cfg_common.common_ctrl_res_set_present) { srsran_coreset_t coreset; if (make_phy_coreset_cfg(pdcch_cfg_common.common_ctrl_res_set, &coreset) == true) { - phy_cfg.pdcch.coreset[coreset.coreset_id] = coreset; - phy_cfg.pdcch.coreset_present[coreset.coreset_id] = true; + phy_cfg.pdcch.coreset[coreset.id] = coreset; + phy_cfg.pdcch.coreset_present[coreset.id] = true; } else { logger.warning("Warning while building coreset structure"); return false; From 1cbd1c9d2652d7d9b31420d6412a084bae40273b Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 14 Apr 2021 11:50:50 +0200 Subject: [PATCH 02/46] Deleted hardcoded phy config --- .../interfaces/rrc_nr_interface_types.h | 847 +----------------- 1 file changed, 1 insertion(+), 846 deletions(-) diff --git a/lib/include/srsran/interfaces/rrc_nr_interface_types.h b/lib/include/srsran/interfaces/rrc_nr_interface_types.h index c96e8c4cb..20d900d2c 100644 --- a/lib/include/srsran/interfaces/rrc_nr_interface_types.h +++ b/lib/include/srsran/interfaces/rrc_nr_interface_types.h @@ -35,852 +35,7 @@ struct phy_cfg_nr_t { phy_cfg_nr_t() { - // physicalCellGroupConfig - // pdsch-HARQ-ACK-Codebook: dynamic (1) - harq_ack.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; - - // commonControlResourceSet - // controlResourceSetId: 1 - // frequencyDomainResources: ff0000000000 - // duration: 1 - // cce-REG-MappingType: nonInterleaved (1) - // nonInterleaved: NULL - // precoderGranularity: sameAsREG-bundle (0) - pdcch.coreset[1].coreset_id = 1; - pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - pdcch.coreset[1].duration = 1; - pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved; - for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { - pdcch.coreset[1].freq_resources[i] = (i < 8); - } - pdcch.coreset_present[1] = true; - - // spCellConfigDedicated - // initialDownlinkBWP - // pdcch-Config: setup (1) - // setup - // controlResourceSetToAddModList: 1 item - // Item 0 - // ControlResourceSet - // controlResourceSetId: 2 - // frequencyDomainResources: ff0000000000 [bit length 45, 3 LSB pad bits, 1111 1111 0000 - // 0000 0000 0000 0000 0000 0000 0000 0000 0... decimal value 35046933135360] - // duration: 1 - // cce-REG-MappingType: nonInterleaved (1) - // nonInterleaved: NULL - // precoderGranularity: sameAsREG-bundle (0) - pdcch.coreset[2].id = 2; - pdcch.coreset[2].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - pdcch.coreset[2].duration = 1; - pdcch.coreset[2].mapping_type = srsran_coreset_mapping_type_non_interleaved; - for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { - pdcch.coreset[2].freq_resources[i] = (i < 8); - } - pdcch.coreset_present[2] = true; - - // pdsch-Config: setup (1) - // setup - // dmrs-DownlinkForPDSCH-MappingTypeA: setup (1) - // setup - // dmrs-AdditionalPosition: pos1 (1) - // tci-StatesToAddModList: 1 item - // Item 0 - // TCI-State - // tci-StateId: 0 - // qcl-Type1 - // referenceSignal: ssb (1) - // ssb: 0 - // qcl-Type: typeD (3) - // resourceAllocation: resourceAllocationType1 (1) - // rbg-Size: config1 (0) - // prb-BundlingType: staticBundling (0) - // staticBundling - // bundleSize: wideband (1) - // zp-CSI-RS-ResourceToAddModList: 1 item - // Item 0 - // ZP-CSI-RS-Resource - // zp-CSI-RS-ResourceId: 0 - // resourceMapping - // frequencyDomainAllocation: row4 (2) - // row4: 80 [bit length 3, 5 LSB pad bits, 100. .... - // decimal value 4] - // nrofPorts: p4 (2) - // firstOFDMSymbolInTimeDomain: 8 - // cdm-Type: fd-CDM2 (1) - // density: one (1) - // one: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // periodicityAndOffset: slots80 (9) - // slots80: 1 - // p-ZP-CSI-RS-ResourceSet: setup (1) - // setup - // zp-CSI-RS-ResourceSetId: 0 - // zp-CSI-RS-ResourceIdList: 1 item - // Item 0 - // ZP-CSI-RS-ResourceId: 0 - srsran_csi_rs_zp_resource_t zp_csi_rs_resource0 = {}; - zp_csi_rs_resource0.resource_mapping.row = srsran_csi_rs_resource_mapping_row_4; - zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[0] = true; - zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[1] = false; - zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[2] = false; - zp_csi_rs_resource0.resource_mapping.nof_ports = 4; - zp_csi_rs_resource0.resource_mapping.first_symbol_idx = 8; - zp_csi_rs_resource0.resource_mapping.cdm = srsran_csi_rs_cdm_fd_cdm2; - zp_csi_rs_resource0.resource_mapping.density = srsran_csi_rs_resource_mapping_density_one; - zp_csi_rs_resource0.resource_mapping.freq_band.start_rb = 0; - zp_csi_rs_resource0.resource_mapping.freq_band.nof_rb = 52; - zp_csi_rs_resource0.periodicity.period = 80; - zp_csi_rs_resource0.periodicity.offset = 1; - pdsch.p_zp_csi_rs_set.data[0] = zp_csi_rs_resource0; - pdsch.p_zp_csi_rs_set.count = 1; - - // pdsch-ConfigCommon: setup (1) - // setup - // pdsch-TimeDomainAllocationList: 2 items - // Item 0 - // PDSCH-TimeDomainResourceAllocation - // mappingType: typeA (0) - // startSymbolAndLength: 40 - // Item 1 - // PDSCH-TimeDomainResourceAllocation - // mappingType: typeA (0) - // startSymbolAndLength: 57 - pdsch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; - pdsch.common_time_ra[0].sliv = 40; - pdsch.common_time_ra[0].k = 0; - pdsch.common_time_ra[1].mapping_type = srsran_sch_mapping_type_A; - pdsch.common_time_ra[1].sliv = 57; - pdsch.common_time_ra[1].k = 0; - pdsch.nof_common_time_ra = 2; - - // pusch-ConfigCommon: setup (1) - // setup - // pusch-TimeDomainAllocationList: 2 items - // Item 0 - // PUSCH-TimeDomainResourceAllocation - // k2: 4 - // mappingType: typeA (0) - // startSymbolAndLength: 27 - // Item 1 - // PUSCH-TimeDomainResourceAllocation - // k2: 5 - // mappingType: typeA (0) - // startSymbolAndLength: 27 - // p0-NominalWithGrant: -90dBm - pusch.common_time_ra[0].mapping_type = srsran_sch_mapping_type_A; - pusch.common_time_ra[0].sliv = 27; - pusch.common_time_ra[0].k = 4; - pusch.common_time_ra[1].mapping_type = srsran_sch_mapping_type_A; - pusch.common_time_ra[1].sliv = 27; - pusch.common_time_ra[1].k = 5; - pusch.nof_common_time_ra = 2; - - // pusch-Config: setup (1) - // setup - // dmrs-UplinkForPUSCH-MappingTypeA: setup (1) - // setup - // dmrs-AdditionalPosition: pos1 (1) - // transformPrecodingDisabled - pusch.dmrs_typeA.additional_pos = srsran_dmrs_sch_add_pos_1; - pusch.dmrs_typeA.present = true; - // pusch-PowerControl - // msg3-Alpha: alpha1 (7) - // p0-NominalWithoutGrant: -90dBm - // p0-AlphaSets: 1 item - // Item 0 - // P0-PUSCH-AlphaSet - // p0-PUSCH-AlphaSetId: 0 - // p0: 0dB - // alpha: alpha1 (7) - // pathlossReferenceRSToAddModList: 1 item - // Item 0 - // PUSCH-PathlossReferenceRS - // pusch-PathlossReferenceRS-Id: 0 - // referenceSignal: ssb-Index (0) - // ssb-Index: 0 - // sri-PUSCH-MappingToAddModList: 1 item - // Item 0 - // SRI-PUSCH-PowerControl - // sri-PUSCH-PowerControlId: 0 - // sri-PUSCH-PathlossReferenceRS-Id: 0 - // sri-P0-PUSCH-AlphaSetId: 0 - // sri-PUSCH-ClosedLoopIndex: i0 (0) - // resourceAllocation: resourceAllocationType1 (1) - // uci-OnPUSCH: setup (1) - // setup - // betaOffsets: semiStatic (1) - // semiStatic - // betaOffsetACK-Index1: 9 - // betaOffsetACK-Index2: 9 - // betaOffsetACK-Index3: 9 - pusch.beta_offsets.ack_index1 = 9; - pusch.beta_offsets.ack_index2 = 9; - pusch.beta_offsets.ack_index3 = 9; - - // betaOffsetCSI-Part1-Index1: 6 - // betaOffsetCSI-Part1-Index2: 6 - pusch.beta_offsets.csi1_index1 = 6; - pusch.beta_offsets.csi1_index2 = 6; - - // betaOffsetCSI-Part2-Index1: 6 - // betaOffsetCSI-Part2-Index2: 6 - pusch.beta_offsets.csi2_index1 = 6; - pusch.beta_offsets.csi2_index2 = 6; - - // scaling: f1 (3) - pusch.scaling = 1; - - // pucch-Config: setup (1) - // setup - // resourceSetToAddModList: 2 items - pucch.enabled = true; - // Item 0 - // PUCCH-ResourceSet - // pucch-ResourceSetId: 0 - // resourceList: 8 items - // Item 0 - // PUCCH-ResourceId: 0 - // Item 1 - // PUCCH-ResourceId: 1 - // Item 2 - // PUCCH-ResourceId: 2 - // Item 3 - // PUCCH-ResourceId: 3 - // Item 4 - // PUCCH-ResourceId: 4 - // Item 5 - // PUCCH-ResourceId: 5 - // Item 6 - // PUCCH-ResourceId: 6 - // Item 7 - // PUCCH-ResourceId: 7 - pucch.sets[0].nof_resources = 8; - - // Item 1 - // PUCCH-ResourceSet - // pucch-ResourceSetId: 1 - // resourceList: 8 items - // Item 0 - // PUCCH-ResourceId: 8 - // Item 1 - // PUCCH-ResourceId: 9 - // Item 2 - // PUCCH-ResourceId: 10 - // Item 3 - // PUCCH-ResourceId: 11 - // Item 4 - // PUCCH-ResourceId: 12 - // Item 5 - // PUCCH-ResourceId: 13 - // Item 6 - // PUCCH-ResourceId: 14 - // Item 7 - // PUCCH-ResourceId: 15 - pucch.sets[1].nof_resources = 8; - - // resourceToAddModList: 18 items - // Item 0 - // PUCCH-Resource - // pucch-ResourceId: 0 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 0 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 0 - pucch.sets[0].resources[0].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[0].starting_prb = 0; - pucch.sets[0].resources[0].initial_cyclic_shift = 0; - pucch.sets[0].resources[0].nof_symbols = 14; - pucch.sets[0].resources[0].start_symbol_idx = 0; - pucch.sets[0].resources[0].time_domain_occ = 0; - - // Item 1 - // PUCCH-Resource - // pucch-ResourceId: 1 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 4 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 0 - pucch.sets[0].resources[1].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[1].starting_prb = 0; - pucch.sets[0].resources[1].initial_cyclic_shift = 4; - pucch.sets[0].resources[1].nof_symbols = 14; - pucch.sets[0].resources[1].start_symbol_idx = 0; - pucch.sets[0].resources[1].time_domain_occ = 0; - - // Item 2 - // PUCCH-Resource - // pucch-ResourceId: 2 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 8 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 0 - pucch.sets[0].resources[2].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[2].starting_prb = 0; - pucch.sets[0].resources[2].initial_cyclic_shift = 8; - pucch.sets[0].resources[2].nof_symbols = 14; - pucch.sets[0].resources[2].start_symbol_idx = 0; - pucch.sets[0].resources[2].time_domain_occ = 0; - - // Item 3 - // PUCCH-Resource - // pucch-ResourceId: 3 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 0 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 1 - pucch.sets[0].resources[3].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[3].starting_prb = 0; - pucch.sets[0].resources[3].initial_cyclic_shift = 0; - pucch.sets[0].resources[3].nof_symbols = 14; - pucch.sets[0].resources[3].start_symbol_idx = 0; - pucch.sets[0].resources[3].time_domain_occ = 1; - - // Item 4 - // PUCCH-Resource - // pucch-ResourceId: 4 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 4 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 1 - pucch.sets[0].resources[4].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[4].starting_prb = 0; - pucch.sets[0].resources[4].initial_cyclic_shift = 4; - pucch.sets[0].resources[4].nof_symbols = 14; - pucch.sets[0].resources[4].start_symbol_idx = 0; - pucch.sets[0].resources[4].time_domain_occ = 1; - - // Item 5 - // PUCCH-Resource - // pucch-ResourceId: 5 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 8 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 1 - pucch.sets[0].resources[5].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[5].starting_prb = 0; - pucch.sets[0].resources[5].initial_cyclic_shift = 8; - pucch.sets[0].resources[5].nof_symbols = 14; - pucch.sets[0].resources[5].start_symbol_idx = 0; - pucch.sets[0].resources[5].time_domain_occ = 1; - - // Item 6 - // PUCCH-Resource - // pucch-ResourceId: 6 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 0 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 2 - pucch.sets[0].resources[6].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[6].starting_prb = 0; - pucch.sets[0].resources[6].initial_cyclic_shift = 0; - pucch.sets[0].resources[6].nof_symbols = 14; - pucch.sets[0].resources[6].start_symbol_idx = 0; - pucch.sets[0].resources[6].time_domain_occ = 2; - - // Item 7 - // PUCCH-Resource - // pucch-ResourceId: 7 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 4 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 2 - pucch.sets[0].resources[7].format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sets[0].resources[7].starting_prb = 0; - pucch.sets[0].resources[7].initial_cyclic_shift = 0; - pucch.sets[0].resources[7].nof_symbols = 14; - pucch.sets[0].resources[7].start_symbol_idx = 0; - pucch.sets[0].resources[7].time_domain_occ = 2; - - // Item 8 - // PUCCH-Resource - // pucch-ResourceId: 8 - // startingPRB: 51 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 0 - pucch.sets[1].resources[0].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[0].starting_prb = 51; - pucch.sets[1].resources[0].nof_prb = 1; - pucch.sets[1].resources[0].nof_symbols = 2; - pucch.sets[1].resources[0].start_symbol_idx = 0; - - // Item 9 - // PUCCH-Resource - // pucch-ResourceId: 9 - // startingPRB: 51 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 2 - pucch.sets[1].resources[1].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[1].starting_prb = 51; - pucch.sets[1].resources[1].nof_prb = 1; - pucch.sets[1].resources[1].nof_symbols = 2; - pucch.sets[1].resources[1].start_symbol_idx = 2; - - // Item 10 - // PUCCH-Resource - // pucch-ResourceId: 10 - // startingPRB: 51 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 4 - pucch.sets[1].resources[2].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[2].starting_prb = 51; - pucch.sets[1].resources[2].nof_prb = 1; - pucch.sets[1].resources[2].nof_symbols = 2; - pucch.sets[1].resources[2].start_symbol_idx = 4; - - // Item 11 - // PUCCH-Resource - // pucch-ResourceId: 11 - // startingPRB: 51 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 6 - pucch.sets[1].resources[3].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[3].starting_prb = 51; - pucch.sets[1].resources[3].nof_prb = 1; - pucch.sets[1].resources[3].nof_symbols = 2; - pucch.sets[1].resources[3].start_symbol_idx = 6; - - // Item 12 - // PUCCH-Resource - // pucch-ResourceId: 12 - // startingPRB: 51 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 8 - pucch.sets[1].resources[4].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[4].starting_prb = 51; - pucch.sets[1].resources[4].nof_prb = 1; - pucch.sets[1].resources[4].nof_symbols = 2; - pucch.sets[1].resources[4].start_symbol_idx = 8; - - // Item 13 - // PUCCH-Resource - // pucch-ResourceId: 13 - // startingPRB: 51 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 10 - pucch.sets[1].resources[5].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[5].starting_prb = 51; - pucch.sets[1].resources[5].nof_prb = 1; - pucch.sets[1].resources[5].nof_symbols = 2; - pucch.sets[1].resources[5].start_symbol_idx = 10; - - // Item 14 - // PUCCH-Resource - // pucch-ResourceId: 14 - // startingPRB: 51 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 12 - pucch.sets[1].resources[6].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[6].starting_prb = 51; - pucch.sets[1].resources[6].nof_prb = 1; - pucch.sets[1].resources[6].nof_symbols = 2; - pucch.sets[1].resources[6].start_symbol_idx = 12; - - // Item 15 - // PUCCH-Resource - // pucch-ResourceId: 15 - // startingPRB: 1 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 0 - pucch.sets[1].resources[7].format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch.sets[1].resources[7].starting_prb = 51; - pucch.sets[1].resources[7].nof_prb = 1; - pucch.sets[1].resources[7].nof_symbols = 2; - pucch.sets[1].resources[7].start_symbol_idx = 2; - - // Item 16 - // PUCCH-Resource - // pucch-ResourceId: 16 - // startingPRB: 0 - // format: format1 (1) - // format1 - // initialCyclicShift: 8 - // nrofSymbols: 14 - // startingSymbolIndex: 0 - // timeDomainOCC: 2 - pucch.sr_resources[1].resource.format = SRSRAN_PUCCH_NR_FORMAT_1; - pucch.sr_resources[1].resource.starting_prb = 0; - pucch.sr_resources[1].resource.initial_cyclic_shift = 8; - pucch.sr_resources[1].resource.nof_symbols = 14; - pucch.sr_resources[1].resource.start_symbol_idx = 0; - pucch.sr_resources[1].resource.time_domain_occ = 2; - - // Item 17 - // PUCCH-Resource - // pucch-ResourceId: 17 - // startingPRB: 1 - // format: format2 (2) - // format2 - // nrofPRBs: 1 - // nrofSymbols: 2 - // startingSymbolIndex: 2 - srsran_pucch_nr_resource_t pucch_res_17 = {}; - pucch_res_17.starting_prb = 1; - pucch_res_17.format = SRSRAN_PUCCH_NR_FORMAT_2; - pucch_res_17.nof_prb = 1; - pucch_res_17.nof_symbols = 2; - pucch_res_17.start_symbol_idx = 2; - - // format1: setup (1) - // setup - // format2: setup (1) - // setup - // maxCodeRate: zeroDot25 (2) - for (uint32_t i = 0; i < SRSRAN_PUCCH_NR_MAX_NOF_SETS; i++) { - srsran_pucch_nr_resource_set_t* set = &pucch.sets[i]; - for (uint32_t j = 0; j < set->nof_resources; j++) { - if (set->resources[j].format == SRSRAN_PUCCH_NR_FORMAT_2) { - set->resources[j].max_code_rate = 2; // 0.25 - } - } - } - pucch_res_17.max_code_rate = 2; - - // schedulingRequestResourceToAddModList: 1 item - // Item 0 - // SchedulingRequestResourceConfig - // schedulingRequestResourceId: 1 - // schedulingRequestID: 0 - // periodicityAndOffset: sl40 (10) - // sl40: 8 - // resource: 16 - pucch.sr_resources[1].sr_id = 0; - pucch.sr_resources[1].period = 40; - pucch.sr_resources[1].offset = 8; - pucch.sr_resources[1].configured = true; - - // dl-DataToUL-ACK: 7 items - // Item 0 - // dl-DataToUL-ACK item: 8 - // Item 1 - // dl-DataToUL-ACK item: 7 - // Item 2 - // dl-DataToUL-ACK item: 6 - // Item 3 - // dl-DataToUL-ACK item: 5 - // Item 4 - // dl-DataToUL-ACK item: 4 - // Item 5 - // dl-DataToUL-ACK item: 12 - // Item 6 - // dl-DataToUL-ACK item: 11 - harq_ack.dl_data_to_ul_ack[0] = 8; - harq_ack.dl_data_to_ul_ack[1] = 7; - harq_ack.dl_data_to_ul_ack[2] = 6; - harq_ack.dl_data_to_ul_ack[3] = 5; - harq_ack.dl_data_to_ul_ack[4] = 4; - harq_ack.dl_data_to_ul_ack[5] = 12; - harq_ack.dl_data_to_ul_ack[6] = 11; - harq_ack.nof_dl_data_to_ul_ack = 7; - - // nzp-CSI-RS-ResourceToAddModList: 5 items - // Item 0 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 0 - // resourceMapping - // frequencyDomainAllocation: row2 (1) - // row2: 8000 [bit length 12, 4 LSB pad bits, 1000 0000 0000 .... decimal value 2048] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 4 - // cdm-Type: noCDM (0) - // density: one (1) - // one: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots80 (9) - // slots80: 1 - // qcl-InfoPeriodicCSI-RS: 0 - srsran_csi_rs_nzp_resource_t nzp_resource_0 = {}; - nzp_resource_0.resource_mapping.row = srsran_csi_rs_resource_mapping_row_2; - nzp_resource_0.resource_mapping.frequency_domain_alloc[0] = true; - nzp_resource_0.resource_mapping.frequency_domain_alloc[1] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[2] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[3] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[4] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[5] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[6] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[7] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[8] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[9] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[10] = false; - nzp_resource_0.resource_mapping.frequency_domain_alloc[11] = false; - nzp_resource_0.resource_mapping.nof_ports = 1; - nzp_resource_0.resource_mapping.first_symbol_idx = 4; - nzp_resource_0.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm; - nzp_resource_0.resource_mapping.density = srsran_csi_rs_resource_mapping_density_one; - nzp_resource_0.resource_mapping.freq_band.start_rb = 0; - nzp_resource_0.resource_mapping.freq_band.nof_rb = 52; - nzp_resource_0.power_control_offset = 0; - nzp_resource_0.power_control_offset_ss = 0; - nzp_resource_0.scrambling_id = 0; - nzp_resource_0.periodicity.period = 80; - nzp_resource_0.periodicity.offset = 1; - - // Item 1 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 1 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 4 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 11 - // qcl-InfoPeriodicCSI-RS: 0 - srsran_csi_rs_nzp_resource_t nzp_resource_1 = {}; - nzp_resource_1.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1; - nzp_resource_1.resource_mapping.frequency_domain_alloc[0] = false; - nzp_resource_1.resource_mapping.frequency_domain_alloc[1] = false; - nzp_resource_1.resource_mapping.frequency_domain_alloc[2] = false; - nzp_resource_1.resource_mapping.frequency_domain_alloc[3] = true; - nzp_resource_1.resource_mapping.nof_ports = 1; - nzp_resource_1.resource_mapping.first_symbol_idx = 4; - nzp_resource_1.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm; - nzp_resource_1.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three; - nzp_resource_1.resource_mapping.freq_band.start_rb = 0; - nzp_resource_1.resource_mapping.freq_band.nof_rb = 52; - nzp_resource_1.power_control_offset = 0; - nzp_resource_1.power_control_offset_ss = 0; - nzp_resource_1.scrambling_id = 0; - nzp_resource_1.periodicity.period = 40; - nzp_resource_1.periodicity.offset = 11; - // Item 2 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 2 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 8 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 11 - // qcl-InfoPeriodicCSI-RS: 0 - srsran_csi_rs_nzp_resource_t nzp_resource_2 = {}; - nzp_resource_2.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1; - nzp_resource_2.resource_mapping.frequency_domain_alloc[0] = false; - nzp_resource_2.resource_mapping.frequency_domain_alloc[1] = false; - nzp_resource_2.resource_mapping.frequency_domain_alloc[2] = false; - nzp_resource_2.resource_mapping.frequency_domain_alloc[3] = true; - nzp_resource_2.resource_mapping.nof_ports = 1; - nzp_resource_2.resource_mapping.first_symbol_idx = 8; - nzp_resource_2.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm; - nzp_resource_2.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three; - nzp_resource_2.resource_mapping.freq_band.start_rb = 0; - nzp_resource_2.resource_mapping.freq_band.nof_rb = 52; - nzp_resource_2.power_control_offset = 0; - nzp_resource_2.power_control_offset_ss = 0; - nzp_resource_2.scrambling_id = 0; - nzp_resource_2.periodicity.period = 40; - nzp_resource_2.periodicity.offset = 11; - // Item 3 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 3 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 4 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 12 - // qcl-InfoPeriodicCSI-RS: 0 - srsran_csi_rs_nzp_resource_t nzp_resource_3 = {}; - nzp_resource_3.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1; - nzp_resource_3.resource_mapping.frequency_domain_alloc[0] = false; - nzp_resource_3.resource_mapping.frequency_domain_alloc[1] = false; - nzp_resource_3.resource_mapping.frequency_domain_alloc[2] = false; - nzp_resource_3.resource_mapping.frequency_domain_alloc[3] = true; - nzp_resource_3.resource_mapping.nof_ports = 1; - nzp_resource_3.resource_mapping.first_symbol_idx = 4; - nzp_resource_3.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm; - nzp_resource_3.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three; - nzp_resource_3.resource_mapping.freq_band.start_rb = 0; - nzp_resource_3.resource_mapping.freq_band.nof_rb = 52; - nzp_resource_3.power_control_offset = 0; - nzp_resource_3.power_control_offset_ss = 0; - nzp_resource_3.scrambling_id = 0; - nzp_resource_3.periodicity.period = 40; - nzp_resource_3.periodicity.offset = 12; - // Item 4 - // NZP-CSI-RS-Resource - // nzp-CSI-RS-ResourceId: 4 - // resourceMapping - // frequencyDomainAllocation: row1 (0) - // row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1] - // nrofPorts: p1 (0) - // firstOFDMSymbolInTimeDomain: 8 - // cdm-Type: noCDM (0) - // density: three (2) - // three: NULL - // freqBand - // startingRB: 0 - // nrofRBs: 52 - // powerControlOffset: 0dB - // powerControlOffsetSS: db0 (1) - // scramblingID: 0 - // periodicityAndOffset: slots40 (7) - // slots40: 12 - // qcl-InfoPeriodicCSI-RS: 0 - srsran_csi_rs_nzp_resource_t nzp_resource_4 = {}; - nzp_resource_4.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1; - nzp_resource_4.resource_mapping.frequency_domain_alloc[0] = false; - nzp_resource_4.resource_mapping.frequency_domain_alloc[1] = false; - nzp_resource_4.resource_mapping.frequency_domain_alloc[2] = false; - nzp_resource_4.resource_mapping.frequency_domain_alloc[3] = true; - nzp_resource_4.resource_mapping.nof_ports = 1; - nzp_resource_4.resource_mapping.first_symbol_idx = 8; - nzp_resource_4.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm; - nzp_resource_4.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three; - nzp_resource_4.resource_mapping.freq_band.start_rb = 0; - nzp_resource_4.resource_mapping.freq_band.nof_rb = 52; - nzp_resource_4.power_control_offset = 0; - nzp_resource_4.power_control_offset_ss = 0; - nzp_resource_4.scrambling_id = 0; - nzp_resource_4.periodicity.period = 40; - nzp_resource_4.periodicity.offset = 12; - // zp-CSI-RS-ResourceSetToAddModList: 2 items - // Item 0 - // NZP-CSI-RS-ResourceSet - // nzp-CSI-ResourceSetId: 0 - // nzp-CSI-RS-Resources: 1 item - // Item 0 - // NZP-CSI-RS-ResourceId: 0 - pdsch.nzp_csi_rs_sets[0].data[0] = nzp_resource_0; - pdsch.nzp_csi_rs_sets[0].count = 1; - pdsch.nzp_csi_rs_sets[0].trs_info = false; - // Item 1 - // NZP-CSI-RS-ResourceSet - // nzp-CSI-ResourceSetId: 1 - // nzp-CSI-RS-Resources: 4 items - // Item 0 - // NZP-CSI-RS-ResourceId: 1 - // Item 1 - // NZP-CSI-RS-ResourceId: 2 - // Item 2 - // NZP-CSI-RS-ResourceId: 3 - // Item 3 - // NZP-CSI-RS-ResourceId: 4 - // trs-Info: true (0) - pdsch.nzp_csi_rs_sets[1].data[0] = nzp_resource_1; - pdsch.nzp_csi_rs_sets[1].data[1] = nzp_resource_2; - pdsch.nzp_csi_rs_sets[1].data[2] = nzp_resource_3; - pdsch.nzp_csi_rs_sets[1].data[3] = nzp_resource_4; - pdsch.nzp_csi_rs_sets[1].count = 4; - pdsch.nzp_csi_rs_sets[1].trs_info = true; - // csi-ReportConfigToAddModList: 1 item - // Item 0 - // CSI-ReportConfig - // reportConfigId: 0 - // resourcesForChannelMeasurement: 0 - // csi-IM-ResourcesForInterference: 1 - // reportConfigType: periodic (0) - // periodic - // reportSlotConfig: slots80 (7) - // slots80: 9 - // pucch-CSI-ResourceList: 1 item - // Item 0 - // PUCCH-CSI-Resource - // uplinkBandwidthPartId: 0 - // pucch-Resource: 17 - // reportQuantity: cri-RI-PMI-CQI (1) - // cri-RI-PMI-CQI: NULL - // reportFreqConfiguration - // cqi-FormatIndicator: widebandCQI (0) - // timeRestrictionForChannelMeasurements: notConfigured (1) - // timeRestrictionForInterferenceMeasurements: notConfigured (1) - // groupBasedBeamReporting: disabled (1) - // disabled - // cqi-Table: table2 (1) - // subbandSize: value1 (0) - csi.reports[0].type = SRSRAN_CSI_REPORT_TYPE_PERIODIC; - csi.reports[0].channel_meas_id = 0; - csi.reports[0].interf_meas_present = true; - csi.reports[0].interf_meas_id = 1; - csi.reports[0].periodic.period = 80; - csi.reports[0].periodic.offset = 9; - csi.reports[0].periodic.resource = pucch_res_17; - csi.reports[0].quantity = SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI; - csi.reports[0].freq_cfg = SRSRAN_CSI_REPORT_FREQ_WIDEBAND; - csi.reports[0].cqi_table = SRSRAN_CSI_CQI_TABLE_2; + } /** From 138230f4e4401eb678a26bf99db9334dff7a6b41 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Wed, 14 Apr 2021 19:24:30 +0200 Subject: [PATCH 03/46] Remove NR RRC log line --- srsue/src/stack/rrc/rrc_nr.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index e2aed6574..5aae159ae 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -89,9 +89,9 @@ void rrc_nr::get_metrics(rrc_nr_metrics_t& m) {} // Timeout callback interface void rrc_nr::timer_expired(uint32_t timeout_id) { - logger.debug("[NR] Handling Timer Expired"); + logger.debug("Handling Timer Expired"); if (timeout_id == fake_measurement_timer.id()) { - logger.debug("[NR] Triggered Fake Measurement"); + logger.debug("Triggered Fake Measurement"); phy_meas_nr_t fake_meas = {}; std::vector phy_meas_nr; @@ -395,13 +395,13 @@ void rrc_nr::phy_meas_stop() { // possbile race condition for fake_measurement timer, which might be set at the same moment as stopped => fix with // phy integration - logger.debug("[NR] Stopping fake measurements"); + logger.debug("Stopping fake measurements"); fake_measurement_timer.stop(); } void rrc_nr::phy_set_cells_to_meas(uint32_t carrier_freq_r15) { - logger.debug("[NR] Measuring phy cell %d ", carrier_freq_r15); + logger.debug("Measuring phy cell %d ", carrier_freq_r15); // Start timer for fake measurements auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); }; fake_measurement_carrier_freq_r15 = carrier_freq_r15; @@ -411,7 +411,7 @@ void rrc_nr::phy_set_cells_to_meas(uint32_t carrier_freq_r15) bool rrc_nr::configure_sk_counter(uint16_t sk_counter) { - logger.info("[NR] Configure new SK counter %d. Update Key for secondary gnb", sk_counter); + logger.info("Configure new SK counter %d. Update Key for secondary gnb", sk_counter); if (usim->generate_nr_context(sk_counter, &sec_cfg) == false) { return false; } From e1752c0878fc6edd2af93d9da0da4ab9911bdcef Mon Sep 17 00:00:00 2001 From: faluco Date: Thu, 15 Apr 2021 14:51:42 +0200 Subject: [PATCH 04/46] Replace the queue in thread pool in favour of a static circular buffer to avoid allocations. --- lib/include/srsran/common/thread_pool.h | 8 +++++--- lib/src/common/thread_pool.cc | 8 ++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/include/srsran/common/thread_pool.h b/lib/include/srsran/common/thread_pool.h index efed3f953..a2ad3f1c6 100644 --- a/lib/include/srsran/common/thread_pool.h +++ b/lib/include/srsran/common/thread_pool.h @@ -20,13 +20,13 @@ #ifndef SRSRAN_THREAD_POOL_H #define SRSRAN_THREAD_POOL_H +#include "srsran/adt/circular_buffer.h" #include "srsran/adt/move_callback.h" #include "srsran/srslog/srslog.h" #include #include #include #include -#include #include #include #include @@ -89,7 +89,9 @@ private: class task_thread_pool { - using task_t = srsran::move_callback; + using task_t = srsran::move_callback; + static constexpr uint32_t max_task_shift = 14; + static constexpr uint32_t max_task_num = 1u << max_task_shift; public: task_thread_pool(uint32_t nof_workers = 1, bool start_deferred = false, int32_t prio_ = -1, uint32_t mask_ = 255); @@ -130,7 +132,7 @@ private: uint32_t mask = 255; srslog::basic_logger& logger; - std::queue pending_tasks; + srsran::dyn_circular_buffer pending_tasks; std::vector > workers; mutable std::mutex queue_mutex; std::condition_variable cv_empty; diff --git a/lib/src/common/thread_pool.cc b/lib/src/common/thread_pool.cc index 8a4391a35..ea40aa6c8 100644 --- a/lib/src/common/thread_pool.cc +++ b/lib/src/common/thread_pool.cc @@ -253,7 +253,7 @@ uint32_t thread_pool::get_nof_workers() *************************************************************************/ task_thread_pool::task_thread_pool(uint32_t nof_workers, bool start_deferred, int32_t prio_, uint32_t mask_) : - logger(srslog::fetch_basic_logger("POOL")), workers(std::max(1u, nof_workers)) + logger(srslog::fetch_basic_logger("POOL")), pending_tasks(max_task_num), workers(std::max(1u, nof_workers)) { if (not start_deferred) { start(prio_, mask_); @@ -322,6 +322,10 @@ void task_thread_pool::push_task(task_t&& task) { { std::lock_guard lock(queue_mutex); + if (pending_tasks.full()) { + logger.error("Cannot push anymore tasks into the queue, maximum size is %u", uint32_t(max_task_num)); + return; + } pending_tasks.push(std::move(task)); } cv_empty.notify_one(); @@ -358,7 +362,7 @@ bool task_thread_pool::worker_t::wait_task(task_t* task) return false; } if (task) { - *task = std::move(parent->pending_tasks.front()); + *task = std::move(parent->pending_tasks.top()); } parent->pending_tasks.pop(); return true; From 791b8d24ce42264e02d1f6c6bab6f486173dc030 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 16 Apr 2021 10:50:44 +0100 Subject: [PATCH 05/46] fix regression in scell activation during intraenb handover --- srsenb/src/stack/mac/sched.cc | 16 ++++++++-------- srsenb/src/stack/mac/sched_ue.cc | 6 ++++-- srsenb/src/stack/rrc/mac_controller.cc | 4 +--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/srsenb/src/stack/mac/sched.cc b/srsenb/src/stack/mac/sched.cc index e7604e056..525b31f54 100644 --- a/srsenb/src/stack/mac/sched.cc +++ b/srsenb/src/stack/mac/sched.cc @@ -268,15 +268,15 @@ std::array sched::get_enb_ue_cc_map(uint16_t rnti) std::array sched::get_scell_activation_mask(uint16_t rnti) { - std::array enb_ue_cc_map = get_enb_ue_cc_map(rnti); - std::array scell_mask = {}; - for (int ue_cc : enb_ue_cc_map) { - if (ue_cc <= 0) { - // inactive or PCell - continue; + std::array scell_mask = {}; + ue_db_access_locked(rnti, [this, &scell_mask](sched_ue& ue) { + for (size_t enb_cc_idx = 0; enb_cc_idx < carrier_schedulers.size(); ++enb_cc_idx) { + const sched_ue_cell* cc_ue = ue.find_ue_carrier(enb_cc_idx); + if (cc_ue != nullptr and (cc_ue->cc_state() == cc_st::active or cc_ue->cc_state() == cc_st::activating)) { + scell_mask[cc_ue->get_ue_cc_idx()] = true; + } } - scell_mask[ue_cc] = true; - } + }); return scell_mask; } diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index b4da8e730..09e30e91b 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -77,10 +77,12 @@ void sched_ue::set_cfg(const ue_cfg_t& cfg_) scell_activation_state_changed |= c.is_scell() and (c.cc_state() == cc_st::activating or c.cc_state() == cc_st::deactivating); } - if (prev_supported_cc_list.empty() or prev_supported_cc_list[0].enb_cc_idx != cfg.supported_cc_list[0].enb_cc_idx) { + bool is_handover = not prev_supported_cc_list.empty() and + prev_supported_cc_list[0].enb_cc_idx != cfg.supported_cc_list[0].enb_cc_idx; + if (prev_supported_cc_list.empty() or is_handover) { logger.info("SCHED: rnti=0x%x PCell is now enb_cc_idx=%d", rnti, cfg.supported_cc_list[0].enb_cc_idx); } - if (scell_activation_state_changed) { + if (scell_activation_state_changed and not is_handover) { lch_handler.pending_ces.emplace_back(srsran::dl_sch_lcid::SCELL_ACTIVATION); logger.info("SCHED: Enqueueing SCell Activation CMD for rnti=0x%x", rnti); } diff --git a/srsenb/src/stack/rrc/mac_controller.cc b/srsenb/src/stack/rrc/mac_controller.cc index 1a69b3e66..ebe53fe35 100644 --- a/srsenb/src/stack/rrc/mac_controller.cc +++ b/srsenb/src/stack/rrc/mac_controller.cc @@ -127,9 +127,7 @@ int mac_controller::handle_crnti_ce(uint32_t temp_crnti) current_sched_ue_cfg = next_sched_ue_cfg; // Disable SCells, until RRCReconfComplete is received, otherwise the SCell Act MAC CE is sent too early - for (uint32_t i = 1; i < current_sched_ue_cfg.supported_cc_list.size(); ++i) { - current_sched_ue_cfg.supported_cc_list[i].active = false; - } + set_scell_activation({0}); // keep DRBs disabled until RRCReconfComplete is received set_drb_activation(false); From b06f16891d0eaadb9ff116195ffa17189c272ace Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 10 Apr 2021 15:20:31 +0100 Subject: [PATCH 06/46] use of a single array-based pool of RLC AM PDU segments to build data PDUs, while avoiding any allocations. Each segment stores its own PDCP SN and RLC SN and has two pointers, one for the next segment of the same RLC PDU, and another for the next segment of the same PDCP PDU. --- lib/include/srsran/upper/rlc_am_lte.h | 115 ++++++++++++++-- lib/src/upper/rlc_am_lte.cc | 188 ++++++++++++++++++-------- 2 files changed, 232 insertions(+), 71 deletions(-) diff --git a/lib/include/srsran/upper/rlc_am_lte.h b/lib/include/srsran/upper/rlc_am_lte.h index 7fe3e80f9..052a82fee 100644 --- a/lib/include/srsran/upper/rlc_am_lte.h +++ b/lib/include/srsran/upper/rlc_am_lte.h @@ -33,6 +33,98 @@ namespace srsran { #undef RLC_AM_BUFFER_DEBUG +/// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state +struct rlc_am_pdu_segment { + const static uint32_t invalid_sn = std::numeric_limits::max(); + + bool empty() const { return rlc_sn() == invalid_sn and pdcp_sn() == invalid_sn; } + void set_ack(bool val = true) { acked = val; } + bool is_acked() const { return acked; } + uint32_t rlc_sn() const { return rlc_sn_; } + uint32_t pdcp_sn() const { return pdcp_sn_; } + +protected: + uint32_t rlc_sn_ = invalid_sn; + uint32_t pdcp_sn_ = invalid_sn; + bool acked = false; +}; + +template +struct pdu_segment_list; +using rlc_pdu_segment_list = pdu_segment_list; +using pdcp_pdu_segment_list = pdu_segment_list; + +/// Pool that manages the allocation of RLC AM PDU Segments to RLC SDUs +struct rlc_am_pdu_segment_pool { + const static size_t MAX_POOL_SIZE = 16384; + + struct segment_resource : public rlc_am_pdu_segment { + int id() const; + void deallocate(); + + using rlc_am_pdu_segment::pdcp_sn_; + using rlc_am_pdu_segment::rlc_sn_; + + // intrusive same RLC PDU segment list + segment_resource* rlc_next = nullptr; + // intrusive same PDCP PDU segment list + segment_resource* pdcp_next = nullptr; + + // intrusive linked lists + segment_resource* next_free = nullptr; + rlc_am_pdu_segment_pool* parent_pool = nullptr; + }; + + rlc_am_pdu_segment_pool(); + rlc_am_pdu_segment_pool(const rlc_am_pdu_segment_pool&) = delete; + rlc_am_pdu_segment_pool(rlc_am_pdu_segment_pool&&) = delete; + bool has_segments() const; + bool + allocate_segment(uint32_t rlc_sn, rlc_pdu_segment_list& rlc_list, uint32_t pdcp_sn, pdcp_pdu_segment_list& pdcp_list); + +private: + segment_resource* free_list = nullptr; + std::array segments; +}; + +template +struct pdu_segment_list { + void push(rlc_am_pdu_segment_pool::segment_resource* obj); + void clear() { head.reset(); } + + struct iterator : public std::iterator { + explicit iterator(rlc_am_pdu_segment_pool::segment_resource* item_ = nullptr) : item(item_) {} + const rlc_am_pdu_segment* operator->() const { return item; } + rlc_am_pdu_segment* operator->() { return item; } + const rlc_am_pdu_segment& operator*() const { return *item; } + rlc_am_pdu_segment& operator*() { return *item; } + iterator& operator++() + { + item = (rlcSnList) ? item->rlc_next : item->pdcp_next; + return *this; + } + bool operator==(iterator other) const { return item == other.item; } + bool operator!=(iterator other) const { return item != other.item; } + + private: + rlc_am_pdu_segment_pool::segment_resource* item; + }; + using const_iterator = iterator; + + iterator begin() { return iterator(head.get()); } + iterator end() { return iterator(nullptr); } + const_iterator begin() const { return iterator(head.get()); } + const_iterator end() const { return iterator(nullptr); } + +private: + struct list_deleter { + void operator()(rlc_am_pdu_segment_pool::segment_resource* ptr); + }; + std::unique_ptr head; +}; + +// + struct rlc_amd_rx_pdu_t { rlc_amd_pdu_header_t header; unique_byte_buffer_t buf; @@ -44,12 +136,12 @@ struct rlc_amd_rx_pdu_segments_t { }; struct rlc_amd_tx_pdu_t { - rlc_amd_pdu_header_t header; - unique_byte_buffer_t buf; - pdcp_sn_vector_t pdcp_sns; - uint32_t retx_count; - uint32_t rlc_sn; - bool is_acked; + rlc_amd_pdu_header_t header; + unique_byte_buffer_t buf; + pdcp_pdu_segment_list pdcp_sn_list; + uint32_t retx_count; + uint32_t rlc_sn = std::numeric_limits::max(); + bool is_acked = false; }; struct rlc_amd_retx_t { @@ -69,7 +161,7 @@ struct pdcp_sdu_info_t { bool fully_txed; // Boolean indicating if the SDU is fully transmitted. bool fully_acked; // Boolean indicating if the SDU is fully acked. This is only necessary temporarely to avoid // duplicate removal from the queue while processing the status report - std::vector rlc_sn_info_list; // List of RLC PDUs in transit and whether they have been acked or not. + rlc_pdu_segment_list rlc_segment_list; // List of RLC PDUs in transit and whether they have been acked or not. }; template @@ -133,7 +225,7 @@ public: buffered_pdus[sn_idx].sn = invalid_sn; buffered_pdus[sn_idx].fully_acked = false; buffered_pdus[sn_idx].fully_txed = false; - buffered_pdus[sn_idx].rlc_sn_info_list.clear(); + buffered_pdus[sn_idx].rlc_segment_list.clear(); count--; } @@ -290,9 +382,10 @@ private: bool do_status(); void check_sn_reached_max_retx(uint32_t sn); - rlc_am_lte* parent = nullptr; - byte_buffer_pool* pool = nullptr; - srslog::basic_logger& logger; + rlc_am_lte* parent = nullptr; + byte_buffer_pool* pool = nullptr; + srslog::basic_logger& logger; + rlc_am_pdu_segment_pool segment_pool; /**************************************************************************** * Configurable parameters diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index 6d783eef2..2f8a6768b 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -16,6 +16,7 @@ #include "srsran/interfaces/ue_rrc_interfaces.h" #include "srsran/srslog/event_trace.h" #include +#include #define MOD 1024 #define RX_MOD_BASE(x) (((x)-vr_r) % 1024) @@ -57,6 +58,87 @@ void log_rlc_am_status_pdu_to_string(srslog::log_channel& log_ch, log_ch(fmt_str, std::forward(args)..., to_c_str(buffer)); } +/******************************* + * RLC AM Segments + ******************************/ + +int rlc_am_pdu_segment_pool::segment_resource::id() const +{ + return std::distance(parent_pool->segments.cbegin(), this); +} + +void rlc_am_pdu_segment_pool::segment_resource::deallocate() +{ + acked = false; + next_free = parent_pool->free_list; + parent_pool->free_list = this; +} + +rlc_am_pdu_segment_pool::rlc_am_pdu_segment_pool() +{ + for (segment_resource& s : segments) { + s.parent_pool = this; + s.next_free = free_list; + free_list = &s; + } +} + +bool rlc_am_pdu_segment_pool::has_segments() const +{ + return free_list != nullptr; +} + +bool rlc_am_pdu_segment_pool::allocate_segment(uint32_t rlc_sn, + rlc_pdu_segment_list& rlc_list, + uint32_t pdcp_sn, + pdcp_pdu_segment_list& pdcp_list) +{ + if (free_list == nullptr) { + return false; + } + segment_resource* segment = free_list; + free_list = segment->next_free; + rlc_list.push(segment); + segment->rlc_sn_ = rlc_sn; + pdcp_list.push(segment); + segment->pdcp_sn_ = pdcp_sn; + return true; +} + +template +void pdu_segment_list::push(rlc_am_pdu_segment_pool::segment_resource* obj) +{ + if (head != nullptr) { + if (rlcSnList) { + obj->rlc_next = head.release(); + } else { + obj->pdcp_next = head.release(); + } + } + head.reset(obj); +} + +template +void pdu_segment_list::list_deleter::operator()(rlc_am_pdu_segment_pool::segment_resource* node) +{ + while (node != nullptr) { + rlc_am_pdu_segment_pool::segment_resource* next = nullptr; + if (rlcSnList) { + next = node->rlc_next; + node->rlc_next = nullptr; + node->rlc_sn_ = rlc_am_pdu_segment::invalid_sn; + } else { + next = node->pdcp_next; + node->pdcp_next = nullptr; + node->pdcp_sn_ = rlc_am_pdu_segment::invalid_sn; + } + if (node->empty()) { + node->deallocate(); + } + node = next; + } +} + /******************************* * rlc_am_lte class ******************************/ @@ -316,7 +398,7 @@ bool rlc_am_lte::rlc_am_lte_tx::has_data() { return (((do_status() && not status_prohibit_timer.is_running())) || // if we have a status PDU to transmit (not retx_queue.empty()) || // if we have a retransmission - (tx_sdu != NULL) || // if we are currently transmitting a SDU + (tx_sdu != nullptr) || // if we are currently transmitting a SDU (tx_sdu_queue.get_n_sdus() != 0)); // or if there is a SDU queued up for transmission } @@ -332,9 +414,13 @@ bool rlc_am_lte::rlc_am_lte_tx::has_data() void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn) { if (tx_window[sn].retx_count == cfg.max_retx_thresh) { - logger.warning("%s Signaling max number of reTx=%d for for SN=%d", RB_NAME, tx_window[sn].retx_count, sn); + logger.warning("%s Signaling max number of reTx=%d for SN=%d", RB_NAME, tx_window[sn].retx_count, sn); parent->rrc->max_retx_attempted(); - parent->pdcp->notify_failure(parent->lcid, tx_window[sn].pdcp_sns); + srsran::pdcp_sn_vector_t pdcp_sns; + for (const rlc_am_pdu_segment& segment : tx_window[sn].pdcp_sn_list) { + pdcp_sns.push_back(segment.pdcp_sn()); + } + parent->pdcp->notify_failure(parent->lcid, pdcp_sns); parent->metrics.num_lost_pdus++; } } @@ -930,7 +1016,6 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt // insert newly assigned SN into window and use reference for in-place operations // NOTE: from now on, we can't return from this function anymore before increasing vt_s rlc_amd_tx_pdu_t& tx_pdu = tx_window.add_pdu(header.sn); - tx_pdu.pdcp_sns.clear(); uint32_t head_len = rlc_am_packed_length(&header); uint32_t to_move = 0; @@ -940,6 +1025,13 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt logger.debug("%s Building PDU - pdu_space: %d, head_len: %d ", RB_NAME, pdu_space, head_len); + bool segments_created = false; + if (not segment_pool.has_segments()) { + logger.info("Can't build a PDU - No segments available"); + tx_window.remove_pdu(tx_pdu.rlc_sn); + return 0; + } + // Check for SDU segment if (tx_sdu != nullptr) { to_move = ((pdu_space - head_len) >= tx_sdu->N_bytes) ? tx_sdu->N_bytes : pdu_space - head_len; @@ -951,15 +1043,11 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt tx_sdu->msg += to_move; if (undelivered_sdu_info_queue.has_pdcp_sn(tx_sdu->md.pdcp_sn)) { pdcp_sdu_info_t& pdcp_sdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; - pdcp_sdu.rlc_sn_info_list.push_back({header.sn, false}); - if (not tx_pdu.pdcp_sns.full()) { - tx_pdu.pdcp_sns.push_back(tx_sdu->md.pdcp_sn); - } else { - logger.warning("Cant't store PDCP_SN=%d for delivery notification.", tx_sdu->md.pdcp_sn); - } + segment_pool.allocate_segment(header.sn, pdcp_sdu.rlc_segment_list, tx_sdu->md.pdcp_sn, tx_pdu.pdcp_sn_list); if (tx_sdu->N_bytes == 0) { pdcp_sdu.fully_txed = true; } + segments_created = true; } else { // PDCP SNs for the RLC SDU has been removed from the queue logger.warning("Couldn't find PDCP_SN=%d in SDU info queue (segment)", tx_sdu->md.pdcp_sn); @@ -987,6 +1075,14 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt // Pull SDUs from queue while (pdu_space > head_len && tx_sdu_queue.get_n_sdus() > 0 && header.N_li < RLC_AM_WINDOW_SIZE) { + if (not segment_pool.has_segments()) { + logger.info("Can't build a PDU segment - No segment resources available"); + if (segments_created) { + break; // continue with the segments created up to this point + } + tx_window.remove_pdu(tx_pdu.rlc_sn); + return 0; + } if (last_li > 0) { header.li[header.N_li] = last_li; header.N_li++; @@ -1019,15 +1115,11 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt tx_sdu->msg += to_move; if (undelivered_sdu_info_queue.has_pdcp_sn(tx_sdu->md.pdcp_sn)) { pdcp_sdu_info_t& pdcp_sdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; - pdcp_sdu.rlc_sn_info_list.push_back({header.sn, false}); - if (not tx_pdu.pdcp_sns.full()) { - tx_pdu.pdcp_sns.push_back(tx_sdu->md.pdcp_sn); - } else { - logger.warning("Cant't store PDCP_SN=%d for delivery notification.", tx_sdu->md.pdcp_sn); - } + segment_pool.allocate_segment(header.sn, pdcp_sdu.rlc_segment_list, tx_sdu->md.pdcp_sn, tx_pdu.pdcp_sn_list); if (tx_sdu->N_bytes == 0) { pdcp_sdu.fully_txed = true; } + segments_created = true; } else { // PDCP SNs for the RLC SDU has been removed from the queue logger.warning("Couldn't find PDCP_SN=%d in SDU info queue.", tx_sdu->md.pdcp_sn); @@ -1186,6 +1278,7 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no if (tx_window.has_sn(i)) { auto& pdu = tx_window[i]; update_notification_ack_info(pdu); + logger.debug("Tx PDU SN=%zd being removed from tx window", i); tx_window.remove_pdu(i); } // Advance window if possible @@ -1202,17 +1295,6 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no logger.error("%s vt_a=%d points to invalid position in Tx window", RB_NAME, vt_a); } - if (not notify_info_vec.empty()) { - // Remove all SDUs that were fully acked - for (uint32_t acked_pdcp_sn : notify_info_vec) { - logger.debug("Erasing SDU info: PDCP_SN=%d", acked_pdcp_sn); - if (not undelivered_sdu_info_queue.has_pdcp_sn(acked_pdcp_sn)) { - logger.error("Could not find info to erase: SN=%d", acked_pdcp_sn); - } - undelivered_sdu_info_queue.clear_pdcp_sdu(acked_pdcp_sn); - } - } - debug_state(); lock.unlock(); @@ -1239,28 +1321,27 @@ void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pd if (not tx_window.has_sn(tx_pdu.header.sn)) { return; } - pdcp_sn_vector_t& pdcp_sns = tx_window[tx_pdu.header.sn].pdcp_sns; - for (uint32_t pdcp_sn : pdcp_sns) { + pdcp_pdu_segment_list& pdcp_sns = tx_window[tx_pdu.header.sn].pdcp_sn_list; + for (rlc_am_pdu_segment& pdcp_segment : pdcp_sns) { // Iterate over all SNs that were TX'ed - auto& info = undelivered_sdu_info_queue[pdcp_sn]; - for (auto& rlc_sn_info : info.rlc_sn_info_list) { - // Mark this SN as acked, if necessary - if (rlc_sn_info.is_acked == false && rlc_sn_info.sn == tx_pdu.header.sn) { - rlc_sn_info.is_acked = true; - } - } + uint32_t pdcp_sn = pdcp_segment.pdcp_sn(); + pdcp_segment.set_ack(); + + pdcp_sdu_info_t& info = undelivered_sdu_info_queue[pdcp_sn]; // Check wether the SDU was fully acked if (info.fully_txed and not info.fully_acked) { // Check if all SNs were ACK'ed - info.fully_acked = std::all_of(info.rlc_sn_info_list.begin(), - info.rlc_sn_info_list.end(), - [](rlc_sn_info_t rlc_sn_info) { return rlc_sn_info.is_acked; }); + info.fully_acked = std::all_of(info.rlc_segment_list.begin(), + info.rlc_segment_list.end(), + [](const rlc_am_pdu_segment& elem) { return elem.is_acked(); }); if (info.fully_acked) { if (not notify_info_vec.full()) { notify_info_vec.push_back(pdcp_sn); } else { logger.warning("Can't notify delivery of PDCP_SN=%d.", pdcp_sn); } + logger.debug("Erasing SDU info: PDCP_SN=%d", pdcp_sn); + undelivered_sdu_info_queue.clear_pdcp_sdu(pdcp_sn); } } } @@ -2120,9 +2201,6 @@ const size_t buffered_pdcp_pdu_list::max_buffer_idx; buffered_pdcp_pdu_list::buffered_pdcp_pdu_list() : buffered_pdus(max_buffer_idx + 1) { - for (size_t i = 0; i < buffered_pdus.size(); ++i) { - buffered_pdus[i].rlc_sn_info_list.reserve(5); - } clear(); } @@ -2133,7 +2211,7 @@ void buffered_pdcp_pdu_list::clear() b.sn = invalid_sn; b.fully_acked = false; b.fully_txed = false; - b.rlc_sn_info_list.clear(); + b.rlc_segment_list.clear(); } } @@ -2393,26 +2471,16 @@ bool rlc_am_is_pdu_segment(uint8_t* payload) return ((*(payload) >> 6) & 0x01) == 1; } -std::string rlc_am_undelivered_sdu_info_to_string(const std::map& info_queue) +void rlc_am_undelivered_sdu_info_to_string(fmt::memory_buffer& buffer, const std::vector& info_queue) { - std::string str = "\n"; - for (const auto& info_it : info_queue) { - uint32_t pdcp_sn = info_it.first; - auto info = info_it.second; - std::string tmp_str = fmt::format("\tPDCP_SN = {}, RLC_SNs = [", pdcp_sn); - for (auto rlc_sn_info : info.rlc_sn_info_list) { - std::string tmp_str2; - if (rlc_sn_info.is_acked) { - tmp_str2 = fmt::format("ACK={}, ", rlc_sn_info.sn); - } else { - tmp_str2 = fmt::format("NACK={}, ", rlc_sn_info.sn); - } - tmp_str += tmp_str2; + fmt::format_to(buffer, "\n"); + for (const auto& pdcp_pdu : info_queue) { + fmt::format_to(buffer, "\tPDCP_SN = {}, RLC_SNs = [", pdcp_pdu.sn); + for (const auto& rlc_sn_info : pdcp_pdu.rlc_segment_list) { + fmt::format_to(buffer, "{}ACK={}, ", rlc_sn_info.is_acked() ? "" : "N", rlc_sn_info.rlc_sn()); } - tmp_str += "]\n"; - str += tmp_str; + fmt::format_to(buffer, "]\n"); } - return str; } void log_rlc_amd_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_amd_pdu_header_t& header) From 7f0083a9858391c88d4f9cfc69e5c1fe8362ba61 Mon Sep 17 00:00:00 2001 From: Francisco Date: Sun, 11 Apr 2021 21:35:47 +0100 Subject: [PATCH 07/46] implementation of intrusive list abstract classes to be used in RLC for lists of segments --- lib/include/srsran/upper/rlc_am_lte.h | 174 +++++++++++++------------- lib/src/upper/rlc_am_lte.cc | 137 +++++++++----------- 2 files changed, 149 insertions(+), 162 deletions(-) diff --git a/lib/include/srsran/upper/rlc_am_lte.h b/lib/include/srsran/upper/rlc_am_lte.h index 052a82fee..cef259475 100644 --- a/lib/include/srsran/upper/rlc_am_lte.h +++ b/lib/include/srsran/upper/rlc_am_lte.h @@ -16,6 +16,7 @@ #include "srsran/adt/accumulators.h" #include "srsran/adt/circular_array.h" #include "srsran/adt/circular_map.h" +#include "srsran/adt/intrusive_list.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" #include "srsran/common/srsran_assert.h" @@ -33,94 +34,101 @@ namespace srsran { #undef RLC_AM_BUFFER_DEBUG -/// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state -struct rlc_am_pdu_segment { - const static uint32_t invalid_sn = std::numeric_limits::max(); - - bool empty() const { return rlc_sn() == invalid_sn and pdcp_sn() == invalid_sn; } - void set_ack(bool val = true) { acked = val; } - bool is_acked() const { return acked; } - uint32_t rlc_sn() const { return rlc_sn_; } - uint32_t pdcp_sn() const { return pdcp_sn_; } - -protected: - uint32_t rlc_sn_ = invalid_sn; - uint32_t pdcp_sn_ = invalid_sn; - bool acked = false; -}; - -template -struct pdu_segment_list; -using rlc_pdu_segment_list = pdu_segment_list; -using pdcp_pdu_segment_list = pdu_segment_list; +struct pdcp_pdu_segment_list; +struct rlc_pdu_segment_list; -/// Pool that manages the allocation of RLC AM PDU Segments to RLC SDUs +/// Pool that manages the allocation of RLC AM PDU Segments to RLC PDUs and tracking of segments ACK state struct rlc_am_pdu_segment_pool { const static size_t MAX_POOL_SIZE = 16384; + using rlc_list_tag = default_intrusive_tag; + struct free_list_tag {}; + + /// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state + struct segment_resource : public intrusive_forward_list_element, + public intrusive_forward_list_element, + public intrusive_double_linked_list_element<> { + const static uint32_t invalid_sn = std::numeric_limits::max(); + + int id() const; + void release_pdcp_sn(); + void release_rlc_sn(); + uint32_t rlc_sn() const { return rlc_sn_; } + uint32_t pdcp_sn() const { return pdcp_sn_; } + bool empty() const { return rlc_sn_ == invalid_sn and pdcp_sn_ == invalid_sn; } + bool is_acked() const { return rlc_sn() != invalid_sn; } - struct segment_resource : public rlc_am_pdu_segment { - int id() const; - void deallocate(); - - using rlc_am_pdu_segment::pdcp_sn_; - using rlc_am_pdu_segment::rlc_sn_; - - // intrusive same RLC PDU segment list - segment_resource* rlc_next = nullptr; - // intrusive same PDCP PDU segment list - segment_resource* pdcp_next = nullptr; - - // intrusive linked lists - segment_resource* next_free = nullptr; + private: + friend struct rlc_am_pdu_segment_pool; + uint32_t rlc_sn_ = invalid_sn; + uint32_t pdcp_sn_ = invalid_sn; rlc_am_pdu_segment_pool* parent_pool = nullptr; }; rlc_am_pdu_segment_pool(); rlc_am_pdu_segment_pool(const rlc_am_pdu_segment_pool&) = delete; rlc_am_pdu_segment_pool(rlc_am_pdu_segment_pool&&) = delete; - bool has_segments() const; + bool has_segments() const { return not free_list.empty(); } bool - allocate_segment(uint32_t rlc_sn, rlc_pdu_segment_list& rlc_list, uint32_t pdcp_sn, pdcp_pdu_segment_list& pdcp_list); + make_segment(uint32_t rlc_sn, uint32_t pdcp_sn, rlc_pdu_segment_list& rlc_list, pdcp_pdu_segment_list& pdcp_list); private: - segment_resource* free_list = nullptr; - std::array segments; + intrusive_forward_list free_list; + std::array segments; }; -template -struct pdu_segment_list { - void push(rlc_am_pdu_segment_pool::segment_resource* obj); - void clear() { head.reset(); } - - struct iterator : public std::iterator { - explicit iterator(rlc_am_pdu_segment_pool::segment_resource* item_ = nullptr) : item(item_) {} - const rlc_am_pdu_segment* operator->() const { return item; } - rlc_am_pdu_segment* operator->() { return item; } - const rlc_am_pdu_segment& operator*() const { return *item; } - rlc_am_pdu_segment& operator*() { return *item; } - iterator& operator++() - { - item = (rlcSnList) ? item->rlc_next : item->pdcp_next; - return *this; - } - bool operator==(iterator other) const { return item == other.item; } - bool operator!=(iterator other) const { return item != other.item; } +/// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state +using rlc_am_pdu_segment = rlc_am_pdu_segment_pool::segment_resource; - private: - rlc_am_pdu_segment_pool::segment_resource* item; - }; - using const_iterator = iterator; +class pdcp_pdu_segment_list +{ + using list_type = intrusive_double_linked_list; + list_type list; - iterator begin() { return iterator(head.get()); } - iterator end() { return iterator(nullptr); } - const_iterator begin() const { return iterator(head.get()); } - const_iterator end() const { return iterator(nullptr); } +public: + using iterator = typename list_type::iterator; + using const_iterator = typename list_type::const_iterator; + + iterator begin() { return list.begin(); } + iterator end() { return list.end(); } + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } + bool empty() const { return list.empty(); } + + pdcp_pdu_segment_list() = default; + pdcp_pdu_segment_list(pdcp_pdu_segment_list&&) noexcept = default; + pdcp_pdu_segment_list& operator=(pdcp_pdu_segment_list&&) noexcept = default; + ~pdcp_pdu_segment_list() { clear(); } + void push(rlc_am_pdu_segment& segment) { list.push_front(&segment); } + void pop(rlc_am_pdu_segment& segment); + void clear() + { + while (not empty()) { + pop(*begin()); + } + } +}; + +struct rlc_pdu_segment_list { + using list_type = intrusive_forward_list; + using iterator = typename list_type::iterator; + using const_iterator = typename list_type::const_iterator; + + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } + iterator begin() { return list.begin(); } + iterator end() { return list.end(); } + bool empty() const { return list.empty(); } + + rlc_pdu_segment_list() = default; + rlc_pdu_segment_list(rlc_pdu_segment_list&& other) noexcept = default; + rlc_pdu_segment_list(const rlc_pdu_segment_list&) = delete; + rlc_pdu_segment_list& operator=(rlc_pdu_segment_list&& other) noexcept = default; + ~rlc_pdu_segment_list() { clear(); } + void push(rlc_am_pdu_segment& segment) { list.push_front(&segment); } + void clear(); private: - struct list_deleter { - void operator()(rlc_am_pdu_segment_pool::segment_resource* ptr); - }; - std::unique_ptr head; + list_type list; }; // @@ -136,12 +144,12 @@ struct rlc_amd_rx_pdu_segments_t { }; struct rlc_amd_tx_pdu_t { - rlc_amd_pdu_header_t header; - unique_byte_buffer_t buf; - pdcp_pdu_segment_list pdcp_sn_list; - uint32_t retx_count; - uint32_t rlc_sn = std::numeric_limits::max(); - bool is_acked = false; + rlc_amd_pdu_header_t header; + unique_byte_buffer_t buf; + rlc_pdu_segment_list segment_list; + uint32_t retx_count; + uint32_t rlc_sn = std::numeric_limits::max(); + bool is_acked = false; }; struct rlc_amd_retx_t { @@ -157,11 +165,10 @@ struct rlc_sn_info_t { }; struct pdcp_sdu_info_t { - uint32_t sn; - bool fully_txed; // Boolean indicating if the SDU is fully transmitted. - bool fully_acked; // Boolean indicating if the SDU is fully acked. This is only necessary temporarely to avoid - // duplicate removal from the queue while processing the status report - rlc_pdu_segment_list rlc_segment_list; // List of RLC PDUs in transit and whether they have been acked or not. + uint32_t sn; + bool fully_txed; // Boolean indicating if the SDU is fully transmitted. + pdcp_pdu_segment_list segment_list; // List of RLC PDUs in transit and whether they have been acked or not. + bool fully_acked() const { return segment_list.empty(); } }; template @@ -222,10 +229,9 @@ public: if (buffered_pdus[sn_idx].sn == invalid_sn) { return; } - buffered_pdus[sn_idx].sn = invalid_sn; - buffered_pdus[sn_idx].fully_acked = false; - buffered_pdus[sn_idx].fully_txed = false; - buffered_pdus[sn_idx].rlc_segment_list.clear(); + buffered_pdus[sn_idx].sn = invalid_sn; + buffered_pdus[sn_idx].fully_txed = false; + buffered_pdus[sn_idx].segment_list.clear(); count--; } diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index 2f8a6768b..ab650a440 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -16,7 +16,6 @@ #include "srsran/interfaces/ue_rrc_interfaces.h" #include "srsran/srslog/event_trace.h" #include -#include #define MOD 1024 #define RX_MOD_BASE(x) (((x)-vr_r) % 1024) @@ -67,75 +66,61 @@ int rlc_am_pdu_segment_pool::segment_resource::id() const return std::distance(parent_pool->segments.cbegin(), this); } -void rlc_am_pdu_segment_pool::segment_resource::deallocate() +void rlc_am_pdu_segment_pool::segment_resource::release_pdcp_sn() { - acked = false; - next_free = parent_pool->free_list; - parent_pool->free_list = this; + pdcp_sn_ = invalid_sn; + if (empty()) { + parent_pool->free_list.push_front(this); + } } -rlc_am_pdu_segment_pool::rlc_am_pdu_segment_pool() +void rlc_am_pdu_segment_pool::segment_resource::release_rlc_sn() { - for (segment_resource& s : segments) { - s.parent_pool = this; - s.next_free = free_list; - free_list = &s; + rlc_sn_ = invalid_sn; + if (empty()) { + parent_pool->free_list.push_front(this); } } -bool rlc_am_pdu_segment_pool::has_segments() const +rlc_am_pdu_segment_pool::rlc_am_pdu_segment_pool() { - return free_list != nullptr; + for (segment_resource& s : segments) { + s.parent_pool = this; + free_list.push_front(&s); + } } -bool rlc_am_pdu_segment_pool::allocate_segment(uint32_t rlc_sn, - rlc_pdu_segment_list& rlc_list, - uint32_t pdcp_sn, - pdcp_pdu_segment_list& pdcp_list) +bool rlc_am_pdu_segment_pool::make_segment(uint32_t rlc_sn, + uint32_t pdcp_sn, + rlc_pdu_segment_list& rlc_list, + pdcp_pdu_segment_list& pdcp_list) { - if (free_list == nullptr) { + if (not has_segments()) { return false; } - segment_resource* segment = free_list; - free_list = segment->next_free; - rlc_list.push(segment); - segment->rlc_sn_ = rlc_sn; - pdcp_list.push(segment); + segment_resource* segment = free_list.pop_front(); + rlc_list.push(*segment); + pdcp_list.push(*segment); + segment->rlc_sn_ = rlc_sn; segment->pdcp_sn_ = pdcp_sn; return true; } -template -void pdu_segment_list::push(rlc_am_pdu_segment_pool::segment_resource* obj) +void pdcp_pdu_segment_list::pop(rlc_am_pdu_segment& segment) { - if (head != nullptr) { - if (rlcSnList) { - obj->rlc_next = head.release(); - } else { - obj->pdcp_next = head.release(); - } - } - head.reset(obj); + // remove from list + list.pop(&segment); + // signal pool that the pdcp handle is released + segment.release_pdcp_sn(); } -template -void pdu_segment_list::list_deleter::operator()(rlc_am_pdu_segment_pool::segment_resource* node) +void rlc_pdu_segment_list::clear() { - while (node != nullptr) { - rlc_am_pdu_segment_pool::segment_resource* next = nullptr; - if (rlcSnList) { - next = node->rlc_next; - node->rlc_next = nullptr; - node->rlc_sn_ = rlc_am_pdu_segment::invalid_sn; - } else { - next = node->pdcp_next; - node->pdcp_next = nullptr; - node->pdcp_sn_ = rlc_am_pdu_segment::invalid_sn; - } - if (node->empty()) { - node->deallocate(); - } - node = next; + while (not empty()) { + // remove from list + rlc_am_pdu_segment* segment = list.pop_front(); + // deallocate if also removed from PDCP + segment->release_rlc_sn(); } } @@ -417,7 +402,7 @@ void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn) logger.warning("%s Signaling max number of reTx=%d for SN=%d", RB_NAME, tx_window[sn].retx_count, sn); parent->rrc->max_retx_attempted(); srsran::pdcp_sn_vector_t pdcp_sns; - for (const rlc_am_pdu_segment& segment : tx_window[sn].pdcp_sn_list) { + for (const rlc_am_pdu_segment& segment : tx_window[sn].segment_list) { pdcp_sns.push_back(segment.pdcp_sn()); } parent->pdcp->notify_failure(parent->lcid, pdcp_sns); @@ -1043,7 +1028,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt tx_sdu->msg += to_move; if (undelivered_sdu_info_queue.has_pdcp_sn(tx_sdu->md.pdcp_sn)) { pdcp_sdu_info_t& pdcp_sdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; - segment_pool.allocate_segment(header.sn, pdcp_sdu.rlc_segment_list, tx_sdu->md.pdcp_sn, tx_pdu.pdcp_sn_list); + segment_pool.make_segment(header.sn, tx_sdu->md.pdcp_sn, tx_pdu.segment_list, pdcp_sdu.segment_list); if (tx_sdu->N_bytes == 0) { pdcp_sdu.fully_txed = true; } @@ -1115,7 +1100,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt tx_sdu->msg += to_move; if (undelivered_sdu_info_queue.has_pdcp_sn(tx_sdu->md.pdcp_sn)) { pdcp_sdu_info_t& pdcp_sdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; - segment_pool.allocate_segment(header.sn, pdcp_sdu.rlc_segment_list, tx_sdu->md.pdcp_sn, tx_pdu.pdcp_sn_list); + segment_pool.make_segment(header.sn, tx_sdu->md.pdcp_sn, tx_pdu.segment_list, pdcp_sdu.segment_list); if (tx_sdu->N_bytes == 0) { pdcp_sdu.fully_txed = true; } @@ -1321,28 +1306,25 @@ void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pd if (not tx_window.has_sn(tx_pdu.header.sn)) { return; } - pdcp_pdu_segment_list& pdcp_sns = tx_window[tx_pdu.header.sn].pdcp_sn_list; - for (rlc_am_pdu_segment& pdcp_segment : pdcp_sns) { - // Iterate over all SNs that were TX'ed - uint32_t pdcp_sn = pdcp_segment.pdcp_sn(); - pdcp_segment.set_ack(); + rlc_pdu_segment_list& pdcp_sns = tx_window[tx_pdu.header.sn].segment_list; + // Iterate over all PDCP SNs of the same RLC PDU that were TX'ed + for (rlc_am_pdu_segment& acked_segment : pdcp_sns) { + uint32_t pdcp_sn = acked_segment.pdcp_sn(); + pdcp_sdu_info_t& info = undelivered_sdu_info_queue[pdcp_sn]; - pdcp_sdu_info_t& info = undelivered_sdu_info_queue[pdcp_sn]; - // Check wether the SDU was fully acked - if (info.fully_txed and not info.fully_acked) { + // Remove RLC SN from PDCP PDU undelivered list + info.segment_list.pop(acked_segment); + + // Check whether the SDU was fully acked + if (info.fully_txed and info.segment_list.empty()) { // Check if all SNs were ACK'ed - info.fully_acked = std::all_of(info.rlc_segment_list.begin(), - info.rlc_segment_list.end(), - [](const rlc_am_pdu_segment& elem) { return elem.is_acked(); }); - if (info.fully_acked) { - if (not notify_info_vec.full()) { - notify_info_vec.push_back(pdcp_sn); - } else { - logger.warning("Can't notify delivery of PDCP_SN=%d.", pdcp_sn); - } - logger.debug("Erasing SDU info: PDCP_SN=%d", pdcp_sn); - undelivered_sdu_info_queue.clear_pdcp_sdu(pdcp_sn); + if (not notify_info_vec.full()) { + notify_info_vec.push_back(pdcp_sn); + } else { + logger.warning("Can't notify delivery of PDCP_SN=%d.", pdcp_sn); } + logger.debug("Erasing SDU info: PDCP_SN=%d", pdcp_sn); + undelivered_sdu_info_queue.clear_pdcp_sdu(pdcp_sn); } } pdcp_sns.clear(); @@ -2208,10 +2190,9 @@ void buffered_pdcp_pdu_list::clear() { count = 0; for (auto& b : buffered_pdus) { - b.sn = invalid_sn; - b.fully_acked = false; - b.fully_txed = false; - b.rlc_segment_list.clear(); + b.sn = invalid_sn; + b.fully_txed = false; + b.segment_list.clear(); } } @@ -2475,9 +2456,9 @@ void rlc_am_undelivered_sdu_info_to_string(fmt::memory_buffer& buffer, const std { fmt::format_to(buffer, "\n"); for (const auto& pdcp_pdu : info_queue) { - fmt::format_to(buffer, "\tPDCP_SN = {}, RLC_SNs = [", pdcp_pdu.sn); - for (const auto& rlc_sn_info : pdcp_pdu.rlc_segment_list) { - fmt::format_to(buffer, "{}ACK={}, ", rlc_sn_info.is_acked() ? "" : "N", rlc_sn_info.rlc_sn()); + fmt::format_to(buffer, "\tPDCP_SN = {}, undelivered RLC SNs = [", pdcp_pdu.sn); + for (const auto& rlc_sn_info : pdcp_pdu.segment_list) { + fmt::format_to(buffer, "{} ", rlc_sn_info.rlc_sn()); } fmt::format_to(buffer, "]\n"); } From c3ec28002b2581cfde19b3a946fabf07af9cfa9d Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 12 Apr 2021 09:42:26 +0100 Subject: [PATCH 08/46] refactor - integration of segment list in rlc_amd_tx_pdu and pdcp_pdu_info classes --- lib/include/srsran/adt/expected.h | 6 +- lib/include/srsran/upper/rlc_am_lte.h | 175 +++++++++++++------------- lib/include/srsran/upper/rlc_common.h | 12 +- lib/src/upper/rlc_am_lte.cc | 112 ++++++++--------- 4 files changed, 151 insertions(+), 154 deletions(-) diff --git a/lib/include/srsran/adt/expected.h b/lib/include/srsran/adt/expected.h index 924c1baf3..51a68dda1 100644 --- a/lib/include/srsran/adt/expected.h +++ b/lib/include/srsran/adt/expected.h @@ -36,15 +36,15 @@ class expected public: expected() : has_val(true), val(T{}) {} - expected(T&& t) : has_val(true), val(std::forward(t)) {} + expected(T&& t) noexcept : has_val(true), val(std::move(t)) {} expected(const T& t) : has_val(true), val(t) {} - expected(E&& e) : has_val(false), unexpected(std::forward(e)) {} + expected(E&& e) noexcept : has_val(false), unexpected(std::move(e)) {} expected(const E& e) : has_val(false), unexpected(e) {} template < typename U, typename std::enable_if::value and not is_expected::type>::value, int>::type = 0> - explicit expected(U&& u) : has_val(true), val(std::forward(u)) + explicit expected(U&& u) noexcept : has_val(true), val(std::forward(u)) {} expected(const expected& other) { diff --git a/lib/include/srsran/upper/rlc_am_lte.h b/lib/include/srsran/upper/rlc_am_lte.h index cef259475..b99934c46 100644 --- a/lib/include/srsran/upper/rlc_am_lte.h +++ b/lib/include/srsran/upper/rlc_am_lte.h @@ -34,8 +34,8 @@ namespace srsran { #undef RLC_AM_BUFFER_DEBUG -struct pdcp_pdu_segment_list; -struct rlc_pdu_segment_list; +class rlc_amd_tx_pdu; +class pdcp_pdu_info; /// Pool that manages the allocation of RLC AM PDU Segments to RLC PDUs and tracking of segments ACK state struct rlc_am_pdu_segment_pool { @@ -55,7 +55,6 @@ struct rlc_am_pdu_segment_pool { uint32_t rlc_sn() const { return rlc_sn_; } uint32_t pdcp_sn() const { return pdcp_sn_; } bool empty() const { return rlc_sn_ == invalid_sn and pdcp_sn_ == invalid_sn; } - bool is_acked() const { return rlc_sn() != invalid_sn; } private: friend struct rlc_am_pdu_segment_pool; @@ -67,9 +66,10 @@ struct rlc_am_pdu_segment_pool { rlc_am_pdu_segment_pool(); rlc_am_pdu_segment_pool(const rlc_am_pdu_segment_pool&) = delete; rlc_am_pdu_segment_pool(rlc_am_pdu_segment_pool&&) = delete; - bool has_segments() const { return not free_list.empty(); } - bool - make_segment(uint32_t rlc_sn, uint32_t pdcp_sn, rlc_pdu_segment_list& rlc_list, pdcp_pdu_segment_list& pdcp_list); + rlc_am_pdu_segment_pool& operator=(const rlc_am_pdu_segment_pool&) = delete; + rlc_am_pdu_segment_pool& operator=(rlc_am_pdu_segment_pool&&) = delete; + bool has_segments() const { return not free_list.empty(); } + bool make_segment(rlc_amd_tx_pdu& rlc_list, pdcp_pdu_info& pdcp_info); private: intrusive_forward_list free_list; @@ -79,77 +79,49 @@ private: /// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state using rlc_am_pdu_segment = rlc_am_pdu_segment_pool::segment_resource; -class pdcp_pdu_segment_list +struct rlc_amd_rx_pdu { + rlc_amd_pdu_header_t header; + unique_byte_buffer_t buf; + uint32_t rlc_sn; + + rlc_amd_rx_pdu() = default; + explicit rlc_amd_rx_pdu(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {} +}; + +struct rlc_amd_rx_pdu_segments_t { + std::list segments; +}; + +/// Class that contains the parameters and state (e.g. segments) of a RLC PDU +class rlc_amd_tx_pdu { - using list_type = intrusive_double_linked_list; + using list_type = intrusive_forward_list; + const static uint32_t invalid_sn = std::numeric_limits::max(); + list_type list; public: using iterator = typename list_type::iterator; using const_iterator = typename list_type::const_iterator; - iterator begin() { return list.begin(); } - iterator end() { return list.end(); } - const_iterator begin() const { return list.begin(); } - const_iterator end() const { return list.end(); } - bool empty() const { return list.empty(); } - - pdcp_pdu_segment_list() = default; - pdcp_pdu_segment_list(pdcp_pdu_segment_list&&) noexcept = default; - pdcp_pdu_segment_list& operator=(pdcp_pdu_segment_list&&) noexcept = default; - ~pdcp_pdu_segment_list() { clear(); } - void push(rlc_am_pdu_segment& segment) { list.push_front(&segment); } - void pop(rlc_am_pdu_segment& segment); - void clear() - { - while (not empty()) { - pop(*begin()); - } - } -}; + const uint32_t rlc_sn = invalid_sn; + uint32_t retx_count = 0; + rlc_amd_pdu_header_t header; + unique_byte_buffer_t buf; -struct rlc_pdu_segment_list { - using list_type = intrusive_forward_list; - using iterator = typename list_type::iterator; - using const_iterator = typename list_type::const_iterator; + explicit rlc_amd_tx_pdu(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {} + rlc_amd_tx_pdu(const rlc_amd_tx_pdu&) = delete; + rlc_amd_tx_pdu(rlc_amd_tx_pdu&& other) noexcept = default; + rlc_amd_tx_pdu& operator=(const rlc_amd_tx_pdu& other) = delete; + rlc_amd_tx_pdu& operator=(rlc_amd_tx_pdu&& other) = delete; + ~rlc_amd_tx_pdu(); + // Segment List Interface + void add_segment(rlc_am_pdu_segment& segment) { list.push_front(&segment); } const_iterator begin() const { return list.begin(); } const_iterator end() const { return list.end(); } iterator begin() { return list.begin(); } iterator end() { return list.end(); } - bool empty() const { return list.empty(); } - - rlc_pdu_segment_list() = default; - rlc_pdu_segment_list(rlc_pdu_segment_list&& other) noexcept = default; - rlc_pdu_segment_list(const rlc_pdu_segment_list&) = delete; - rlc_pdu_segment_list& operator=(rlc_pdu_segment_list&& other) noexcept = default; - ~rlc_pdu_segment_list() { clear(); } - void push(rlc_am_pdu_segment& segment) { list.push_front(&segment); } - void clear(); - -private: - list_type list; -}; - -// - -struct rlc_amd_rx_pdu_t { - rlc_amd_pdu_header_t header; - unique_byte_buffer_t buf; - uint32_t rlc_sn; -}; - -struct rlc_amd_rx_pdu_segments_t { - std::list segments; -}; - -struct rlc_amd_tx_pdu_t { - rlc_amd_pdu_header_t header; - unique_byte_buffer_t buf; - rlc_pdu_segment_list segment_list; - uint32_t retx_count; - uint32_t rlc_sn = std::numeric_limits::max(); - bool is_acked = false; }; struct rlc_amd_retx_t { @@ -164,11 +136,45 @@ struct rlc_sn_info_t { bool is_acked; }; -struct pdcp_sdu_info_t { - uint32_t sn; - bool fully_txed; // Boolean indicating if the SDU is fully transmitted. - pdcp_pdu_segment_list segment_list; // List of RLC PDUs in transit and whether they have been acked or not. - bool fully_acked() const { return segment_list.empty(); } +/// Class that contains the parameters and state (e.g. unACKed segments) of a PDCP PDU +class pdcp_pdu_info +{ + using list_type = intrusive_double_linked_list; + const static uint32_t invalid_sn = std::numeric_limits::max(); + + list_type list; // List of unACKed RLC PDUs that contain segments that belong to the PDCP PDU. + +public: + using iterator = typename list_type::iterator; + using const_iterator = typename list_type::const_iterator; + + // Copy is forbidden to avoid multiple PDCP SN references to the same segment + pdcp_pdu_info() = default; + pdcp_pdu_info(pdcp_pdu_info&&) noexcept = default; + pdcp_pdu_info(const pdcp_pdu_info&) noexcept = delete; + pdcp_pdu_info& operator=(const pdcp_pdu_info&) noexcept = delete; + pdcp_pdu_info& operator=(pdcp_pdu_info&&) noexcept = default; + ~pdcp_pdu_info() { clear(); } + + uint32_t sn = invalid_sn; + bool fully_txed = false; // Boolean indicating if the SDU is fully transmitted. + + bool fully_acked() const { return list.empty(); } + bool valid() const { return sn != invalid_sn; } + + // Interface for list of unACKed RLC segments of the PDCP PDU + void add_segment(rlc_am_pdu_segment& segment) { list.push_front(&segment); } + void ack_segment(rlc_am_pdu_segment& segment); + void clear() + { + sn = invalid_sn; + fully_txed = false; + while (not list.empty()) { + ack_segment(list.front()); + } + } + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } }; template @@ -176,8 +182,7 @@ struct rlc_ringbuffer_t { T& add_pdu(size_t sn) { srsran_expect(not has_sn(sn), "The same SN=%zd should not be added twice", sn); - window.overwrite(sn, T{}); - window[sn].rlc_sn = sn; + window.overwrite(sn, T(sn)); return window[sn]; } void remove_pdu(size_t sn) @@ -229,20 +234,18 @@ public: if (buffered_pdus[sn_idx].sn == invalid_sn) { return; } - buffered_pdus[sn_idx].sn = invalid_sn; - buffered_pdus[sn_idx].fully_txed = false; - buffered_pdus[sn_idx].segment_list.clear(); + buffered_pdus[sn_idx].clear(); count--; } - pdcp_sdu_info_t& operator[](uint32_t sn) + pdcp_pdu_info& operator[](uint32_t sn) { - assert(has_pdcp_sn(sn)); + srsran_expect(has_pdcp_sn(sn), "Invalid access to non-existent PDCP SN=%d", sn); return buffered_pdus[get_idx(sn)]; } bool has_pdcp_sn(uint32_t pdcp_sn) const { - assert(pdcp_sn <= max_pdcp_sn or pdcp_sn == status_report_sn); + srsran_expect(pdcp_sn <= max_pdcp_sn or pdcp_sn == status_report_sn, "Invalid PDCP SN=%d", pdcp_sn); return buffered_pdus[get_idx(pdcp_sn)].sn == pdcp_sn; } uint32_t nof_sdus() const { return count; } @@ -259,8 +262,8 @@ private: } // size equal to buffer_size + 1 (last element for Status Report) - std::vector buffered_pdus; - uint32_t count = 0; + std::vector buffered_pdus; + uint32_t count = 0; }; class pdu_retx_queue @@ -376,7 +379,7 @@ private: int build_retx_pdu(uint8_t* payload, uint32_t nof_bytes); int build_segment(uint8_t* payload, uint32_t nof_bytes, rlc_amd_retx_t retx); int build_data_pdu(uint8_t* payload, uint32_t nof_bytes); - void update_notification_ack_info(const rlc_amd_tx_pdu_t& tx_pdu); + void update_notification_ack_info(uint32_t rlc_sn); void debug_state(); @@ -438,9 +441,9 @@ private: bsr_callback_t bsr_callback; // Tx windows - rlc_ringbuffer_t tx_window; - pdu_retx_queue retx_queue; - pdcp_sn_vector_t notify_info_vec; + rlc_ringbuffer_t tx_window; + pdu_retx_queue retx_queue; + pdcp_sn_vector_t notify_info_vec; // Mutexes std::mutex mutex; @@ -481,7 +484,7 @@ private: bool inside_rx_window(const int16_t sn); void debug_state(); void print_rx_segments(); - bool add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_amd_rx_pdu_t* segment); + bool add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_amd_rx_pdu* segment); rlc_am_lte* parent = nullptr; byte_buffer_pool* pool = nullptr; @@ -512,7 +515,7 @@ private: std::mutex mutex; // Rx windows - rlc_ringbuffer_t rx_window; + rlc_ringbuffer_t rx_window; std::map rx_segments; bool poll_received = false; @@ -564,7 +567,7 @@ uint32_t rlc_am_packed_length(rlc_status_pdu_t* status); uint32_t rlc_am_packed_length(rlc_amd_retx_t retx); bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status); bool rlc_am_is_pdu_segment(uint8_t* payload); -std::string rlc_am_undelivered_sdu_info_to_string(const std::map& info_queue); +std::string rlc_am_undelivered_sdu_info_to_string(const std::map& info_queue); void log_rlc_amd_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_amd_pdu_header_t& header); bool rlc_am_start_aligned(const uint8_t fi); bool rlc_am_end_aligned(const uint8_t fi); diff --git a/lib/include/srsran/upper/rlc_common.h b/lib/include/srsran/upper/rlc_common.h index f48939dcc..44568cec7 100644 --- a/lib/include/srsran/upper/rlc_common.h +++ b/lib/include/srsran/upper/rlc_common.h @@ -104,10 +104,18 @@ typedef struct { class rlc_amd_pdu_header_t { public: - rlc_amd_pdu_header_t() {} - + rlc_amd_pdu_header_t() = default; rlc_amd_pdu_header_t(const rlc_amd_pdu_header_t& h) { copy(h); } + rlc_amd_pdu_header_t(rlc_amd_pdu_header_t&& h) noexcept { copy(h); } rlc_amd_pdu_header_t& operator=(const rlc_amd_pdu_header_t& h) + { + if (this == &h) { + return *this; + } + copy(h); + return *this; + } + rlc_amd_pdu_header_t& operator=(rlc_amd_pdu_header_t&& h) noexcept { copy(h); return *this; diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index ab650a440..0ce92b535 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -90,23 +90,20 @@ rlc_am_pdu_segment_pool::rlc_am_pdu_segment_pool() } } -bool rlc_am_pdu_segment_pool::make_segment(uint32_t rlc_sn, - uint32_t pdcp_sn, - rlc_pdu_segment_list& rlc_list, - pdcp_pdu_segment_list& pdcp_list) +bool rlc_am_pdu_segment_pool::make_segment(rlc_amd_tx_pdu& rlc_list, pdcp_pdu_info& pdcp_list) { if (not has_segments()) { return false; } segment_resource* segment = free_list.pop_front(); - rlc_list.push(*segment); - pdcp_list.push(*segment); - segment->rlc_sn_ = rlc_sn; - segment->pdcp_sn_ = pdcp_sn; + segment->rlc_sn_ = rlc_list.rlc_sn; + segment->pdcp_sn_ = pdcp_list.sn; + rlc_list.add_segment(*segment); + pdcp_list.add_segment(*segment); return true; } -void pdcp_pdu_segment_list::pop(rlc_am_pdu_segment& segment) +void pdcp_pdu_info::ack_segment(rlc_am_pdu_segment& segment) { // remove from list list.pop(&segment); @@ -114,9 +111,9 @@ void pdcp_pdu_segment_list::pop(rlc_am_pdu_segment& segment) segment.release_pdcp_sn(); } -void rlc_pdu_segment_list::clear() +rlc_amd_tx_pdu::~rlc_amd_tx_pdu() { - while (not empty()) { + while (not list.empty()) { // remove from list rlc_am_pdu_segment* segment = list.pop_front(); // deallocate if also removed from PDCP @@ -402,7 +399,7 @@ void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn) logger.warning("%s Signaling max number of reTx=%d for SN=%d", RB_NAME, tx_window[sn].retx_count, sn); parent->rrc->max_retx_attempted(); srsran::pdcp_sn_vector_t pdcp_sns; - for (const rlc_am_pdu_segment& segment : tx_window[sn].segment_list) { + for (const rlc_am_pdu_segment& segment : tx_window[sn]) { pdcp_sns.push_back(segment.pdcp_sn()); } parent->pdcp->notify_failure(parent->lcid, pdcp_sns); @@ -622,7 +619,7 @@ void rlc_am_lte::rlc_am_lte_tx::retransmit_pdu() } // select first PDU in tx window for retransmission - rlc_amd_tx_pdu_t& pdu = tx_window[vt_a]; + rlc_amd_tx_pdu& pdu = tx_window[vt_a]; logger.info("%s Schedule SN=%d for reTx.", RB_NAME, pdu.rlc_sn); rlc_amd_retx_t& retx = retx_queue.push(); retx.is_segment = false; @@ -983,7 +980,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt srsran::console("tx_window size: %zd PDUs\n", tx_window.size()); srsran::console("vt_a = %d, vt_ms = %d, vt_s = %d, poll_sn = %d\n", vt_a, vt_ms, vt_s, poll_sn); srsran::console("retx_queue size: %zd PDUs\n", retx_queue.size()); - std::map::iterator txit; + std::map::iterator txit; for (txit = tx_window.begin(); txit != tx_window.end(); txit++) { srsran::console("tx_window - SN=%d\n", txit->first); } @@ -998,9 +995,14 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt header.fi = RLC_FI_FIELD_START_AND_END_ALIGNED; header.sn = vt_s; + if (not segment_pool.has_segments()) { + logger.info("Can't build a PDU - No segments available"); + return 0; + } + // insert newly assigned SN into window and use reference for in-place operations // NOTE: from now on, we can't return from this function anymore before increasing vt_s - rlc_amd_tx_pdu_t& tx_pdu = tx_window.add_pdu(header.sn); + rlc_amd_tx_pdu& tx_pdu = tx_window.add_pdu(header.sn); uint32_t head_len = rlc_am_packed_length(&header); uint32_t to_move = 0; @@ -1010,13 +1012,6 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt logger.debug("%s Building PDU - pdu_space: %d, head_len: %d ", RB_NAME, pdu_space, head_len); - bool segments_created = false; - if (not segment_pool.has_segments()) { - logger.info("Can't build a PDU - No segments available"); - tx_window.remove_pdu(tx_pdu.rlc_sn); - return 0; - } - // Check for SDU segment if (tx_sdu != nullptr) { to_move = ((pdu_space - head_len) >= tx_sdu->N_bytes) ? tx_sdu->N_bytes : pdu_space - head_len; @@ -1027,12 +1022,11 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt tx_sdu->N_bytes -= to_move; tx_sdu->msg += to_move; if (undelivered_sdu_info_queue.has_pdcp_sn(tx_sdu->md.pdcp_sn)) { - pdcp_sdu_info_t& pdcp_sdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; - segment_pool.make_segment(header.sn, tx_sdu->md.pdcp_sn, tx_pdu.segment_list, pdcp_sdu.segment_list); + pdcp_pdu_info& pdcp_pdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; + segment_pool.make_segment(tx_pdu, pdcp_pdu); if (tx_sdu->N_bytes == 0) { - pdcp_sdu.fully_txed = true; + pdcp_pdu.fully_txed = true; } - segments_created = true; } else { // PDCP SNs for the RLC SDU has been removed from the queue logger.warning("Couldn't find PDCP_SN=%d in SDU info queue (segment)", tx_sdu->md.pdcp_sn); @@ -1062,7 +1056,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt while (pdu_space > head_len && tx_sdu_queue.get_n_sdus() > 0 && header.N_li < RLC_AM_WINDOW_SIZE) { if (not segment_pool.has_segments()) { logger.info("Can't build a PDU segment - No segment resources available"); - if (segments_created) { + if (pdu_ptr != pdu->msg) { break; // continue with the segments created up to this point } tx_window.remove_pdu(tx_pdu.rlc_sn); @@ -1099,12 +1093,11 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt tx_sdu->N_bytes -= to_move; tx_sdu->msg += to_move; if (undelivered_sdu_info_queue.has_pdcp_sn(tx_sdu->md.pdcp_sn)) { - pdcp_sdu_info_t& pdcp_sdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; - segment_pool.make_segment(header.sn, tx_sdu->md.pdcp_sn, tx_pdu.segment_list, pdcp_sdu.segment_list); + pdcp_pdu_info& pdcp_pdu = undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn]; + segment_pool.make_segment(tx_pdu, pdcp_pdu); if (tx_sdu->N_bytes == 0) { - pdcp_sdu.fully_txed = true; + pdcp_pdu.fully_txed = true; } - segments_created = true; } else { // PDCP SNs for the RLC SDU has been removed from the queue logger.warning("Couldn't find PDCP_SN=%d in SDU info queue.", tx_sdu->md.pdcp_sn); @@ -1158,9 +1151,6 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt // Write final header and TX tx_pdu.buf = std::move(pdu); tx_pdu.header = header; - tx_pdu.is_acked = false; - tx_pdu.retx_count = 0; - tx_pdu.rlc_sn = header.sn; const byte_buffer_t* buffer_ptr = tx_pdu.buf.get(); uint8_t* ptr = payload; @@ -1261,8 +1251,7 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no if (!nack) { // ACKed SNs get marked and removed from tx_window so PDCP get's only notified once if (tx_window.has_sn(i)) { - auto& pdu = tx_window[i]; - update_notification_ack_info(pdu); + update_notification_ack_info(i); logger.debug("Tx PDU SN=%zd being removed from tx window", i); tx_window.remove_pdu(i); } @@ -1296,27 +1285,27 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no * @tx_pdu: RLC PDU that was ack'ed. * @notify_info_vec: Vector which will keep track of the PDCP PDU SNs that have been fully ack'ed. */ -void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pdu_t& tx_pdu) +void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(uint32_t rlc_sn) { logger.debug("Updating ACK info: RLC SN=%d, number of notified SDU=%ld, number of undelivered SDUs=%ld", - tx_pdu.header.sn, + rlc_sn, notify_info_vec.size(), undelivered_sdu_info_queue.nof_sdus()); // Iterate over all undelivered SDUs - if (not tx_window.has_sn(tx_pdu.header.sn)) { + if (not tx_window.has_sn(rlc_sn)) { return; } - rlc_pdu_segment_list& pdcp_sns = tx_window[tx_pdu.header.sn].segment_list; + auto& acked_pdu = tx_window[rlc_sn]; // Iterate over all PDCP SNs of the same RLC PDU that were TX'ed - for (rlc_am_pdu_segment& acked_segment : pdcp_sns) { - uint32_t pdcp_sn = acked_segment.pdcp_sn(); - pdcp_sdu_info_t& info = undelivered_sdu_info_queue[pdcp_sn]; + for (rlc_am_pdu_segment& acked_segment : acked_pdu) { + uint32_t pdcp_sn = acked_segment.pdcp_sn(); + pdcp_pdu_info& info = undelivered_sdu_info_queue[pdcp_sn]; // Remove RLC SN from PDCP PDU undelivered list - info.segment_list.pop(acked_segment); + info.ack_segment(acked_segment); // Check whether the SDU was fully acked - if (info.fully_txed and info.segment_list.empty()) { + if (info.fully_txed and info.fully_acked()) { // Check if all SNs were ACK'ed if (not notify_info_vec.full()) { notify_info_vec.push_back(pdcp_sn); @@ -1327,7 +1316,6 @@ void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pd undelivered_sdu_info_queue.clear_pdcp_sdu(pdcp_sn); } } - pdcp_sns.clear(); } void rlc_am_lte::rlc_am_lte_tx::debug_state() @@ -1479,7 +1467,7 @@ void rlc_am_lte::rlc_am_lte_rx::stop() */ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_amd_pdu_header_t& header) { - std::map::iterator it; + std::map::iterator it; logger.info(payload, nof_bytes, "%s Rx data PDU SN=%d (%d B)", RB_NAME, header.sn, nof_bytes); log_rlc_amd_pdu_header_to_string(logger.debug, header); @@ -1515,8 +1503,8 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b } // Write to rx window - rlc_amd_rx_pdu_t& pdu = rx_window.add_pdu(header.sn); - pdu.buf = srsran::make_byte_buffer(); + rlc_amd_rx_pdu& pdu = rx_window.add_pdu(header.sn); + pdu.buf = srsran::make_byte_buffer(); if (pdu.buf == NULL) { #ifdef RLC_AM_BUFFER_DEBUG srsran::console("Fatal Error: Couldn't allocate PDU in handle_data_pdu().\n"); @@ -1620,7 +1608,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa return; } - rlc_amd_rx_pdu_t segment; + rlc_amd_rx_pdu segment; segment.buf = srsran::make_byte_buffer(); if (segment.buf == NULL) { #ifdef RLC_AM_BUFFER_DEBUG @@ -1813,7 +1801,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() it = rx_segments.find(vr_r); if (rx_segments.end() != it) { logger.debug("Erasing segments of SN=%d", vr_r); - std::list::iterator segit; + std::list::iterator segit; for (segit = it->second.segments.begin(); segit != it->second.segments.end(); ++segit) { logger.debug(" Erasing segment of SN=%d SO=%d Len=%d N_li=%d", segit->header.sn, @@ -1975,7 +1963,7 @@ void rlc_am_lte::rlc_am_lte_rx::print_rx_segments() std::stringstream ss; ss << "rx_segments:" << std::endl; for (it = rx_segments.begin(); it != rx_segments.end(); it++) { - std::list::iterator segit; + std::list::iterator segit; for (segit = it->second.segments.begin(); segit != it->second.segments.end(); segit++) { ss << " SN=" << segit->header.sn << " SO:" << segit->header.so << " N:" << segit->buf->N_bytes << " N_li: " << segit->header.N_li << std::endl; @@ -1985,7 +1973,7 @@ void rlc_am_lte::rlc_am_lte_rx::print_rx_segments() } // NOTE: Preference would be to capture by value, and then move; but header is stack allocated -bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_amd_rx_pdu_t* segment) +bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_amd_rx_pdu* segment) { // Find segment insertion point in the list of segments auto it1 = pdu->segments.begin(); @@ -1997,7 +1985,7 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t* // Check if the insertion point was found if (it1 != pdu->segments.end()) { // Found insertion point - rlc_amd_rx_pdu_t& s = *it1; + rlc_amd_rx_pdu& s = *it1; if (s.header.so == segment->header.so) { // Same Segment offset if (segment->buf->N_bytes > s.buf->N_bytes) { @@ -2015,8 +2003,8 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t* } // Check for complete - uint32_t so = 0; - std::list::iterator it, tmpit; + uint32_t so = 0; + std::list::iterator it, tmpit; for (it = pdu->segments.begin(); it != pdu->segments.end(); /* Do not increment */) { // Check that there is no gap between last segment and current; overlap allowed if (so < it->header.so) { @@ -2189,10 +2177,8 @@ buffered_pdcp_pdu_list::buffered_pdcp_pdu_list() : buffered_pdus(max_buffer_idx void buffered_pdcp_pdu_list::clear() { count = 0; - for (auto& b : buffered_pdus) { - b.sn = invalid_sn; - b.fully_txed = false; - b.segment_list.clear(); + for (pdcp_pdu_info& b : buffered_pdus) { + b.clear(); } } @@ -2452,13 +2438,13 @@ bool rlc_am_is_pdu_segment(uint8_t* payload) return ((*(payload) >> 6) & 0x01) == 1; } -void rlc_am_undelivered_sdu_info_to_string(fmt::memory_buffer& buffer, const std::vector& info_queue) +void rlc_am_undelivered_sdu_info_to_string(fmt::memory_buffer& buffer, const std::vector& info_queue) { fmt::format_to(buffer, "\n"); for (const auto& pdcp_pdu : info_queue) { fmt::format_to(buffer, "\tPDCP_SN = {}, undelivered RLC SNs = [", pdcp_pdu.sn); - for (const auto& rlc_sn_info : pdcp_pdu.segment_list) { - fmt::format_to(buffer, "{} ", rlc_sn_info.rlc_sn()); + for (const auto& nacked_segment : pdcp_pdu) { + fmt::format_to(buffer, "{} ", nacked_segment.rlc_sn()); } fmt::format_to(buffer, "]\n"); } From e3e4564a7eb82ee8422b2b3f4a250ec8615d2e53 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 16 Apr 2021 12:49:18 +0100 Subject: [PATCH 09/46] fix inconsistency in use of invalid_sn and status_report_sn throughout rlc am code --- lib/include/srsran/upper/rlc_am_lte.h | 65 +++++++++++++++------------ lib/src/upper/rlc_am_lte.cc | 10 ++--- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/lib/include/srsran/upper/rlc_am_lte.h b/lib/include/srsran/upper/rlc_am_lte.h index b99934c46..e6e46d079 100644 --- a/lib/include/srsran/upper/rlc_am_lte.h +++ b/lib/include/srsran/upper/rlc_am_lte.h @@ -47,19 +47,20 @@ struct rlc_am_pdu_segment_pool { struct segment_resource : public intrusive_forward_list_element, public intrusive_forward_list_element, public intrusive_double_linked_list_element<> { - const static uint32_t invalid_sn = std::numeric_limits::max(); + const static uint32_t invalid_rlc_sn = std::numeric_limits::max(); + const static uint32_t invalid_pdcp_sn = std::numeric_limits::max() - 1; // -1 for Status Report int id() const; void release_pdcp_sn(); void release_rlc_sn(); uint32_t rlc_sn() const { return rlc_sn_; } uint32_t pdcp_sn() const { return pdcp_sn_; } - bool empty() const { return rlc_sn_ == invalid_sn and pdcp_sn_ == invalid_sn; } + bool empty() const { return rlc_sn_ == invalid_rlc_sn and pdcp_sn_ == invalid_pdcp_sn; } private: friend struct rlc_am_pdu_segment_pool; - uint32_t rlc_sn_ = invalid_sn; - uint32_t pdcp_sn_ = invalid_sn; + uint32_t rlc_sn_ = invalid_rlc_sn; + uint32_t pdcp_sn_ = invalid_pdcp_sn; rlc_am_pdu_segment_pool* parent_pool = nullptr; }; @@ -95,8 +96,8 @@ struct rlc_amd_rx_pdu_segments_t { /// Class that contains the parameters and state (e.g. segments) of a RLC PDU class rlc_amd_tx_pdu { - using list_type = intrusive_forward_list; - const static uint32_t invalid_sn = std::numeric_limits::max(); + using list_type = intrusive_forward_list; + const static uint32_t invalid_rlc_sn = std::numeric_limits::max(); list_type list; @@ -104,7 +105,7 @@ public: using iterator = typename list_type::iterator; using const_iterator = typename list_type::const_iterator; - const uint32_t rlc_sn = invalid_sn; + const uint32_t rlc_sn = invalid_rlc_sn; uint32_t retx_count = 0; rlc_amd_pdu_header_t header; unique_byte_buffer_t buf; @@ -139,12 +140,14 @@ struct rlc_sn_info_t { /// Class that contains the parameters and state (e.g. unACKed segments) of a PDCP PDU class pdcp_pdu_info { - using list_type = intrusive_double_linked_list; - const static uint32_t invalid_sn = std::numeric_limits::max(); + using list_type = intrusive_double_linked_list; list_type list; // List of unACKed RLC PDUs that contain segments that belong to the PDCP PDU. public: + const static uint32_t status_report_sn = std::numeric_limits::max(); + const static uint32_t invalid_pdcp_sn = std::numeric_limits::max() - 1; + using iterator = typename list_type::iterator; using const_iterator = typename list_type::const_iterator; @@ -156,18 +159,18 @@ public: pdcp_pdu_info& operator=(pdcp_pdu_info&&) noexcept = default; ~pdcp_pdu_info() { clear(); } - uint32_t sn = invalid_sn; + uint32_t sn = invalid_pdcp_sn; bool fully_txed = false; // Boolean indicating if the SDU is fully transmitted. - bool fully_acked() const { return list.empty(); } - bool valid() const { return sn != invalid_sn; } + bool fully_acked() const { return fully_txed and list.empty(); } + bool valid() const { return sn != invalid_pdcp_sn; } // Interface for list of unACKed RLC segments of the PDCP PDU void add_segment(rlc_am_pdu_segment& segment) { list.push_front(&segment); } void ack_segment(rlc_am_pdu_segment& segment); void clear() { - sn = invalid_sn; + sn = invalid_pdcp_sn; fully_txed = false; while (not list.empty()) { ack_segment(list.front()); @@ -220,49 +223,55 @@ public: void add_pdcp_sdu(uint32_t sn) { + srsran_expect(sn <= max_pdcp_sn or sn == status_report_sn, "Invalid PDCP SN=%d", sn); srsran_assert(not has_pdcp_sn(sn), "Cannot re-add same PDCP SN twice"); - uint32_t sn_idx = get_idx(sn); - if (buffered_pdus[sn_idx].sn != invalid_sn) { - clear_pdcp_sdu(buffered_pdus[sn_idx].sn); + pdcp_pdu_info& pdu = get_pdu_(sn); + if (pdu.valid()) { + pdu.clear(); + count--; } - buffered_pdus[get_idx(sn)].sn = sn; + pdu.sn = sn; count++; } void clear_pdcp_sdu(uint32_t sn) { - uint32_t sn_idx = get_idx(sn); - if (buffered_pdus[sn_idx].sn == invalid_sn) { + pdcp_pdu_info& pdu = get_pdu_(sn); + if (not pdu.valid()) { return; } - buffered_pdus[sn_idx].clear(); + pdu.clear(); count--; } pdcp_pdu_info& operator[](uint32_t sn) { srsran_expect(has_pdcp_sn(sn), "Invalid access to non-existent PDCP SN=%d", sn); - return buffered_pdus[get_idx(sn)]; + return get_pdu_(sn); } bool has_pdcp_sn(uint32_t pdcp_sn) const { srsran_expect(pdcp_sn <= max_pdcp_sn or pdcp_sn == status_report_sn, "Invalid PDCP SN=%d", pdcp_sn); - return buffered_pdus[get_idx(pdcp_sn)].sn == pdcp_sn; + return get_pdu_(pdcp_sn).sn == pdcp_sn; } uint32_t nof_sdus() const { return count; } private: const static size_t max_pdcp_sn = 262143u; - const static size_t max_buffer_idx = 4096u; - const static uint32_t status_report_sn = std::numeric_limits::max(); - const static uint32_t invalid_sn = std::numeric_limits::max() - 1; + const static size_t buffer_size = 4096u; + const static uint32_t status_report_sn = pdcp_pdu_info::status_report_sn; - size_t get_idx(uint32_t sn) const + pdcp_pdu_info& get_pdu_(uint32_t sn) + { + return (sn == status_report_sn) ? status_report_pdu : buffered_pdus[static_cast(sn % buffer_size)]; + } + const pdcp_pdu_info& get_pdu_(uint32_t sn) const { - return (sn != status_report_sn) ? static_cast(sn % max_buffer_idx) : max_buffer_idx; + return (sn == status_report_sn) ? status_report_pdu : buffered_pdus[static_cast(sn % buffer_size)]; } - // size equal to buffer_size + 1 (last element for Status Report) + // size equal to buffer_size std::vector buffered_pdus; + pdcp_pdu_info status_report_pdu; uint32_t count = 0; }; diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index 0ce92b535..e0ee95767 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -68,7 +68,7 @@ int rlc_am_pdu_segment_pool::segment_resource::id() const void rlc_am_pdu_segment_pool::segment_resource::release_pdcp_sn() { - pdcp_sn_ = invalid_sn; + pdcp_sn_ = invalid_pdcp_sn; if (empty()) { parent_pool->free_list.push_front(this); } @@ -76,7 +76,7 @@ void rlc_am_pdu_segment_pool::segment_resource::release_pdcp_sn() void rlc_am_pdu_segment_pool::segment_resource::release_rlc_sn() { - rlc_sn_ = invalid_sn; + rlc_sn_ = invalid_rlc_sn; if (empty()) { parent_pool->free_list.push_front(this); } @@ -1305,7 +1305,7 @@ void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(uint32_t rlc_sn) info.ack_segment(acked_segment); // Check whether the SDU was fully acked - if (info.fully_txed and info.fully_acked()) { + if (info.fully_acked()) { // Check if all SNs were ACK'ed if (not notify_info_vec.full()) { notify_info_vec.push_back(pdcp_sn); @@ -2167,9 +2167,7 @@ void rlc_am_lte::rlc_am_lte_rx::debug_state() logger.debug("%s vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d", RB_NAME, vr_r, vr_mr, vr_x, vr_ms, vr_h); } -const size_t buffered_pdcp_pdu_list::max_buffer_idx; - -buffered_pdcp_pdu_list::buffered_pdcp_pdu_list() : buffered_pdus(max_buffer_idx + 1) +buffered_pdcp_pdu_list::buffered_pdcp_pdu_list() : buffered_pdus(buffered_pdcp_pdu_list::buffer_size) { clear(); } From b9ae064338950aa7eb2b5cb99921451320f2e117 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 15 Apr 2021 23:30:20 +0200 Subject: [PATCH 10/46] mac_nr: add DL HARQ this commit adds a complete DL HARQ entity to the MAC of the UE. It also refactors demux into an own class and adapts the PHY-MAC interface to use the new MAC capabilities. --- .../srsran/interfaces/mac_interface_types.h | 9 +- .../srsran/interfaces/ue_nr_interfaces.h | 43 +++- lib/src/common/basic_vnf.cc | 12 +- lib/src/phy/phch/ra_nr.c | 2 + lib/src/upper/pdcp_entity_lte.cc | 2 +- srsue/hdr/phy/nr/cc_worker.h | 3 - srsue/hdr/stack/mac_nr/demux_nr.h | 60 +++++ srsue/hdr/stack/mac_nr/dl_harq_nr.h | 103 ++++++++ srsue/hdr/stack/mac_nr/mac_nr.h | 23 +- srsue/hdr/stack/mac_nr/mac_nr_interfaces.h | 10 + srsue/hdr/stack/mac_nr/proc_ra_nr.h | 4 +- srsue/hdr/stack/ue_stack_lte.h | 18 +- srsue/hdr/stack/ue_stack_nr.h | 9 +- srsue/src/phy/nr/cc_worker.cc | 51 ++-- srsue/src/stack/mac_nr/CMakeLists.txt | 11 +- srsue/src/stack/mac_nr/demux_nr.cc | 81 ++++++ srsue/src/stack/mac_nr/dl_harq_nr.cc | 243 ++++++++++++++++++ srsue/src/stack/mac_nr/mac_nr.cc | 150 ++++++----- srsue/src/stack/mac_nr/proc_ra_nr.cc | 64 ++--- .../src/stack/mac_nr/test/proc_ra_nr_test.cc | 13 +- srsue/src/stack/ue_stack_lte.cc | 2 +- 21 files changed, 744 insertions(+), 169 deletions(-) create mode 100644 srsue/hdr/stack/mac_nr/demux_nr.h create mode 100644 srsue/hdr/stack/mac_nr/dl_harq_nr.h create mode 100644 srsue/src/stack/mac_nr/demux_nr.cc create mode 100644 srsue/src/stack/mac_nr/dl_harq_nr.cc diff --git a/lib/include/srsran/interfaces/mac_interface_types.h b/lib/include/srsran/interfaces/mac_interface_types.h index 964b8ef34..e5ec84609 100644 --- a/lib/include/srsran/interfaces/mac_interface_types.h +++ b/lib/include/srsran/interfaces/mac_interface_types.h @@ -87,6 +87,13 @@ struct ul_harq_cfg_t { } }; +/// NR specific config for DL HARQ with configurable number of processes +struct dl_harq_cfg_nr_t { + uint8_t nof_procs; // Number of HARQ processes used in the DL + dl_harq_cfg_nr_t() { reset(); } + void reset() { nof_procs = SRSRAN_DEFAULT_HARQ_PROC_DL_NR; } +}; + struct rach_cfg_t { bool enabled; uint32_t nof_preambles; @@ -145,7 +152,7 @@ struct sr_cfg_item_nr_t { #define SRSRAN_MAX_MAX_NR_OF_SR_CFG_PER_CELL_GROUP (8) struct sr_cfg_nr_t { - bool enabled; + bool enabled; uint8_t num_items; sr_cfg_item_nr_t item[SRSRAN_MAX_MAX_NR_OF_SR_CFG_PER_CELL_GROUP]; }; diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index 0ba59cb61..5e003d33a 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -33,13 +33,31 @@ public: class mac_interface_phy_nr { public: + /// For DL, PDU buffer is allocated and passed to MAC in tb_decoded() + typedef struct { + bool enabled; /// Whether or not PHY should attempt to decode PDSCH + srsran_softbuffer_rx_t* softbuffer; /// Pointer to softbuffer to use + } tb_dl_t; + + /// Struct provided by MAC with all necessary information for PHY + typedef struct { + tb_dl_t tb; // only single TB in DL + } tb_action_dl_t; + typedef struct { - srsran::unique_byte_buffer_t tb[SRSRAN_MAX_TB]; - uint32_t pid; uint16_t rnti; uint32_t tti; + uint8_t pid; // HARQ process ID + uint8_t rv; // Redundancy Version + uint8_t ndi; // Raw new data indicator extracted from DCI + uint32_t tbs; // Transport block size in Bytes } mac_nr_grant_dl_t; + typedef struct { + srsran::unique_byte_buffer_t payload; // TB when decoded successfully, nullptr otherwise + bool ack; // HARQ information + } tb_action_dl_result_t; + // UL grant as conveyed between PHY and MAC typedef struct { uint16_t rnti; @@ -74,8 +92,25 @@ public: virtual sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) = 0; virtual sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) = 0; - /// Indicate succussfully received TB to MAC. The TB buffer is allocated in the PHY and handed as unique_ptr to MAC - virtual void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) = 0; + /** + * @brief Indicate reception of DL grant to MAC + * + * The TB buffer is allocated in the PHY and handed as unique_ptr to MAC. + * + * @param cc_idx The carrier index on which the grant has been received + * @param grant Reference to the grant + * @param action Pointer to the TB action to be filled by MAC + */ + virtual void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) = 0; + + /** + * Indicate decoding of PDSCH + * + * @param cc_idx The index of the carrier for which the PDSCH has been decoded + * @param grant The original DL grant + * @param result Payload (if any) and ack information + */ + virtual void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) = 0; /** * @brief Indicate reception of UL grant to MAC diff --git a/lib/src/common/basic_vnf.cc b/lib/src/common/basic_vnf.cc index 69a020e47..81170e633 100644 --- a/lib/src/common/basic_vnf.cc +++ b/lib/src/common/basic_vnf.cc @@ -182,12 +182,14 @@ int srsran_basic_vnf::handle_dl_ind(basic_vnf_api::dl_ind_msg_t* msg) } for (uint32_t i = 0; i < msg->nof_pdus; ++i) { - dl_grant.tb[i] = srsran::make_byte_buffer(); - if (dl_grant.tb[i] && dl_grant.tb[i]->get_tailroom() >= msg->pdus[i].length) { - memcpy(dl_grant.tb[i]->msg, msg->pdus[i].data, msg->pdus[i].length); - dl_grant.tb[i]->N_bytes = msg->pdus[i].length; + srsue::stack_interface_phy_nr::tb_action_dl_result_t result = {}; + result.payload = srsran::make_byte_buffer(); + if (result.payload != nullptr && result.payload->get_tailroom() >= msg->pdus[i].length) { + result.ack = true; + memcpy(result.payload->msg, msg->pdus[i].data, msg->pdus[i].length); + result.payload->N_bytes = msg->pdus[i].length; if (msg->pdus[i].type == basic_vnf_api::PDSCH) { - m_ue_stack->tb_decoded(cc_idx, dl_grant); + m_ue_stack->tb_decoded(cc_idx, dl_grant, std::move(result)); } } else { logger.error("TB too big to fit into buffer (%d)", msg->pdus[i].length); diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 9387df894..bbe8fbbf2 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -677,6 +677,8 @@ int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier, pdsch_grant->rnti_type = dci_dl->ctx.rnti_type; pdsch_grant->tb[0].rv = dci_dl->rv; pdsch_grant->tb[0].mcs = dci_dl->mcs; + pdsch_grant->tb[0].ndi = dci_dl->ndi; + pdsch_grant->tb[0].pid = dci_dl->pid; // 5.1.4 PDSCH resource mapping if (ra_dl_resource_mapping(carrier, slot, pdsch_hl_cfg, pdsch_cfg) < SRSRAN_SUCCESS) { diff --git a/lib/src/upper/pdcp_entity_lte.cc b/lib/src/upper/pdcp_entity_lte.cc index 8401e8180..631a9e62d 100644 --- a/lib/src/upper/pdcp_entity_lte.cc +++ b/lib/src/upper/pdcp_entity_lte.cc @@ -719,7 +719,7 @@ void pdcp_entity_lte::notify_delivery(const pdcp_sn_vector_t& pdcp_sns) } // Find undelivered PDU info if (not undelivered_sdus->has_sdu(sn)) { - logger.warning("Could not find PDU for delivery notification. Notified SN=%d", sn); + logger.info("Could not find PDU for delivery notification. Notified SN=%d", sn); } else { // Metrics auto& sdu = (*undelivered_sdus)[sn]; diff --git a/srsue/hdr/phy/nr/cc_worker.h b/srsue/hdr/phy/nr/cc_worker.h index 80002d8b7..84b7f7c6d 100644 --- a/srsue/hdr/phy/nr/cc_worker.h +++ b/srsue/hdr/phy/nr/cc_worker.h @@ -51,9 +51,6 @@ private: srsran_ue_ul_nr_t ue_ul = {}; srslog::basic_logger& logger; - // Temporal attributes - srsran_softbuffer_rx_t softbuffer_rx = {}; - // Methods for DL... void decode_pdcch_ul(); void decode_pdcch_dl(); diff --git a/srsue/hdr/stack/mac_nr/demux_nr.h b/srsue/hdr/stack/mac_nr/demux_nr.h new file mode 100644 index 000000000..d14d24999 --- /dev/null +++ b/srsue/hdr/stack/mac_nr/demux_nr.h @@ -0,0 +1,60 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSLTE_DEMUX_NR_H +#define SRSLTE_DEMUX_NR_H + +#include "mac_nr_interfaces.h" +#include "srsran/common/block_queue.h" +#include "srsran/interfaces/ue_rlc_interfaces.h" + +namespace srsue { + +/** + * @brief Logical Channel Demultiplexing and MAC CE dissassemble according to TS 38.321 + * + * Currently only SDU handling for SCH PDU processing is implemented. + * Downlink CE are parsed but not handled. + * + * PDUs can be pushed by multiple HARQ processes in parallel. + * Handling of the PDUs is done from Stack thread which reads the enqueued PDUs + * from the thread-safe queue. + */ +class demux_nr : public demux_interface_harq_nr +{ +public: + demux_nr(srslog::basic_logger& logger_); + ~demux_nr(); + + int32_t init(rlc_interface_mac* rlc_); + + void process_pdus(); /// Called by MAC to process received PDUs + + // HARQ interface + void push_pdu(srsran::unique_byte_buffer_t pdu, uint32_t tti); + +private: + // internal helpers + void handle_pdu(srsran::unique_byte_buffer_t pdu); + + srslog::basic_logger& logger; + rlc_interface_mac* rlc = nullptr; + + ///< currently only DCH PDUs supported (add BCH, PCH, etc) + srsran::block_queue pdu_queue; + + srsran::mac_sch_pdu_nr rx_pdu; +}; + +} // namespace srsue + +#endif // SRSLTE_DEMUX_NR_H diff --git a/srsue/hdr/stack/mac_nr/dl_harq_nr.h b/srsue/hdr/stack/mac_nr/dl_harq_nr.h new file mode 100644 index 000000000..308834842 --- /dev/null +++ b/srsue/hdr/stack/mac_nr/dl_harq_nr.h @@ -0,0 +1,103 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSLTE_DL_HARQ_NR_H +#define SRSLTE_DL_HARQ_NR_H + +#include "srsran/interfaces/mac_interface_types.h" +#include "srsran/interfaces/ue_nr_interfaces.h" +#include "srsran/srslog/logger.h" +#include "srsue/hdr/stack/mac_nr/mac_nr_interfaces.h" +#include + +namespace srsue { + +/** + * @brief Downlink HARQ entity as defined in 5.3.2 of 38.321 + * + * The class supports a configurable number of HARQ processes (up to 16). + * + * The class is configured (init and reset) by the MAC class from the + * Stack thread context. Main functionality, however, is carried + * out from a PHY worker context. + * + * Concurrent access from threads is protected through rwlocks. + * + */ +class dl_harq_entity_nr +{ + using mac_nr_grant_dl_t = mac_interface_phy_nr::mac_nr_grant_dl_t; + +public: + dl_harq_entity_nr(uint8_t cc_idx_, mac_interface_harq_nr* mac_, demux_interface_harq_nr* demux_unit_); + ~dl_harq_entity_nr(); + + int32_t set_config(const srsran::dl_harq_cfg_nr_t& cfg_); + void reset(); + + /// PHY->MAC interface for DL processes + void new_grant_dl(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_t* action); + void tb_decoded(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_result_t result); + + float get_average_retx(); + +private: + class dl_harq_process_nr + { + public: + dl_harq_process_nr(dl_harq_entity_nr* parent); + ~dl_harq_process_nr(); + bool init(int pid); + void reset(void); + uint8_t get_ndi(); + + void + new_grant_dl(const mac_nr_grant_dl_t& grant, const bool& ndi_toggled, mac_interface_phy_nr::tb_action_dl_t* action); + void tb_decoded(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_result_t result); + + private: + dl_harq_entity_nr* harq_entity = nullptr; + srslog::basic_logger& logger; + + bool is_first_tb = true; + + bool is_bcch = false; + uint32_t pid = 0; // HARQ Proccess ID + bool acked = false; + uint32_t n_retx = 0; + + mac_nr_grant_dl_t current_grant = {}; + std::unique_ptr softbuffer_rx; + }; + + // Private members of dl_harq_entity_nr + mac_interface_harq_nr* mac = nullptr; + srsran::dl_harq_cfg_nr_t cfg = {}; + std::array, SRSRAN_MAX_HARQ_PROC_DL_NR> harq_procs; + dl_harq_process_nr bcch_proc; + demux_interface_harq_nr* demux_unit = nullptr; + srslog::basic_logger& logger; + uint16_t last_temporal_crnti = SRSRAN_INVALID_RNTI; + + float average_retx = 0.0; + uint64_t nof_pkts = 0; + uint8_t cc_idx = 0; + + pthread_rwlock_t rwlock; +}; + +typedef std::unique_ptr dl_harq_entity_nr_ptr; +typedef std::array dl_harq_entity_nr_vector; + +} // namespace srsue + +#endif // SRSLTE_DL_HARQ_NR_H diff --git a/srsue/hdr/stack/mac_nr/mac_nr.h b/srsue/hdr/stack/mac_nr/mac_nr.h index 354499434..c6dc63d13 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr.h +++ b/srsue/hdr/stack/mac_nr/mac_nr.h @@ -13,16 +13,17 @@ #ifndef SRSUE_MAC_NR_H #define SRSUE_MAC_NR_H +#include "dl_harq_nr.h" #include "mac_nr_interfaces.h" #include "proc_bsr_nr.h" #include "proc_ra_nr.h" #include "proc_sr_nr.h" -#include "srsran/common/block_queue.h" #include "srsran/common/mac_pcap.h" #include "srsran/interfaces/mac_interface_types.h" #include "srsran/interfaces/ue_nr_interfaces.h" #include "srsran/srslog/srslog.h" #include "srsue/hdr/stack/mac_common/mac_common.h" +#include "srsue/hdr/stack/mac_nr/demux_nr.h" #include "srsue/hdr/stack/mac_nr/mux_nr.h" #include "srsue/hdr/stack/ue_stack_base.h" #include "ul_harq_nr.h" @@ -44,7 +45,7 @@ public: mac_nr(srsran::ext_task_sched_handle task_sched_); ~mac_nr(); - int init(const mac_nr_args_t& args_, phy_interface_mac_nr* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc_); + int init(const mac_nr_args_t& args_, phy_interface_mac_nr* phy_, rlc_interface_mac* rlc_, rrc_interface_mac* rrc_); void stop(); void reset(); @@ -59,7 +60,8 @@ public: sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti); int sf_indication(const uint32_t tti); - void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant); + void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result); + void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action); void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action); void prach_sent(const uint32_t tti, const uint32_t s_id, @@ -111,7 +113,9 @@ public: static bool is_in_window(uint32_t tti, int* start, int* len); private: - void write_pcap(const uint32_t cc_idx, mac_nr_grant_dl_t& grant); // If PCAPs are enabled for this MAC + void write_pcap(const uint32_t cc_idx, + const mac_nr_grant_dl_t& grant, + tb_action_dl_result_t& tb); // If PCAPs are enabled for this MAC void handle_pdu(srsran::unique_byte_buffer_t pdu); void get_ul_data(const mac_nr_grant_ul_t& grant, srsran::byte_buffer_t* tx_pdu); @@ -145,14 +149,8 @@ private: uint16_t c_rnti = SRSRAN_INVALID_RNTI; uint64_t contention_id = 0; - srsran::block_queue - pdu_queue; ///< currently only DCH PDUs supported (add BCH, PCH, etc) - std::array metrics = {}; - /// Rx buffer - srsran::mac_sch_pdu_nr rx_pdu; - srsran::task_multiqueue::queue_handle stack_task_dispatch_queue; // MAC Uplink-related procedures @@ -160,10 +158,11 @@ private: proc_sr_nr proc_sr; proc_bsr_nr proc_bsr; mux_nr mux; + demux_nr demux; - // UL HARQ + // DL/UL HARQ + dl_harq_entity_nr_vector dl_harq = {}; ul_harq_entity_nr_vector ul_harq = {}; - ul_harq_cfg_t ul_harq_cfg; const uint8_t PCELL_CC_IDX = 0; }; diff --git a/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h b/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h index 2370eb96e..0e265beab 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h +++ b/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h @@ -77,6 +77,16 @@ public: virtual uint16_t get_csrnti() = 0; }; +/** + * @brief Interface from HARQ class to demux class + */ +class demux_interface_harq_nr +{ +public: + /// Inform demux unit about a newly decoded TB. + virtual void push_pdu(srsran::unique_byte_buffer_t pdu, uint32_t tti) = 0; +}; + } // namespace srsue #endif // SRSUE_MAC_NR_INTERFACES_H \ No newline at end of file diff --git a/srsue/hdr/stack/mac_nr/proc_ra_nr.h b/srsue/hdr/stack/mac_nr/proc_ra_nr.h index ce684868f..cdef546c2 100644 --- a/srsue/hdr/stack/mac_nr/proc_ra_nr.h +++ b/srsue/hdr/stack/mac_nr/proc_ra_nr.h @@ -43,7 +43,7 @@ public: // PHY interfaces void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id); - void handle_rar_pdu(mac_interface_phy_nr::mac_nr_grant_dl_t& grant); + void handle_rar_pdu(mac_interface_phy_nr::tb_action_dl_result_t& grant); void pdcch_to_crnti(); void start_by_rrc(); @@ -104,7 +104,7 @@ private: void ra_procedure_initialization(); void ra_resource_selection(); void ra_preamble_transmission(); - void ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_dl_t& grant); + void ra_response_reception(const mac_interface_phy_nr::tb_action_dl_result_t& tb); void ra_contention_resolution(); void ra_contention_resolution(uint64_t rx_contention_id); void ra_completion(); diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index f365b296a..e83c9f9b9 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -96,7 +96,7 @@ public: mac.new_grant_ul(cc_idx, grant, action); } - void new_grant_dl(uint32_t cc_idx, mac_grant_dl_t grant, tb_action_dl_t* action) final + void new_grant_dl(uint32_t cc_idx, mac_grant_dl_t grant, mac_interface_phy_lte::tb_action_dl_t* action) final { mac.new_grant_dl(cc_idx, grant, action); } @@ -113,7 +113,7 @@ public: void mch_decoded(uint32_t len, bool crc) final { mac.mch_decoded(len, crc); } - void new_mch_dl(const srsran_pdsch_grant_t& phy_grant, tb_action_dl_t* action) final + void new_mch_dl(const srsran_pdsch_grant_t& phy_grant, mac_interface_phy_lte::tb_action_dl_t* action) final { mac.new_mch_dl(phy_grant, action); } @@ -124,8 +124,18 @@ public: // MAC Interface for NR PHY int sf_indication(const uint32_t tti) final { return SRSRAN_SUCCESS; } - void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) final { mac_nr.tb_decoded(cc_idx, grant); } - + void tb_decoded(const uint32_t cc_idx, + const mac_nr_grant_dl_t& grant, + mac_interface_phy_nr::tb_action_dl_result_t result) final + { + mac_nr.tb_decoded(cc_idx, grant, std::move(result)); + } + void new_grant_dl(const uint32_t cc_idx, + const mac_nr_grant_dl_t& grant, + mac_interface_phy_nr::tb_action_dl_t* action) final + { + mac_nr.new_grant_dl(cc_idx, grant, action); + } void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, mac_interface_phy_nr::tb_action_ul_t* action) final diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index 674c06469..661cfc373 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -80,7 +80,14 @@ public: run_tti(tti); return SRSRAN_SUCCESS; } - void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) final { mac->tb_decoded(cc_idx, grant); } + void tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) final + { + mac->tb_decoded(cc_idx, grant, std::move(result)); + } + void new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) final + { + mac->new_grant_dl(cc_idx, grant, action); + } void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) final { mac->new_grant_ul(cc_idx, grant, action); diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 7b80e54da..95aaad815 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -38,19 +38,12 @@ cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& log, state* phy_sta ERROR("Error initiating UE DL NR"); return; } - - if (srsran_softbuffer_rx_init_guru(&softbuffer_rx, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) < - SRSRAN_SUCCESS) { - ERROR("Error init soft-buffer"); - return; - } } cc_worker::~cc_worker() { srsran_ue_dl_nr_free(&ue_dl); srsran_ue_ul_nr_free(&ue_ul); - srsran_softbuffer_rx_free(&softbuffer_rx); for (cf_t* p : rx_buffer) { if (p != nullptr) { free(p); @@ -240,6 +233,23 @@ bool cc_worker::work_dl() return true; } + // 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 = pdsch_cfg.grant.tb[0].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); + + // Early stop if MAC says it doesn't need the TB + if (not dl_action.tb.enabled) { + logger.info("Decoding not required. Skipping PDSCH"); + return true; + } + // Get data buffer srsran::unique_byte_buffer_t data = srsran::make_byte_buffer(); if (data == nullptr) { @@ -248,14 +258,10 @@ bool cc_worker::work_dl() } data->N_bytes = pdsch_cfg.grant.tb[0].tbs / 8U; - // Get soft-buffer from MAC - // ... - srsran_softbuffer_rx_reset(&softbuffer_rx); - // Initialise PDSCH Result srsran_pdsch_res_nr_t pdsch_res = {}; pdsch_res.tb[0].payload = data->msg; - pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx; + pdsch_cfg.grant.tb[0].softbuffer.rx = dl_action.tb.softbuffer; // Decode actual PDSCH transmission if (srsran_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, &pdsch_res) < SRSRAN_SUCCESS) { @@ -276,21 +282,16 @@ bool cc_worker::work_dl() } // Notify MAC about PDSCH decoding result - if (pdsch_res.tb[0].crc) { - // Prepare grant - mac_interface_phy_nr::mac_nr_grant_dl_t mac_nr_grant = {}; - mac_nr_grant.tb[0] = std::move(data); - mac_nr_grant.pid = pid; - mac_nr_grant.rnti = pdsch_cfg.grant.rnti; - mac_nr_grant.tti = dl_slot_cfg.idx; - - if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_ra) { - phy->rar_grant_tti = dl_slot_cfg.idx; - } + 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)); - // Send data to MAC - phy->stack->tb_decoded(cc_idx, mac_nr_grant); + if (pdsch_cfg.grant.rnti_type == srsran_rnti_type_ra) { + phy->rar_grant_tti = dl_slot_cfg.idx; + } + if (pdsch_res.tb[0].crc) { // Generate DL metrics dl_metrics_t dl_m = {}; dl_m.mcs = pdsch_cfg.grant.tb[0].mcs; diff --git a/srsue/src/stack/mac_nr/CMakeLists.txt b/srsue/src/stack/mac_nr/CMakeLists.txt index 9553e6fbd..6c186bd52 100644 --- a/srsue/src/stack/mac_nr/CMakeLists.txt +++ b/srsue/src/stack/mac_nr/CMakeLists.txt @@ -6,8 +6,15 @@ # the distribution. # -set(SOURCES mac_nr.cc proc_ra_nr.cc proc_bsr_nr.cc proc_sr_nr.cc mux_nr.cc ul_harq_nr.cc) +set(SOURCES mac_nr.cc + proc_ra_nr.cc + proc_bsr_nr.cc + proc_sr_nr.cc + mux_nr.cc + demux_nr.cc + dl_harq_nr.cc + ul_harq_nr.cc) add_library(srsue_mac_nr STATIC ${SOURCES}) target_link_libraries(srsue_mac_nr srsue_mac_common srsran_mac) -add_subdirectory(test) \ No newline at end of file +add_subdirectory(test) diff --git a/srsue/src/stack/mac_nr/demux_nr.cc b/srsue/src/stack/mac_nr/demux_nr.cc new file mode 100644 index 000000000..dce9c4e87 --- /dev/null +++ b/srsue/src/stack/mac_nr/demux_nr.cc @@ -0,0 +1,81 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsue/hdr/stack/mac_nr/demux_nr.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/interfaces/ue_rlc_interfaces.h" + +namespace srsue { + +demux_nr::demux_nr(srslog::basic_logger& logger_) : logger(logger_) {} + +demux_nr::~demux_nr() {} + +int32_t demux_nr::init(rlc_interface_mac* rlc_) +{ + rlc = rlc_; + return SRSRAN_SUCCESS; +} + +// Enqueues PDU and returns quickly +void demux_nr::push_pdu(srsran::unique_byte_buffer_t pdu, uint32_t tti) +{ + pdu_queue.push(std::move(pdu)); +} + +void demux_nr::process_pdus() +{ + while (not pdu_queue.empty()) { + srsran::unique_byte_buffer_t pdu = pdu_queue.wait_pop(); + handle_pdu(std::move(pdu)); + } +} + +/// Handling of DLSCH PDUs only +void demux_nr::handle_pdu(srsran::unique_byte_buffer_t pdu) +{ + logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes); + + rx_pdu.init_rx(); + if (rx_pdu.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { + return; + } + + for (uint32_t i = 0; i < rx_pdu.get_num_subpdus(); ++i) { + srsran::mac_sch_subpdu_nr subpdu = rx_pdu.get_subpdu(i); + logger.info("Handling subPDU %d/%d: rnti=0x%x lcid=%d, sdu_len=%d", + i + 1, + rx_pdu.get_num_subpdus(), + subpdu.get_c_rnti(), + subpdu.get_lcid(), + subpdu.get_sdu_length()); + + // Handle Timing Advance CE + switch (subpdu.get_lcid()) { + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::DRX_CMD: + logger.info("DRX CE not implemented."); + break; + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::TA_CMD: + logger.info("Timing Advance CE not implemented."); + break; + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CON_RES_ID: + logger.info("Contention Resolution CE not implemented."); + break; + default: + if (subpdu.is_sdu()) { + rlc->write_pdu(subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); + } + } + } +} + +} // namespace srsue diff --git a/srsue/src/stack/mac_nr/dl_harq_nr.cc b/srsue/src/stack/mac_nr/dl_harq_nr.cc new file mode 100644 index 000000000..c0466aaea --- /dev/null +++ b/srsue/src/stack/mac_nr/dl_harq_nr.cc @@ -0,0 +1,243 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsue/hdr/stack/mac_nr/dl_harq_nr.h" +#include "srsran/common/mac_pcap.h" +#include "srsran/common/rwlock_guard.h" +#include "srsran/srslog/logger.h" +#include "srsue/hdr/stack/mac_nr/demux_nr.h" + +namespace srsue { + +dl_harq_entity_nr::dl_harq_entity_nr(uint8_t cc_idx_, + mac_interface_harq_nr* mac_, + demux_interface_harq_nr* demux_unit_) : + logger(srslog::fetch_basic_logger("MAC-NR")), cc_idx(cc_idx_), mac(mac_), demux_unit(demux_unit_), bcch_proc(this) +{ + // Init broadcast HARQ process + bcch_proc.init(-1); + pthread_rwlock_init(&rwlock, NULL); +} + +dl_harq_entity_nr::~dl_harq_entity_nr() +{ + pthread_rwlock_destroy(&rwlock); +} + +// Called from Stack thread through MAC (TODO: add shared::mutex) +int32_t dl_harq_entity_nr::set_config(const srsran::dl_harq_cfg_nr_t& cfg_) +{ + srsran::rwlock_write_guard lock(rwlock); + if (cfg_.nof_procs < 1 || cfg_.nof_procs > SRSRAN_MAX_HARQ_PROC_DL_NR) { + logger.error("Invalid configuration: %d HARQ processes not supported", cfg_.nof_procs); + return SRSRAN_ERROR; + } + + // clear old processees + for (auto& proc : harq_procs) { + proc = nullptr; + } + + // Allocate and init configured HARQ processes + for (uint32_t i = 0; i < cfg.nof_procs; i++) { + harq_procs[i] = std::unique_ptr(new dl_harq_process_nr(this)); + if (!harq_procs.at(i)->init(i)) { + logger.error("Error while initializing DL-HARQ process %d", i); + return SRSRAN_ERROR; + } + } + + cfg = cfg_; + + logger.debug("cc_idx=%d, set number of HARQ processes for DL to %d", cc_idx, cfg.nof_procs); + + return SRSRAN_SUCCESS; +} + +// Called from PHY workers +void dl_harq_entity_nr::new_grant_dl(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_t* action) +{ + srsran::rwlock_read_guard lock(rwlock); + + *action = {}; + + // Fetch HARQ process + dl_harq_process_nr* proc_ptr = nullptr; + if (grant.rnti == SRSRAN_SIRNTI) { + // Set BCCH PID for SI RNTI + proc_ptr = &bcch_proc; + } else { + if (grant.pid >= cfg.nof_procs) { + logger.error("Invalid PID: %d", grant.pid); + return; + } + proc_ptr = harq_procs.at(grant.pid).get(); + } + + // Check NDI toggled state before forwarding to process + bool ndi_toggled = (grant.ndi != harq_procs.at(grant.pid)->get_ndi()); + + if (grant.rnti == mac->get_temp_crnti() && last_temporal_crnti != mac->get_temp_crnti()) { + // Consider the NDI to have been toggled + last_temporal_crnti = mac->get_temp_crnti(); + logger.info("Considering NDI in pid=%d to be toggled for first Temporal C-RNTI", grant.pid); + ndi_toggled = true; + } + + proc_ptr->new_grant_dl(std::move(grant), ndi_toggled, action); +} + +/// Called from PHY workers +void dl_harq_entity_nr::tb_decoded(const mac_nr_grant_dl_t& grant, mac_interface_phy_nr::tb_action_dl_result_t result) +{ + srsran::rwlock_read_guard lock(rwlock); + + if (grant.rnti == SRSRAN_SIRNTI) { + bcch_proc.tb_decoded(grant, std::move(result)); + } else { + if (grant.pid >= cfg.nof_procs) { + logger.error("Invalid PID: %d", grant.pid); + return; + } + harq_procs.at(grant.pid)->tb_decoded(grant, std::move(result)); + } +} + +/// Called from MAC (Stack thread after, e.g. time alignment expire) +void dl_harq_entity_nr::reset() +{ + srsran::rwlock_write_guard lock(rwlock); + for (const auto& proc : harq_procs) { + if (proc != nullptr) { + proc->reset(); + } + } + bcch_proc.reset(); +} + +float dl_harq_entity_nr::get_average_retx() +{ + return average_retx; +} + +dl_harq_entity_nr::dl_harq_process_nr::dl_harq_process_nr(dl_harq_entity_nr* parent_) : + harq_entity(parent_), + softbuffer_rx(std::unique_ptr(new srsran_softbuffer_rx_t())), + logger(srslog::fetch_basic_logger("MAC-NR")) +{} + +dl_harq_entity_nr::dl_harq_process_nr::~dl_harq_process_nr() +{ + if (softbuffer_rx != nullptr) { + srsran_softbuffer_rx_free(softbuffer_rx.get()); + } +} + +bool dl_harq_entity_nr::dl_harq_process_nr::init(int pid_) +{ + if (softbuffer_rx == nullptr || srsran_softbuffer_rx_init_guru(softbuffer_rx.get(), + SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, + SRSRAN_LDPC_MAX_LEN_ENCODED_CB) != SRSRAN_SUCCESS) { + logger.error("Couldn't allocate and/or initialize softbuffer"); + return false; + } + + if (pid_ < 0) { + is_bcch = true; + pid = 0; + } else { + pid = (uint32_t)pid_; + is_bcch = false; + } + + return true; +} + +void dl_harq_entity_nr::dl_harq_process_nr::reset(void) +{ + current_grant = {}; + is_first_tb = true; + n_retx = 0; +} + +uint8_t dl_harq_entity_nr::dl_harq_process_nr::get_ndi() +{ + return current_grant.ndi; +} + +void dl_harq_entity_nr::dl_harq_process_nr::new_grant_dl(const mac_nr_grant_dl_t& grant, + const bool& ndi_toggled, + mac_interface_phy_nr::tb_action_dl_t* action) +{ + // Determine if it's a new transmission 5.3.2.2 + if (ndi_toggled || // 1st condition (NDI has changed) + (is_bcch && grant.rv == 0) || // 2nd condition (Broadcast and 1st transmission) + is_first_tb) // 3rd condition (is first tx for this tb) + { + // New transmission + n_retx = 0; + srsran_softbuffer_rx_reset_tbs(softbuffer_rx.get(), grant.tbs * 8); + + action->tb.enabled = true; + action->tb.softbuffer = softbuffer_rx.get(); + + // reset conditions + is_first_tb = false; + } else { + // This is a retransmission + if (not acked) { + // If data has not yet been successfully decoded, instruct the PHY to combine the received data + action->tb.enabled = true; + action->tb.softbuffer = softbuffer_rx.get(); + } else { + logger.info("DL %d: Received duplicate. Discarding and retransmitting ACK (n_retx=%d)", pid, n_retx); + } + } + + // increment counter and store grant + n_retx++; + current_grant = grant; +} + +void dl_harq_entity_nr::dl_harq_process_nr::tb_decoded(const mac_nr_grant_dl_t& grant, + mac_interface_phy_nr::tb_action_dl_result_t result) +{ + acked = result.ack; + + if (acked and result.payload != nullptr) { + if (is_bcch) { + logger.warning("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH) not implemented", grant.tbs); + reset(); + } else { + if (grant.rnti == harq_entity->mac->get_temp_crnti()) { + logger.debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI) not implemented", + grant.tbs); + } else { + logger.debug("Delivering PDU=%d bytes to Dissassemble and Demux unit", grant.tbs); + harq_entity->demux_unit->push_pdu(std::move(result.payload), grant.tti); + + // Compute average number of retransmissions per packet + harq_entity->average_retx = SRSRAN_VEC_CMA((float)n_retx, harq_entity->average_retx, harq_entity->nof_pkts++); + } + } + } + + logger.info("DL %d: %s tbs=%d, rv=%d, ack=%s, ndi=%d", + pid, + grant.rv == 0 ? "newTX" : "reTX ", + grant.tbs, + grant.rv, + acked ? "OK" : "KO", + grant.ndi); +} + +} // namespace srsue diff --git a/srsue/src/stack/mac_nr/mac_nr.cc b/srsue/src/stack/mac_nr/mac_nr.cc index e15d1d978..0c4f10778 100644 --- a/srsue/src/stack/mac_nr/mac_nr.cc +++ b/srsue/src/stack/mac_nr/mac_nr.cc @@ -24,9 +24,11 @@ mac_nr::mac_nr(srsran::ext_task_sched_handle task_sched_) : proc_sr(logger), proc_bsr(logger), mux(*this, logger), + demux(logger), pcap(nullptr) { // Create PCell HARQ entities + dl_harq.at(PCELL_CC_IDX) = dl_harq_entity_nr_ptr(new dl_harq_entity_nr(PCELL_CC_IDX, this, &demux)); ul_harq.at(PCELL_CC_IDX) = ul_harq_entity_nr_ptr(new ul_harq_entity_nr(PCELL_CC_IDX, this, &proc_ra, &mux)); } @@ -62,12 +64,25 @@ int mac_nr::init(const mac_nr_args_t& args_, return SRSRAN_ERROR; } + if (demux.init(rlc) != SRSRAN_SUCCESS) { + logger.error("Couldn't initialize demux unit."); + return SRSRAN_ERROR; + } + // Configure PCell HARQ entities if (ul_harq.at(PCELL_CC_IDX)->init() != SRSRAN_SUCCESS) { logger.error("Couldn't initialize UL HARQ entity."); return SRSRAN_ERROR; } + // Set default config until RRC + dl_harq_cfg_nr_t harq_cfg = {}; + harq_cfg.reset(); + if (dl_harq.at(PCELL_CC_IDX)->set_config(harq_cfg) != SRSRAN_SUCCESS) { + logger.error("Couldn't configure DL HARQ entity."); + return SRSRAN_ERROR; + } + started = true; return SRSRAN_SUCCESS; @@ -98,6 +113,8 @@ void mac_nr::run_tti(const uint32_t tti) return; } + logger.set_context(tti); + // Step all procedures logger.debug("Running MAC tti=%d", tti); @@ -106,6 +123,9 @@ void mac_nr::run_tti(const uint32_t tti) proc_bsr.step(tti, mac_buffer_states); proc_sr.step(tti); + + // process received PDUs + stack_task_dispatch_queue.push([this]() { process_pdus(); }); } void mac_nr::update_buffer_states() @@ -228,49 +248,80 @@ bool mac_nr::sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul } // This function handles all PCAP writing for a decoded DL TB -void mac_nr::write_pcap(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) +void mac_nr::write_pcap(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t& tb) { if (pcap) { - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; ++i) { - if (grant.tb[i] != nullptr) { - if (proc_ra.has_rar_rnti() && grant.rnti == proc_ra.get_rar_rnti()) { - pcap->write_dl_ra_rnti_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); - } else if (grant.rnti == SRSRAN_PRNTI) { - pcap->write_dl_pch_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); - } else { - pcap->write_dl_crnti_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); - } + if (tb.ack && tb.payload != nullptr) { + if (proc_ra.has_rar_rnti() && grant.rnti == proc_ra.get_rar_rnti()) { + pcap->write_dl_ra_rnti_nr(tb.payload->msg, tb.payload->N_bytes, grant.rnti, true, grant.tti); + } else if (grant.rnti == SRSRAN_PRNTI) { + pcap->write_dl_pch_nr(tb.payload->msg, tb.payload->N_bytes, grant.rnti, true, grant.tti); + } else { + pcap->write_dl_crnti_nr(tb.payload->msg, tb.payload->N_bytes, grant.rnti, true, grant.tti); } } } } /** - * \brief Called from PHY after decoding a TB - * - * The TB can directly be used + * \brief Called from PHY after decoding PDCCH for DL reception * - * @param cc_idx - * @param grant structure + * @param cc_idx The CC index + * @param grant The DL grant + * @param action The DL action to be filled by MAC */ -void mac_nr::tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) +void mac_nr::new_grant_dl(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_t* action) +{ + logger.debug("new_grant_dl(): cc_idx=%d, tti=%d, rnti=%d, pid=%d, tbs=%d, ndi=%d, rv=%d", + cc_idx, + grant.tti, + grant.rnti, + grant.pid, + grant.tbs, + grant.ndi, + grant.rv); + + // Assert HARQ entity + if (dl_harq.at(cc_idx) == nullptr) { + logger.error("HARQ entity %d has not been created", cc_idx); + return; + } + + dl_harq.at(cc_idx)->new_grant_dl(grant, action); +} + +void mac_nr::tb_decoded(const uint32_t cc_idx, const mac_nr_grant_dl_t& grant, tb_action_dl_result_t result) { - write_pcap(cc_idx, grant); - // handle PDU + logger.debug("tb_decoded(): cc_idx=%d, tti=%d, rnti=%d, pid=%d, tbs=%d, ndi=%d, rv=%d, result=%s", + cc_idx, + grant.tti, + grant.rnti, + grant.pid, + grant.tbs, + grant.ndi, + grant.rv, + result.ack ? "OK" : "KO"); + + write_pcap(cc_idx, grant, result); + if (proc_ra.has_rar_rnti() && grant.rnti == proc_ra.get_rar_rnti()) { - proc_ra.handle_rar_pdu(grant); + proc_ra.handle_rar_pdu(result); } else { - // Push DL PDUs to queue for background processing - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; ++i) { - if (grant.tb[i] != nullptr) { - metrics[cc_idx].rx_pkts++; - metrics[cc_idx].rx_brate += grant.tb[i]->N_bytes * 8; - pdu_queue.push(std::move(grant.tb[i])); - } + // Assert HARQ entity + if (dl_harq.at(cc_idx) == nullptr) { + logger.error("HARQ entity %d has not been created", cc_idx); + return; } + + dl_harq.at(cc_idx)->tb_decoded(grant, std::move(result)); } - stack_task_dispatch_queue.push([this]() { process_pdus(); }); + // do metrics + metrics[cc_idx].rx_brate += grant.tbs * 8; + metrics[cc_idx].rx_pkts++; + if (not result.ack) { + metrics[cc_idx].rx_errors++; + } } void mac_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action) @@ -395,7 +446,7 @@ bool mac_nr::set_crnti(const uint16_t c_rnti_) void mac_nr::start_ra_procedure() { - stack_task_dispatch_queue.push([this]() {proc_ra.start_by_rrc();}); + stack_task_dispatch_queue.push([this]() { proc_ra.start_by_rrc(); }); } bool mac_nr::is_valid_crnti(const uint16_t crnti) @@ -435,48 +486,7 @@ void mac_nr::get_metrics(mac_metrics_t m[SRSRAN_MAX_CARRIERS]) */ void mac_nr::process_pdus() { - while (started and not pdu_queue.empty()) { - srsran::unique_byte_buffer_t pdu = pdu_queue.wait_pop(); - // TODO: delegate to demux class - handle_pdu(std::move(pdu)); - } -} - -void mac_nr::handle_pdu(srsran::unique_byte_buffer_t pdu) -{ - logger.info(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes); - - rx_pdu.init_rx(); - if (rx_pdu.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { - return; - } - - for (uint32_t i = 0; i < rx_pdu.get_num_subpdus(); ++i) { - srsran::mac_sch_subpdu_nr subpdu = rx_pdu.get_subpdu(i); - logger.info("Handling subPDU %d/%d: rnti=0x%x lcid=%d, sdu_len=%d", - i + 1, - rx_pdu.get_num_subpdus(), - subpdu.get_c_rnti(), - subpdu.get_lcid(), - subpdu.get_sdu_length()); - - // Handle Timing Advance CE - switch (subpdu.get_lcid()) { - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::DRX_CMD: - logger.info("DRX CE not implemented."); - break; - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::TA_CMD: - logger.info("Timing Advance CE not implemented."); - break; - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CON_RES_ID: - logger.info("Contention Resolution CE not implemented."); - break; - default: - if (subpdu.is_sdu()) { - rlc->write_pdu(subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); - } - } - } + demux.process_pdus(); } uint64_t mac_nr::get_contention_id() diff --git a/srsue/src/stack/mac_nr/proc_ra_nr.cc b/srsue/src/stack/mac_nr/proc_ra_nr.cc index 9a39d3c76..0a94bf0b7 100644 --- a/srsue/src/stack/mac_nr/proc_ra_nr.cc +++ b/srsue/src/stack/mac_nr/proc_ra_nr.cc @@ -178,7 +178,7 @@ void proc_ra_nr::ra_preamble_transmission() } // 5.1.4 Random Access Preamble transmission -void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_dl_t& grant) +void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::tb_action_dl_result_t& tb) { if (state != WAITING_FOR_RESPONSE_RECEPTION) { logger.warning( @@ -190,34 +190,32 @@ void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_ // Stop rar timer rar_timeout_timer.stop(); - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; ++i) { - if (grant.tb[i] != nullptr) { - srsran::mac_rar_pdu_nr pdu; - if (!pdu.unpack(grant.tb[i]->msg, grant.tb[i]->N_bytes)) { - logger.warning("Error unpacking RAR PDU (%d)", i); - return; - } - logger.info("%s", pdu.to_string()); - - for (auto& subpdu : pdu.get_subpdus()) { - if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) { - logger.debug("PROC RA NR: Setting UL grant and prepare Msg3"); - temp_crnti = subpdu.get_temp_crnti(); - - // Set Temporary-C-RNTI if provided, otherwise C-RNTI is ok - phy->set_ul_grant(subpdu.get_ul_grant(), temp_crnti, srsran_rnti_type_ra); - - // reset all parameters that are used before rar - rar_rnti = SRSRAN_INVALID_RNTI; - mac.msg3_prepare(); - current_ta = subpdu.get_ta(); - - // Set Backoff parameter - if (subpdu.has_backoff()) { - preamble_backoff = backoff_table_nr[subpdu.get_backoff() % 16]; // TODO multiplied with SCALING_FACTOR_BI. - } else { - preamble_backoff = 0; - } + if (tb.ack && tb.payload != nullptr) { + srsran::mac_rar_pdu_nr pdu; + if (!pdu.unpack(tb.payload->msg, tb.payload->N_bytes)) { + logger.warning("Error unpacking RAR PDU"); + return; + } + logger.info("%s", pdu.to_string()); + + for (auto& subpdu : pdu.get_subpdus()) { + if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) { + logger.debug("PROC RA NR: Setting UL grant and prepare Msg3"); + temp_crnti = subpdu.get_temp_crnti(); + + // Set Temporary-C-RNTI if provided, otherwise C-RNTI is ok + phy->set_ul_grant(subpdu.get_ul_grant(), temp_crnti, srsran_rnti_type_ra); + + // reset all parameters that are used before rar + rar_rnti = SRSRAN_INVALID_RNTI; + mac.msg3_prepare(); + current_ta = subpdu.get_ta(); + + // Set Backoff parameter + if (subpdu.has_backoff()) { + preamble_backoff = backoff_table_nr[subpdu.get_backoff() % 16]; // TODO multiplied with SCALING_FACTOR_BI. + } else { + preamble_backoff = 0; } } } @@ -345,11 +343,13 @@ void proc_ra_nr::prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t } // Called by PHY thread through MAC parent -void proc_ra_nr::handle_rar_pdu(mac_interface_phy_nr::mac_nr_grant_dl_t& grant) +void proc_ra_nr::handle_rar_pdu(mac_interface_phy_nr::tb_action_dl_result_t& result) { // Defer the handling of the grant to main stack thread in ra_response_reception - auto task_handler = [this](const mac_interface_phy_nr::mac_nr_grant_dl_t& t) { ra_response_reception(std::move(t)); }; - task_queue.push(std::bind(task_handler, std::move(grant))); + auto task_handler = [this](const mac_interface_phy_nr::tb_action_dl_result_t& t) { + ra_response_reception(std::move(t)); + }; + task_queue.push(std::bind(task_handler, std::move(result))); } // Called from PHY thread, defer actions therefore. diff --git a/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc b/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc index 3d9bc0e6d..4867c6edb 100644 --- a/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc +++ b/srsue/src/stack/mac_nr/test/proc_ra_nr_test.cc @@ -72,7 +72,7 @@ public: void rrc_ra_problem() { logger.warning("Dummy MAC RRC ra problem"); } private: - uint16_t crnti = SRSRAN_INVALID_RNTI; + uint16_t crnti = SRSRAN_INVALID_RNTI; srslog::basic_logger& logger; }; @@ -124,12 +124,13 @@ int proc_ra_normal_test() mac_interface_phy_nr::mac_nr_grant_dl_t grant; grant.rnti = 0x16; grant.tti = rach_cfg.ra_responseWindow + tti_start + 3; - grant.pid = 0x0123; + grant.pid = 0x0; uint8_t mac_dl_rar_pdu[] = {0x40, 0x06, 0x68, 0x03, 0x21, 0x46, 0x46, 0x02, 0x00, 0x00, 0x00}; - grant.tb[0] = srsran::make_byte_buffer(); - TESTASSERT(grant.tb[0] != nullptr); - grant.tb[0].get()->append_bytes(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)); - proc_ra_nr.handle_rar_pdu(grant); + mac_interface_phy_nr::tb_action_dl_result_t result = {}; + result.payload = srsran::make_byte_buffer(); + TESTASSERT(result.payload != nullptr); + result.payload.get()->append_bytes(mac_dl_rar_pdu, sizeof(mac_dl_rar_pdu)); + proc_ra_nr.handle_rar_pdu(result); task_sched.tic(); task_sched.run_pending_tasks(); diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 0d7eeee8f..5a92b142e 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -34,7 +34,7 @@ ue_stack_lte::ue_stack_lte() : rrc_logger(srslog::fetch_basic_logger("RRC", false)), usim_logger(srslog::fetch_basic_logger("USIM", false)), nas_logger(srslog::fetch_basic_logger("NAS", false)), - mac_nr_logger(srslog::fetch_basic_logger("MAC-NR", false)), + mac_nr_logger(srslog::fetch_basic_logger("MAC-NR")), rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", false)), mac_pcap(), mac_nr_pcap(), From bfe2ad98ef3e6a0145fe8fc7aa7ceff35d36d983 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 16 Apr 2021 21:35:36 +0200 Subject: [PATCH 11/46] Added parsing for NR DL HARQ cfg --- lib/include/srsran/asn1/rrc_nr_utils.h | 3 +++ .../srsran/interfaces/ue_nr_interfaces.h | 1 + lib/src/asn1/rrc_nr_utils.cc | 13 ++++++++++++ srsue/hdr/stack/mac_nr/mac_nr.h | 1 + srsue/src/stack/mac_nr/mac_nr.cc | 21 ++++++++++++------- srsue/src/stack/rrc/rrc_nr.cc | 17 +++++++++++++++ 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 025b68ce1..60657b918 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -50,6 +50,7 @@ struct beta_offsets_s; struct uci_on_pusch_s; struct zp_csi_rs_res_s; struct nzp_csi_rs_res_s; +struct pdsch_serving_cell_cfg_s; } // namespace rrc_nr } // namespace asn1 @@ -98,6 +99,8 @@ bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s & nzp_csi logical_channel_config_t make_mac_logical_channel_cfg_t(uint8_t lcid, const asn1::rrc_nr::lc_ch_cfg_s& asn1_type); rach_nr_cfg_t make_mac_rach_cfg(const asn1::rrc_nr::rach_cfg_common_s& asn1_type); bool make_mac_phr_cfg_t(const asn1::rrc_nr::phr_cfg_s& asn1_type, phr_cfg_nr_t* phr_cfg_nr); +bool make_mac_dl_harq_cfg_nr_t(const asn1::rrc_nr::pdsch_serving_cell_cfg_s& asn1_type, + dl_harq_cfg_nr_t* out_dl_harq_cfg_nr); /*************************** * RLC Config **************************/ diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index 5e003d33a..c355440cc 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -149,6 +149,7 @@ public: virtual int setup_lcid(const srsran::logical_channel_config_t& config) = 0; virtual int set_config(const srsran::bsr_cfg_nr_t& bsr_cfg) = 0; virtual int set_config(const srsran::sr_cfg_nr_t& sr_cfg) = 0; + virtual int set_config(const srsran::dl_harq_cfg_nr_t& dl_hrq_cfg) = 0; virtual void set_config(const srsran::rach_nr_cfg_t& rach_cfg) = 0; virtual int add_tag_config(const srsran::tag_cfg_nr_t& tag_cfg) = 0; virtual int set_config(const srsran::phr_cfg_nr_t& phr_cfg) = 0; diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 21d6a3d9f..0692cffcd 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -66,6 +66,19 @@ logical_channel_config_t make_mac_logical_channel_cfg_t(uint8_t lcid, const lc_c return logical_channel_config; } +bool make_mac_dl_harq_cfg_nr_t(const pdsch_serving_cell_cfg_s& asn1_type, dl_harq_cfg_nr_t* out_dl_harq_cfg_nr) +{ + dl_harq_cfg_nr_t dl_harq_cfg_nr; + if (asn1_type.nrof_harq_processes_for_pdsch_present) { + dl_harq_cfg_nr.nof_procs = asn1_type.nrof_harq_processes_for_pdsch; + } else { + asn1::log_warning("Option nrof_harq_processes_for_pdsch not present"); + return false; + } + *out_dl_harq_cfg_nr = dl_harq_cfg_nr; + return true; +} + bool make_mac_phr_cfg_t(const phr_cfg_s& asn1_type, phr_cfg_nr_t* phr_cfg_nr) { phr_cfg_nr->extended = asn1_type.ext; diff --git a/srsue/hdr/stack/mac_nr/mac_nr.h b/srsue/hdr/stack/mac_nr/mac_nr.h index c6dc63d13..883011dc3 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr.h +++ b/srsue/hdr/stack/mac_nr/mac_nr.h @@ -79,6 +79,7 @@ public: int set_config(const srsran::bsr_cfg_nr_t& bsr_cfg); int set_config(const srsran::sr_cfg_nr_t& sr_cfg); void set_config(const srsran::rach_nr_cfg_t& rach_cfg); + int set_config(const srsran::dl_harq_cfg_nr_t& dl_hrq_cfg); void set_contention_id(const uint64_t ue_identity); bool set_crnti(const uint16_t crnti); int add_tag_config(const srsran::tag_cfg_nr_t& tag_cfg); diff --git a/srsue/src/stack/mac_nr/mac_nr.cc b/srsue/src/stack/mac_nr/mac_nr.cc index 0c4f10778..b360ee679 100644 --- a/srsue/src/stack/mac_nr/mac_nr.cc +++ b/srsue/src/stack/mac_nr/mac_nr.cc @@ -75,14 +75,6 @@ int mac_nr::init(const mac_nr_args_t& args_, return SRSRAN_ERROR; } - // Set default config until RRC - dl_harq_cfg_nr_t harq_cfg = {}; - harq_cfg.reset(); - if (dl_harq.at(PCELL_CC_IDX)->set_config(harq_cfg) != SRSRAN_SUCCESS) { - logger.error("Couldn't configure DL HARQ entity."); - return SRSRAN_ERROR; - } - started = true; return SRSRAN_SUCCESS; @@ -412,6 +404,19 @@ int mac_nr::set_config(const srsran::phr_cfg_nr_t& phr_cfg) return SRSRAN_SUCCESS; } +int mac_nr::set_config(const srsran::dl_harq_cfg_nr_t& dl_hrq_cfg) +{ + for (const auto& cc : dl_harq) { + if (cc != nullptr) { + if (cc->set_config(dl_hrq_cfg) != SRSRAN_SUCCESS) { + logger.error("Couldn't configure DL HARQ entity."); + return SRSRAN_ERROR; + } + } + } + return SRSRAN_SUCCESS; +} + int mac_nr::set_config(const srsran::bsr_cfg_nr_t& bsr_cfg) { return proc_bsr.set_config(bsr_cfg); diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 5aae159ae..18dbecf05 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -1140,6 +1140,23 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) logger.warning("Option ul_cfg not present"); return false; } + + if (sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present) { + if (sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.type() == + setup_release_c::types_opts::setup) { + dl_harq_cfg_nr_t dl_harq_cfg_nr; + if (make_mac_dl_harq_cfg_nr_t(sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.setup(), &dl_harq_cfg_nr) == + false) { + logger.warning("Failed to make dl_harq_cfg_nr config"); + return false; + } + mac->set_config(dl_harq_cfg_nr); + } + } else { + logger.warning("Option pdsch_serving_cell_cfg not present"); + return false; + } + if (sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present) { if (sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.type() == setup_release_c::types_opts::setup) { if (apply_csi_meas_cfg(sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup()) == false) { From e7096d705e9921bf708658cf9366a5d4548e5994 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Apr 2021 19:21:04 +0200 Subject: [PATCH 12/46] Fix NR RRC config NZP-CSI-RS --- srsue/src/stack/rrc/rrc_nr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 18dbecf05..efaea6a05 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -704,7 +704,7 @@ bool rrc_nr::apply_csi_meas_cfg(const asn1::rrc_nr::csi_meas_cfg_s& csi_meas_cfg logger.warning("Can not find p_zp_csi_rs_res in temporally stored csi_rs_zp_res"); return false; } - phy_cfg.pdsch.nzp_csi_rs_sets[set_id].data[i] = csi_rs_nzp_res[res]; + phy_cfg.pdsch.nzp_csi_rs_sets[set_id].data[j] = csi_rs_nzp_res[res]; phy_cfg.pdsch.nzp_csi_rs_sets[set_id].count += 1; } if (csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list[i].trs_info_present) { From 52bf973981981d951975d9faaa418b8a28907fed Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 16 Apr 2021 17:43:28 +0100 Subject: [PATCH 13/46] s1ap - set cause to transport when gtpu fails to allocate TEID --- srsenb/src/stack/rrc/rrc_mobility.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 90f5744e5..e0f2409c4 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -835,8 +835,8 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev& logger.error("Failed to allocate GTPU TEID for E-RAB id=%d", fwd_erab.erab_id); not_admitted_erabs.emplace_back(); not_admitted_erabs.back().erab_id = erab.second.id; - not_admitted_erabs.back().cause.set_radio_network().value = - asn1::s1ap::cause_radio_network_opts::no_radio_res_available_in_target_cell; + not_admitted_erabs.back().cause.set_transport().value = + asn1::s1ap::cause_transport_opts::transport_res_unavailable; admitted_erabs.pop_back(); continue; } @@ -912,8 +912,8 @@ bool rrc::ue::rrc_mobility::apply_ho_prep_cfg(const ho_prep_info_r8_ies_s& if (rrc_ue->bearer_list.add_gtpu_bearer(erab.erab_id) != SRSRAN_SUCCESS) { erabs_failed_to_setup.emplace_back(); erabs_failed_to_setup.back().erab_id = erab.erab_id; - erabs_failed_to_setup.back().cause.set_radio_network().value = - asn1::s1ap::cause_radio_network_opts::no_radio_res_available_in_target_cell; + erabs_failed_to_setup.back().cause.set_transport().value = + asn1::s1ap::cause_transport_opts::transport_res_unavailable; continue; } } From 01ce0718be48ef9981c90ad25f42e54ef34bfb37 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Apr 2021 11:58:43 +0200 Subject: [PATCH 14/46] NR-PUSCH RE mapping correction and NR-SCH detailed grant information --- lib/include/srsran/phy/phch/phch_cfg_nr.h | 2 + lib/include/srsran/phy/phch/pusch_nr.h | 1 + lib/src/phy/phch/csi.c | 4 +- lib/src/phy/phch/pdsch_nr.c | 31 +- lib/src/phy/phch/phch_cfg_nr.c | 247 ++++++++++++++++ lib/src/phy/phch/pusch_nr.c | 331 ++++++---------------- lib/src/phy/phch/sch_nr.c | 7 +- lib/src/phy/phch/test/pusch_nr_test.c | 9 + lib/src/phy/phch/uci_nr.c | 8 +- lib/test/phy/phy_dl_nr_test.c | 9 + srsue/hdr/phy/nr/cc_worker.h | 6 +- srsue/src/phy/nr/cc_worker.cc | 39 ++- 12 files changed, 397 insertions(+), 297 deletions(-) create mode 100644 lib/src/phy/phch/phch_cfg_nr.c diff --git a/lib/include/srsran/phy/phch/phch_cfg_nr.h b/lib/include/srsran/phy/phch/phch_cfg_nr.h index 6f20e4d6e..3171835dc 100644 --- a/lib/include/srsran/phy/phch/phch_cfg_nr.h +++ b/lib/include/srsran/phy/phch/phch_cfg_nr.h @@ -245,4 +245,6 @@ typedef struct SRSRAN_API { bool freq_hopping_enabled; } srsran_sch_cfg_nr_t; +SRSRAN_API uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len); + #endif // SRSRAN_PHCH_CFG_NR_H diff --git a/lib/include/srsran/phy/phch/pusch_nr.h b/lib/include/srsran/phy/phch/pusch_nr.h index ee06daf18..265cd466a 100644 --- a/lib/include/srsran/phy/phch/pusch_nr.h +++ b/lib/include/srsran/phy/phch/pusch_nr.h @@ -50,6 +50,7 @@ typedef struct SRSRAN_API { srsran_evm_buffer_t* evm_buffer; bool meas_time_en; uint32_t meas_time_us; + srsran_re_pattern_t dmrs_re_pattern; srsran_uci_cfg_nr_t uci_cfg; ///< Internal UCI bits configuration uint8_t* g_ulsch; ///< Temporal Encoded UL-SCH data uint8_t* g_ack; ///< Temporal Encoded HARQ-ACK bits diff --git a/lib/src/phy/phch/csi.c b/lib/src/phy/phch/csi.c index 9811a5d11..474ac4300 100644 --- a/lib/src/phy/phch/csi.c +++ b/lib/src/phy/phch/csi.c @@ -307,11 +307,11 @@ uint32_t srsran_csi_str(const srsran_csi_report_cfg_t* report_cfg, for (uint32_t i = 0; i < nof_reports; i++) { if (report_cfg[i].freq_cfg == SRSRAN_CSI_REPORT_FREQ_WIDEBAND && report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) { - len = srsran_print_check(str, str_len, len, ", cqi=%d", report_value[i].wideband_cri_ri_pmi_cqi.cqi); + len = srsran_print_check(str, str_len, len, "cqi=%d ", report_value[i].wideband_cri_ri_pmi_cqi.cqi); } else if (report_cfg[i].quantity == SRSRAN_CSI_REPORT_QUANTITY_NONE) { char tmp[20] = {}; srsran_vec_sprint_bin(tmp, sizeof(tmp), report_value[i].none, report_cfg->K_csi_rs); - len = srsran_print_check(str, str_len, len, ", csi=%s", tmp); + len = srsran_print_check(str, str_len, len, "csi=%s ", tmp); } } return len; diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 257a961b5..924bfda4f 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -185,6 +185,8 @@ void srsran_pdsch_nr_free(srsran_pdsch_nr_t* q) if (q->evm_buffer != NULL) { srsran_evm_free(q->evm_buffer); } + + SRSRAN_MEM_ZERO(q, srsran_pdsch_nr_t, 1); } static inline uint32_t pdsch_nr_put_rb(cf_t* dst, cf_t* src, bool* rvd_mask) @@ -575,7 +577,6 @@ static uint32_t pdsch_nr_grant_info(const srsran_pdsch_nr_t* q, uint32_t str_len) { uint32_t len = 0; - len = srsran_print_check(str, str_len, len, "rnti=0x%x ", grant->rnti); uint32_t first_prb = SRSRAN_MAX_PRB_NR; for (uint32_t i = 0; i < SRSRAN_MAX_PRB_NR && first_prb == SRSRAN_MAX_PRB_NR; i++) { @@ -585,27 +586,8 @@ static uint32_t pdsch_nr_grant_info(const srsran_pdsch_nr_t* q, } // Append time-domain resource mapping - len = srsran_print_check(str, - str_len, - len, - "beta_dmrs=%.3f CDM-grp=%d k0=%d prb=%d:%d symb=%d:%d mapping=%s ", - isnormal(grant->beta_dmrs) ? grant->beta_dmrs : 1.0f, - grant->nof_dmrs_cdm_groups_without_data, - grant->k, - first_prb, - grant->nof_prb, - grant->S, - grant->L, - srsran_sch_mapping_type_to_str(grant->mapping)); - - // Skip frequency domain resources... - // ... - - // Append spatial resources - len = srsran_print_check(str, str_len, len, "Nl=%d ", grant->nof_layers); - - // Append scrambling ID - len = srsran_print_check(str, str_len, len, "n_scid=%d ", grant->n_scid); + len = srsran_print_check( + str, str_len, len, "rnti=0x%x prb=%d:%d symb=%d:%d ", grant->rnti, first_prb, grant->nof_prb, grant->S, grant->L); // Append TB info for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { @@ -634,11 +616,6 @@ uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q, len += pdsch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len); - if (cfg->rvd_re.count != 0) { - len = srsran_print_check(str, str_len, len, "Reserved: "); - len += srsran_re_pattern_list_info(&cfg->rvd_re, &str[len], str_len - len); - } - if (q->meas_time_en) { len = srsran_print_check(str, str_len, len, " t=%d us", q->meas_time_us); } diff --git a/lib/src/phy/phch/phch_cfg_nr.c b/lib/src/phy/phch/phch_cfg_nr.c new file mode 100644 index 000000000..1974f1061 --- /dev/null +++ b/lib/src/phy/phch/phch_cfg_nr.c @@ -0,0 +1,247 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#include "srsran/phy/phch/phch_cfg_nr.h" +#include "srsran/phy/ch_estimation/dmrs_sch.h" +#include "srsran/phy/phch/uci_nr.h" + +static const char* dmrs_sch_type_to_str(srsran_dmrs_sch_type_t type) +{ + switch (type) { + case srsran_dmrs_sch_type_1: + return "1"; + case srsran_dmrs_sch_type_2: + return "2"; + default:; // Do nothing + } + return "invalid"; +} + +static const char* dmrs_sch_add_pos_to_str(srsran_dmrs_sch_add_pos_t add_pos) +{ + switch (add_pos) { + case srsran_dmrs_sch_add_pos_2: + return "2"; + case srsran_dmrs_sch_add_pos_0: + return "0"; + case srsran_dmrs_sch_add_pos_1: + return "1"; + case srsran_dmrs_sch_add_pos_3: + return "3"; + default:; // Do nothing + } + return "invalid"; +} + +static const char* dmrs_sch_len_to_str(srsran_dmrs_sch_len_t len) +{ + switch (len) { + case srsran_dmrs_sch_len_1: + return "single"; + case srsran_dmrs_sch_len_2: + return "double"; + default:; // Do nothing + } + return "invalid"; +} + +static const char* dmrs_sch_typeApos_to_str(srsran_dmrs_sch_typeA_pos_t typeA_pos) +{ + switch (typeA_pos) { + case srsran_dmrs_sch_typeA_pos_2: + return "2"; + case srsran_dmrs_sch_typeA_pos_3: + return "3"; + default:; // Do nothing + } + return "invalid"; +} + +static uint32_t phch_cfg_nr_dmrs_to_str(const srsran_dmrs_sch_cfg_t* dmrs, + const srsran_sch_grant_nr_t* grant, + char* str, + uint32_t str_len) +{ + uint32_t len = 0; + + len = srsran_print_check(str, str_len, len, " DMRS:\n"); + len = srsran_print_check(str, str_len, len, " type=%s\n", dmrs_sch_type_to_str(dmrs->type)); + len = srsran_print_check(str, str_len, len, " add_pos=%s\n", dmrs_sch_add_pos_to_str(dmrs->additional_pos)); + len = srsran_print_check(str, str_len, len, " len=%s\n", dmrs_sch_len_to_str(dmrs->length)); + len = srsran_print_check(str, str_len, len, " typeA_pos=%s\n", dmrs_sch_typeApos_to_str(dmrs->typeA_pos)); + + if (dmrs->scrambling_id0_present) { + len = srsran_print_check(str, str_len, len, " scrambling_id_0=%03x\n", dmrs->scrambling_id0); + } + + if (dmrs->scrambling_id1_present) { + len = srsran_print_check(str, str_len, len, " scrambling_id_1=%03x\n", dmrs->scrambling_id1); + } + + if (dmrs->lte_CRS_to_match_around) { + len = srsran_print_check(str, str_len, len, " lte_CRS_to_match_around=y\n"); + } + + if (dmrs->additional_DMRS_DL_Alt) { + len = srsran_print_check(str, str_len, len, " additional_DMRS_DL_Alt=y\n"); + } + + srsran_re_pattern_t pattern = {}; + if (srsran_dmrs_sch_rvd_re_pattern(dmrs, grant, &pattern) == SRSRAN_SUCCESS) { + len = srsran_print_check(str, str_len, len, " rvd_pattern: "); + len += srsran_re_pattern_info(&pattern, &str[len], str_len - len); + len = srsran_print_check(str, str_len, len, "\n"); + } + + return len; +} + +static const char* sch_mapping_to_str(srsran_sch_mapping_type_t mapping) +{ + switch (mapping) { + case srsran_sch_mapping_type_A: + return "A"; + case srsran_sch_mapping_type_B: + return "B"; + default:; // Do nothing + } + return "invalid"; +} + +static const char* sch_xoverhead_to_str(srsran_xoverhead_t xoverhead) +{ + switch (xoverhead) { + case srsran_xoverhead_0: + return "0"; + case srsran_xoverhead_6: + return "6"; + case srsran_xoverhead_12: + return "12"; + case srsran_xoverhead_18: + return "18"; + default:; // Do nothing + } + return "invalid"; +} + +static uint32_t phch_cfg_tb_to_str(const srsran_sch_tb_t* tb, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + if (!tb->enabled) { + return len; + } + + len = srsran_print_check(str, str_len, len, " CW%d:\n", tb->cw_idx); + len = srsran_print_check(str, str_len, len, " mod=%s\n", srsran_mod_string(tb->mod)); + len = srsran_print_check(str, str_len, len, " nof_layers=%d\n", tb->N_L); + len = srsran_print_check(str, str_len, len, " mcs=%d\n", tb->mcs); + len = srsran_print_check(str, str_len, len, " tbs=%d\n", tb->tbs); + len = srsran_print_check(str, str_len, len, " R=%.3f\n", tb->R); + len = srsran_print_check(str, str_len, len, " rv=%d\n", tb->rv); + len = srsran_print_check(str, str_len, len, " ndi=%d\n", tb->ndi); + len = srsran_print_check(str, str_len, len, " pid=%d\n", tb->pid); + len = srsran_print_check(str, str_len, len, " nof_re=%d\n", tb->nof_re); + len = srsran_print_check(str, str_len, len, " nof_bits=%d\n", tb->nof_bits); + + return len; +} + +static uint32_t phch_cfg_grant_to_str(const srsran_sch_grant_nr_t* grant, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + uint32_t first_prb = SRSRAN_MAX_PRB_NR; + for (uint32_t i = 0; i < SRSRAN_MAX_PRB_NR && first_prb == SRSRAN_MAX_PRB_NR; i++) { + if (grant->prb_idx[i]) { + first_prb = i; + } + } + + len = srsran_print_check(str, str_len, len, " Grant:\n"); + len = srsran_print_check(str, str_len, len, " rnti=0x%x\n", grant->rnti); + len = srsran_print_check(str, str_len, len, " rnti_type=%s\n", srsran_rnti_type_str(grant->rnti_type)); + len = srsran_print_check(str, str_len, len, " k=%d\n", grant->k); + len = srsran_print_check(str, str_len, len, " mapping=%s\n", sch_mapping_to_str(grant->mapping)); + len = srsran_print_check(str, str_len, len, " t_alloc=%d:%d\n", grant->S, grant->L); + len = srsran_print_check(str, str_len, len, " f_alloc=%d:%d\n", first_prb, grant->nof_prb); + len = srsran_print_check(str, str_len, len, " nof_dmrs_cdm_grps=%d\n", grant->nof_dmrs_cdm_groups_without_data); + len = srsran_print_check(str, str_len, len, " beta_dmrs=%f\n", grant->beta_dmrs); + len = srsran_print_check(str, str_len, len, " nof_layers=%d\n", grant->nof_layers); + len = srsran_print_check(str, str_len, len, " n_scid=%d\n", grant->n_scid); + len = srsran_print_check(str, str_len, len, " tb_scaling_field=%d\n", grant->tb_scaling_field); + + for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { + len += phch_cfg_tb_to_str(&grant->tb[i], &str[len], str_len - len); + } + + return len; +} + +static uint32_t phch_cfg_sch_to_str(const srsran_sch_cfg_t* sch, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + len = srsran_print_check(str, str_len, len, " SCH:\n"); + len = srsran_print_check(str, str_len, len, " mcs_table=%s\n", srsran_mcs_table_to_str(sch->mcs_table)); + len = srsran_print_check(str, str_len, len, " xoverhead=%s\n", sch_xoverhead_to_str(sch->xoverhead)); + + return len; +} + +static uint32_t phch_cfg_rvd_to_str(const srsran_re_pattern_list_t* pattern_list, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + if (pattern_list->count == 0) { + return len; + } + + len = srsran_print_check(str, str_len, len, " Reserved:\n"); + for (uint32_t i = 0; i < pattern_list->count; i++) { + len = srsran_print_check(str, str_len, len, " %d=", i); + len += srsran_re_pattern_info(&pattern_list->data[i], &str[len], str_len - len); + len = srsran_print_check(str, str_len, len, "\n"); + } + + return len; +} + +uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + if (sch_cfg->scambling_id) { + len = srsran_print_check(str, str_len, len, " scrambling_id=0x%03x\n", sch_cfg->scrambling_id_present); + } + + // Append DMRS information + len += phch_cfg_nr_dmrs_to_str(&sch_cfg->dmrs, &sch_cfg->grant, &str[len], str_len - len); + + // Append grant information + len += phch_cfg_grant_to_str(&sch_cfg->grant, &str[len], str_len - len); + + // Append SCH information + len += phch_cfg_sch_to_str(&sch_cfg->sch_cfg, &str[len], str_len - len); + + // Append SCH information + len += phch_cfg_rvd_to_str(&sch_cfg->rvd_re, &str[len], str_len - len); + + // UCI configuration + if (srsran_uci_nr_total_bits(&sch_cfg->uci)) { + len = srsran_print_check(str, str_len, len, " scaling=%.2f\n", sch_cfg->scaling); + len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", sch_cfg->beta_csi_part1_offset); + len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", sch_cfg->beta_csi_part2_offset); + len = srsran_print_check(str, str_len, len, " beta_harq_ack_offset=%.2f\n", sch_cfg->beta_harq_ack_offset); + } + + return len; +} diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 60050f532..6b47d8b5d 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -227,171 +227,25 @@ void srsran_pusch_nr_free(srsran_pusch_nr_t* q) SRSRAN_MEM_ZERO(q, srsran_pusch_nr_t, 1); } -/** - * @brief copies a number of countiguous Resource Elements - * @param sf_symbols slot symbols in frequency domain - * @param symbols resource elements - * @param count number of resource elements to copy - * @param put Direction, symbols are copied into sf_symbols if put is true, otherwise sf_symbols are copied into symbols - */ -static void srsran_pusch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count, bool put) -{ - if (put) { - srsran_vec_cf_copy(sf_symbols, symbols, count); - } else { - srsran_vec_cf_copy(symbols, sf_symbols, count); - } -} - -/* - * As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2: - * - * +---+---+---+---+---+---+---+---+---+---+---+---+ - * | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | - * +---+---+---+---+---+---+---+---+---+---+---+---+ - * -- k --> - * - * If the number of DMRS CDM groups without data is set to: - * - 1, data is mapped in RE marked as 2 - * - Otherwise, no data is mapped in this symbol - */ -static uint32_t srsran_pusch_nr_cp_dmrs_type1(const srsran_pusch_nr_t* q, - const srsran_sch_grant_nr_t* grant, - cf_t* symbols, - cf_t* sf_symbols, - bool put) +static inline uint32_t pusch_nr_put_rb(cf_t* dst, cf_t* src, bool* rvd_mask) { uint32_t count = 0; - uint32_t delta = 0; - - if (grant->nof_dmrs_cdm_groups_without_data != 1) { - return count; - } - - for (uint32_t i = 0; i < q->carrier.nof_prb; i++) { - if (grant->prb_idx[i]) { - for (uint32_t j = 0; j < SRSRAN_NRE; j += 2) { - if (put) { - sf_symbols[i * SRSRAN_NRE + delta + j + 1] = symbols[count++]; - } else { - symbols[count++] = sf_symbols[i * SRSRAN_NRE + delta + j + 1]; - } - } + for (uint32_t i = 0; i < SRSRAN_NRE; i++) { + if (!rvd_mask[i]) { + dst[i] = src[count++]; } } - return count; } -/* - * As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with groups 2 and 3: - * - * +---+---+---+---+---+---+---+---+---+---+---+---+ - * | 1 | 1 | 2 | 2 | 3 | 3 | 1 | 1 | 2 | 2 | 3 | 3 | - * +---+---+---+---+---+---+---+---+---+---+---+---+ - * -- k --> - * - * If the number of DMRS CDM groups without data is set to: - * - 1, data is mapped in RE marked as 2 and 3 - * - 2, data is mapped in RE marked as 3 - * - otherwise, no data is mapped in this symbol - */ -static uint32_t srsran_pusch_nr_cp_dmrs_type2(const srsran_pusch_nr_t* q, - const srsran_sch_grant_nr_t* grant, - cf_t* symbols, - cf_t* sf_symbols, - bool put) +static inline uint32_t pusch_nr_get_rb(cf_t* dst, cf_t* src, bool* rvd_mask) { uint32_t count = 0; - - if (grant->nof_dmrs_cdm_groups_without_data != 1 && grant->nof_dmrs_cdm_groups_without_data != 2) { - return count; - } - - uint32_t re_offset = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 2 : 4; - uint32_t re_count = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 4 : 2; - - for (uint32_t i = 0; i < q->carrier.nof_prb; i++) { - if (grant->prb_idx[i]) { - // Copy RE between pilot pairs - srsran_pusch_re_cp(&sf_symbols[i * SRSRAN_NRE + re_offset], &symbols[count], re_count, put); - count += re_count; - - // Copy RE after second pilot - srsran_pusch_re_cp(&sf_symbols[(i + 1) * SRSRAN_NRE - re_count], &symbols[count], re_count, put); - count += re_count; + for (uint32_t i = 0; i < SRSRAN_NRE; i++) { + if (!rvd_mask[i]) { + dst[count++] = src[i]; } } - - return count; -} - -static uint32_t srsran_pusch_nr_cp_dmrs(const srsran_pusch_nr_t* q, - const srsran_sch_cfg_nr_t* cfg, - const srsran_sch_grant_nr_t* grant, - cf_t* symbols, - cf_t* sf_symbols, - bool put) -{ - uint32_t count = 0; - - const srsran_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs; - - switch (dmrs_cfg->type) { - case srsran_dmrs_sch_type_1: - count = srsran_pusch_nr_cp_dmrs_type1(q, grant, symbols, sf_symbols, put); - break; - case srsran_dmrs_sch_type_2: - count = srsran_pusch_nr_cp_dmrs_type2(q, grant, symbols, sf_symbols, put); - break; - } - - return count; -} - -static uint32_t srsran_pusch_nr_cp_clean(const srsran_pusch_nr_t* q, - const srsran_sch_grant_nr_t* grant, - cf_t* symbols, - cf_t* sf_symbols, - bool put) -{ - uint32_t count = 0; - uint32_t start = 0; // Index of the start of continuous data - uint32_t length = 0; // End of continuous RE - - for (uint32_t i = 0; i < q->carrier.nof_prb; i++) { - if (grant->prb_idx[i]) { - // If fist continuous block, save start - if (length == 0) { - start = i * SRSRAN_NRE; - } - length += SRSRAN_NRE; - } else { - // Consecutive block is finished - if (put) { - srsran_vec_cf_copy(&sf_symbols[start], &symbols[count], length); - } else { - srsran_vec_cf_copy(&symbols[count], &sf_symbols[start], length); - } - - // Increase RE count - count += length; - - // Reset consecutive block - length = 0; - } - } - - // Copy last contiguous block - if (length > 0) { - if (put) { - srsran_vec_cf_copy(&sf_symbols[start], &symbols[count], length); - } else { - srsran_vec_cf_copy(&symbols[count], &sf_symbols[start], length); - } - count += length; - } - return count; } @@ -402,55 +256,60 @@ static int srsran_pusch_nr_cp(const srsran_pusch_nr_t* q, cf_t* sf_symbols, bool put) { - uint32_t count = 0; - uint32_t dmrs_l_idx[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {}; - uint32_t dmrs_l_count = 0; + uint32_t count = 0; - // Get symbol indexes carrying DMRS - int32_t nof_dmrs_symbols = srsran_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, dmrs_l_idx); - if (nof_dmrs_symbols < SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } + for (uint32_t l = grant->S; l < grant->S + grant->L; l++) { + // Initialise reserved RE mask to all false + bool rvd_mask[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {}; - if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { - DEBUG("dmrs_l_idx="); - srsran_vec_fprint_i(stdout, (int32_t*)dmrs_l_idx, nof_dmrs_symbols); - } + // Reserve DMRS + if (srsran_re_pattern_to_symbol_mask(&q->dmrs_re_pattern, l, rvd_mask) < SRSRAN_SUCCESS) { + ERROR("Error generating DMRS reserved RE mask"); + return SRSRAN_ERROR; + } - for (uint32_t l = grant->S; l < grant->S + grant->L; l++) { - // Advance DMRS symbol counter until: - // - the current DMRS symbol index is greater or equal than current symbol l - // - no more DMRS symbols - while (dmrs_l_idx[dmrs_l_count] < l && dmrs_l_count < nof_dmrs_symbols) { - dmrs_l_count++; + // Reserve RE from configuration + if (srsran_re_pattern_list_to_symbol_mask(&cfg->rvd_re, l, rvd_mask) < SRSRAN_SUCCESS) { + ERROR("Error generating reserved RE mask"); + return SRSRAN_ERROR; } - if (l == dmrs_l_idx[dmrs_l_count]) { - count += srsran_pusch_nr_cp_dmrs( - q, cfg, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSRAN_NRE], put); - } else { - count += - srsran_pusch_nr_cp_clean(q, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSRAN_NRE], put); + // Actual copy + for (uint32_t rb = 0; rb < q->carrier.nof_prb; rb++) { + // Skip PRB if not available in grant + if (!grant->prb_idx[rb]) { + continue; + } + + // Calculate RE index at the begin of the symbol + uint32_t re_idx = (q->carrier.nof_prb * l + rb) * SRSRAN_NRE; + + // Put or get + if (put) { + count += pusch_nr_put_rb(&sf_symbols[re_idx], &symbols[count], &rvd_mask[rb * SRSRAN_NRE]); + } else { + count += pusch_nr_get_rb(&symbols[count], &sf_symbols[re_idx], &rvd_mask[rb * SRSRAN_NRE]); + } } } return count; } -static int srsran_pusch_nr_put(const srsran_pusch_nr_t* q, - const srsran_sch_cfg_nr_t* cfg, - const srsran_sch_grant_nr_t* grant, - cf_t* symbols, - cf_t* sf_symbols) +static int pusch_nr_put(const srsran_pusch_nr_t* q, + const srsran_sch_cfg_nr_t* cfg, + const srsran_sch_grant_nr_t* grant, + cf_t* symbols, + cf_t* sf_symbols) { return srsran_pusch_nr_cp(q, cfg, grant, symbols, sf_symbols, true); } -static int srsran_pusch_nr_get(const srsran_pusch_nr_t* q, - const srsran_sch_cfg_nr_t* cfg, - const srsran_sch_grant_nr_t* grant, - cf_t* symbols, - cf_t* sf_symbols) +static int pusch_nr_get(const srsran_pusch_nr_t* q, + const srsran_sch_cfg_nr_t* cfg, + const srsran_sch_grant_nr_t* grant, + cf_t* symbols, + cf_t* sf_symbols) { return srsran_pusch_nr_cp(q, cfg, grant, symbols, sf_symbols, false); } @@ -950,6 +809,12 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q, return SRSRAN_ERROR; } + // Compute DMRS pattern + if (srsran_dmrs_sch_rvd_re_pattern(&cfg->dmrs, grant, &q->dmrs_re_pattern) < SRSRAN_SUCCESS) { + ERROR("Error computing DMRS pattern"); + return SRSRAN_ERROR; + } + // Fill UCI configuration for PUSCH configuration if (pusch_nr_fill_uci_cfg(q, cfg) < SRSRAN_SUCCESS) { ERROR("Error filling UCI configuration for PUSCH"); @@ -982,7 +847,7 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q, // ... Not implemented // 7.3.1.6 Mapping from virtual to physical resource blocks - int n = srsran_pusch_nr_put(q, cfg, grant, x[0], sf_symbols[0]); + int n = pusch_nr_put(q, cfg, grant, x[0], sf_symbols[0]); if (n < SRSRAN_SUCCESS) { ERROR("Putting NR PUSCH resources"); return SRSRAN_ERROR; @@ -1166,6 +1031,12 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q, return SRSRAN_ERROR; } + // Compute DMRS pattern + if (srsran_dmrs_sch_rvd_re_pattern(&cfg->dmrs, grant, &q->dmrs_re_pattern) < SRSRAN_SUCCESS) { + ERROR("Error computing DMRS pattern"); + return SRSRAN_ERROR; + } + // Fill UCI configuration for PUSCH configuration if (pusch_nr_fill_uci_cfg(q, cfg) < SRSRAN_SUCCESS) { ERROR("Error filling UCI configuration for PUSCH"); @@ -1185,7 +1056,7 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q, } // Demapping from virtual to physical resource blocks - uint32_t nof_re_get = srsran_pusch_nr_get(q, cfg, grant, q->x[0], sf_symbols[0]); + uint32_t nof_re_get = pusch_nr_get(q, cfg, grant, q->x[0], sf_symbols[0]); if (nof_re_get != nof_re) { ERROR("Inconsistent number of RE (%d!=%d)", nof_re_get, nof_re); return SRSRAN_ERROR; @@ -1230,14 +1101,14 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q, return SRSRAN_SUCCESS; } -static uint32_t srsran_pusch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg, - const srsran_sch_grant_nr_t* grant, - const srsran_pusch_res_nr_t* res, - char* str, - uint32_t str_len) +static uint32_t pusch_nr_grant_info(const srsran_pusch_nr_t* q, + const srsran_sch_cfg_nr_t* cfg, + const srsran_sch_grant_nr_t* grant, + const srsran_pusch_res_nr_t* res, + char* str, + uint32_t str_len) { uint32_t len = 0; - len = srsran_print_check(str, str_len, len, "rnti=0x%x", grant->rnti); uint32_t first_prb = SRSRAN_MAX_PRB_NR; for (uint32_t i = 0; i < SRSRAN_MAX_PRB_NR && first_prb == SRSRAN_MAX_PRB_NR; i++) { @@ -1247,29 +1118,20 @@ static uint32_t srsran_pusch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg, } // Append time-domain resource mapping - len = srsran_print_check(str, - str_len, - len, - ",k2=%d,prb=%d:%d,S=%d,L=%d,mapping=%s", - grant->k, - first_prb, - grant->nof_prb, - grant->S, - grant->L, - srsran_sch_mapping_type_to_str(grant->mapping)); - - // Skip frequency domain resources... - // ... - - // Append spatial resources - len = srsran_print_check(str, str_len, len, ",Nl=%d", grant->nof_layers); - - // Append scrambling ID - len = srsran_print_check(str, str_len, len, ",n_scid=%d,", grant->n_scid); + len = srsran_print_check( + str, str_len, len, "rnti=0x%x prb=%d:%d symb=%d:%d ", grant->rnti, first_prb, grant->nof_prb, grant->S, grant->L); // Append TB info for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { len += srsran_sch_nr_tb_info(&grant->tb[i], &res->tb[i], &str[len], str_len - len); + + if (res != NULL) { + if (grant->tb[i].enabled && !isnan(res->evm[i])) { + len = srsran_print_check(str, str_len, len, "evm=%.2f ", res->evm[i]); + if (i < SRSRAN_MAX_CODEWORDS - 1) { + } + } + } } return len; @@ -1288,45 +1150,18 @@ uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q, return 0; } - len += srsran_pusch_nr_grant_info(cfg, grant, res, &str[len], str_len - len); + len += pusch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len); - if (q->evm_buffer != NULL) { - len = srsran_print_check(str, str_len, len, ",evm={", 0); - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { - if (grant->tb[i].enabled && !isnan(res->evm[i])) { - len = srsran_print_check(str, str_len, len, "%.2f", res[i].evm); - if (i < SRSRAN_MAX_CODEWORDS - 1) { - if (grant->tb[i + 1].enabled) { - len = srsran_print_check(str, str_len, len, ",", 0); - } - } - } - } - len = srsran_print_check(str, str_len, len, "}", 0); - } - - if (res != NULL) { + if (res != NULL && srsran_uci_nr_total_bits(&cfg->uci) > 0) { + len = srsran_print_check(str, str_len, len, "UCI: "); srsran_uci_data_nr_t uci_data = {}; uci_data.cfg = cfg->uci; - uci_data.value = res[0].uci; + uci_data.value = res->uci; len += srsran_uci_nr_info(&uci_data, &str[len], str_len - len); - - len = srsran_print_check(str, str_len, len, ",crc={", 0); - for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { - if (grant->tb[i].enabled) { - len = srsran_print_check(str, str_len, len, "%s", res->tb[i].crc ? "OK" : "KO"); - if (i < SRSRAN_MAX_CODEWORDS - 1) { - if (grant->tb[i + 1].enabled) { - len = srsran_print_check(str, str_len, len, ",", 0); - } - } - } - } - len = srsran_print_check(str, str_len, len, "}", 0); } if (q->meas_time_en) { - len = srsran_print_check(str, str_len, len, ", t=%d us", q->meas_time_us); + len = srsran_print_check(str, str_len, len, " t=%d us", q->meas_time_us); } return len; @@ -1345,7 +1180,7 @@ uint32_t srsran_pusch_nr_tx_info(const srsran_pusch_nr_t* q, return 0; } - len += srsran_pusch_nr_grant_info(cfg, grant, NULL, &str[len], str_len - len); + len += pusch_nr_grant_info(q, cfg, grant, NULL, &str[len], str_len - len); if (uci_value != NULL) { srsran_uci_data_nr_t uci_data = {}; diff --git a/lib/src/phy/phch/sch_nr.c b/lib/src/phy/phch/sch_nr.c index 0a42f133f..06ec1284f 100644 --- a/lib/src/phy/phch/sch_nr.c +++ b/lib/src/phy/phch/sch_nr.c @@ -734,15 +734,12 @@ int srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, const srsran_sch_tb_res_nr_ len = srsran_print_check(str, str_len, len, - "CW%d: mod=%s Nl=%d tbs=%d R=%.3f rv=%d Nre=%d Nbit=%d ", + "CW%d: mod=%s tbs=%d R=%.3f rv=%d ", tb->cw_idx, srsran_mod_string(tb->mod), - tb->N_L, tb->tbs / 8, tb->R, - tb->rv, - tb->nof_re, - tb->nof_bits); + tb->rv); if (res != NULL) { len = srsran_print_check(str, str_len, len, "CRC=%s iter=%.1f ", res->crc ? "OK" : "KO", res->avg_iter); diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index 9a0fd39d4..1e91e9e52 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -340,6 +340,15 @@ int main(int argc, char** argv) } } + if (srsran_verbose >= SRSRAN_VERBOSE_INFO) { + char str[512]; + srsran_pusch_nr_rx_info(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &data_rx, str, (uint32_t)sizeof(str)); + + char str_extra[2048]; + srsran_phch_cfg_nr_info(&pusch_cfg, str_extra, (uint32_t)sizeof(str_extra)); + INFO("PUSCH: %s\n%s", str, str_extra); + } + printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pusch_cfg.grant.tb[0].tbs, data_rx.evm[0]); } } diff --git a/lib/src/phy/phch/uci_nr.c b/lib/src/phy/phch/uci_nr.c index 9162d3091..b20b65bf1 100644 --- a/lib/src/phy/phch/uci_nr.c +++ b/lib/src/phy/phch/uci_nr.c @@ -986,9 +986,9 @@ uint32_t srsran_uci_nr_info(const srsran_uci_data_nr_t* uci_data, char* str, uin uint32_t len = 0; if (uci_data->cfg.o_ack > 0) { - char str2[10]; - srsran_vec_sprint_bin(str2, 10, uci_data->value.ack, uci_data->cfg.o_ack); - len = srsran_print_check(str, str_len, len, ", ack=%s", str2); + char str_ack[10]; + srsran_vec_sprint_bin(str_ack, (uint32_t)sizeof(str_ack), uci_data->value.ack, uci_data->cfg.o_ack); + len = srsran_print_check(str, str_len, len, "ack=%s ", str_ack); } if (uci_data->cfg.nof_csi > 0) { @@ -996,7 +996,7 @@ uint32_t srsran_uci_nr_info(const srsran_uci_data_nr_t* uci_data, char* str, uin } if (uci_data->cfg.o_sr > 0) { - len = srsran_print_check(str, str_len, len, ", sr=%d", uci_data->value.sr); + len = srsran_print_check(str, str_len, len, "sr=%d ", uci_data->value.sr); } return len; diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 4a90602ca..35871f720 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -448,6 +448,15 @@ int main(int argc, char** argv) } } + if (srsran_verbose >= SRSRAN_VERBOSE_INFO) { + char str[512]; + srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str, (uint32_t)sizeof(str)); + + char str_extra[2048]; + srsran_phch_cfg_nr_info(&pdsch_cfg, str_extra, (uint32_t)sizeof(str_extra)); + INFO("PDSCH: %s\n%s", str, str_extra); + } + INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs, pdsch_res.evm[0]); // Count the Tx/Rx'd number of bits diff --git a/srsue/hdr/phy/nr/cc_worker.h b/srsue/hdr/phy/nr/cc_worker.h index 84b7f7c6d..c75f60d9a 100644 --- a/srsue/hdr/phy/nr/cc_worker.h +++ b/srsue/hdr/phy/nr/cc_worker.h @@ -39,6 +39,10 @@ public: int read_pdsch_d(cf_t* pdsch_d); private: + // PHY lib temporal logger types + typedef std::array str_info_t; + typedef std::array str_extra_t; + bool configured = false; srsran_slot_cfg_t dl_slot_cfg = {}; srsran_slot_cfg_t ul_slot_cfg = {}; @@ -51,7 +55,7 @@ private: srsran_ue_ul_nr_t ue_ul = {}; srslog::basic_logger& logger; - // Methods for DL... + // Methods for DCI blind search void decode_pdcch_ul(); void decode_pdcch_dl(); }; diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 95aaad815..6d2caf6ef 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -271,9 +271,21 @@ bool cc_worker::work_dl() // Logging if (logger.info.enabled()) { - std::array str; - srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str.data(), str.size()); - logger.info(pdsch_res.tb[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, "PDSCH: cc=%d, %s", cc_idx, str.data()); + str_info_t str; + srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str.data(), (uint32_t)str.size()); + + if (logger.debug.enabled()) { + str_extra_t str_extra; + srsran_phch_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, %s\n%s", + cc_idx, + str.data(), + str_extra.data()); + } else { + logger.info(pdsch_res.tb[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, "PDSCH: cc=%d, %s", cc_idx, str.data()); + } } // Enqueue PDSCH ACK information only if the RNTI is type C @@ -398,14 +410,21 @@ bool cc_worker::work_ul() // PUSCH Logging if (logger.info.enabled()) { - std::array str; + str_info_t str; srsran_ue_ul_nr_pusch_info(&ue_ul, &pusch_cfg, &data.uci, str.data(), str.size()); - logger.info(ul_action.tb.payload->msg, - pusch_cfg.grant.tb[0].tbs / 8, - "PUSCH: cc=%d, %s, tti_tx=%d", - cc_idx, - str.data(), - ul_slot_cfg.idx); + + if (logger.debug.enabled()) { + str_extra_t str_extra; + srsran_phch_cfg_nr_info(&pusch_cfg, str_extra.data(), (uint32_t)str_extra.size()); + logger.info(ul_action.tb.payload->msg, + pusch_cfg.grant.tb[0].tbs / 8, + "PUSCH: cc=%d, %s\n%s", + cc_idx, + str.data(), + str_extra.data()); + } else { + logger.info(ul_action.tb.payload->msg, pusch_cfg.grant.tb[0].tbs / 8, "PUSCH: cc=%d, %s", cc_idx, str.data()); + } } // Set metrics From 7e06e789d59ca0c044989ef135e0f7d89b985a88 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Apr 2021 13:02:23 +0200 Subject: [PATCH 15/46] Fic NR UCI in the info string --- lib/src/phy/phch/phch_cfg_nr.c | 29 +++++++++++++++++++++++------ lib/src/phy/phch/pusch_nr.c | 2 +- lib/src/phy/phch/ra_nr.c | 2 +- srsue/src/phy/nr/cc_worker.cc | 10 ++++++++-- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/src/phy/phch/phch_cfg_nr.c b/lib/src/phy/phch/phch_cfg_nr.c index 1974f1061..4cf2d0f19 100644 --- a/lib/src/phy/phch/phch_cfg_nr.c +++ b/lib/src/phy/phch/phch_cfg_nr.c @@ -11,6 +11,7 @@ */ #include "srsran/phy/phch/phch_cfg_nr.h" #include "srsran/phy/ch_estimation/dmrs_sch.h" +#include "srsran/phy/phch/csi.h" #include "srsran/phy/phch/uci_nr.h" static const char* dmrs_sch_type_to_str(srsran_dmrs_sch_type_t type) @@ -215,6 +216,27 @@ static uint32_t phch_cfg_rvd_to_str(const srsran_re_pattern_list_t* pattern_list return len; } +static uint32_t phch_cfg_uci_to_str(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + if (srsran_uci_nr_total_bits(&sch_cfg->uci) == 0) { + return len; + } + + len = srsran_print_check(str, str_len, len, " UCI:\n", sch_cfg->scaling); + len = srsran_print_check(str, str_len, len, " scaling=%.2f\n", sch_cfg->scaling); + len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", sch_cfg->beta_csi_part1_offset); + len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", sch_cfg->beta_csi_part2_offset); + len = srsran_print_check(str, str_len, len, " beta_harq_ack_offset=%.2f\n", sch_cfg->beta_harq_ack_offset); + + len = srsran_print_check( + str, str_len, len, " o_csi1=%d\n", srsran_csi_part1_nof_bits(sch_cfg->uci.csi, sch_cfg->uci.nof_csi)); + len = srsran_print_check(str, str_len, len, " o_ack=%d\n", sch_cfg->uci.o_ack); + + return len; +} + uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len) { uint32_t len = 0; @@ -236,12 +258,7 @@ uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, len += phch_cfg_rvd_to_str(&sch_cfg->rvd_re, &str[len], str_len - len); // UCI configuration - if (srsran_uci_nr_total_bits(&sch_cfg->uci)) { - len = srsran_print_check(str, str_len, len, " scaling=%.2f\n", sch_cfg->scaling); - len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", sch_cfg->beta_csi_part1_offset); - len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", sch_cfg->beta_csi_part2_offset); - len = srsran_print_check(str, str_len, len, " beta_harq_ack_offset=%.2f\n", sch_cfg->beta_harq_ack_offset); - } + len += phch_cfg_uci_to_str(sch_cfg, &str[len], str_len - len); return len; } diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 6b47d8b5d..2b086d76d 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -1190,7 +1190,7 @@ uint32_t srsran_pusch_nr_tx_info(const srsran_pusch_nr_t* q, } if (q->meas_time_en) { - len = srsran_print_check(str, str_len, len, ", t=%d us", q->meas_time_us); + len = srsran_print_check(str, str_len, len, " t=%d us", q->meas_time_us); } return len; diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index bbe8fbbf2..fd3ce41c0 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -819,7 +819,7 @@ static float ra_ul_beta_offset_ack_semistatic(const srsran_beta_offsets_t* beta_ if (uci_cfg->o_ack > 11) { beta_offset_index = beta_offsets->ack_index3; } else if (uci_cfg->o_ack > 2) { - beta_offset_index = beta_offsets->ack_index1; + beta_offset_index = beta_offsets->ack_index2; } // Protect table boundary diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 6d2caf6ef..7097127d0 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -418,12 +418,18 @@ bool cc_worker::work_ul() srsran_phch_cfg_nr_info(&pusch_cfg, str_extra.data(), (uint32_t)str_extra.size()); logger.info(ul_action.tb.payload->msg, pusch_cfg.grant.tb[0].tbs / 8, - "PUSCH: cc=%d, %s\n%s", + "PUSCH: cc=%d %s tti_tx=%d\n%s", cc_idx, str.data(), + ul_slot_cfg.idx, str_extra.data()); } else { - logger.info(ul_action.tb.payload->msg, pusch_cfg.grant.tb[0].tbs / 8, "PUSCH: cc=%d, %s", cc_idx, str.data()); + logger.info(ul_action.tb.payload->msg, + pusch_cfg.grant.tb[0].tbs / 8, + "PUSCH: cc=%d %s tti_tx=%d", + cc_idx, + str.data(), + ul_slot_cfg.idx); } } From abfc1da92177a43772e159643a6e0a35ffc9f612 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Apr 2021 18:33:41 +0200 Subject: [PATCH 16/46] Multiple NR-PUSCH fixes --- lib/include/srsran/phy/phch/phch_cfg_nr.h | 13 +- lib/include/srsran/phy/phch/pusch_nr.h | 1 - lib/include/srsran/phy/phch/ra_nr.h | 4 +- lib/include/srsran/phy/phch/sch_cfg_nr.h | 4 +- lib/include/srsran/phy/phch/uci_cfg_nr.h | 1 + lib/src/phy/phch/phch_cfg_nr.c | 24 ++- lib/src/phy/phch/pusch_nr.c | 173 ++++------------------ lib/src/phy/phch/ra_nr.c | 163 ++++++++++++++++++-- lib/src/phy/phch/test/pusch_nr_test.c | 15 +- lib/src/phy/phch/uci_nr.c | 8 +- lib/test/phy/phy_dl_nr_test.c | 2 +- srsue/src/phy/nr/cc_worker.cc | 6 +- 12 files changed, 220 insertions(+), 194 deletions(-) diff --git a/lib/include/srsran/phy/phch/phch_cfg_nr.h b/lib/include/srsran/phy/phch/phch_cfg_nr.h index 3171835dc..99d028bfe 100644 --- a/lib/include/srsran/phy/phch/phch_cfg_nr.h +++ b/lib/include/srsran/phy/phch/phch_cfg_nr.h @@ -164,6 +164,11 @@ typedef struct { uint32_t csi1_index2; ///< Use for more than 11 CSI bits. Set to 13 if absent. uint32_t csi2_index1; ///< Use for up to 11 CSI bits. Set to 13 if absent. uint32_t csi2_index2; ///< Use for more than 11 CSI bits. Set to 13 if absent. + + /// Fix values for testing purposes + float fix_ack; ///< Set to a non-zero value for fixing a beta offset value + float fix_csi1; + float fix_csi2; } srsran_beta_offsets_t; /** @@ -238,13 +243,11 @@ typedef struct SRSRAN_API { /// PUSCH only parameters srsran_uci_cfg_nr_t uci; ///< Uplink Control Information configuration bool enable_transform_precoder; - float beta_harq_ack_offset; - float beta_csi_part1_offset; - float beta_csi_part2_offset; - float scaling; bool freq_hopping_enabled; } srsran_sch_cfg_nr_t; -SRSRAN_API uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len); +SRSRAN_API uint32_t srsran_sch_cfg_nr_nof_re(const srsran_sch_cfg_nr_t* sch_cfg); + +SRSRAN_API uint32_t srsran_sch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len); #endif // SRSRAN_PHCH_CFG_NR_H diff --git a/lib/include/srsran/phy/phch/pusch_nr.h b/lib/include/srsran/phy/phch/pusch_nr.h index 265cd466a..f61755caa 100644 --- a/lib/include/srsran/phy/phch/pusch_nr.h +++ b/lib/include/srsran/phy/phch/pusch_nr.h @@ -51,7 +51,6 @@ typedef struct SRSRAN_API { bool meas_time_en; uint32_t meas_time_us; srsran_re_pattern_t dmrs_re_pattern; - srsran_uci_cfg_nr_t uci_cfg; ///< Internal UCI bits configuration uint8_t* g_ulsch; ///< Temporal Encoded UL-SCH data uint8_t* g_ack; ///< Temporal Encoded HARQ-ACK bits uint8_t* g_csi1; ///< Temporal Encoded CSI part 1 bits diff --git a/lib/include/srsran/phy/phch/ra_nr.h b/lib/include/srsran/phy/phch/ra_nr.h index 344ef060d..a2ddd5042 100644 --- a/lib/include/srsran/phy/phch/ra_nr.h +++ b/lib/include/srsran/phy/phch/ra_nr.h @@ -128,12 +128,14 @@ SRSRAN_API int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrie * * @remark Implement procedure described in TS 38.213 9.3 UCI reporting in physical uplink shared channel * + * @param carrier Carrier information struct * @param pusch_hl_cfg PUSCH configuration provided by higher layers * @param uci_cfg Uplink Control Information configuration for this PUSCH transmission * @param pusch_cfg PUSCH configuration after applying the procedure * @return SRSRAN_SUCCESS if the procedure is successful, SRSRAN_ERROR code otherwise */ -SRSRAN_API int srsran_ra_ul_set_grant_uci_nr(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, +SRSRAN_API int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carrier, + const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, const srsran_uci_cfg_nr_t* uci_cfg, srsran_sch_cfg_nr_t* pusch_cfg); diff --git a/lib/include/srsran/phy/phch/sch_cfg_nr.h b/lib/include/srsran/phy/phch/sch_cfg_nr.h index 178cd57f2..9a3c580f8 100644 --- a/lib/include/srsran/phy/phch/sch_cfg_nr.h +++ b/lib/include/srsran/phy/phch/sch_cfg_nr.h @@ -32,8 +32,8 @@ typedef struct SRSRAN_API { int rv; ///< Redundancy version int ndi; ///< New Data Indicator int pid; ///< HARQ Process ID - uint32_t nof_re; ///< Number of available resource elements to send, known as N_RE - uint32_t nof_bits; ///< Number of available bits to send, known as G + uint32_t nof_re; ///< Number of available resource elements to transmit ULSCH (data) and UCI (control) + uint32_t nof_bits; ///< Number of available bits to send ULSCH uint32_t cw_idx; bool enabled; diff --git a/lib/include/srsran/phy/phch/uci_cfg_nr.h b/lib/include/srsran/phy/phch/uci_cfg_nr.h index b47e65507..7330333d5 100644 --- a/lib/include/srsran/phy/phch/uci_cfg_nr.h +++ b/lib/include/srsran/phy/phch/uci_cfg_nr.h @@ -62,6 +62,7 @@ typedef struct { float alpha; ///< Higher layer parameter scaling float beta_harq_ack_offset; float beta_csi1_offset; + float beta_csi2_offset; uint32_t nof_re; bool csi_part2_present; } srsran_uci_nr_pusch_cfg_t; diff --git a/lib/src/phy/phch/phch_cfg_nr.c b/lib/src/phy/phch/phch_cfg_nr.c index 4cf2d0f19..c4b427b3a 100644 --- a/lib/src/phy/phch/phch_cfg_nr.c +++ b/lib/src/phy/phch/phch_cfg_nr.c @@ -216,28 +216,26 @@ static uint32_t phch_cfg_rvd_to_str(const srsran_re_pattern_list_t* pattern_list return len; } -static uint32_t phch_cfg_uci_to_str(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len) +static uint32_t phch_cfg_uci_to_str(const srsran_uci_cfg_nr_t* uci, char* str, uint32_t str_len) { uint32_t len = 0; - if (srsran_uci_nr_total_bits(&sch_cfg->uci) == 0) { + if (srsran_uci_nr_total_bits(uci) == 0) { return len; } - len = srsran_print_check(str, str_len, len, " UCI:\n", sch_cfg->scaling); - len = srsran_print_check(str, str_len, len, " scaling=%.2f\n", sch_cfg->scaling); - len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", sch_cfg->beta_csi_part1_offset); - len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", sch_cfg->beta_csi_part2_offset); - len = srsran_print_check(str, str_len, len, " beta_harq_ack_offset=%.2f\n", sch_cfg->beta_harq_ack_offset); - - len = srsran_print_check( - str, str_len, len, " o_csi1=%d\n", srsran_csi_part1_nof_bits(sch_cfg->uci.csi, sch_cfg->uci.nof_csi)); - len = srsran_print_check(str, str_len, len, " o_ack=%d\n", sch_cfg->uci.o_ack); + len = srsran_print_check(str, str_len, len, " UCI:\n"); + len = srsran_print_check(str, str_len, len, " alpha=%.2f\n", uci->pusch.alpha); + len = srsran_print_check(str, str_len, len, " beta_harq_ack_offset=%.2f\n", uci->pusch.beta_harq_ack_offset); + len = srsran_print_check(str, str_len, len, " beta_csi_part1_offset=%.2f\n", uci->pusch.beta_csi1_offset); + len = srsran_print_check(str, str_len, len, " beta_csi_part2_offset=%.2f\n", uci->pusch.beta_csi1_offset); + len = srsran_print_check(str, str_len, len, " o_csi1=%d\n", srsran_csi_part1_nof_bits(uci->csi, uci->nof_csi)); + len = srsran_print_check(str, str_len, len, " o_ack=%d\n", uci->o_ack); return len; } -uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len) +uint32_t srsran_sch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, uint32_t str_len) { uint32_t len = 0; @@ -258,7 +256,7 @@ uint32_t srsran_phch_cfg_nr_info(const srsran_sch_cfg_nr_t* sch_cfg, char* str, len += phch_cfg_rvd_to_str(&sch_cfg->rvd_re, &str[len], str_len - len); // UCI configuration - len += phch_cfg_uci_to_str(sch_cfg, &str[len], str_len - len); + len += phch_cfg_uci_to_str(&sch_cfg->uci, &str[len], str_len - len); return len; } diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 2b086d76d..908e38273 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -328,121 +328,6 @@ pusch_nr_cinit(const srsran_carrier_nr_t* carrier, const srsran_sch_cfg_nr_t* cf return cinit; } -static inline int pusch_nr_fill_uci_cfg(srsran_pusch_nr_t* q, const srsran_sch_cfg_nr_t* cfg) -{ - if (cfg->grant.nof_prb == 0) { - ERROR("Invalid number of PRB (%d)", cfg->grant.nof_prb); - return SRSRAN_ERROR; - } - - // Initially, copy all fields - q->uci_cfg = cfg->uci; - - // Reset UCI PUSCH configuration - SRSRAN_MEM_ZERO(&q->uci_cfg.pusch, srsran_uci_nr_pusch_cfg_t, 1); - - // Get DMRS symbol indexes - uint32_t nof_dmrs_l = 0; - uint32_t dmrs_l[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {}; - int n = srsran_dmrs_sch_get_symbols_idx(&cfg->dmrs, &cfg->grant, dmrs_l); - if (n < SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - nof_dmrs_l = (uint32_t)n; - - // Find OFDM symbol index of the first OFDM symbol after the first set of consecutive OFDM symbol(s) carrying DMRS - // Starts at first OFDM symbol carrying DMRS - for (uint32_t l = dmrs_l[0], dmrs_l_idx = 0; l < cfg->grant.S + cfg->grant.L; l++) { - // Check if it is not carrying DMRS... - if (l != dmrs_l[dmrs_l_idx]) { - // Set value and stop iterating - q->uci_cfg.pusch.l0 = l; - break; - } - - // Move to the next DMRS OFDM symbol index - if (dmrs_l_idx < nof_dmrs_l) { - dmrs_l_idx++; - } - } - - // Find OFDM symbol index of the first OFDM symbol that does not carry DMRS - // Starts at first OFDM symbol of the PUSCH transmission - for (uint32_t l = cfg->grant.S, dmrs_l_idx = 0; l < cfg->grant.S + cfg->grant.L; l++) { - // Check if it is not carrying DMRS... - if (l != dmrs_l[dmrs_l_idx]) { - q->uci_cfg.pusch.l1 = l; - break; - } - - // Move to the next DMRS OFDM symbol index - if (dmrs_l_idx < nof_dmrs_l) { - dmrs_l_idx++; - } - } - - // Number of DMRS per PRB - uint32_t n_sc_dmrs = SRSRAN_DMRS_SCH_SC(cfg->grant.nof_dmrs_cdm_groups_without_data, cfg->dmrs.type); - - // Set UCI RE number of candidates per OFDM symbol according to TS 38.312 6.3.2.4.2.1 - for (uint32_t l = 0, dmrs_l_idx = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) { - // Skip if OFDM symbol is outside of the PUSCH transmission - if (l < cfg->grant.S || l >= (cfg->grant.S + cfg->grant.L)) { - q->uci_cfg.pusch.M_pusch_sc[l] = 0; - q->uci_cfg.pusch.M_uci_sc[l] = 0; - continue; - } - - // OFDM symbol carries DMRS - if (l == dmrs_l[dmrs_l_idx]) { - // Calculate PUSCH RE candidates - q->uci_cfg.pusch.M_pusch_sc[l] = cfg->grant.nof_prb * (SRSRAN_NRE - n_sc_dmrs); - - // The Number of RE candidates for UCI are 0 - q->uci_cfg.pusch.M_uci_sc[l] = 0; - - // Advance DMRS symbol index - dmrs_l_idx++; - - // Skip to next symbol - continue; - } - - // Number of RE for Phase Tracking Reference Signals (PT-RS) - uint32_t M_ptrs_sc = 0; // Not implemented yet - - // Number of RE given by the grant - q->uci_cfg.pusch.M_pusch_sc[l] = cfg->grant.nof_prb * SRSRAN_NRE; - - // Calculate the number of UCI candidates - q->uci_cfg.pusch.M_uci_sc[l] = q->uci_cfg.pusch.M_pusch_sc[l] - M_ptrs_sc; - } - - // Generate SCH Transport block information - srsran_sch_nr_tb_info_t sch_tb_info = {}; - if (srsran_sch_nr_fill_tb_info(&q->carrier, &cfg->sch_cfg, &cfg->grant.tb[0], &sch_tb_info) < SRSRAN_SUCCESS) { - ERROR("Generating TB info"); - return SRSRAN_ERROR; - } - - // Calculate the sum of codeblock sizes - for (uint32_t i = 0; i < sch_tb_info.C; i++) { - // Accumulate codeblock size if mask is enabled - q->uci_cfg.pusch.K_sum += (sch_tb_info.mask[i]) ? sch_tb_info.Kr : 0; - } - - // Set other PUSCH parameters - q->uci_cfg.pusch.modulation = cfg->grant.tb[0].mod; - q->uci_cfg.pusch.nof_layers = cfg->grant.nof_layers; - q->uci_cfg.pusch.R = (float)cfg->grant.tb[0].R; - q->uci_cfg.pusch.alpha = cfg->scaling; - q->uci_cfg.pusch.beta_harq_ack_offset = cfg->beta_harq_ack_offset; - q->uci_cfg.pusch.beta_csi1_offset = cfg->beta_csi_part1_offset; - q->uci_cfg.pusch.nof_re = cfg->grant.tb[0].nof_re; - - return SRSRAN_SUCCESS; -} - // Implements TS 38.212 6.2.7 Data and control multiplexing (for NR-PUSCH) static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* cfg) { @@ -479,7 +364,7 @@ static int pusch_nr_gen_mux_uci(srsran_pusch_nr_t* q, const srsran_uci_cfg_nr_t* if (cfg->o_ack <= 2) { // the number of reserved resource elements for potential HARQ-ACK transmission is calculated according to Clause // 6.3.2.4.2.1, by setting O_ACK = 2 ; - G_ack_rvd = srsran_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, 2); + G_ack_rvd = srsran_uci_nr_pusch_ack_nof_bits(&cfg->pusch, 2); // Disable non reserved HARQ-ACK bits G_ack = 0; @@ -695,7 +580,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q, } // Encode HARQ-ACK bits - int E_uci_ack = srsran_uci_nr_encode_pusch_ack(&q->uci, &q->uci_cfg, uci, q->g_ack); + int E_uci_ack = srsran_uci_nr_encode_pusch_ack(&q->uci, &cfg->uci, uci, q->g_ack); if (E_uci_ack < SRSRAN_SUCCESS) { ERROR("Error encoding HARQ-ACK bits"); return SRSRAN_ERROR; @@ -703,7 +588,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q, q->G_ack = (uint32_t)E_uci_ack; // Encode CSI part 1 - int E_uci_csi1 = srsran_uci_nr_encode_pusch_csi1(&q->uci, &q->uci_cfg, uci, q->g_csi1); + int E_uci_csi1 = srsran_uci_nr_encode_pusch_csi1(&q->uci, &cfg->uci, uci, q->g_csi1); if (E_uci_csi1 < SRSRAN_SUCCESS) { ERROR("Error encoding HARQ-ACK bits"); return SRSRAN_ERROR; @@ -715,7 +600,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q, q->G_csi2 = 0; // Generate PUSCH UCI/UL-SCH multiplexing - if (pusch_nr_gen_mux_uci(q, &q->uci_cfg) < SRSRAN_SUCCESS) { + if (pusch_nr_gen_mux_uci(q, &cfg->uci) < SRSRAN_SUCCESS) { ERROR("Error generating PUSCH mux tables"); return SRSRAN_ERROR; } @@ -727,7 +612,8 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q, } // Multiplex UL-SCH with UCI only if it is necessary - uint8_t* b = q->g_ulsch; + uint32_t nof_bits = tb->nof_re * srsran_mod_bits_x_symbol(tb->mod); + uint8_t* b = q->g_ulsch; if (q->uci_mux) { // Change b location b = q->b[tb->cw_idx]; @@ -755,15 +641,15 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q, if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { DEBUG("b="); - srsran_vec_fprint_b(stdout, b, tb->nof_bits); + srsran_vec_fprint_b(stdout, b, nof_bits); } // 7.3.1.1 Scrambling uint32_t cinit = pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx); - srsran_sequence_apply_bit(b, q->b[tb->cw_idx], tb->nof_bits, cinit); + srsran_sequence_apply_bit(b, q->b[tb->cw_idx], nof_bits, cinit); // Special Scrambling condition - if (q->uci_cfg.o_ack <= 2) { + if (cfg->uci.o_ack <= 2) { for (uint32_t i = 0; i < q->G_ack; i++) { uint32_t idx = q->pos_ack[i]; if (q->g_ack[i] == (uint8_t)UCI_BIT_REPETITION) { @@ -777,7 +663,7 @@ static inline int pusch_nr_encode_codeword(srsran_pusch_nr_t* q, } // 7.3.1.2 Modulation - srsran_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], tb->nof_bits); + srsran_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], nof_bits); if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { DEBUG("d="); @@ -795,6 +681,7 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q, { // Check input pointers if (!q || !cfg || !grant || !data || !sf_symbols) { + ERROR("Invalid inputs"); return SRSRAN_ERROR_INVALID_INPUTS; } @@ -815,12 +702,6 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q, return SRSRAN_ERROR; } - // Fill UCI configuration for PUSCH configuration - if (pusch_nr_fill_uci_cfg(q, cfg) < SRSRAN_SUCCESS) { - ERROR("Error filling UCI configuration for PUSCH"); - return SRSRAN_ERROR; - } - // 7.3.1.1 and 7.3.1.2 uint32_t nof_cw = 0; for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { @@ -895,8 +776,11 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, srsran_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re); } + // Total number of bits + uint32_t nof_bits = tb->nof_re * srsran_mod_bits_x_symbol(tb->mod); + // Calculate HARQ-ACK bits - int n = srsran_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, q->uci_cfg.o_ack); + int n = srsran_uci_nr_pusch_ack_nof_bits(&cfg->uci.pusch, cfg->uci.o_ack); if (n < SRSRAN_SUCCESS) { ERROR("Calculating G_ack"); return SRSRAN_ERROR; @@ -904,7 +788,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, q->G_ack = (uint32_t)n; // Calculate CSI part 1 bits - n = srsran_uci_nr_pusch_csi1_nof_bits(&q->uci_cfg); + n = srsran_uci_nr_pusch_csi1_nof_bits(&cfg->uci); if (n < SRSRAN_SUCCESS) { ERROR("Calculating G_csi1"); return SRSRAN_ERROR; @@ -916,7 +800,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, q->G_csi2 = 0; // Generate PUSCH UCI/UL-SCH multiplexing - if (pusch_nr_gen_mux_uci(q, &q->uci_cfg) < SRSRAN_SUCCESS) { + if (pusch_nr_gen_mux_uci(q, &cfg->uci) < SRSRAN_SUCCESS) { ERROR("Error generating PUSCH mux tables"); return SRSRAN_ERROR; } @@ -929,16 +813,15 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, // EVM if (q->evm_buffer != NULL) { - res->evm[tb->cw_idx] = - srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits); + res->evm[tb->cw_idx] = srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, nof_bits); } // Descrambling - srsran_sequence_apply_c(llr, llr, tb->nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx)); + srsran_sequence_apply_c(llr, llr, nof_bits, pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx)); if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) { DEBUG("b="); - srsran_vec_fprint_bs(stdout, llr, tb->nof_bits); + srsran_vec_fprint_bs(stdout, llr, nof_bits); } // Demultiplex UCI only if necessary @@ -948,7 +831,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, for (uint32_t i = 0; i < q->G_ulsch; i++) { g_ulsch[i] = -llr[q->pos_ulsch[i]]; } - for (uint32_t i = q->G_ulsch; i < tb->nof_bits; i++) { + for (uint32_t i = q->G_ulsch; i < nof_bits; i++) { g_ulsch[i] = 0; } @@ -972,7 +855,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, // Decode HARQ-ACK if (q->G_ack) { - if (srsran_uci_nr_decode_pusch_ack(&q->uci, &q->uci_cfg, g_ack, &res->uci)) { + if (srsran_uci_nr_decode_pusch_ack(&q->uci, &cfg->uci, g_ack, &res->uci)) { ERROR("Error in UCI decoding"); return SRSRAN_ERROR; } @@ -980,7 +863,7 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, // Decode CSI part 1 if (q->G_csi1) { - if (srsran_uci_nr_decode_pusch_csi1(&q->uci, &q->uci_cfg, g_csi1, &res->uci)) { + if (srsran_uci_nr_decode_pusch_csi1(&q->uci, &cfg->uci, g_csi1, &res->uci)) { ERROR("Error in UCI decoding"); return SRSRAN_ERROR; } @@ -992,13 +875,13 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q, // Change LLR pointer llr = g_ulsch; } else { - for (uint32_t i = 0; i < tb->nof_bits; i++) { + for (uint32_t i = 0; i < nof_bits; i++) { llr[i] *= -1; } } // Decode Ul-SCH - if (tb->nof_bits != 0) { + if (nof_bits != 0) { if (srsran_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, &res->tb[tb->cw_idx]) < SRSRAN_SUCCESS) { ERROR("Error in SCH decoding"); return SRSRAN_ERROR; @@ -1037,12 +920,6 @@ int srsran_pusch_nr_decode(srsran_pusch_nr_t* q, return SRSRAN_ERROR; } - // Fill UCI configuration for PUSCH configuration - if (pusch_nr_fill_uci_cfg(q, cfg) < SRSRAN_SUCCESS) { - ERROR("Error filling UCI configuration for PUSCH"); - return SRSRAN_ERROR; - } - uint32_t nof_cw = 0; for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { nof_cw += grant->tb[tb].enabled ? 1 : 0; diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index fd3ce41c0..e5f2cdae0 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -16,6 +16,7 @@ #include "srsran/phy/phch/pdsch_nr.h" #include "srsran/phy/phch/ra_dl_nr.h" #include "srsran/phy/phch/ra_ul_nr.h" +#include "srsran/phy/phch/uci_nr.h" #include "srsran/phy/utils/debug.h" typedef struct { @@ -814,6 +815,10 @@ int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrier, static float ra_ul_beta_offset_ack_semistatic(const srsran_beta_offsets_t* beta_offsets, const srsran_uci_cfg_nr_t* uci_cfg) { + if (isnormal(beta_offsets->fix_ack)) { + return beta_offsets->fix_ack; + } + // Select Beta Offset index from the number of HARQ-ACK bits uint32_t beta_offset_index = beta_offsets->ack_index1; if (uci_cfg->o_ack > 11) { @@ -843,6 +848,11 @@ static float ra_ul_beta_offset_csi_semistatic(const srsran_beta_offsets_t* beta_ const srsran_uci_cfg_nr_t* uci_cfg, bool part2) { + float fix_beta_offset = part2 ? beta_offsets->fix_csi2 : beta_offsets->fix_csi1; + if (isnormal(fix_beta_offset)) { + return fix_beta_offset; + } + // Calculate number of CSI bits; CSI part 2 is not supported. uint32_t O_csi = part2 ? 0 : srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi); @@ -865,35 +875,162 @@ static float ra_ul_beta_offset_csi_semistatic(const srsran_beta_offsets_t* beta_ return ra_nr_beta_offset_csi_table[beta_offset_index]; } -int srsran_ra_ul_set_grant_uci_nr(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, +int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carrier, + const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, const srsran_uci_cfg_nr_t* uci_cfg, srsran_sch_cfg_nr_t* pusch_cfg) { + if (pusch_cfg->grant.nof_prb == 0) { + ERROR("Invalid number of PRB (%d)", pusch_cfg->grant.nof_prb); + return SRSRAN_ERROR; + } + + // Initially, copy all fields + pusch_cfg->uci = *uci_cfg; + + // Reset UCI PUSCH configuration + SRSRAN_MEM_ZERO(&pusch_cfg->uci.pusch, srsran_uci_nr_pusch_cfg_t, 1); + + // Get DMRS symbol indexes + uint32_t nof_dmrs_l = 0; + uint32_t dmrs_l[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {}; + int n = srsran_dmrs_sch_get_symbols_idx(&pusch_cfg->dmrs, &pusch_cfg->grant, dmrs_l); + if (n < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + nof_dmrs_l = (uint32_t)n; + + // Find OFDM symbol index of the first OFDM symbol after the first set of consecutive OFDM symbol(s) carrying DMRS + // Starts at first OFDM symbol carrying DMRS + for (uint32_t l = dmrs_l[0], dmrs_l_idx = 0; l < pusch_cfg->grant.S + pusch_cfg->grant.L; l++) { + // Check if it is not carrying DMRS... + if (l != dmrs_l[dmrs_l_idx]) { + // Set value and stop iterating + pusch_cfg->uci.pusch.l0 = l; + break; + } + + // Move to the next DMRS OFDM symbol index + if (dmrs_l_idx < nof_dmrs_l) { + dmrs_l_idx++; + } + } + + // Find OFDM symbol index of the first OFDM symbol that does not carry DMRS + // Starts at first OFDM symbol of the PUSCH transmission + for (uint32_t l = pusch_cfg->grant.S, dmrs_l_idx = 0; l < pusch_cfg->grant.S + pusch_cfg->grant.L; l++) { + // Check if it is not carrying DMRS... + if (l != dmrs_l[dmrs_l_idx]) { + pusch_cfg->uci.pusch.l1 = l; + break; + } + + // Move to the next DMRS OFDM symbol index + if (dmrs_l_idx < nof_dmrs_l) { + dmrs_l_idx++; + } + } + + // Number of DMRS per PRB + uint32_t n_sc_dmrs = SRSRAN_DMRS_SCH_SC(pusch_cfg->grant.nof_dmrs_cdm_groups_without_data, pusch_cfg->dmrs.type); + + // Set UCI RE number of candidates per OFDM symbol according to TS 38.312 6.3.2.4.2.1 + for (uint32_t l = 0, dmrs_l_idx = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) { + // Skip if OFDM symbol is outside of the PUSCH transmission + if (l < pusch_cfg->grant.S || l >= (pusch_cfg->grant.S + pusch_cfg->grant.L)) { + pusch_cfg->uci.pusch.M_pusch_sc[l] = 0; + pusch_cfg->uci.pusch.M_uci_sc[l] = 0; + continue; + } + + // OFDM symbol carries DMRS + if (l == dmrs_l[dmrs_l_idx]) { + // Calculate PUSCH RE candidates + pusch_cfg->uci.pusch.M_pusch_sc[l] = pusch_cfg->grant.nof_prb * (SRSRAN_NRE - n_sc_dmrs); + + // The Number of RE candidates for UCI are 0 + pusch_cfg->uci.pusch.M_uci_sc[l] = 0; + + // Advance DMRS symbol index + dmrs_l_idx++; + + // Skip to next symbol + continue; + } + + // Number of RE for Phase Tracking Reference Signals (PT-RS) + uint32_t M_ptrs_sc = 0; // Not implemented yet + + // Number of RE given by the grant + pusch_cfg->uci.pusch.M_pusch_sc[l] = pusch_cfg->grant.nof_prb * SRSRAN_NRE; + + // Calculate the number of UCI candidates + pusch_cfg->uci.pusch.M_uci_sc[l] = pusch_cfg->uci.pusch.M_pusch_sc[l] - M_ptrs_sc; + } + + // Generate SCH Transport block information + srsran_sch_nr_tb_info_t sch_tb_info = {}; + if (srsran_sch_nr_fill_tb_info(carrier, &pusch_cfg->sch_cfg, &pusch_cfg->grant.tb[0], &sch_tb_info) < + SRSRAN_SUCCESS) { + ERROR("Generating TB info"); + return SRSRAN_ERROR; + } + + // Calculate the sum of codeblock sizes + for (uint32_t i = 0; i < sch_tb_info.C; i++) { + // Accumulate codeblock size if mask is enabled + pusch_cfg->uci.pusch.K_sum += (sch_tb_info.mask[i]) ? sch_tb_info.Kr : 0; + } + + // Set other PUSCH parameters + pusch_cfg->uci.pusch.modulation = pusch_cfg->grant.tb[0].mod; + pusch_cfg->uci.pusch.nof_layers = pusch_cfg->grant.nof_layers; + pusch_cfg->uci.pusch.R = (float)pusch_cfg->grant.tb[0].R; + pusch_cfg->uci.pusch.nof_re = pusch_cfg->grant.tb[0].nof_re; + // Select beta offsets - pusch_cfg->beta_harq_ack_offset = ra_ul_beta_offset_ack_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg); - if (!isnormal(pusch_cfg->beta_harq_ack_offset)) { + pusch_cfg->uci.pusch.beta_harq_ack_offset = ra_ul_beta_offset_ack_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg); + if (!isnormal(pusch_cfg->uci.pusch.beta_harq_ack_offset)) { return SRSRAN_ERROR; } - pusch_cfg->beta_csi_part1_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, false); - if (!isnormal(pusch_cfg->beta_csi_part1_offset)) { + pusch_cfg->uci.pusch.beta_csi1_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, false); + if (!isnormal(pusch_cfg->uci.pusch.beta_csi1_offset)) { return SRSRAN_ERROR; } - pusch_cfg->beta_csi_part2_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, true); - if (!isnormal(pusch_cfg->beta_csi_part2_offset)) { + pusch_cfg->uci.pusch.beta_csi2_offset = ra_ul_beta_offset_csi_semistatic(&pusch_hl_cfg->beta_offsets, uci_cfg, true); + if (!isnormal(pusch_cfg->uci.pusch.beta_csi2_offset)) { return SRSRAN_ERROR; } - // pusch_cfg->beta_csi_part2_offset = pusch_hl_cfg->beta_offset_csi2; - pusch_cfg->scaling = pusch_hl_cfg->scaling; - if (!isnormal(pusch_cfg->scaling)) { - ERROR("Invalid Scaling (%f)", pusch_cfg->scaling); + pusch_cfg->uci.pusch.alpha = pusch_hl_cfg->scaling; + if (!isnormal(pusch_cfg->uci.pusch.alpha)) { + ERROR("Invalid Scaling (%f)", pusch_cfg->uci.pusch.alpha); return SRSRAN_ERROR; } - // Copy UCI configuration - pusch_cfg->uci = *uci_cfg; + // Calculate number of UCI encoded bits + int Gack = 0; + if (pusch_cfg->uci.o_ack > 2) { + Gack = srsran_uci_nr_pusch_ack_nof_bits(&pusch_cfg->uci.pusch, pusch_cfg->uci.o_ack); + if (Gack < SRSRAN_SUCCESS) { + ERROR("Error calculating Qdack"); + return SRSRAN_ERROR; + } + } + int Gcsi1 = srsran_uci_nr_pusch_csi1_nof_bits(&pusch_cfg->uci); + if (Gcsi1 < SRSRAN_SUCCESS) { + ERROR("Error calculating Qdack"); + return SRSRAN_ERROR; + } + int Gcsi2 = 0; // NOT supported + + // Update Number of TB encoded bits + for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { + pusch_cfg->grant.tb[i].nof_bits = + pusch_cfg->grant.tb[i].nof_re * srsran_mod_bits_x_symbol(pusch_cfg->grant.tb[i].mod) - Gack - Gcsi1 - Gcsi2; + } return SRSRAN_SUCCESS; } diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index 1e91e9e52..0c00392e6 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -187,9 +187,11 @@ int main(int argc, char** argv) mcs_end = SRSRAN_MIN(mcs + 1, mcs_end); } - pusch_cfg.scaling = 0.5f; - pusch_cfg.beta_harq_ack_offset = 2.0f; - pusch_cfg.beta_csi_part1_offset = 2.0f; + srsran_sch_hl_cfg_nr_t sch_hl_cfg = {}; + sch_hl_cfg.scaling = 1.0f; + sch_hl_cfg.beta_offsets.fix_ack = 12.625f; + sch_hl_cfg.beta_offsets.fix_csi1 = 2.25f; + sch_hl_cfg.beta_offsets.fix_csi2 = 2.25f; if (srsran_chest_dl_res_init(&chest, carrier.nof_prb) < SRSRAN_SUCCESS) { ERROR("Initiating chest"); @@ -245,6 +247,11 @@ int main(int argc, char** argv) data_rx.uci.csi[0].none = csi_report_rx; } + if (srsran_ra_ul_set_grant_uci_nr(&carrier, &sch_hl_cfg, &pusch_cfg.uci, &pusch_cfg) < SRSRAN_SUCCESS) { + ERROR("Setting UCI"); + goto clean_exit; + } + if (srsran_pusch_nr_encode(&pusch_tx, &pusch_cfg, &pusch_cfg.grant, &data_tx, sf_symbols) < SRSRAN_SUCCESS) { ERROR("Error encoding"); goto clean_exit; @@ -345,7 +352,7 @@ int main(int argc, char** argv) srsran_pusch_nr_rx_info(&pusch_rx, &pusch_cfg, &pusch_cfg.grant, &data_rx, str, (uint32_t)sizeof(str)); char str_extra[2048]; - srsran_phch_cfg_nr_info(&pusch_cfg, str_extra, (uint32_t)sizeof(str_extra)); + srsran_sch_cfg_nr_info(&pusch_cfg, str_extra, (uint32_t)sizeof(str_extra)); INFO("PUSCH: %s\n%s", str, str_extra); } diff --git a/lib/src/phy/phch/uci_nr.c b/lib/src/phy/phch/uci_nr.c index b20b65bf1..6f862cf8f 100644 --- a/lib/src/phy/phch/uci_nr.c +++ b/lib/src/phy/phch/uci_nr.c @@ -383,16 +383,18 @@ static int uci_nr_decode_1_bit(srsran_uci_nr_t* q, } // Correlate LLR - float corr = 0.0f; - float pwr = 0.0f; + float corr = 0.0f; + float pwr = 0.0f; + uint32_t count = 0; for (uint32_t i = 0; i < E; i += Qm) { float t = (float)llr[i]; corr += t; pwr += t * t; + count++; } // Normalise correlation - float norm_corr = Qm * corr / (E * sqrtf(pwr)); + float norm_corr = fabsf(corr) / sqrtf(pwr * count); // Take decoded decision with threshold *decoded_ok = (norm_corr > q->one_bit_threshold); diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 35871f720..96f377979 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -453,7 +453,7 @@ int main(int argc, char** argv) srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str, (uint32_t)sizeof(str)); char str_extra[2048]; - srsran_phch_cfg_nr_info(&pdsch_cfg, str_extra, (uint32_t)sizeof(str_extra)); + srsran_sch_cfg_nr_info(&pdsch_cfg, str_extra, (uint32_t)sizeof(str_extra)); INFO("PDSCH: %s\n%s", str, str_extra); } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 7097127d0..3a899cb74 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -276,7 +276,7 @@ bool cc_worker::work_dl() if (logger.debug.enabled()) { str_extra_t str_extra; - srsran_phch_cfg_nr_info(&pdsch_cfg, str_extra.data(), (uint32_t)str_extra.size()); + 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, %s\n%s", @@ -392,7 +392,7 @@ bool cc_worker::work_ul() } // Set UCI configuration following procedures - srsran_ra_ul_set_grant_uci_nr(&phy->cfg.pusch, &uci_data.cfg, &pusch_cfg); + srsran_ra_ul_set_grant_uci_nr(&phy->carrier, &phy->cfg.pusch, &uci_data.cfg, &pusch_cfg); // Assigning MAC provided values to PUSCH config structs pusch_cfg.grant.tb[0].softbuffer.tx = ul_action.tb.softbuffer; @@ -415,7 +415,7 @@ bool cc_worker::work_ul() if (logger.debug.enabled()) { str_extra_t str_extra; - srsran_phch_cfg_nr_info(&pusch_cfg, str_extra.data(), (uint32_t)str_extra.size()); + srsran_sch_cfg_nr_info(&pusch_cfg, str_extra.data(), (uint32_t)str_extra.size()); logger.info(ul_action.tb.payload->msg, pusch_cfg.grant.tb[0].tbs / 8, "PUSCH: cc=%d %s tti_tx=%d\n%s", From 8ffced7e885e9c37aaefd51f2c2191c30252cc86 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Apr 2021 19:21:54 +0200 Subject: [PATCH 17/46] NR PHY logging minor corrections --- lib/include/srsran/phy/phch/sch_cfg_nr.h | 1 - lib/src/phy/phch/pdsch_nr.c | 2 +- lib/src/phy/phch/phch_cfg_nr.c | 3 +-- lib/src/phy/phch/ra_nr.c | 1 - srsue/src/phy/nr/cc_worker.cc | 19 ++++++++++++++----- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/include/srsran/phy/phch/sch_cfg_nr.h b/lib/include/srsran/phy/phch/sch_cfg_nr.h index 9a3c580f8..8c4d8159c 100644 --- a/lib/include/srsran/phy/phch/sch_cfg_nr.h +++ b/lib/include/srsran/phy/phch/sch_cfg_nr.h @@ -31,7 +31,6 @@ typedef struct SRSRAN_API { double R; ///< Target LDPC rate int rv; ///< Redundancy version int ndi; ///< New Data Indicator - int pid; ///< HARQ Process ID uint32_t nof_re; ///< Number of available resource elements to transmit ULSCH (data) and UCI (control) uint32_t nof_bits; ///< Number of available bits to send ULSCH uint32_t cw_idx; diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 924bfda4f..aac6d28e6 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -617,7 +617,7 @@ uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q, len += pdsch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len); if (q->meas_time_en) { - len = srsran_print_check(str, str_len, len, " t=%d us", q->meas_time_us); + len = srsran_print_check(str, str_len, len, " t=%dus ", q->meas_time_us); } return len; diff --git a/lib/src/phy/phch/phch_cfg_nr.c b/lib/src/phy/phch/phch_cfg_nr.c index c4b427b3a..246367aa1 100644 --- a/lib/src/phy/phch/phch_cfg_nr.c +++ b/lib/src/phy/phch/phch_cfg_nr.c @@ -149,7 +149,6 @@ static uint32_t phch_cfg_tb_to_str(const srsran_sch_tb_t* tb, char* str, uint32_ len = srsran_print_check(str, str_len, len, " R=%.3f\n", tb->R); len = srsran_print_check(str, str_len, len, " rv=%d\n", tb->rv); len = srsran_print_check(str, str_len, len, " ndi=%d\n", tb->ndi); - len = srsran_print_check(str, str_len, len, " pid=%d\n", tb->pid); len = srsran_print_check(str, str_len, len, " nof_re=%d\n", tb->nof_re); len = srsran_print_check(str, str_len, len, " nof_bits=%d\n", tb->nof_bits); @@ -208,7 +207,7 @@ static uint32_t phch_cfg_rvd_to_str(const srsran_re_pattern_list_t* pattern_list len = srsran_print_check(str, str_len, len, " Reserved:\n"); for (uint32_t i = 0; i < pattern_list->count; i++) { - len = srsran_print_check(str, str_len, len, " %d=", i); + len = srsran_print_check(str, str_len, len, " %d: ", i); len += srsran_re_pattern_info(&pattern_list->data[i], &str[len], str_len - len); len = srsran_print_check(str, str_len, len, "\n"); } diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index e5f2cdae0..4fa39b0e6 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -791,7 +791,6 @@ int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrier, pusch_grant->tb[0].rv = dci_ul->rv; pusch_grant->tb[0].mcs = dci_ul->mcs; pusch_grant->tb[0].ndi = dci_ul->ndi; - pusch_grant->tb[0].pid = dci_ul->pid; // 5.1.6.2 DM-RS reception procedure if (ra_ul_dmrs(pusch_hl_cfg, pusch_grant, pusch_cfg) < SRSRAN_SUCCESS) { diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 3a899cb74..9b8935ebb 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -274,17 +274,24 @@ bool cc_worker::work_dl() str_info_t str; srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str.data(), (uint32_t)str.size()); - if (logger.debug.enabled()) { + if (logger.info.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, %s\n%s", + "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, %s", cc_idx, str.data()); + logger.info(pdsch_res.tb[0].payload, + pdsch_cfg.grant.tb[0].tbs / 8, + "PDSCH: cc=%d pid=%d %s", + pid, + cc_idx, + pid, + str.data()); } } @@ -418,16 +425,18 @@ bool cc_worker::work_ul() srsran_sch_cfg_nr_info(&pusch_cfg, str_extra.data(), (uint32_t)str_extra.size()); logger.info(ul_action.tb.payload->msg, pusch_cfg.grant.tb[0].tbs / 8, - "PUSCH: cc=%d %s tti_tx=%d\n%s", + "PUSCH: cc=%d pid=%d %s tti_tx=%d\n%s", cc_idx, + pid, str.data(), ul_slot_cfg.idx, str_extra.data()); } else { logger.info(ul_action.tb.payload->msg, pusch_cfg.grant.tb[0].tbs / 8, - "PUSCH: cc=%d %s tti_tx=%d", + "PUSCH: cc=%d pid=%d %s tti_tx=%d", cc_idx, + pid, str.data(), ul_slot_cfg.idx); } From ed0929b46d32384606d95cdae0ce400dfb168bf7 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Apr 2021 19:24:35 +0200 Subject: [PATCH 18/46] NR PHY logging minor corrections --- lib/src/phy/phch/pdsch_nr.c | 2 +- lib/src/phy/phch/pusch_nr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index aac6d28e6..943dce860 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -617,7 +617,7 @@ uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q, len += pdsch_nr_grant_info(q, cfg, grant, res, &str[len], str_len - len); if (q->meas_time_en) { - len = srsran_print_check(str, str_len, len, " t=%dus ", q->meas_time_us); + len = srsran_print_check(str, str_len, len, "t_us=%d ", q->meas_time_us); } return len; diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 908e38273..942137555 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -1038,7 +1038,7 @@ uint32_t srsran_pusch_nr_rx_info(const srsran_pusch_nr_t* q, } if (q->meas_time_en) { - len = srsran_print_check(str, str_len, len, " t=%d us", q->meas_time_us); + len = srsran_print_check(str, str_len, len, "t_us=%d ", q->meas_time_us); } return len; From 53b38fccf9ed7d6dc900a5a6b10714db4ea2d015 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 16 Apr 2021 19:43:22 +0200 Subject: [PATCH 19/46] Fix compile and other --- lib/src/phy/phch/ra_nr.c | 1 - srsue/src/phy/nr/cc_worker.cc | 11 ++--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 4fa39b0e6..19db16677 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -679,7 +679,6 @@ int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier, pdsch_grant->tb[0].rv = dci_dl->rv; pdsch_grant->tb[0].mcs = dci_dl->mcs; pdsch_grant->tb[0].ndi = dci_dl->ndi; - pdsch_grant->tb[0].pid = dci_dl->pid; // 5.1.4 PDSCH resource mapping if (ra_dl_resource_mapping(carrier, slot, pdsch_hl_cfg, pdsch_cfg) < SRSRAN_SUCCESS) { diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 9b8935ebb..06bbf8056 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -226,18 +226,11 @@ bool cc_worker::work_dl() 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)) { - // As HARQ processes are not implemented nor LDPC early-stop, retransmissions are disabled for performance reasons - if (pdsch_cfg.grant.tb[0].rv != 0) { - phy->set_pending_ack(dl_slot_cfg.idx, ack_resource, true); - logger.warning("PDSCH Retransmission with rv=%d not supported", pdsch_cfg.grant.tb[0].rv); - return true; - } - // 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 = pdsch_cfg.grant.tb[0].pid; + 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; @@ -274,7 +267,7 @@ bool cc_worker::work_dl() str_info_t str; srsran_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, &pdsch_res, str.data(), (uint32_t)str.size()); - if (logger.info.enabled()) { + 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, From 0df218ab9061220acb0177a08d027162af1bf96c Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sat, 17 Apr 2021 14:50:09 +0200 Subject: [PATCH 20/46] cc_worker: fix PDSCH log fmt::v7::format_error --- srsue/src/phy/nr/cc_worker.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 06bbf8056..164c7419e 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -281,7 +281,6 @@ bool cc_worker::work_dl() logger.info(pdsch_res.tb[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, "PDSCH: cc=%d pid=%d %s", - pid, cc_idx, pid, str.data()); From edd150b29ff27d7058e8d658a1b2695e509cec1d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sat, 17 Apr 2021 21:36:24 +0200 Subject: [PATCH 21/46] fix PID not being set when reading pending UL grant this should fix #2679 --- srsue/hdr/phy/nr/state.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index c1298d624..1129d8eb4 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -148,8 +148,9 @@ public: return false; } - // Load shared channel configuration + // Load shared channel configuration and PID pusch_cfg = pending_grant.sch_cfg; + pid = pending_grant.pid; // Reset entry pending_grant.enable = false; From 73d6b33920968569f949bbc0f5041280c89c345b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sun, 18 Apr 2021 15:27:19 +0200 Subject: [PATCH 22/46] {ul,dl}_harq_nr: reword log entries if HARQ PID isn't found --- srsue/src/stack/mac_nr/dl_harq_nr.cc | 4 ++-- srsue/src/stack/mac_nr/ul_harq_nr.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/srsue/src/stack/mac_nr/dl_harq_nr.cc b/srsue/src/stack/mac_nr/dl_harq_nr.cc index c0466aaea..14a99b9a6 100644 --- a/srsue/src/stack/mac_nr/dl_harq_nr.cc +++ b/srsue/src/stack/mac_nr/dl_harq_nr.cc @@ -77,7 +77,7 @@ void dl_harq_entity_nr::new_grant_dl(const mac_nr_grant_dl_t& grant, mac_interfa proc_ptr = &bcch_proc; } else { if (grant.pid >= cfg.nof_procs) { - logger.error("Invalid PID: %d", grant.pid); + logger.error("Grant for invalid HARQ PID=%d", grant.pid); return; } proc_ptr = harq_procs.at(grant.pid).get(); @@ -105,7 +105,7 @@ void dl_harq_entity_nr::tb_decoded(const mac_nr_grant_dl_t& grant, mac_interface bcch_proc.tb_decoded(grant, std::move(result)); } else { if (grant.pid >= cfg.nof_procs) { - logger.error("Invalid PID: %d", grant.pid); + logger.error("Decoded TB for invalid HARQ PID=%d", grant.pid); return; } harq_procs.at(grant.pid)->tb_decoded(grant, std::move(result)); diff --git a/srsue/src/stack/mac_nr/ul_harq_nr.cc b/srsue/src/stack/mac_nr/ul_harq_nr.cc index 8a20da657..fd3f090bb 100644 --- a/srsue/src/stack/mac_nr/ul_harq_nr.cc +++ b/srsue/src/stack/mac_nr/ul_harq_nr.cc @@ -60,7 +60,7 @@ void ul_harq_entity_nr::new_grant_ul(const mac_interface_phy_nr::mac_nr_grant_ul mac_interface_phy_nr::tb_action_ul_t* action) { if (grant.pid >= harq_procs.size()) { - logger.error("Invalid PID: %d", grant.pid); + logger.error("UL grant for invalid HARQ PID=%d", grant.pid); return; } @@ -99,7 +99,7 @@ void ul_harq_entity_nr::new_grant_ul(const mac_interface_phy_nr::mac_nr_grant_ul int ul_harq_entity_nr::get_current_tbs(uint32_t pid) { if (pid >= harq_procs.size()) { - logger.error("Invalid PID: %d", pid); + logger.error("Invalid HARQ PID=%d", pid); return 0; } return harq_procs.at(pid).get_current_tbs(); From 936bebcfd70dd671db1568e035fb7bc48d0e8989 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sun, 18 Apr 2021 15:27:56 +0200 Subject: [PATCH 23/46] rrc_nr_utils: fix extraction of HARQ processes from ASN1 reconfig --- lib/src/asn1/rrc_nr_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 0692cffcd..3c6e42fa6 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -70,7 +70,7 @@ bool make_mac_dl_harq_cfg_nr_t(const pdsch_serving_cell_cfg_s& asn1_type, dl_har { dl_harq_cfg_nr_t dl_harq_cfg_nr; if (asn1_type.nrof_harq_processes_for_pdsch_present) { - dl_harq_cfg_nr.nof_procs = asn1_type.nrof_harq_processes_for_pdsch; + dl_harq_cfg_nr.nof_procs = asn1_type.nrof_harq_processes_for_pdsch.to_number(); } else { asn1::log_warning("Option nrof_harq_processes_for_pdsch not present"); return false; From 9009c3439c4cf27dbd22e7fd029580f60a133dff Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 19 Apr 2021 10:44:59 +0200 Subject: [PATCH 24/46] rlc_um_nr: convert log entries to info if they are expected dropping a PDU and not being able to build a PDU if the grant is too small is expected and should therefore not cause a log warning. --- lib/src/upper/rlc_um_nr.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/src/upper/rlc_um_nr.cc b/lib/src/upper/rlc_um_nr.cc index 03f7bf4da..b02060334 100644 --- a/lib/src/upper/rlc_um_nr.cc +++ b/lib/src/upper/rlc_um_nr.cc @@ -156,10 +156,10 @@ int rlc_um_nr::rlc_um_nr_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t* p // Calculate actual header length uint32_t head_len = rlc_um_nr_packed_length(header); if (pdu_space <= head_len + 1) { - logger.warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header", - rb_name.c_str(), - nof_bytes, - head_len); + logger.info("%s Cannot build a PDU - %d bytes available, %d bytes required for header", + rb_name.c_str(), + nof_bytes, + head_len); return 0; } @@ -287,7 +287,7 @@ void rlc_um_nr::rlc_um_nr_rx::timer_expired(uint32_t timeout_id) if (reassembly_timer.id() == timeout_id) { logger.info("%s reassembly timeout expiry - updating RX_Next_Reassembly and reassembling", rb_name.c_str()); - logger.warning("Lost PDU SN: %d", RX_Next_Reassembly); + logger.info("Lost PDU SN=%d", RX_Next_Reassembly); metrics.num_lost_pdus++; if (rx_sdu != nullptr) { @@ -341,8 +341,8 @@ unique_byte_buffer_t rlc_um_nr::rlc_um_nr_rx::rlc_um_nr_strip_pdu_header(const r const uint32_t nof_bytes) { unique_byte_buffer_t sdu = make_byte_buffer(); - if (!sdu) { - logger.error("Discarting packet: no space in buffer pool"); + if (sdu == nullptr) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); return nullptr; } memcpy(sdu->msg, payload, nof_bytes); From 87f9b2babc0e99263c3b51a49bb04152ac5b354e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 19 Apr 2021 10:46:09 +0200 Subject: [PATCH 25/46] mac_nr: turn off warning for non-implemented features they cause RFCI to fail, features are known to be missing. --- srsue/src/stack/mac_nr/mac_nr.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srsue/src/stack/mac_nr/mac_nr.cc b/srsue/src/stack/mac_nr/mac_nr.cc index b360ee679..6ca01ecb3 100644 --- a/srsue/src/stack/mac_nr/mac_nr.cc +++ b/srsue/src/stack/mac_nr/mac_nr.cc @@ -388,19 +388,19 @@ int mac_nr::setup_lcid(const srsran::logical_channel_config_t& config) int mac_nr::add_tag_config(const srsran::tag_cfg_nr_t& tag_cfg) { - logger.warning("Add tag config not supported yet"); + logger.info("Add tag config not supported yet"); return SRSRAN_SUCCESS; } int mac_nr::remove_tag_config(const uint32_t tag_id) { - logger.warning("Remove tag config not supported yet"); + logger.info("Remove tag config not supported yet"); return SRSRAN_SUCCESS; } int mac_nr::set_config(const srsran::phr_cfg_nr_t& phr_cfg) { - logger.warning("Add phr config not supported yet"); + logger.info("Add phr config not supported yet"); return SRSRAN_SUCCESS; } From f42d4dbc28da21170d09e28cddc2a7a87736cca8 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 16 Apr 2021 14:22:26 +0200 Subject: [PATCH 26/46] Refactored carrier config --- lib/include/srsran/phy/common/phy_common_nr.h | 23 +++++++++++++++---- lib/src/phy/ch_estimation/csi_rs.c | 2 +- lib/src/phy/ch_estimation/dmrs_pdcch.c | 12 +++++----- lib/src/phy/ch_estimation/dmrs_pucch.c | 8 +++---- lib/src/phy/ch_estimation/dmrs_sch.c | 14 +++++------ lib/src/phy/ch_estimation/test/csi_rs_test.c | 18 ++++++++------- .../phy/ch_estimation/test/dmrs_pdcch_test.c | 6 ++--- .../phy/ch_estimation/test/dmrs_pdsch_test.c | 19 ++++++++------- lib/src/phy/phch/pdcch_nr.c | 2 +- lib/src/phy/phch/pdsch_nr.c | 2 +- lib/src/phy/phch/pucch_nr.c | 10 ++++---- lib/src/phy/phch/pusch_nr.c | 2 +- lib/src/phy/phch/test/pdcch_nr_test.c | 14 ++++++----- lib/src/phy/phch/test/pdsch_nr_test.c | 13 +++++++---- lib/src/phy/phch/test/pucch_nr_test.c | 22 ++++++++++-------- lib/src/phy/phch/test/pusch_nr_test.c | 14 ++++++----- lib/src/phy/phch/test/sch_nr_test.c | 12 ++++++---- lib/src/phy/ue/ue_dl_nr.c | 2 +- lib/test/phy/phy_dl_nr_test.c | 17 +++++++------- srsenb/src/enb_cfg_parser.cc | 2 +- srsue/hdr/phy/nr/state.h | 4 ++-- srsue/src/phy/nr/sf_worker.cc | 2 +- srsue/src/phy/nr/worker_pool.cc | 6 ++--- 23 files changed, 129 insertions(+), 97 deletions(-) diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 46f7b0476..5acd3fafe 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -260,14 +260,29 @@ typedef enum SRSRAN_API { srsran_resource_alloc_dynamic, } srsran_resource_alloc_t; +/** + * @brief Subcarrier spacing 15 or 30 kHz <6GHz and 60 or 120 kHz >6GHz + * @remark Described in TS 38.331 V15.10.0 subcarrier spacing + */ + +typedef enum SRSRAN_API { + srsran_subcarrier_spacing_15kHz = 0, + srsran_subcarrier_spacing_30kHz, + srsran_subcarrier_spacing_60kHz, + srsran_subcarrier_spacing_120kHz, + srsran_subcarrier_spacing_240kHz, +} srsran_subcarrier_spacing_t; + /** * @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP) */ typedef struct SRSRAN_API { - uint32_t id; - uint32_t numerology; - uint32_t nof_prb; - uint32_t start; + uint32_t pci; + uint32_t absolute_frequency_ssb; + uint32_t absolute_frequency_point_a; + srsran_subcarrier_spacing_t scs; + uint32_t nof_prb; + uint32_t start; uint32_t max_mimo_layers; ///< @brief DL: Indicates the maximum number of MIMO layers to be used for PDSCH in all BWPs ///< of this serving cell. (see TS 38.212 [17], clause 5.4.2.1). UL: Indicates the maximum ///< MIMO layer to be used for PUSCH in all BWPs of the normal UL of this serving cell (see diff --git a/lib/src/phy/ch_estimation/csi_rs.c b/lib/src/phy/ch_estimation/csi_rs.c index 6a8f1c9e4..767c6a799 100644 --- a/lib/src/phy/ch_estimation/csi_rs.c +++ b/lib/src/phy/ch_estimation/csi_rs.c @@ -174,7 +174,7 @@ static uint32_t csi_rs_cinit(const srsran_carrier_nr_t* carrier, const srsran_csi_rs_nzp_resource_t* resource, uint32_t l) { - uint32_t n = SRSRAN_SLOT_NR_MOD(carrier->numerology, slot_cfg->idx); + uint32_t n = SRSRAN_SLOT_NR_MOD(carrier->scs, slot_cfg->idx); uint32_t n_id = resource->scrambling_id; return ((SRSRAN_NSYMB_PER_SLOT_NR * n + l + 1UL) * (2UL * n_id) << 10UL) + n_id; diff --git a/lib/src/phy/ch_estimation/dmrs_pdcch.c b/lib/src/phy/ch_estimation/dmrs_pdcch.c index bc6b9565e..914992fdc 100644 --- a/lib/src/phy/ch_estimation/dmrs_pdcch.c +++ b/lib/src/phy/ch_estimation/dmrs_pdcch.c @@ -154,13 +154,13 @@ int srsran_dmrs_pdcch_put(const srsran_carrier_nr_t* carrier, } // Use cell id if the DMR scrambling id is not provided by higher layers - uint32_t n_id = carrier->id; + uint32_t n_id = carrier->pci; if (coreset->dmrs_scrambling_id_present) { n_id = coreset->dmrs_scrambling_id; } // Bound slot index - uint32_t slot_idx = SRSRAN_SLOT_NR_MOD(carrier->numerology, slot_cfg->idx); + uint32_t slot_idx = SRSRAN_SLOT_NR_MOD(carrier->scs, slot_cfg->idx); for (uint32_t l = 0; l < coreset->duration; l++) { // Get Cin @@ -350,13 +350,13 @@ int srsran_dmrs_pdcch_estimate(srsran_dmrs_pdcch_estimator_t* q, } // Use cell id if the DMR scrambling id is not provided by higher layers - uint32_t n_id = q->carrier.id; + uint32_t n_id = q->carrier.pci; if (q->coreset.dmrs_scrambling_id_present) { n_id = q->coreset.dmrs_scrambling_id; } // Bound slot index - uint32_t slot_idx = SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot_cfg->idx); + uint32_t slot_idx = SRSRAN_SLOT_NR_MOD(q->carrier.scs, slot_cfg->idx); // Extract pilots for (uint32_t l = 0; l < q->coreset.duration; l++) { @@ -476,7 +476,7 @@ int srsran_dmrs_pdcch_get_measure(const srsran_dmrs_pdcch_estimator_t* q, // Measure CFO only from the second and third symbols if (l != 0) { // Calculates the time between the previous and the current symbol - float Ts = srsran_symbol_distance_s(l - 1, l, q->carrier.numerology); + float Ts = srsran_symbol_distance_s(l - 1, l, q->carrier.scs); if (isnormal(Ts)) { // Compute phase difference between symbols and convert to Hz cfo_avg_Hz += cargf(corr[l] * conjf(corr[l - 1])) / (2.0f * (float)M_PI * Ts); @@ -495,7 +495,7 @@ int srsran_dmrs_pdcch_get_measure(const srsran_dmrs_pdcch_estimator_t* q, measure->cfo_hz = NAN; } measure->sync_error_us = - sync_err_avg / (4.0e-6f * (float)q->coreset.duration * SRSRAN_SUBC_SPACING_NR(q->carrier.numerology)); + sync_err_avg / (4.0e-6f * (float)q->coreset.duration * SRSRAN_SUBC_SPACING_NR(q->carrier.scs)); // Convert power measurements into logarithmic scale measure->rsrp_dBfs = srsran_convert_power_to_dB(measure->rsrp); diff --git a/lib/src/phy/ch_estimation/dmrs_pucch.c b/lib/src/phy/ch_estimation/dmrs_pucch.c index fd76e7a44..2d036e9f7 100644 --- a/lib/src/phy/ch_estimation/dmrs_pucch.c +++ b/lib/src/phy/ch_estimation/dmrs_pucch.c @@ -247,7 +247,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q, // Compute Time Aligment error in microseconds if (isnormal(ta_err)) { - ta_err /= 15e3f * (float)(1U << carrier->numerology); // Convert from normalized frequency to seconds + ta_err /= 15e3f * (float)(1U << carrier->scs); // Convert from normalized frequency to seconds ta_err *= 1e6f; // Convert to micro-seconds ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second res->ta_us = ta_err; @@ -289,8 +289,8 @@ static uint32_t dmrs_pucch_format2_cinit(const srsran_carrier_nr_t* car const srsran_slot_cfg_t* slot, uint32_t l) { - uint64_t n = SRSRAN_SLOT_NR_MOD(carrier->numerology, slot->idx); - uint64_t n_id = (cfg->scrambling_id_present) ? cfg->scambling_id : carrier->id; + uint64_t n = SRSRAN_SLOT_NR_MOD(carrier->scs, slot->idx); + uint64_t n_id = (cfg->scrambling_id_present) ? cfg->scambling_id : carrier->pci; return SRSRAN_SEQUENCE_MOD((((SRSRAN_NSYMB_PER_SLOT_NR * n + l + 1UL) * (2UL * n_id + 1UL)) << 17UL) + 2UL * n_id); } @@ -409,7 +409,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q, // Compute Time Aligment error in microseconds if (isnormal(ta_err)) { - ta_err /= 15e3f * (float)(1U << carrier->numerology) * 3; // Convert from normalized frequency to seconds + ta_err /= 15e3f * (float)(1U << carrier->scs) * 3; // Convert from normalized frequency to seconds ta_err *= 1e6f; // Convert to micro-seconds ta_err = roundf(ta_err * 10.0f) / 10.0f; // Round to one tenth of micro-second res->ta_us = ta_err; diff --git a/lib/src/phy/ch_estimation/dmrs_sch.c b/lib/src/phy/ch_estimation/dmrs_sch.c index 8292a3958..5153c8bf6 100644 --- a/lib/src/phy/ch_estimation/dmrs_sch.c +++ b/lib/src/phy/ch_estimation/dmrs_sch.c @@ -503,7 +503,7 @@ static uint32_t srsran_dmrs_sch_seed(const srsran_carrier_nr_t* carrier, const srsran_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs; // Calculate scrambling IDs - uint32_t n_id = carrier->id; + uint32_t n_id = carrier->pci; uint32_t n_scid = (grant->n_scid) ? 1 : 0; if (!grant->n_scid && dmrs_cfg->scrambling_id0_present) { // n_scid = 0 and ID0 present @@ -640,7 +640,7 @@ int srsran_dmrs_sch_put_sf(srsran_dmrs_sch_t* q, // Iterate symbols for (uint32_t i = 0; i < nof_symbols; i++) { uint32_t l = symbols[i]; // Symbol index inside the slot - uint32_t slot_idx = SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot_cfg->idx); // Slot index in the frame + uint32_t slot_idx = SRSRAN_SLOT_NR_MOD(q->carrier.scs, slot_cfg->idx); // Slot index in the frame uint32_t cinit = srsran_dmrs_sch_seed(&q->carrier, pdsch_cfg, grant, slot_idx, l); srsran_dmrs_sch_put_symbol(q, pdsch_cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l]); @@ -771,7 +771,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q, uint32_t l = symbols[i]; // Symbol index inside the slot uint32_t cinit = - srsran_dmrs_sch_seed(&q->carrier, cfg, grant, SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot->idx), l); + srsran_dmrs_sch_seed(&q->carrier, cfg, grant, SRSRAN_SLOT_NR_MOD(q->carrier.scs, slot->idx), l); nof_pilots_x_symbol = srsran_dmrs_sch_get_symbol( q, cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l], &q->pilot_estimates[nof_pilots_x_symbol * i]); @@ -789,7 +789,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q, sync_err += srsran_vec_estimate_frequency(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol); } sync_err /= (float)nof_symbols; - chest_res->sync_error = sync_err / (dmrs_stride * SRSRAN_SUBC_SPACING_NR(q->carrier.numerology)); + chest_res->sync_error = sync_err / (dmrs_stride * SRSRAN_SUBC_SPACING_NR(q->carrier.scs)); #if DMRS_SCH_SYNC_PRECOMPENSATE // Pre-compensate synchronization error @@ -828,7 +828,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q, // Measure CFO if more than one symbol is used float cfo_avg = 0.0; for (uint32_t i = 0; i < nof_symbols - 1; i++) { - float time_diff = srsran_symbol_distance_s(symbols[i], symbols[i + 1], q->carrier.numerology); + float time_diff = srsran_symbol_distance_s(symbols[i], symbols[i + 1], q->carrier.scs); float phase_diff = cargf(corr[i + 1] * conjf(corr[i])); if (isnormal(time_diff)) { @@ -843,11 +843,11 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q, if (isnormal(cfo_avg)) { // Calculate phase of the first OFDM symbol (l = 0) float arg0 = - cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.numerology) * cfo_avg; + cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.scs) * cfo_avg; // Calculate CFO corrections for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) { - float arg = arg0 + 2.0f * M_PI * cfo_avg * srsran_symbol_distance_s(0, l, q->carrier.numerology); + float arg = arg0 + 2.0f * M_PI * cfo_avg * srsran_symbol_distance_s(0, l, q->carrier.scs); cfo_correction[l] = cexpf(I * arg); } diff --git a/lib/src/phy/ch_estimation/test/csi_rs_test.c b/lib/src/phy/ch_estimation/test/csi_rs_test.c index 2a8b7da05..606bd02bb 100644 --- a/lib/src/phy/ch_estimation/test/csi_rs_test.c +++ b/lib/src/phy/ch_estimation/test/csi_rs_test.c @@ -18,11 +18,13 @@ #include static srsran_carrier_nr_t carrier = { - 0, // cell_id - 0, // numerology - 50, // nof_prb - 0, // start - 1 // max_mimo_layers + 1, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + 50, // nof_prb + 0, // start + 1 // max_mimo_layers }; static float snr_dB = 20.0; @@ -70,7 +72,7 @@ static void usage(char* prog) { printf("Usage: %s [recov]\n", prog); printf("\t-p nof_prb [Default %d]\n", carrier.nof_prb); - printf("\t-c cell_id [Default %d]\n", carrier.id); + printf("\t-c cell_id [Default %d]\n", carrier.pci); printf("\t-s SNR in dB [Default %.2f]\n", snr_dB); printf("\t-S Start RB index [Default %d]\n", start_rb); printf("\t-L Number of RB [Default %d]\n", nof_rb); @@ -88,7 +90,7 @@ static void parse_args(int argc, char** argv) carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); break; case 'c': - carrier.id = (uint32_t)strtol(argv[optind], NULL, 10); + carrier.pci = (uint32_t)strtol(argv[optind], NULL, 10); break; case 'o': power_control_offset = strtof(argv[optind], NULL); @@ -169,7 +171,7 @@ int main(int argc, char** argv) resource.resource_mapping.freq_band.nof_rb <= nof_rb_end; resource.resource_mapping.freq_band.nof_rb += 4) { // Iterate for all slot numbers - for (slot_cfg.idx = 0; slot_cfg.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.numerology); slot_cfg.idx++) { + for (slot_cfg.idx = 0; slot_cfg.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.scs); slot_cfg.idx++) { // Steer Frequency allocation for (uint32_t freq_dom_alloc = 0; freq_dom_alloc < nof_freq_dom_alloc; freq_dom_alloc++) { for (uint32_t i = 0; i < nof_freq_dom_alloc; i++) { diff --git a/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c b/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c index 8334f1231..52b5033ff 100644 --- a/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c +++ b/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c @@ -30,7 +30,7 @@ void usage(char* prog) printf("\t-r nof_prb [Default %d]\n", carrier.nof_prb); printf("\t-e extended cyclic prefix [Default normal]\n"); - printf("\t-c cell_id [Default %d]\n", carrier.id); + printf("\t-c cell_id [Default %d]\n", carrier.pci); printf("\t-v increase verbosity\n"); } @@ -44,7 +44,7 @@ static void parse_args(int argc, char** argv) carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); break; case 'c': - carrier.id = (uint32_t)strtol(argv[optind], NULL, 10); + carrier.pci = (uint32_t)strtol(argv[optind], NULL, 10); break; case 'v': srsran_verbose++; @@ -68,7 +68,7 @@ static int run_test(srsran_dmrs_pdcch_estimator_t* estimator, srsran_dci_location_t dci_location = {}; dci_location.L = aggregation_level; - for (slot_cfg.idx = 0; slot_cfg.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.numerology); slot_cfg.idx++) { + for (slot_cfg.idx = 0; slot_cfg.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.scs); slot_cfg.idx++) { uint32_t locations[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {}; int nof_locations = diff --git a/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c b/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c index d3137d8a9..c19b711a2 100644 --- a/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c +++ b/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c @@ -20,12 +20,15 @@ #include #include + static srsran_carrier_nr_t carrier = { - 0, // cell_id - 0, // numerology - 50, // nof_prb - 0, // start - 1 // max_mimo_layers + 1, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + 50, // nof_prb + 0, // start + 1 // max_mimo_layers }; typedef struct { @@ -130,7 +133,7 @@ static void usage(char* prog) printf("\t-r nof_prb [Default %d]\n", carrier.nof_prb); - printf("\t-c cell_id [Default %d]\n", carrier.id); + printf("\t-c cell_id [Default %d]\n", carrier.pci); printf("\t-v increase verbosity\n"); } @@ -144,7 +147,7 @@ static void parse_args(int argc, char** argv) carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); break; case 'c': - carrier.id = (uint32_t)strtol(argv[optind], NULL, 10); + carrier.pci = (uint32_t)strtol(argv[optind], NULL, 10); break; case 'v': srsran_verbose++; @@ -218,7 +221,7 @@ static int run_test(srsran_dmrs_sch_t* dmrs_pdsch, TESTASSERT(assert_cfg(pdsch_cfg, grant) == SRSRAN_SUCCESS); srsran_slot_cfg_t slot_cfg = {}; - for (slot_cfg.idx = 0; slot_cfg.idx < SRSRAN_NSLOTS_PER_FRAME_NR(dmrs_pdsch->carrier.numerology); slot_cfg.idx++) { + for (slot_cfg.idx = 0; slot_cfg.idx < SRSRAN_NSLOTS_PER_FRAME_NR(dmrs_pdsch->carrier.scs); slot_cfg.idx++) { TESTASSERT(srsran_dmrs_sch_put_sf(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols) == SRSRAN_SUCCESS); TESTASSERT(srsran_dmrs_sch_estimate(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols, chest_res) == diff --git a/lib/src/phy/phch/pdcch_nr.c b/lib/src/phy/phch/pdcch_nr.c index 0165f943e..85df70ceb 100644 --- a/lib/src/phy/phch/pdcch_nr.c +++ b/lib/src/phy/phch/pdcch_nr.c @@ -327,7 +327,7 @@ static uint32_t pdcch_nr_c_init(const srsran_pdcch_nr_t* q, const srsran_dci_msg { uint32_t n_id = (dci_msg->ctx.ss_type == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present) ? q->coreset.dmrs_scrambling_id - : q->carrier.id; + : q->carrier.pci; uint32_t n_rnti = (dci_msg->ctx.ss_type == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present) ? dci_msg->ctx.rnti : 0U; diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 943dce860..587effdbf 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -295,7 +295,7 @@ static int srsran_pdsch_nr_get(const srsran_pdsch_nr_t* q, static uint32_t pdsch_nr_cinit(const srsran_carrier_nr_t* carrier, const srsran_sch_cfg_nr_t* cfg, uint16_t rnti, uint32_t cw_idx) { - uint32_t n_id = carrier->id; + uint32_t n_id = carrier->pci; if (cfg->scrambling_id_present && SRSRAN_RNTI_ISUSER(rnti)) { n_id = cfg->scambling_id; } diff --git a/lib/src/phy/phch/pucch_nr.c b/lib/src/phy/phch/pucch_nr.c index cba565583..6c9e214e9 100644 --- a/lib/src/phy/phch/pucch_nr.c +++ b/lib/src/phy/phch/pucch_nr.c @@ -28,7 +28,7 @@ int srsran_pucch_nr_group_sequence(const srsran_carrier_nr_t* carrier, { uint32_t f_gh = 0; uint32_t f_ss = 0; - uint32_t n_id = cfg->hopping_id_present ? cfg->hopping_id : carrier->id; + uint32_t n_id = cfg->hopping_id_present ? cfg->hopping_id : carrier->pci; switch (cfg->group_hopping) { case SRSRAN_PUCCH_NR_GROUP_HOPPING_NEITHER: @@ -71,13 +71,13 @@ int srsran_pucch_nr_alpha_idx(const srsran_carrier_nr_t* carrier, } // Compute number of slot - uint32_t n_slot = SRSRAN_SLOT_NR_MOD(carrier->numerology, slot->idx); + uint32_t n_slot = SRSRAN_SLOT_NR_MOD(carrier->scs, slot->idx); // Generate pseudo-random sequence - uint32_t cinit = cfg->hopping_id_present ? cfg->hopping_id : carrier->id; + uint32_t cinit = cfg->hopping_id_present ? cfg->hopping_id : carrier->pci; uint8_t cs[SRSRAN_NSYMB_PER_SLOT_NR * SRSRAN_NSLOTS_PER_FRAME_NR(SRSRAN_NR_MAX_NUMEROLOGY) * 8U] = {}; srsran_sequence_apply_bit( - cs, cs, SRSRAN_NSYMB_PER_SLOT_NR * SRSRAN_NSLOTS_PER_FRAME_NR(carrier->numerology) * 8, cinit); + cs, cs, SRSRAN_NSYMB_PER_SLOT_NR * SRSRAN_NSLOTS_PER_FRAME_NR(carrier->scs) * 8, cinit); // Create n_cs parameter uint32_t n_cs = 0; @@ -536,7 +536,7 @@ static uint32_t pucch_nr_format2_cinit(const srsran_carrier_nr_t* carri const srsran_pucch_nr_common_cfg_t* pucch_cfg, const srsran_uci_cfg_nr_t* uci_cfg) { - uint32_t n_id = (pucch_cfg->scrambling_id_present) ? pucch_cfg->scrambling_id_present : carrier->id; + uint32_t n_id = (pucch_cfg->scrambling_id_present) ? pucch_cfg->scrambling_id_present : carrier->pci; return ((uint32_t)uci_cfg->pucch.rnti << 15U) + n_id; } diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 942137555..1d7c8e880 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -317,7 +317,7 @@ static int pusch_nr_get(const srsran_pusch_nr_t* q, static uint32_t pusch_nr_cinit(const srsran_carrier_nr_t* carrier, const srsran_sch_cfg_nr_t* cfg, uint16_t rnti, uint32_t cw_idx) { - uint32_t n_id = carrier->id; + uint32_t n_id = carrier->pci; if (cfg->scrambling_id_present && SRSRAN_RNTI_ISUSER(rnti)) { n_id = cfg->scambling_id; } diff --git a/lib/src/phy/phch/test/pdcch_nr_test.c b/lib/src/phy/phch/test/pdcch_nr_test.c index afe6562e8..5bd26d061 100644 --- a/lib/src/phy/phch/test/pdcch_nr_test.c +++ b/lib/src/phy/phch/test/pdcch_nr_test.c @@ -16,11 +16,13 @@ #include static srsran_carrier_nr_t carrier = { - 0, // cell_id - 0, // numerology - 50, // nof_prb - 0, // start - 1 // max_mimo_layers + 1, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + 50, // nof_prb + 0, // start + 1 // max_mimo_layers }; static uint16_t rnti = 0x1234; @@ -185,7 +187,7 @@ int main(int argc, char** argv) aggregation_level++) { uint32_t L = 1U << aggregation_level; - for (uint32_t slot_idx = 0; slot_idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.numerology); slot_idx++) { + for (uint32_t slot_idx = 0; slot_idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.scs); slot_idx++) { uint32_t dci_locations[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {}; // Calculate candidate locations diff --git a/lib/src/phy/phch/test/pdsch_nr_test.c b/lib/src/phy/phch/test/pdsch_nr_test.c index a644f8768..b6bd1bca3 100644 --- a/lib/src/phy/phch/test/pdsch_nr_test.c +++ b/lib/src/phy/phch/test/pdsch_nr_test.c @@ -21,13 +21,16 @@ #include static srsran_carrier_nr_t carrier = { - 1, // cell_id - 0, // numerology - SRSRAN_MAX_PRB_NR, // nof_prb - 0, // start - 1 // max_mimo_layers + 1, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + SRSRAN_MAX_PRB_NR, // nof_prb + 0, // start + 1 // max_mimo_layers }; + static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t mcs = 30; // Set to 30 for steering static srsran_sch_cfg_nr_t pdsch_cfg = {}; diff --git a/lib/src/phy/phch/test/pucch_nr_test.c b/lib/src/phy/phch/test/pucch_nr_test.c index a50f280a7..f2a5ed12b 100644 --- a/lib/src/phy/phch/test/pucch_nr_test.c +++ b/lib/src/phy/phch/test/pucch_nr_test.c @@ -23,11 +23,13 @@ #include static srsran_carrier_nr_t carrier = { - 0, // cell_id - 0, // numerology - 6, // nof_prb - 0, // start - 1 // max_mimo_layers + 1, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + 6, // nof_prb + 0, // start + 1 // max_mimo_layers }; static uint32_t starting_prb_stride = 4; @@ -43,7 +45,7 @@ static int test_pucch_format0(srsran_pucch_nr_t* pucch, const srsran_pucch_nr_co srsran_pucch_nr_resource_t resource = {}; resource.format = SRSRAN_PUCCH_NR_FORMAT_0; - for (slot.idx = 0; slot.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.numerology); slot.idx++) { + for (slot.idx = 0; slot.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.scs); slot.idx++) { for (resource.starting_prb = 0; resource.starting_prb < carrier.nof_prb; resource.starting_prb += starting_prb_stride) { for (resource.nof_symbols = 1; resource.nof_symbols <= 2; resource.nof_symbols++) { @@ -91,7 +93,7 @@ static int test_pucch_format1(srsran_pucch_nr_t* pucch, srsran_pucch_nr_resource_t resource = {}; resource.format = SRSRAN_PUCCH_NR_FORMAT_1; - for (slot.idx = 0; slot.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.numerology); slot.idx++) { + for (slot.idx = 0; slot.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.scs); slot.idx++) { for (resource.starting_prb = 0; resource.starting_prb < carrier.nof_prb; resource.starting_prb += starting_prb_stride) { for (resource.nof_symbols = SRSRAN_PUCCH_NR_FORMAT1_MIN_NSYMB; @@ -164,7 +166,7 @@ static int test_pucch_format2(srsran_pucch_nr_t* pucch, srsran_pucch_nr_resource_t resource = {}; resource.format = SRSRAN_PUCCH_NR_FORMAT_2; - for (slot.idx = 0; slot.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.numerology); slot.idx++) { + for (slot.idx = 0; slot.idx < SRSRAN_NSLOTS_PER_FRAME_NR(carrier.scs); slot.idx++) { for (resource.nof_symbols = SRSRAN_PUCCH_NR_FORMAT2_MIN_NSYMB; resource.nof_symbols <= SRSRAN_PUCCH_NR_FORMAT2_MAX_NSYMB; resource.nof_symbols++) { @@ -247,7 +249,7 @@ static int test_pucch_format2(srsran_pucch_nr_t* pucch, static void usage(char* prog) { printf("Usage: %s [csNnv]\n", prog); - printf("\t-c cell id [Default %d]\n", carrier.id); + printf("\t-c cell id [Default %d]\n", carrier.pci); printf("\t-n nof_prb [Default %d]\n", carrier.nof_prb); printf("\t-f format [Default %d]\n", format); printf("\t-s SNR in dB [Default %.2f]\n", snr_db); @@ -260,7 +262,7 @@ static void parse_args(int argc, char** argv) while ((opt = getopt(argc, argv, "cnfsv")) != -1) { switch (opt) { case 'c': - carrier.id = (uint32_t)strtol(argv[optind], NULL, 10); + carrier.pci = (uint32_t)strtol(argv[optind], NULL, 10); break; case 'n': carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); diff --git a/lib/src/phy/phch/test/pusch_nr_test.c b/lib/src/phy/phch/test/pusch_nr_test.c index 0c00392e6..bd72b1f09 100644 --- a/lib/src/phy/phch/test/pusch_nr_test.c +++ b/lib/src/phy/phch/test/pusch_nr_test.c @@ -20,11 +20,13 @@ #include static srsran_carrier_nr_t carrier = { - 1, // cell_id - 0, // numerology - SRSRAN_MAX_PRB_NR, // nof_prb - 0, // start - 1 // max_mimo_layers + 1, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + SRSRAN_MAX_PRB_NR, // nof_prb + 0, // start + 1 // max_mimo_layers }; static uint32_t n_prb = 0; // Set to 0 for steering @@ -158,7 +160,7 @@ int main(int argc, char** argv) } // Use grant default A time resources with m=0 - if (srsran_ra_ul_nr_pusch_time_resource_default_A(carrier.numerology, 0, &pusch_cfg.grant) < SRSRAN_SUCCESS) { + if (srsran_ra_ul_nr_pusch_time_resource_default_A(carrier.scs, 0, &pusch_cfg.grant) < SRSRAN_SUCCESS) { ERROR("Error loading default grant"); goto clean_exit; } diff --git a/lib/src/phy/phch/test/sch_nr_test.c b/lib/src/phy/phch/test/sch_nr_test.c index cc338a567..4b1859de1 100644 --- a/lib/src/phy/phch/test/sch_nr_test.c +++ b/lib/src/phy/phch/test/sch_nr_test.c @@ -19,11 +19,13 @@ #include static srsran_carrier_nr_t carrier = { - 0, // cell_id - 0, // numerology - SRSRAN_MAX_PRB_NR, // nof_prb - 0, // start - 1 // max_mimo_layers + 1, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + SRSRAN_MAX_PRB_NR, // nof_prb + 0, // start + 1 // max_mimo_layers }; static uint32_t n_prb = 0; // Set to 0 for steering diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index 2e4db9fcf..7c0cf344f 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -373,7 +373,7 @@ static int ue_dl_nr_find_dci_ss(srsran_ue_dl_nr_t* q, // Calculate possible PDCCH DCI candidates uint32_t candidates[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {}; int nof_candidates = srsran_pdcch_nr_locations_coreset( - coreset, search_space, rnti, L, SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot_cfg->idx), candidates); + coreset, search_space, rnti, L, SRSRAN_SLOT_NR_MOD(q->carrier.scs, slot_cfg->idx), candidates); if (nof_candidates < SRSRAN_SUCCESS) { ERROR("Error calculating DCI candidate location"); return SRSRAN_ERROR; diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 96f377979..13a2f351c 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -20,12 +20,13 @@ #include static srsran_carrier_nr_t carrier = { - 501, // cell_id - 0, // numerology - 52, // nof_prb - 0, // start - 1 // max_mimo_layers - + 501, // pci + 0, // absolute_frequency_ssb + 0, // absolute_frequency_point_a + srsran_subcarrier_spacing_15kHz, // scs + 52, // nof_prb + 0, // start + 1 // max_mimo_layers }; static uint32_t n_prb = 0; // Set to 0 for steering @@ -375,7 +376,7 @@ int main(int argc, char** argv) search_space, pdsch_cfg.grant.rnti, L, - SRSRAN_SLOT_NR_MOD(carrier.numerology, slot.idx), + SRSRAN_SLOT_NR_MOD(carrier.scs, slot.idx), ncce_candidates); if (nof_candidates < SRSRAN_SUCCESS) { ERROR("Error getting PDCCH candidates"); @@ -407,7 +408,7 @@ int main(int argc, char** argv) // Emulate channel CFO if (isnormal(cfo_hz) && ue_dl.fft[0].cfg.symbol_sz > 0) { srsran_vec_apply_cfo(buffer_ue[0], - cfo_hz / (ue_dl.fft[0].cfg.symbol_sz * SRSRAN_SUBC_SPACING_NR(carrier.numerology)), + cfo_hz / (ue_dl.fft[0].cfg.symbol_sz * SRSRAN_SUBC_SPACING_NR(carrier.scs)), buffer_ue[0], sf_len); } diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index fb1912067..547fe34a5 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1002,7 +1002,7 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ phy_cell_cfg_nr_t phy_cell_cfg = {}; phy_cell_cfg.carrier.max_mimo_layers = cell_cfg_.nof_ports; phy_cell_cfg.carrier.nof_prb = cell_cfg_.nof_prb; - phy_cell_cfg.carrier.id = cfg.pci; + phy_cell_cfg.carrier.pci = cfg.pci; phy_cell_cfg.cell_id = cfg.cell_id; phy_cell_cfg.root_seq_idx = cfg.root_seq_idx; phy_cell_cfg.rf_port = cfg.rf_port; diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index 1129d8eb4..4c90767b1 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -86,11 +86,11 @@ public: state() { - carrier.id = 500; + carrier.pci = 500; carrier.nof_prb = 100; carrier.max_mimo_layers = 1; - info_metrics.pci = carrier.id; + info_metrics.pci = carrier.pci; // Hard-coded values, this should be set when the measurements take place csi_measurements[0].K_csi_rs = 1; diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index 1e0a5eed0..cf6ace0e1 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -99,7 +99,7 @@ void sf_worker::work_imp() // Notify MAC about PRACH transmission phy_state->stack->prach_sent(TTI_TX(tti_rx), srsran_prach_nr_start_symbol_fr1_unpaired(phy_state->cfg.prach.config_idx), - SRSRAN_SLOT_NR_MOD(phy_state->carrier.numerology, TTI_TX(tti_rx)), + SRSRAN_SLOT_NR_MOD(phy_state->carrier.scs, TTI_TX(tti_rx)), 0, 0); diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 54bb9375f..9a3ab0191 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -22,7 +22,7 @@ bool worker_pool::init(const phy_args_nr_t& args, phy_common* common, stack_inte phy_state.args = args; // Set carrier attributes - phy_state.carrier.id = 500; + phy_state.carrier.pci = 500; phy_state.carrier.nof_prb = args.nof_prb; // Set NR arguments @@ -72,7 +72,7 @@ sf_worker* worker_pool::wait_worker(uint32_t tti) sf_worker* worker = (sf_worker*)pool.wait_worker(tti); // Generate PRACH if ready - if (prach_buffer->is_ready_to_send(tti, phy_state.carrier.id)) { + if (prach_buffer->is_ready_to_send(tti, phy_state.carrier.pci)) { uint32_t nof_prach_sf = 0; float prach_target_power = 0.0f; cf_t* prach_ptr = prach_buffer->generate(0.0f, &nof_prach_sf, &prach_target_power); @@ -129,7 +129,7 @@ bool worker_pool::set_config(const srsran::phy_cfg_nr_t& cfg) // Set PRACH hard-coded cell srsran_cell_t cell = {}; cell.nof_prb = 50; - cell.id = phy_state.carrier.id; + cell.id = phy_state.carrier.pci; if (not prach_buffer->set_cell(cell, phy_state.cfg.prach)) { logger.error("Error setting PRACH cell"); return false; From db9dd857836a89c77a8996a3406985acd432e52a Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 16 Apr 2021 14:22:04 +0200 Subject: [PATCH 27/46] Parse carrier config in NR RRC reconfig --- lib/include/srsran/asn1/rrc_nr_utils.h | 2 + .../interfaces/rrc_nr_interface_types.h | 8 ++-- lib/src/asn1/rrc_nr_utils.cc | 42 ++++++++++++++++++- srsue/src/stack/rrc/rrc_nr.cc | 16 ++++++- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 60657b918..f3453b951 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -51,6 +51,7 @@ struct uci_on_pusch_s; struct zp_csi_rs_res_s; struct nzp_csi_rs_res_s; struct pdsch_serving_cell_cfg_s; +struct freq_info_dl_s; } // namespace rrc_nr } // namespace asn1 @@ -93,6 +94,7 @@ bool make_phy_beta_offsets(const asn1::rrc_nr::beta_offsets_s& beta_offsets, bool make_phy_pusch_scaling(const asn1::rrc_nr::uci_on_pusch_s& uci_on_pusch, float* scaling); bool make_phy_zp_csi_rs_resource(const asn1::rrc_nr::zp_csi_rs_res_s & zp_csi_rs_res, srsran_csi_rs_zp_resource_t* zp_csi_rs_resource); bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s & nzp_csi_rs_res, srsran_csi_rs_nzp_resource_t* csi_rs_nzp_resource); +bool make_phy_carrier_cfg(const asn1::rrc_nr::freq_info_dl_s &freq_info_dl, srsran_carrier_nr_t* carrier_nr); /*************************** * MAC Config **************************/ diff --git a/lib/include/srsran/interfaces/rrc_nr_interface_types.h b/lib/include/srsran/interfaces/rrc_nr_interface_types.h index 20d900d2c..0f796b646 100644 --- a/lib/include/srsran/interfaces/rrc_nr_interface_types.h +++ b/lib/include/srsran/interfaces/rrc_nr_interface_types.h @@ -32,11 +32,9 @@ struct phy_cfg_nr_t { srsran_pdcch_cfg_nr_t pdcch = {}; srsran_ue_dl_nr_harq_ack_cfg_t harq_ack = {}; srsran_csi_hl_cfg_t csi = {}; - - phy_cfg_nr_t() - { - - } + srsran_carrier_nr_t carrier = {}; + + phy_cfg_nr_t() {} /** * @param carrier diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 3c6e42fa6..f5965107c 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -323,7 +323,7 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, bool make_phy_harq_ack_cfg(const phys_cell_group_cfg_s& phys_cell_group_cfg, srsran_ue_dl_nr_harq_ack_cfg_t* in_srsran_ue_dl_nr_harq_ack_cfg) { - srsran_ue_dl_nr_harq_ack_cfg_t srsran_ue_dl_nr_harq_ack_cfg; + srsran_ue_dl_nr_harq_ack_cfg_t srsran_ue_dl_nr_harq_ack_cfg = {}; switch (phys_cell_group_cfg.pdsch_harq_ack_codebook) { case phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::dynamic_value: srsran_ue_dl_nr_harq_ack_cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic; @@ -1174,6 +1174,46 @@ bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nz *out_csi_rs_nzp_resource = csi_rs_nzp_resource; return true; } + +bool make_phy_carrier_cfg(const freq_info_dl_s& asn1_freq_info_dl, srsran_carrier_nr_t* out_carrier_nr) +{ + srsran_carrier_nr_t carrier_nr = {}; + if (asn1_freq_info_dl.absolute_freq_ssb_present) { + carrier_nr.absolute_frequency_ssb = asn1_freq_info_dl.absolute_freq_ssb_present; + } else { + asn1::log_warning("Option absolute_freq_ssb not present"); + return false; + } + carrier_nr.absolute_frequency_point_a = asn1_freq_info_dl.absolute_freq_point_a; + if (asn1_freq_info_dl.scs_specific_carrier_list.size() != 1) { + asn1::log_warning("Option absolute_freq_ssb not present"); + return false; + } + + carrier_nr.nof_prb = asn1_freq_info_dl.scs_specific_carrier_list[0].carrier_bw; + + switch (asn1_freq_info_dl.scs_specific_carrier_list[0].subcarrier_spacing) { + case subcarrier_spacing_opts::options::khz15: + carrier_nr.scs = srsran_subcarrier_spacing_15kHz; + break; + case subcarrier_spacing_opts::options::khz30: + carrier_nr.scs = srsran_subcarrier_spacing_30kHz; + break; + case subcarrier_spacing_opts::options::khz60: + carrier_nr.scs = srsran_subcarrier_spacing_60kHz; + break; + case subcarrier_spacing_opts::options::khz120: + carrier_nr.scs = srsran_subcarrier_spacing_120kHz; + break; + case subcarrier_spacing_opts::options::khz240: + carrier_nr.scs = srsran_subcarrier_spacing_240kHz; + break; + default: + asn1::log_warning("Not supported subcarrier spacing "); + } + *out_carrier_nr = carrier_nr; + return true; +} } // namespace srsran namespace srsenb { diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index efaea6a05..dd7e94ed6 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -722,6 +722,15 @@ bool rrc_nr::apply_csi_meas_cfg(const asn1::rrc_nr::csi_meas_cfg_s& csi_meas_cfg bool rrc_nr::apply_dl_common_cfg(const asn1::rrc_nr::dl_cfg_common_s& dl_cfg_common) { if (dl_cfg_common.init_dl_bwp_present) { + if (dl_cfg_common.freq_info_dl_present) { + if (make_phy_carrier_cfg(dl_cfg_common.freq_info_dl, &phy_cfg.carrier) == false) { + logger.warning("Warning while making carrier phy config"); + return false; + } + } else { + logger.warning("Option freq_info_dl not present"); + return false; + } if (dl_cfg_common.init_dl_bwp.pdsch_cfg_common_present) { if (dl_cfg_common.init_dl_bwp.pdsch_cfg_common.type() == asn1::rrc_nr::setup_release_c::types_opts::setup) { @@ -1031,8 +1040,13 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) if (sp_cell_cfg.recfg_with_sync_present) { const recfg_with_sync_s& recfg_with_sync = sp_cell_cfg.recfg_with_sync; mac->set_crnti(recfg_with_sync.new_ue_id); - // Common config if (recfg_with_sync.sp_cell_cfg_common_present) { + if (recfg_with_sync.sp_cell_cfg_common.pci_present) { + phy_cfg.carrier.pci = recfg_with_sync.sp_cell_cfg_common.pci; + } else { + logger.warning("Option PCI not present"); + return false; + } if (recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present) { if (apply_ul_common_cfg(recfg_with_sync.sp_cell_cfg_common.ul_cfg_common) == false) { return false; From 3f15fc281168a462b1a8df296d02dc7c47f6fe59 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 16 Apr 2021 09:23:12 +0100 Subject: [PATCH 28/46] implemented bounded_bitset::find_first(...) --- lib/include/srsran/adt/bounded_bitset.h | 68 ++++++++++++++++++++++++- lib/test/adt/bounded_bitset_test.cc | 28 ++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/adt/bounded_bitset.h b/lib/include/srsran/adt/bounded_bitset.h index 22d656668..37226db90 100644 --- a/lib/include/srsran/adt/bounded_bitset.h +++ b/lib/include/srsran/adt/bounded_bitset.h @@ -26,6 +26,31 @@ constexpr uint32_t ceil_div(uint32_t x, uint32_t y) return (x + y - 1) / y; } +template +Integer mask_trailing_ones(size_t N) +{ + static_assert(std::is_unsigned::value, "T must be unsigned integer"); + return N == 0 ? 0 : (static_cast(-1) >> (sizeof(Integer) * 8U - N)); +} + +template +Integer mask_leading_ones(size_t N) +{ + return ~mask_trailing_ones(8U * sizeof(Integer) - N); +} + +template +Integer mask_trailing_zeros(size_t N) +{ + return mask_leading_ones(8U * sizeof(Integer) - N); +} + +template +Integer mask_leading_zeros(size_t N) +{ + return mask_trailing_ones(8U * sizeof(Integer) - N); +} + template class bounded_bitset { @@ -100,8 +125,7 @@ public: bounded_bitset& fill(size_t startpos, size_t endpos, bool value = true) { - assert_within_bounds_(startpos, false); - assert_within_bounds_(endpos, false); + assert_range_bounds_(startpos, endpos); // NOTE: can be optimized if (value) { for (size_t i = startpos; i < endpos; ++i) { @@ -115,6 +139,37 @@ public: return *this; } + int find_first(size_t startpos, size_t endpos, bool value = true) const noexcept + { + assert_range_bounds_(startpos, endpos); + if (startpos == endpos) { + return -1; + } + + size_t startword = startpos / bits_per_word; + size_t lastword = (endpos - 1) / bits_per_word; + + for (size_t i = startword; i <= lastword; ++i) { + word_t w = buffer[i]; + if (not value) { + w = ~w; + } + + if (i == startword) { + size_t offset = startpos % bits_per_word; + w &= mask_trailing_zeros(offset); + } + if (i == lastword) { + size_t offset = (endpos - 1) % bits_per_word; + w &= mask_trailing_ones(offset + 1); + } + if (w != 0) { + return static_cast(i * bits_per_word + (bits_per_word - __builtin_clzl(w) - 1)); + } + } + return -1; + } + bool all() const noexcept { const size_t nw = nof_words_(); @@ -307,6 +362,15 @@ private: size()); } + void assert_range_bounds_(size_t startpos, size_t endpos) const + { + srsran_assert(startpos <= endpos and endpos <= size(), + "ERROR: range [%zd, %zd) out-of-bounds for bitsize of size=%zd", + startpos, + endpos, + size()); + } + static word_t maskbit(size_t pos) { return (static_cast(1)) << (pos % bits_per_word); } static size_t max_nof_words_() { return (N - 1) / bits_per_word + 1; } diff --git a/lib/test/adt/bounded_bitset_test.cc b/lib/test/adt/bounded_bitset_test.cc index fbc7f3437..2790880ee 100644 --- a/lib/test/adt/bounded_bitset_test.cc +++ b/lib/test/adt/bounded_bitset_test.cc @@ -13,6 +13,14 @@ #include "srsran/adt/bounded_bitset.h" #include "srsran/common/test_common.h" +void test_bit_operations() +{ + TESTASSERT(0 == srsran::mask_trailing_ones(0)); + TESTASSERT(0b11 == srsran::mask_trailing_ones(2)); + TESTASSERT(0b11111111 == srsran::mask_trailing_ones(8)); + TESTASSERT(0b1111 == srsran::mask_trailing_ones(4)); +} + int test_zero_bitset() { srsran::bounded_bitset<25> mask; @@ -176,14 +184,34 @@ int test_bitset_resize() return SRSRAN_SUCCESS; } +void test_bitset_find() +{ + { + srsran::bounded_bitset<25> bitset(6); + bitset.set(2); + TESTASSERT(bitset.find_first(0, 6) == 2); + TESTASSERT(bitset.find_first(3, 6) == -1); + bitset.set(5); + TESTASSERT(bitset.find_first(3, 6) == 5); + } + { + srsran::bounded_bitset<100> bitset(95); + bitset.set(94); + TESTASSERT(bitset.find_first(0, 93) == -1); + TESTASSERT(bitset.find_first(0, bitset.size()) == 94); + } +} + int main() { + test_bit_operations(); TESTASSERT(test_zero_bitset() == SRSRAN_SUCCESS); TESTASSERT(test_ones_bitset() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_set() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_bitwise_oper() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_print() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_resize() == SRSRAN_SUCCESS); + test_bitset_find(); printf("Success\n"); return 0; } From 22024ac35d5465eaf3688ed2452517e5a613fd02 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 16 Apr 2021 16:51:14 +0100 Subject: [PATCH 29/46] implemented bounded_bitset::find_lowest(...) for both reverse and non-reverse bit ordering. Applied this method to UL scheduling search for PRB intervals --- lib/include/srsran/adt/bounded_bitset.h | 235 ++++++++++++++---- lib/test/adt/bounded_bitset_test.cc | 92 ++++++- srsenb/src/stack/mac/schedulers/sched_base.cc | 29 ++- 3 files changed, 286 insertions(+), 70 deletions(-) diff --git a/lib/include/srsran/adt/bounded_bitset.h b/lib/include/srsran/adt/bounded_bitset.h index 37226db90..3faa87c0c 100644 --- a/lib/include/srsran/adt/bounded_bitset.h +++ b/lib/include/srsran/adt/bounded_bitset.h @@ -27,28 +27,109 @@ constexpr uint32_t ceil_div(uint32_t x, uint32_t y) } template -Integer mask_trailing_ones(size_t N) +Integer mask_msb_zeros(size_t N) { static_assert(std::is_unsigned::value, "T must be unsigned integer"); - return N == 0 ? 0 : (static_cast(-1) >> (sizeof(Integer) * 8U - N)); + return (N == 0) ? static_cast(-1) : (N == sizeof(Integer) * 8U) ? 0 : (static_cast(-1) >> (N)); } template -Integer mask_leading_ones(size_t N) +Integer mask_lsb_ones(size_t N) { - return ~mask_trailing_ones(8U * sizeof(Integer) - N); + return mask_msb_zeros(sizeof(Integer) * 8U - N); } template -Integer mask_trailing_zeros(size_t N) +Integer mask_msb_ones(size_t N) { - return mask_leading_ones(8U * sizeof(Integer) - N); + return ~mask_msb_zeros(N); } template -Integer mask_leading_zeros(size_t N) +Integer mask_lsb_zeros(size_t N) { - return mask_trailing_ones(8U * sizeof(Integer) - N); + return ~mask_lsb_ones(N); +} + +namespace detail { + +template +struct zerobit_counter { + static Integer msb_count(Integer value) + { + if (value == 0) { + return std::numeric_limits::digits; + } + Integer ret = 0; + for (Integer shift = std::numeric_limits::digits >> 1; shift != 0; shift >>= 1) { + Integer tmp = value >> shift; + if (tmp != 0) { + value = tmp; + } else { + ret |= shift; + } + } + return ret; + } + static Integer lsb_count(Integer value) + { + if (value == 0) { + return std::numeric_limits::digits; + } + Integer ret = 0; + for (Integer shift = std::numeric_limits::digits >> 1, mask = std::numeric_limits::max() >> shift; + shift != 0; + shift >>= 1, mask >>= shift) { + if ((value & mask) == 0) { + value >>= shift; + ret |= shift; + } + } + return ret; + } +}; + +/// Specializations for unsigned +template +struct zerobit_counter { + static Integer msb_count(Integer value) + { + return (value) ? __builtin_clz(value) : std::numeric_limits::digits; + } + static Integer lsb_count(Integer value) + { + return (value) ? __builtin_ctz(value) : std::numeric_limits::digits; + } +}; + +/// Specializations for unsigned long +template +struct zerobit_counter { + static Integer msb_count(Integer value) + { + return (value) ? __builtin_clzl(value) : std::numeric_limits::digits; + } + static Integer lsb_count(Integer value) + { + return (value) ? __builtin_ctzl(value) : std::numeric_limits::digits; + } +}; + +} // namespace detail + +/// uses lsb as zero position +template +Integer find_first_msb_one(Integer value) +{ + return (value) ? (sizeof(Integer) * 8U - 1 - detail::zerobit_counter::msb_count(value)) + : std::numeric_limits::digits; +} + +/// uses lsb as zero position +template +Integer find_first_lsb_one(Integer value) +{ + return detail::zerobit_counter::lsb_count(value); } template @@ -139,35 +220,17 @@ public: return *this; } - int find_first(size_t startpos, size_t endpos, bool value = true) const noexcept + int find_lowest(size_t startpos, size_t endpos, bool value = true) const noexcept { assert_range_bounds_(startpos, endpos); if (startpos == endpos) { return -1; } - size_t startword = startpos / bits_per_word; - size_t lastword = (endpos - 1) / bits_per_word; - - for (size_t i = startword; i <= lastword; ++i) { - word_t w = buffer[i]; - if (not value) { - w = ~w; - } - - if (i == startword) { - size_t offset = startpos % bits_per_word; - w &= mask_trailing_zeros(offset); - } - if (i == lastword) { - size_t offset = (endpos - 1) % bits_per_word; - w &= mask_trailing_ones(offset + 1); - } - if (w != 0) { - return static_cast(i * bits_per_word + (bits_per_word - __builtin_clzl(w) - 1)); - } + if (not reversed) { + return find_first_(startpos, endpos, value); } - return -1; + return find_first_reversed_(startpos, endpos, value); } bool all() const noexcept @@ -328,33 +391,35 @@ private: } } - bool test_(size_t pos) const noexcept + size_t get_bitidx_(size_t bitpos) const noexcept { return reversed ? size() - 1 - bitpos : bitpos; } + + bool test_(size_t bitpos) const noexcept { - pos = reversed ? size() - 1 - pos : pos; - return ((get_word_(pos) & maskbit(pos)) != static_cast(0)); + bitpos = get_bitidx_(bitpos); + return ((get_word_(bitpos) & maskbit(bitpos)) != static_cast(0)); } - void set_(size_t pos) noexcept + void set_(size_t bitpos) noexcept { - pos = reversed ? size() - 1 - pos : pos; - get_word_(pos) |= maskbit(pos); + bitpos = get_bitidx_(bitpos); + get_word_(bitpos) |= maskbit(bitpos); } - void reset_(size_t pos) noexcept + void reset_(size_t bitpos) noexcept { - pos = reversed ? size() - 1 - pos : pos; - get_word_(pos) &= ~(maskbit(pos)); + bitpos = get_bitidx_(bitpos); + get_word_(bitpos) &= ~(maskbit(bitpos)); } size_t nof_words_() const noexcept { return size() > 0 ? (size() - 1) / bits_per_word + 1 : 0; } - word_t& get_word_(size_t pos) noexcept { return buffer[pos / bits_per_word]; } + word_t& get_word_(size_t bitidx) noexcept { return buffer[bitidx / bits_per_word]; } - const word_t& get_word_(size_t pos) const { return buffer[pos / bits_per_word]; } + const word_t& get_word_(size_t bitidx) const { return buffer[bitidx / bits_per_word]; } size_t word_idx_(size_t pos) const { return pos / bits_per_word; } - void assert_within_bounds_(size_t pos, bool strict) const + void assert_within_bounds_(size_t pos, bool strict) const noexcept { srsran_assert(pos < size() or (not strict and pos == size()), "ERROR: index=%zd is out-of-bounds for bitset of size=%zd", @@ -362,7 +427,7 @@ private: size()); } - void assert_range_bounds_(size_t startpos, size_t endpos) const + void assert_range_bounds_(size_t startpos, size_t endpos) const noexcept { srsran_assert(startpos <= endpos and endpos <= size(), "ERROR: range [%zd, %zd) out-of-bounds for bitsize of size=%zd", @@ -371,9 +436,89 @@ private: size()); } - static word_t maskbit(size_t pos) { return (static_cast(1)) << (pos % bits_per_word); } + static word_t maskbit(size_t pos) noexcept { return (static_cast(1)) << (pos % bits_per_word); } + + static size_t max_nof_words_() noexcept { return (N - 1) / bits_per_word + 1; } + + int find_last_(size_t startpos, size_t endpos, bool value) const noexcept + { + size_t startword = startpos / bits_per_word; + size_t lastword = (endpos - 1) / bits_per_word; + + for (size_t i = lastword; i != startpos - 1; --i) { + word_t w = buffer[i]; + if (not value) { + w = ~w; + } + + if (i == startword) { + size_t offset = startpos % bits_per_word; + w &= (reversed) ? mask_msb_zeros(offset) : mask_lsb_zeros(offset); + } + if (i == lastword) { + size_t offset = (endpos - 1) % bits_per_word; + w &= (reversed) ? mask_msb_ones(offset + 1) : mask_lsb_ones(offset + 1); + } + if (w != 0) { + return static_cast(i * bits_per_word + find_first_msb_one(w)); + } + } + return -1; + } + + int find_first_(size_t startpos, size_t endpos, bool value) const noexcept + { + size_t startword = startpos / bits_per_word; + size_t lastword = (endpos - 1) / bits_per_word; - static size_t max_nof_words_() { return (N - 1) / bits_per_word + 1; } + for (size_t i = startword; i <= lastword; ++i) { + word_t w = buffer[i]; + if (not value) { + w = ~w; + } + + if (i == startword) { + size_t offset = startpos % bits_per_word; + w &= mask_lsb_zeros(offset); + } + if (i == lastword) { + size_t offset = (endpos - 1) % bits_per_word; + w &= mask_lsb_ones(offset + 1); + } + if (w != 0) { + return static_cast(i * bits_per_word + find_first_lsb_one(w)); + } + } + return -1; + } + + int find_first_reversed_(size_t startpos, size_t endpos, bool value) const noexcept + { + size_t startbitpos = get_bitidx_(startpos), lastbitpos = get_bitidx_(endpos - 1); + size_t startword = startbitpos / bits_per_word; + size_t lastword = lastbitpos / bits_per_word; + + for (size_t i = startword; i != lastword - 1; --i) { + word_t w = buffer[i]; + if (not value) { + w = ~w; + } + + if (i == startword) { + size_t offset = startbitpos % bits_per_word; + w &= mask_lsb_ones(offset + 1); + } + if (i == lastword) { + size_t offset = lastbitpos % bits_per_word; + w &= mask_lsb_zeros(offset); + } + if (w != 0) { + word_t pos = find_first_msb_one(w); + return static_cast(size() - 1 - (pos + i * bits_per_word)); + } + } + return -1; + } }; template diff --git a/lib/test/adt/bounded_bitset_test.cc b/lib/test/adt/bounded_bitset_test.cc index 2790880ee..4034e334f 100644 --- a/lib/test/adt/bounded_bitset_test.cc +++ b/lib/test/adt/bounded_bitset_test.cc @@ -15,10 +15,35 @@ void test_bit_operations() { - TESTASSERT(0 == srsran::mask_trailing_ones(0)); - TESTASSERT(0b11 == srsran::mask_trailing_ones(2)); - TESTASSERT(0b11111111 == srsran::mask_trailing_ones(8)); - TESTASSERT(0b1111 == srsran::mask_trailing_ones(4)); + TESTASSERT(0 == srsran::mask_lsb_ones(0)); + TESTASSERT(0 == srsran::mask_msb_ones(0)); + TESTASSERT(0 == srsran::mask_lsb_ones(0)); + TESTASSERT(0 == srsran::mask_msb_ones(0)); + TESTASSERT(0b11111111 == srsran::mask_lsb_zeros(0)); + TESTASSERT(0b11111111 == srsran::mask_msb_zeros(0)); + TESTASSERT((uint32_t)-1 == srsran::mask_lsb_zeros(0)); + TESTASSERT((uint32_t)-1 == srsran::mask_msb_zeros(0)); + + TESTASSERT(0b11 == srsran::mask_lsb_ones(2)); + TESTASSERT(0b11000000 == srsran::mask_msb_ones(2)); + TESTASSERT(0b11111100 == srsran::mask_lsb_zeros(2)); + TESTASSERT(0b00111111 == srsran::mask_msb_zeros(2)); + + TESTASSERT(0b11111111 == srsran::mask_lsb_ones(8)); + TESTASSERT(0b1111 == srsran::mask_lsb_ones(4)); + + TESTASSERT(srsran::find_first_lsb_one(0) == std::numeric_limits::digits); + TESTASSERT(srsran::find_first_msb_one(0) == std::numeric_limits::digits); + TESTASSERT(srsran::find_first_lsb_one(1) == 0); + TESTASSERT(srsran::find_first_msb_one(1) == 0); + TESTASSERT(srsran::find_first_lsb_one(0b11) == 0); + TESTASSERT(srsran::find_first_lsb_one(0b10) == 1); + TESTASSERT(srsran::find_first_msb_one(0b11) == 1); + TESTASSERT(srsran::find_first_msb_one(0b10) == 1); + TESTASSERT(srsran::find_first_lsb_one(0b11) == 0); + TESTASSERT(srsran::find_first_lsb_one(0b10) == 1); + TESTASSERT(srsran::find_first_msb_one(0b11) == 1); + TESTASSERT(srsran::find_first_msb_one(0b10) == 1); } int test_zero_bitset() @@ -184,21 +209,63 @@ int test_bitset_resize() return SRSRAN_SUCCESS; } +template void test_bitset_find() { { - srsran::bounded_bitset<25> bitset(6); + srsran::bounded_bitset<25, reversed> bitset(6); + + // 0b000000 + TESTASSERT(bitset.find_lowest(0, bitset.size(), false) == 0); + TESTASSERT(bitset.find_lowest(0, bitset.size(), true) == -1); + + // 0b000100 bitset.set(2); - TESTASSERT(bitset.find_first(0, 6) == 2); - TESTASSERT(bitset.find_first(3, 6) == -1); + TESTASSERT(bitset.find_lowest(0, 6) == 2); + TESTASSERT(bitset.find_lowest(0, 6, false) == 0); + TESTASSERT(bitset.find_lowest(3, 6) == -1); + TESTASSERT(bitset.find_lowest(3, 6, false) == 3); + + // 0b000101 + bitset.set(0); + TESTASSERT(bitset.find_lowest(0, 6) == 0); + TESTASSERT(bitset.find_lowest(0, 6, false) == 1); + TESTASSERT(bitset.find_lowest(3, 6) == -1); + TESTASSERT(bitset.find_lowest(3, 6, false) == 3); + + // 0b100101 bitset.set(5); - TESTASSERT(bitset.find_first(3, 6) == 5); + TESTASSERT(bitset.find_lowest(0, 6) == 0); + TESTASSERT(bitset.find_lowest(0, 6, false) == 1); + TESTASSERT(bitset.find_lowest(3, 6) == 5); + + // 0b111111 + bitset.fill(0, 6); + TESTASSERT(bitset.find_lowest(0, 6) == 0); + TESTASSERT(bitset.find_lowest(0, 6, false) == -1); + TESTASSERT(bitset.find_lowest(3, 6, false) == -1); } { - srsran::bounded_bitset<100> bitset(95); + srsran::bounded_bitset<100, reversed> bitset(95); + + // 0b0...0 + TESTASSERT(bitset.find_lowest(0, bitset.size()) == -1); + + // 0b1000... bitset.set(94); - TESTASSERT(bitset.find_first(0, 93) == -1); - TESTASSERT(bitset.find_first(0, bitset.size()) == 94); + TESTASSERT(bitset.find_lowest(0, 93) == -1); + TESTASSERT(bitset.find_lowest(0, bitset.size()) == 94); + + // 0b1000...010 + bitset.set(1); + TESTASSERT(bitset.find_lowest(0, bitset.size()) == 1); + TESTASSERT(bitset.find_lowest(1, bitset.size()) == 1); + TESTASSERT(bitset.find_lowest(2, bitset.size()) == 94); + + // 0b11..11 + bitset.fill(0, bitset.size()); + TESTASSERT(bitset.find_lowest(0, bitset.size()) == 0); + TESTASSERT(bitset.find_lowest(5, bitset.size()) == 5); } } @@ -211,7 +278,8 @@ int main() TESTASSERT(test_bitset_bitwise_oper() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_print() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_resize() == SRSRAN_SUCCESS); - test_bitset_find(); + test_bitset_find(); + test_bitset_find(); printf("Success\n"); return 0; } diff --git a/srsenb/src/stack/mac/schedulers/sched_base.cc b/srsenb/src/stack/mac/schedulers/sched_base.cc index 96edc0014..123eccf8f 100644 --- a/srsenb/src/stack/mac/schedulers/sched_base.cc +++ b/srsenb/src/stack/mac/schedulers/sched_base.cc @@ -23,22 +23,25 @@ template ::value, prb_interval, rbg_interval>::type> RBInterval find_contiguous_interval(const RBMask& in_mask, uint32_t max_size) { - RBInterval interv, max_interv; + RBInterval max_interv; - for (uint32_t n = 0; n < in_mask.size() and interv.length() < max_size; n++) { - if (not in_mask.test(n) and interv.empty()) { - // new interval - interv.set(n, n + 1); - } else if (not in_mask.test(n)) { - // extend current interval - interv.resize_by(1); - } else if (not interv.empty()) { - // reset interval - max_interv = interv.length() > max_interv.length() ? interv : max_interv; - interv = {}; + for (size_t n = 0; n < in_mask.size(); n++) { + int pos = in_mask.find_lowest(n, in_mask.size(), false); + if (pos < 0) { + break; + } + + size_t max_pos = std::min(in_mask.size(), (size_t)pos + max_size); + int pos2 = in_mask.find_lowest(pos, max_pos, true); + RBInterval interv(pos, pos2 < 0 ? max_pos : pos2); + if (interv.length() >= max_size) { + return interv; + } + if (interv.length() > max_interv.length()) { + max_interv = interv; } } - return interv.length() > max_interv.length() ? interv : max_interv; + return max_interv; } /**************************** From 8ed8b94ca5da1d213d55e85248a19d3b5c6f9333 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 16 Apr 2021 17:21:47 +0100 Subject: [PATCH 30/46] in search for contiguous prb interval, skip already scanned prbs --- srsenb/src/stack/mac/schedulers/sched_base.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsenb/src/stack/mac/schedulers/sched_base.cc b/srsenb/src/stack/mac/schedulers/sched_base.cc index 123eccf8f..0eb785a5f 100644 --- a/srsenb/src/stack/mac/schedulers/sched_base.cc +++ b/srsenb/src/stack/mac/schedulers/sched_base.cc @@ -25,7 +25,7 @@ RBInterval find_contiguous_interval(const RBMask& in_mask, uint32_t max_size) { RBInterval max_interv; - for (size_t n = 0; n < in_mask.size(); n++) { + for (size_t n = 0; n < in_mask.size();) { int pos = in_mask.find_lowest(n, in_mask.size(), false); if (pos < 0) { break; @@ -40,6 +40,7 @@ RBInterval find_contiguous_interval(const RBMask& in_mask, uint32_t max_size) if (interv.length() > max_interv.length()) { max_interv = interv; } + n = interv.stop(); } return max_interv; } From ac375f07d9e9b04453cf1e170cced05ff260aabb Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 19 Apr 2021 10:44:30 +0100 Subject: [PATCH 31/46] add precompiler guards to restrict builtin use to gcc and clang --- lib/include/srsran/adt/bounded_bitset.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/include/srsran/adt/bounded_bitset.h b/lib/include/srsran/adt/bounded_bitset.h index 3faa87c0c..cd4eb732d 100644 --- a/lib/include/srsran/adt/bounded_bitset.h +++ b/lib/include/srsran/adt/bounded_bitset.h @@ -89,6 +89,7 @@ struct zerobit_counter { } }; +#ifdef __GNUC__ // clang and gcc /// Specializations for unsigned template struct zerobit_counter { @@ -101,7 +102,9 @@ struct zerobit_counter { return (value) ? __builtin_ctz(value) : std::numeric_limits::digits; } }; +#endif +#ifdef __GNUC__ // clang and gcc /// Specializations for unsigned long template struct zerobit_counter { @@ -114,6 +117,7 @@ struct zerobit_counter { return (value) ? __builtin_ctzl(value) : std::numeric_limits::digits; } }; +#endif } // namespace detail From 0999b271baec9d540969b6fe92753b8d997a88b2 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Apr 2021 11:05:02 +0200 Subject: [PATCH 32/46] Added RFNOC based LO frequency offset --- lib/src/phy/rf/rf_uhd_generic.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/src/phy/rf/rf_uhd_generic.h b/lib/src/phy/rf/rf_uhd_generic.h index 6b408b4a8..4d63509a4 100644 --- a/lib/src/phy/rf/rf_uhd_generic.h +++ b/lib/src/phy/rf/rf_uhd_generic.h @@ -24,6 +24,7 @@ private: uhd::stream_args_t stream_args = {}; double lo_freq_tx_hz = 0.0; double lo_freq_rx_hz = 0.0; + double lo_freq_offset_hz = 0.0; uhd_error usrp_make_internal(const uhd::device_addr_t& dev_addr) override { @@ -161,6 +162,20 @@ public: dev_addr.pop("lo_freq_rx_hz"); } + // LO Frequency offset automatic + if (dev_addr.has_key("lo_freq_offset_hz")) { + lo_freq_offset_hz = dev_addr.cast("lo_freq_offset_hz", lo_freq_offset_hz); + dev_addr.pop("lo_freq_offset_hz"); + + if (std::isnormal(lo_freq_tx_hz)) { + Warning("'lo_freq_offset_hz' overrides 'lo_freq_tx_hz' (" << lo_freq_tx_hz / 1e6 << " MHz)"); + } + + if (std::isnormal(lo_freq_rx_hz)) { + Warning("'lo_freq_offset_hz' overrides 'lo_freq_rx_hz' (" << lo_freq_rx_hz / 1e6 << " MHz)"); + } + } + // Make USRP uhd_error err = usrp_multi_make(dev_addr); if (err != UHD_ERROR_NONE) { @@ -339,6 +354,10 @@ public: // Create Tune request uhd::tune_request_t tune_request(target_freq); + if (std::isnormal(lo_freq_offset_hz)) { + lo_freq_tx_hz = target_freq + lo_freq_offset_hz; + } + // If the LO frequency is defined, force a LO frequency and use the if (std::isnormal(lo_freq_tx_hz)) { tune_request.rf_freq = lo_freq_tx_hz; @@ -356,6 +375,10 @@ public: // Create Tune request uhd::tune_request_t tune_request(target_freq); + if (std::isnormal(lo_freq_offset_hz)) { + lo_freq_rx_hz = target_freq + lo_freq_offset_hz; + } + // If the LO frequency is defined, force a LO frequency and use the if (std::isnormal(lo_freq_rx_hz)) { tune_request.rf_freq = lo_freq_rx_hz; From 1c1d7e24477bf9e3bcc13addf9a23e453eea503d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Apr 2021 11:06:52 +0200 Subject: [PATCH 33/46] Revert "Review soft demodulator zero check" This reverts commit b8a9a7fc70233c6d54c3acaab7e344db40d8aade. --- lib/include/srsran/phy/modem/demod_soft.h | 10 --- lib/src/phy/modem/demod_soft.c | 31 +------ lib/src/phy/modem/test/soft_demod_test.c | 99 +++++++++++------------ lib/src/phy/phch/pdsch_nr.c | 2 +- 4 files changed, 52 insertions(+), 90 deletions(-) diff --git a/lib/include/srsran/phy/modem/demod_soft.h b/lib/include/srsran/phy/modem/demod_soft.h index 64d680b28..ea3337942 100644 --- a/lib/include/srsran/phy/modem/demod_soft.h +++ b/lib/include/srsran/phy/modem/demod_soft.h @@ -33,14 +33,4 @@ SRSRAN_API int srsran_demod_soft_demodulate_s(srsran_mod_t modulation, const cf_ SRSRAN_API int srsran_demod_soft_demodulate_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols); -/** - * @brief Soft-demodulates complex symbols into 8-bit LLR. It forces zero symbols produce zero LLRs. - * @param modulation Modulation - * @param symbols Complex symbols - * @param llr 8-bit LLRs - * @param nsymbols Number of symbols - * @return SRSLTE_SUCCESS if the provided pointers are valid, SRSLTE_ERROR code otherwise - */ -SRSRAN_API int srsran_demod_soft_demodulate2_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols); - #endif // SRSRAN_DEMOD_SOFT_H diff --git a/lib/src/phy/modem/demod_soft.c b/lib/src/phy/modem/demod_soft.c index b7ef05d42..a81bf1eaf 100644 --- a/lib/src/phy/modem/demod_soft.c +++ b/lib/src/phy/modem/demod_soft.c @@ -883,9 +883,6 @@ int srsran_demod_soft_demodulate(srsran_mod_t modulation, const cf_t* symbols, f int srsran_demod_soft_demodulate_s(srsran_mod_t modulation, const cf_t* symbols, short* llr, int nsymbols) { - if (symbols == NULL || llr == NULL) { - return SRSRAN_ERROR_INVALID_INPUTS; - } switch (modulation) { case SRSRAN_MOD_BPSK: demod_bpsk_lte_s(symbols, llr, nsymbols); @@ -911,9 +908,6 @@ int srsran_demod_soft_demodulate_s(srsran_mod_t modulation, const cf_t* symbols, int srsran_demod_soft_demodulate_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols) { - if (symbols == NULL || llr == NULL) { - return SRSRAN_ERROR_INVALID_INPUTS; - } switch (modulation) { case SRSRAN_MOD_BPSK: demod_bpsk_lte_b(symbols, llr, nsymbols); @@ -932,34 +926,17 @@ int srsran_demod_soft_demodulate_b(srsran_mod_t modulation, const cf_t* symbols, break; default: ERROR("Invalid modulation %d", modulation); - return SRSRAN_ERROR; - } - return SRSRAN_SUCCESS; -} - -int srsran_demod_soft_demodulate2_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols) -{ - if (symbols == NULL || llr == NULL) { - return SRSRAN_ERROR_INVALID_INPUTS; - } - if (srsran_demod_soft_demodulate_b(modulation, symbols, llr, nsymbols) < SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - - // If the number of bits is 2 or less, this is unnecessary - if (modulation < SRSRAN_MOD_16QAM) { - return SRSRAN_SUCCESS; + return -1; } - // Iterate all symbols seeking for zero LLR uint32_t nof_bits_x_symbol = srsran_mod_bits_x_symbol(modulation); for (uint32_t i = 0; i < nsymbols; i++) { - if (symbols[i] == 0.0f) { + if (!isnormal(__real__ symbols[i]) || !isnormal(__imag__ symbols[i])) { for (uint32_t j = 0; j < nof_bits_x_symbol; j++) { llr[i * nof_bits_x_symbol + j] = 0; } } } - return SRSRAN_SUCCESS; -} \ No newline at end of file + return 0; +} diff --git a/lib/src/phy/modem/test/soft_demod_test.c b/lib/src/phy/modem/test/soft_demod_test.c index 3465098bb..ee3ee49f3 100644 --- a/lib/src/phy/modem/test/soft_demod_test.c +++ b/lib/src/phy/modem/test/soft_demod_test.c @@ -10,8 +10,11 @@ * */ +#include +#include #include #include +#include #include #include #include @@ -22,7 +25,7 @@ static uint32_t nof_frames = 10; static uint32_t num_bits = 1000; static srsran_mod_t modulation = SRSRAN_MOD_NITEMS; -static void usage(char* prog) +void usage(char* prog) { printf("Usage: %s [nfv] -m modulation (1: BPSK, 2: QPSK, 4: QAM16, 6: QAM64)\n", prog); printf("\t-n num_bits [Default %d]\n", num_bits); @@ -30,7 +33,7 @@ static void usage(char* prog) printf("\t-v srsran_verbose [Default None]\n"); } -static void parse_args(int argc, char** argv) +void parse_args(int argc, char** argv) { int opt; while ((opt = getopt(argc, argv, "nmvf")) != -1) { @@ -79,16 +82,33 @@ static void parse_args(int argc, char** argv) } } +float mse_threshold() +{ + switch (modulation) { + case SRSRAN_MOD_BPSK: + return 1.0e-6; + case SRSRAN_MOD_QPSK: + return 1.0e-6; + case SRSRAN_MOD_16QAM: + return 0.11; + case SRSRAN_MOD_64QAM: + return 0.19; + case SRSRAN_MOD_256QAM: + return 0.3; + default: + return -1.0f; + } +} + int main(int argc, char** argv) { + int i; srsran_modem_table_t mod; - uint8_t* input = NULL; - cf_t* symbols = NULL; - float* llr = NULL; - short* llr_s = NULL; - int8_t* llr_b = NULL; - int8_t* llr_b2 = NULL; - srsran_random_t random_gen = srsran_random_init(0); + uint8_t * input, *output; + cf_t* symbols; + float* llr; + short* llr_s; + int8_t* llr_b; parse_args(argc, argv); @@ -107,6 +127,11 @@ int main(int argc, char** argv) perror("malloc"); exit(-1); } + output = srsran_vec_u8_malloc(num_bits); + if (!output) { + perror("malloc"); + exit(-1); + } symbols = srsran_vec_cf_malloc(num_bits / mod.nbits_x_symbol); if (!symbols) { perror("malloc"); @@ -131,21 +156,17 @@ int main(int argc, char** argv) exit(-1); } - llr_b2 = srsran_vec_i8_malloc(num_bits); - if (!llr_b2) { - perror("malloc"); - exit(-1); - } + /* generate random data */ + srand(0); int ret = -1; struct timeval t[3]; - float mean_texec = 0.0f; - float mean_texec_s = 0.0f; - float mean_texec_b = 0.0f; - float mean_texec_b2 = 0.0f; + float mean_texec = 0.0; + float mean_texec_s = 0.0; + float mean_texec_b = 0.0; for (int n = 0; n < nof_frames; n++) { - for (int i = 0; i < num_bits; i++) { - input[i] = srsran_random_uniform_int_dist(random_gen, 0, 1); + for (i = 0; i < num_bits; i++) { + input[i] = rand() % 2; } /* modulate */ @@ -179,15 +200,6 @@ int main(int argc, char** argv) mean_texec_b = SRSRAN_VEC_CMA((float)t[0].tv_usec, mean_texec_b, n - 1); } - gettimeofday(&t[1], NULL); - srsran_demod_soft_demodulate2_b(modulation, symbols, llr_b2, num_bits / mod.nbits_x_symbol); - gettimeofday(&t[2], NULL); - get_time_interval(t); - - if (n > 0) { - mean_texec_b2 = SRSRAN_VEC_CMA((float)t[0].tv_usec, mean_texec_b2, n - 1); - } - if (SRSRAN_VERBOSE_ISDEBUG()) { printf("bits="); srsran_vec_fprint_b(stdout, input, num_bits); @@ -203,27 +215,12 @@ int main(int argc, char** argv) printf("llr_b="); srsran_vec_fprint_bs(stdout, llr_b, num_bits); - - printf("llr_b2="); - srsran_vec_fprint_bs(stdout, llr_b2, num_bits); } // Check demodulation errors - for (int j = 0; j < num_bits; j++) { - if (input[j] != (llr[j] > 0 ? 1 : 0)) { - ERROR("Error in bit %d\n", j); - goto clean_exit; - } - if (input[j] != (llr_s[j] > 0 ? 1 : 0)) { - ERROR("Error in bit %d\n", j); - goto clean_exit; - } - if (input[j] != (llr_b[j] > 0 ? 1 : 0)) { - ERROR("Error in bit %d\n", j); - goto clean_exit; - } - if (input[j] != (llr_b2[j] > 0 ? 1 : 0)) { - ERROR("Error in bit %d\n", j); + for (int i = 0; i < num_bits; i++) { + if (input[i] != (llr[i] > 0 ? 1 : 0)) { + printf("Error in bit %d\n", i); goto clean_exit; } } @@ -231,23 +228,21 @@ int main(int argc, char** argv) ret = 0; clean_exit: - srsran_random_free(random_gen); free(llr_b); free(llr_s); free(llr); free(symbols); + free(output); free(input); srsran_modem_table_free(&mod); - printf("Mean Throughput: %.2f/%.2f/%.2f/%.2f. Mbps ExTime: %.2f/%.2f/%.2f/%.2f us\n", + printf("Mean Throughput: %.2f/%.2f/%.2f. Mbps ExTime: %.2f/%.2f/%.2f us\n", num_bits / mean_texec, num_bits / mean_texec_s, num_bits / mean_texec_b, - num_bits / mean_texec_b2, mean_texec, mean_texec_s, - mean_texec_b, - mean_texec_b2); + mean_texec_b); exit(ret); } diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 587effdbf..a77f98879 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -458,7 +458,7 @@ static inline int pdsch_nr_decode_codeword(srsran_pdsch_nr_t* q, // Demodulation int8_t* llr = (int8_t*)q->b[tb->cw_idx]; - if (srsran_demod_soft_demodulate2_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) { + if (srsran_demod_soft_demodulate_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) { return SRSRAN_ERROR; } From 93c3dc1cb18afc98b94a26ab0428add093d470e8 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Apr 2021 11:07:08 +0200 Subject: [PATCH 34/46] Revert "Demodulator sets LLR to zero for 0.0 symbols" This reverts commit 1a6e5cdee5f52451c85221b08e10b82865c99848. --- lib/src/phy/modem/demod_soft.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/src/phy/modem/demod_soft.c b/lib/src/phy/modem/demod_soft.c index a81bf1eaf..dac7a5f09 100644 --- a/lib/src/phy/modem/demod_soft.c +++ b/lib/src/phy/modem/demod_soft.c @@ -928,15 +928,5 @@ int srsran_demod_soft_demodulate_b(srsran_mod_t modulation, const cf_t* symbols, ERROR("Invalid modulation %d", modulation); return -1; } - - uint32_t nof_bits_x_symbol = srsran_mod_bits_x_symbol(modulation); - for (uint32_t i = 0; i < nsymbols; i++) { - if (!isnormal(__real__ symbols[i]) || !isnormal(__imag__ symbols[i])) { - for (uint32_t j = 0; j < nof_bits_x_symbol; j++) { - llr[i * nof_bits_x_symbol + j] = 0; - } - } - } - return 0; } From 53e41a165c3307a228c49cf21a58ce256bb7d3b3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Apr 2021 11:24:25 +0200 Subject: [PATCH 35/46] Revert zeros around DC REs in NR PDSCH --- lib/include/srsran/phy/phch/pdsch_nr.h | 4 ---- lib/src/phy/phch/pdsch_nr.c | 29 +------------------------- lib/test/phy/phy_dl_nr_test.c | 1 - 3 files changed, 1 insertion(+), 33 deletions(-) diff --git a/lib/include/srsran/phy/phch/pdsch_nr.h b/lib/include/srsran/phy/phch/pdsch_nr.h index b8e166105..f3326f55f 100644 --- a/lib/include/srsran/phy/phch/pdsch_nr.h +++ b/lib/include/srsran/phy/phch/pdsch_nr.h @@ -37,8 +37,6 @@ typedef struct SRSRAN_API { srsran_sch_nr_args_t sch; bool measure_evm; bool measure_time; - bool disable_zero_re_around_dc; ///< PDSCH NR sets the LLR around the DC to zero to avoid noise - uint32_t nof_zero_re_around_dc; ///< Number of RE to set to zero around DC. It uses default value if 0. } srsran_pdsch_nr_args_t; /** @@ -59,8 +57,6 @@ typedef struct SRSRAN_API { uint32_t meas_time_us; srsran_re_pattern_t dmrs_re_pattern; uint32_t nof_rvd_re; - uint32_t nof_zero_re_around_dc; ///< Sets a number of RE surrounding the center of the resource grid to zero. Set to 0 - ///< for disabling. } srsran_pdsch_nr_t; /** diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index a77f98879..5c184cbc7 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -17,9 +17,6 @@ #include "srsran/phy/mimo/precoding.h" #include "srsran/phy/modem/demod_soft.h" -///@brief Default number of zero RE around DC -#define PDSCH_NR_DEFAULT_NOF_ZERO_RE_AROUND_DC 3 - int pdsch_nr_init_common(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args) { SRSRAN_MEM_ZERO(q, srsran_pdsch_nr_t, 1); @@ -34,14 +31,6 @@ int pdsch_nr_init_common(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* arg } } - if (!args->disable_zero_re_around_dc) { - if (args->nof_zero_re_around_dc == 0) { - q->nof_zero_re_around_dc = PDSCH_NR_DEFAULT_NOF_ZERO_RE_AROUND_DC; - } else { - q->nof_zero_re_around_dc = args->nof_zero_re_around_dc; - } - } - return SRSRAN_SUCCESS; } @@ -250,23 +239,7 @@ static int srsran_pdsch_nr_cp(const srsran_pdsch_nr_t* q, if (put) { count += pdsch_nr_put_rb(&sf_symbols[re_idx], &symbols[count], &rvd_mask[rb * SRSRAN_NRE]); } else { - uint32_t k_begin = rb * SRSRAN_NRE; - uint32_t k_end = (rb + 1) * SRSRAN_NRE; - uint32_t k_dc_begin = q->carrier.nof_prb * SRSRAN_NRE / 2 - q->nof_zero_re_around_dc / 2; - uint32_t k_dc_end = q->carrier.nof_prb * SRSRAN_NRE / 2 + SRSRAN_CEIL(q->nof_zero_re_around_dc, 2); - if (k_begin <= k_dc_end && k_end >= k_dc_begin && q->nof_zero_re_around_dc > 0) { - for (uint32_t k = k_begin; k < k_end; k++) { - if (!rvd_mask[k]) { - if (k >= k_dc_begin && k < k_dc_end) { - symbols[count++] = 0.0f; - } else { - symbols[count++] = sf_symbols[q->carrier.nof_prb * l * SRSRAN_NRE + k]; - } - } - } - } else { - count += pdsch_nr_get_rb(&symbols[count], &sf_symbols[re_idx], &rvd_mask[rb * SRSRAN_NRE]); - } + count += pdsch_nr_get_rb(&symbols[count], &sf_symbols[re_idx], &rvd_mask[rb * SRSRAN_NRE]); } } } diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 13a2f351c..a5f61aacd 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -214,7 +214,6 @@ int main(int argc, char** argv) ue_dl_args.pdsch.sch.disable_simd = false; ue_dl_args.pdsch.sch.decoder_use_flooded = false; ue_dl_args.pdsch.measure_evm = true; - ue_dl_args.pdsch.disable_zero_re_around_dc = true; ue_dl_args.pdcch.disable_simd = false; ue_dl_args.pdcch.measure_evm = true; ue_dl_args.nof_max_prb = carrier.nof_prb; From aadbe6d8803b738e76359727b24824203771c674 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Apr 2021 11:25:58 +0200 Subject: [PATCH 36/46] Normalise NR PUSCH to maximum Tx power --- lib/src/phy/ue/ue_ul_nr.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index 74b313828..9f61052d7 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -123,6 +123,13 @@ int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q, // Generate signal srsran_ofdm_tx_sf(&q->ifft); + // Normalise to peak + uint32_t max_idx = srsran_vec_max_abs_ci(q->ifft.cfg.out_buffer, q->ifft.sf_sz); + float max_peak = cabsf(q->ifft.cfg.out_buffer[max_idx]); + if (isnormal(max_peak)) { + srsran_vec_sc_prod_cfc(q->ifft.cfg.out_buffer, 0.99f / max_peak, q->ifft.cfg.out_buffer, q->ifft.sf_sz); + } + return SRSRAN_SUCCESS; } From 77b6b60b82977419bc38b140c8583e9f792a0e06 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Apr 2021 13:09:57 +0200 Subject: [PATCH 37/46] Fix rach_cfg.nof_groupA_preambles --- lib/src/asn1/rrc_utils.cc | 4 +++- srsue/src/stack/mac/proc_ra.cc | 36 ++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/src/asn1/rrc_utils.cc b/lib/src/asn1/rrc_utils.cc index 3d3c1f787..d1428c407 100644 --- a/lib/src/asn1/rrc_utils.cc +++ b/lib/src/asn1/rrc_utils.cc @@ -379,7 +379,9 @@ void set_mac_cfg_t_rach_cfg_common(mac_cfg_t* cfg, const asn1::rrc::rach_cfg_com cfg->rach_cfg.messagePowerOffsetGroupB = asn1_type.preamb_info.preambs_group_a_cfg.msg_pwr_offset_group_b.to_number(); } else { - cfg->rach_cfg.nof_groupA_preambles = 0; + // If the field is not signalled, the size of the random access preambles group A [6] is equal to + // numberOfRA-Preambles + cfg->rach_cfg.nof_groupA_preambles = cfg->rach_cfg.nof_preambles; } // Power ramping diff --git a/srsue/src/stack/mac/proc_ra.cc b/srsue/src/stack/mac/proc_ra.cc index 4374bbe74..e14758ba8 100644 --- a/srsue/src/stack/mac/proc_ra.cc +++ b/srsue/src/stack/mac/proc_ra.cc @@ -111,10 +111,6 @@ void ra_proc::read_params() maskIndex = 0; // same } - if (rach_cfg.nof_groupA_preambles == 0) { - rach_cfg.nof_groupA_preambles = rach_cfg.nof_preambles; - } - phy_interface_mac_lte::prach_info_t prach_info = phy_h->prach_get_info(); delta_preamble_db = delta_preamble_db_table[prach_info.preamble_format % 5]; @@ -231,31 +227,43 @@ void ra_proc::initialization() void ra_proc::resource_selection() { ra_group_t sel_group; + uint32_t nof_groupB_preambles = rach_cfg.nof_preambles - rach_cfg.nof_groupA_preambles; - uint32_t nof_groupB_preambles = 0; - if (rach_cfg.nof_groupA_preambles > 0) { - nof_groupB_preambles = rach_cfg.nof_preambles - rach_cfg.nof_groupA_preambles; - } - + // If ra-PreambleIndex (Random Access Preamble) and ra-PRACH-MaskIndex (PRACH Mask Index) have been + // explicitly signalled and ra-PreambleIndex is not 000000: if (preambleIndex > 0) { - // Preamble is chosen by Higher layers (ie Network) + // the Random Access Preamble and the PRACH Mask Index are those explicitly signalled. sel_maskIndex = maskIndex; sel_preamble = (uint32_t)preambleIndex; } else { - // Preamble is chosen by MAC UE + // else the Random Access Preamble shall be selected by the UE as follows: if (!mux_unit->msg3_is_transmitted()) { - if (nof_groupB_preambles && + // If Msg3 has not yet been transmitted, the UE shall: + // if Random Access Preambles group B exists and if the potential message size (data available for transmission + // plus MAC header and, where required, MAC control elements) is greater than messageSizeGroupA and if the + // pathloss is less than P CMAX – preambleInitialReceivedTargetPower – deltaPreambleMsg3 – + // messagePowerOffsetGroupB, then: + if (nof_groupB_preambles > 0 && new_ra_msg_len > rach_cfg.messageSizeGroupA) { // Check also pathloss (Pcmax,deltaPreamble and powerOffset) + // select the Random Access Preambles group B; sel_group = RA_GROUP_B; } else { + // else: + // select the Random Access Preambles group A. sel_group = RA_GROUP_A; } last_msg3_group = sel_group; } else { + // else, if Msg3 is being retransmitted, the UE shall: + // select the same group of Random Access Preambles as was used for the preamble transmission attempt + // corresponding to the first transmission of Msg3. sel_group = last_msg3_group; } + + // randomly select a Random Access Preamble within the selected group. The random function shall be such + // that each of the allowed selections can be chosen with equal probability; if (sel_group == RA_GROUP_A) { - if (rach_cfg.nof_groupA_preambles) { + if (rach_cfg.nof_groupA_preambles > 0) { // randomly choose preamble from [0 nof_groupA_preambles) sel_preamble = rand() % rach_cfg.nof_groupA_preambles; } else { @@ -273,6 +281,8 @@ void ra_proc::resource_selection() return; } } + + // set PRACH Mask Index to 0. sel_maskIndex = 0; } From 6ed6da1f12b6d382639e97a26283d6b49b9d288d Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Thu, 8 Apr 2021 17:20:01 +0200 Subject: [PATCH 38/46] Refactor ue config for eutra and nr config section --- srsue/src/CMakeLists.txt | 4 ++-- srsue/src/main.cc | 24 +++++++++++++----------- srsue/src/ue.cc | 16 +++++++--------- srsue/ue.conf.example | 38 +++++++++++++++++++++++++++++--------- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index 48c2c89e3..63c55fbc5 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -48,8 +48,8 @@ endif(NOT SRSGUI_FOUND) # Checks that ue.conf.example is valid and it does not leak memory if RF fails if (ZEROMQ_FOUND) add_test(ue_rf_failure srsue ${CMAKE_SOURCE_DIR}/srsue/ue.conf.example --rf.device_name=zmq) - add_test(ue_rf_failure_max_channels srsue ${CMAKE_SOURCE_DIR}/srsue/ue.conf.example --rf.device_name=zmq --rf.nof_antennas=4 --rf.nof_carriers=5) - add_test(ue_rf_failure_exceeds_channels srsue ${CMAKE_SOURCE_DIR}/srsue/ue.conf.example --rf.device_name=zmq --rf.nof_antennas=5 --rf.nof_carriers=5) + add_test(ue_rf_failure_max_channels srsue ${CMAKE_SOURCE_DIR}/srsue/ue.conf.example --rf.device_name=zmq --rf.nof_antennas=4 --rat.eutra.nof_carriers=5) + add_test(ue_rf_failure_exceeds_channels srsue ${CMAKE_SOURCE_DIR}/srsue/ue.conf.example --rf.device_name=zmq --rf.nof_antennas=5 --rat.eutra.nof_carriers=5) endif(ZEROMQ_FOUND) ######################################################################## diff --git a/srsue/src/main.cc b/srsue/src/main.cc index a8fa32a91..3ba5e3196 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -66,13 +66,8 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("ue.phy", bpo::value(&args->phy.type)->default_value("lte"), "Type of the PHY [lte]") ("ue.stack", bpo::value(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]") - ("rf.dl_earfcn", bpo::value(&args->phy.dl_earfcn)->default_value("3400"), "Downlink EARFCN list") - ("rf.ul_earfcn", bpo::value(&args->phy.ul_earfcn), "Uplink EARFCN list. Optional.") - ("rf.dl_nr_arfcn", bpo::value(&args->phy.dl_nr_arfcn)->default_value("632628"), "Downlink NR-ARFCN list") ("rf.srate", bpo::value(&args->rf.srate_hz)->default_value(0.0), "Force Tx and Rx sampling rate in Hz") ("rf.freq_offset", bpo::value(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset") - ("rf.dl_freq", bpo::value(&args->phy.dl_freq)->default_value(-1), "Downlink Frequency (if positive overrides EARFCN)") - ("rf.ul_freq", bpo::value(&args->phy.ul_freq)->default_value(-1), "Uplink Frequency (if positive overrides EARFCN)") ("rf.rx_gain", bpo::value(&args->rf.rx_gain)->default_value(-1), "Front-end receiver gain") ("rf.tx_gain", bpo::value(&args->rf.tx_gain)->default_value(-1), "Front-end transmitter gain (all channels)") ("rf.tx_gain[0]", bpo::value(&args->rf.tx_gain_ch[0])->default_value(-1), "Front-end transmitter gain CH0") @@ -85,7 +80,6 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("rf.rx_gain[2]", bpo::value(&args->rf.rx_gain_ch[2])->default_value(-1), "Front-end receiver gain CH2") ("rf.rx_gain[3]", bpo::value(&args->rf.rx_gain_ch[3])->default_value(-1), "Front-end receiver gain CH3") ("rf.rx_gain[4]", bpo::value(&args->rf.rx_gain_ch[4])->default_value(-1), "Front-end receiver gain CH4") - ("rf.nof_carriers", bpo::value(&args->rf.nof_carriers)->default_value(1), "Number of carriers") ("rf.nof_antennas", bpo::value(&args->rf.nof_antennas)->default_value(1), "Number of antennas per carrier") ("rf.device_name", bpo::value(&args->rf.device_name)->default_value("auto"), "Front-end device name") @@ -115,11 +109,22 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("rf.bands.tx[4].min", bpo::value(&args->rf.ch_tx_bands[4].min)->default_value(0), "Lower frequency boundary for CH4-TX") ("rf.bands.tx[4].max", bpo::value(&args->rf.ch_tx_bands[4].max)->default_value(0), "Higher frequency boundary for CH4-TX") + ("rat.eutra.dl_earfcn", bpo::value(&args->phy.dl_earfcn)->default_value("3400"), "Downlink EARFCN list") + ("rat.eutra.ul_earfcn", bpo::value(&args->phy.ul_earfcn), "Uplink EARFCN list. Optional.") + ("rat.eutra.dl_freq", bpo::value(&args->phy.dl_freq)->default_value(-1), "Downlink Frequency (if positive overrides EARFCN)") + ("rat.eutra.ul_freq", bpo::value(&args->phy.ul_freq)->default_value(-1), "Uplink Frequency (if positive overrides EARFCN)") + ("rat.eutra.nof_carriers", bpo::value(&args->phy.nof_lte_carriers)->default_value(1), "Number of carriers") + + ("rat.nr.dl_arfcn", bpo::value(&args->phy.dl_nr_arfcn)->default_value("634240"), "Downlink NR-ARFCN list") + ("rat.nr.dl_freq", bpo::value(&args->phy.nr_freq_hz)->default_value(3513.6e6), "NR DL frequency") + ("rat.nr.nof_carriers", bpo::value(&args->phy.nof_nr_carriers)->default_value(0), "Number of NR carriers") + ("rat.nr.nof_prb", bpo::value(&args->phy.nr_nof_prb)->default_value(52), "NR carrier bandwidth") + ("rrc.feature_group", bpo::value(&args->stack.rrc.feature_group)->default_value(0xe6041000), "Hex value of the featureGroupIndicators field in the" "UECapabilityInformation message. Default 0xe6041000") ("rrc.ue_category", bpo::value(&args->stack.rrc.ue_category_str)->default_value(SRSRAN_UE_CATEGORY_DEFAULT), "UE Category (1 to 10)") - ("rrc.ue_category_dl", bpo::value(&args->stack.rrc.ue_category_dl)->default_value(-1), "UE Category DL v12 (valid values: 0, 4, 6, 7, 9 to 16)") - ("rrc.ue_category_ul", bpo::value(&args->stack.rrc.ue_category_ul)->default_value(-1), "UE Category UL v12 (valid values: 0, 3, 5, 7, 8 and 13)") + ("rrc.ue_category_dl", bpo::value(&args->stack.rrc.ue_category_dl)->default_value(-1), "UE Category DL v12 (valid values: 0, 4, 6, 7, 9 to 16)") + ("rrc.ue_category_ul", bpo::value(&args->stack.rrc.ue_category_ul)->default_value(-1), "UE Category UL v12 (valid values: 0, 3, 5, 7, 8 and 13)") ("rrc.release", bpo::value(&args->stack.rrc.release)->default_value(SRSRAN_RELEASE_DEFAULT), "UE Release (8 to 12)") ("rrc.mbms_service_id", bpo::value(&args->stack.rrc.mbms_service_id)->default_value(-1), "MBMS service id for autostart (-1 means disabled)") ("rrc.mbms_service_port", bpo::value(&args->stack.rrc.mbms_service_port)->default_value(4321), "Port of the MBMS service") @@ -438,9 +443,6 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("vnf.type", bpo::value(&args->phy.vnf_args.type)->default_value("ue"), "VNF instance type [gnb,ue]") ("vnf.addr", bpo::value(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface") ("vnf.port", bpo::value(&args->phy.vnf_args.bind_port)->default_value(3334), "Bind port") - ("nr.nof_carriers", bpo::value(&args->phy.nof_nr_carriers)->default_value(0), "Number of NR carriers") - ("nr.nof_prb", bpo::value(&args->phy.nr_nof_prb)->default_value(50), "NR carrier bandwidth") - ("nr.freq", bpo::value(&args->phy.nr_freq_hz)->default_value(2630e6), "NR carrier bandwidth") ; // Positional options - config file location diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index b125be16d..ebf492716 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -196,23 +196,21 @@ int ue::parse_args(const all_args_t& args_) return SRSRAN_ERROR; } - if (args.rf.nof_carriers > SRSRAN_MAX_CARRIERS) { - fprintf(stderr, "Maximum number of carriers exceeded (%d > %d)\n", args.rf.nof_carriers, SRSRAN_MAX_CARRIERS); - return SRSRAN_ERROR; - } + args.rf.nof_carriers = args.phy.nof_lte_carriers + args.phy.nof_nr_carriers; - if (args.rf.nof_carriers <= args.phy.nof_nr_carriers) { + if (args.rf.nof_carriers > SRSRAN_MAX_CARRIERS) { fprintf(stderr, - "Maximum number of carriers enough for NR and LTE (%d <= %d)\n", + "Maximum number of carriers exceeded (%d > %d) (nof_lte_carriers %d + nof_nr_carriers %d)\n", args.rf.nof_carriers, + SRSRAN_MAX_CARRIERS, + args.phy.nof_lte_carriers, args.phy.nof_nr_carriers); return SRSRAN_ERROR; } // replicate some RF parameter to make them available to PHY - args.phy.nof_lte_carriers = args.rf.nof_carriers - args.phy.nof_nr_carriers; - args.phy.nof_rx_ant = args.rf.nof_antennas; - args.phy.agc_enable = args.rf.rx_gain < 0.0f; + args.phy.nof_rx_ant = args.rf.nof_antennas; + args.phy.agc_enable = args.rf.rx_gain < 0.0f; // populate DL EARFCN list if (not args.phy.dl_earfcn.empty()) { diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index b9ac0e85c..6ec400c90 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -5,16 +5,10 @@ ##################################################################### # RF configuration # -# dl_earfcn: Downlink EARFCN code. # freq_offset: Uplink and Downlink optional frequency offset (in Hz) # tx_gain: Transmit gain (dB). # rx_gain: Optional receive gain (dB). If disabled, AGC if enabled # -# Optional parameters: -# dl_nr_arfcn: Downlink NR ARFCN for EN-DC -# dl_freq: Override DL frequency corresponding to dl_earfcn -# ul_freq: Override UL frequency corresponding to dl_earfcn -# nof_carriers: Number of carriers # nof_antennas: Number of antennas per carrier (all carriers have the same number of antennas) # device_name: Device driver family. Supported options: "auto" (uses first found), "UHD" or "bladeRF" # device_args: Arguments for the device driver. Options are "auto" or any string. @@ -29,13 +23,10 @@ # Default is auto (yes for UHD, no for rest) ##################################################################### [rf] -dl_earfcn = 3350 -#dl_nr_arfcn = 632628 freq_offset = 0 tx_gain = 80 #rx_gain = 40 -#nof_carriers = 1 #nof_antennas = 1 # For best performance in 2x2 MIMO and >= 15 MHz use the following device_args settings: @@ -52,6 +43,35 @@ tx_gain = 80 #device_name = zmq #device_args = tx_port=tcp://*:2001,rx_port=tcp://localhost:2000,id=ue,base_srate=23.04e6 +##################################################################### +# EUTRA RAT configuration +# +# dl_earfcn: Downlink EARFCN list. +# +# Optional parameters: +# dl_freq: Override DL frequency corresponding to dl_earfcn +# ul_freq: Override UL frequency corresponding to dl_earfcn +# nof_carriers: Number of carriers +##################################################################### +[rat.eutra] +dl_earfcn = 3350 +#nof_carriers = 1 + +##################################################################### +# NR RAT configuration +# +# Optional parameters: +# dl_arfcn: Downlink NR ARFCN for EN-DC +# dl_freq: Override DL frequency corresponding to rat.nr.dl_arfcn +# nof_carriers: Number of NR carriers (must be at least 1 for DC support) +# nof_prb: Number of PRBs +##################################################################### +[rat.nr] +# dl_arfcn = 634240 +# dl_freq = 3513.6e6 +# nof_prb = 52 +# nof_carriers = 0 + ##################################################################### # Packet capture configuration # From 75cd5e65e5a20374630b582f4a0337e742e7cb19 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 16 Apr 2021 21:06:04 +0200 Subject: [PATCH 39/46] Removed arfcn and freq, and nof_prbs from config file --- srsue/hdr/stack/rrc/rrc_nr.h | 1 + srsue/src/main.cc | 9 +++++---- srsue/src/ue.cc | 21 ++++----------------- srsue/ue.conf.example | 10 +++------- 4 files changed, 13 insertions(+), 28 deletions(-) diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 82edb843c..0dc3a35bf 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -40,6 +40,7 @@ struct core_less_args_t { struct rrc_nr_args_t { core_less_args_t coreless; + std::string supported_bands_nr_str; std::vector supported_bands_nr; std::vector supported_bands_eutra; std::string log_level; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 3ba5e3196..00588147f 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -115,10 +115,11 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("rat.eutra.ul_freq", bpo::value(&args->phy.ul_freq)->default_value(-1), "Uplink Frequency (if positive overrides EARFCN)") ("rat.eutra.nof_carriers", bpo::value(&args->phy.nof_lte_carriers)->default_value(1), "Number of carriers") - ("rat.nr.dl_arfcn", bpo::value(&args->phy.dl_nr_arfcn)->default_value("634240"), "Downlink NR-ARFCN list") - ("rat.nr.dl_freq", bpo::value(&args->phy.nr_freq_hz)->default_value(3513.6e6), "NR DL frequency") - ("rat.nr.nof_carriers", bpo::value(&args->phy.nof_nr_carriers)->default_value(0), "Number of NR carriers") - ("rat.nr.nof_prb", bpo::value(&args->phy.nr_nof_prb)->default_value(52), "NR carrier bandwidth") + ("rat.nr.bands", bpo::value(&args->stack.rrc_nr.supported_bands_nr_str)->default_value("78"), "Supported NR bands") + ("rat.nr.dl_arfcn", bpo::value(&args->phy.dl_nr_arfcn)->default_value("634240"), "Downlink NR-ARFCN list") + ("rat.nr.dl_freq", bpo::value(&args->phy.nr_freq_hz)->default_value(3513.6e6), "NR DL frequency") + ("rat.nr.nof_carriers", bpo::value(&args->phy.nof_nr_carriers)->default_value(0), "Number of NR carriers") + ("rat.nr.nof_prb", bpo::value(&args->phy.nr_nof_prb)->default_value(52), "NR carrier bandwidth") ("rrc.feature_group", bpo::value(&args->stack.rrc.feature_group)->default_value(0xe6041000), "Hex value of the featureGroupIndicators field in the" "UECapabilityInformation message. Default 0xe6041000") diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index ebf492716..19b15d55a 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -255,25 +255,12 @@ int ue::parse_args(const all_args_t& args_) // populate NR DL ARFCNs if (args.phy.nof_nr_carriers > 0) { - if (not args.phy.dl_nr_arfcn.empty()) { - // Parse list - srsran::string_parse_list(args.phy.dl_nr_arfcn, ',', args.phy.dl_nr_arfcn_list); - + if (not args.stack.rrc_nr.supported_bands_nr_str.empty()) { // Populates supported bands - for (uint32_t& arfcn : args.phy.dl_nr_arfcn_list) { - std::vector bands = bands_helper.get_bands_nr(arfcn); - for (const auto& band : bands) { - // make sure we don't add duplicates - if (std::find(args.stack.rrc_nr.supported_bands_nr.begin(), - args.stack.rrc_nr.supported_bands_nr.end(), - band) == args.stack.rrc_nr.supported_bands_nr.end()) { - args.stack.rrc_nr.supported_bands_nr.push_back(band); - } - } - } + srsran::string_parse_list(args.stack.rrc_nr.supported_bands_nr_str, ',', args.stack.rrc_nr.supported_bands_nr); } else { - logger.error("Error: dl_nr_arfcn list is empty"); - srsran::console("Error: dl_nr_arfcn list is empty\n"); + logger.error("Error: rat.nr.bands list is empty"); + srsran::console("Error: rat.nr.bands list is empty\n"); return SRSRAN_ERROR; } } diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 6ec400c90..2c0d52351 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -61,15 +61,11 @@ dl_earfcn = 3350 # NR RAT configuration # # Optional parameters: -# dl_arfcn: Downlink NR ARFCN for EN-DC -# dl_freq: Override DL frequency corresponding to rat.nr.dl_arfcn -# nof_carriers: Number of NR carriers (must be at least 1 for DC support) -# nof_prb: Number of PRBs +# bands: List of support NR bands seperated by a comma (default 78) +# nof_carriers: Number of NR carriers (must be at least 1 for NR support) ##################################################################### [rat.nr] -# dl_arfcn = 634240 -# dl_freq = 3513.6e6 -# nof_prb = 52 +# bands = 78 # nof_carriers = 0 ##################################################################### From c8d3e133dcdb379e664941b1d7738b46e07fb926 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 19 Apr 2021 19:11:20 +0200 Subject: [PATCH 40/46] ue: bump default RRC release announced to 15 --- srsue/hdr/stack/rrc/rrc.h | 2 +- srsue/src/main.cc | 2 +- srsue/ue.conf.example | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 06ae6302b..a6e474742 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -49,9 +49,9 @@ typedef struct { #define SRSRAN_UE_CATEGORY_DEFAULT "4" #define SRSRAN_UE_CATEGORY_MIN 1 #define SRSRAN_UE_CATEGORY_MAX 21 -#define SRSRAN_RELEASE_DEFAULT 8 #define SRSRAN_RELEASE_MIN 8 #define SRSRAN_RELEASE_MAX 15 +#define SRSRAN_RELEASE_DEFAULT (SRSRAN_RELEASE_MAX) using srsran::byte_buffer_t; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 00588147f..64dd90d7f 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -126,7 +126,7 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("rrc.ue_category", bpo::value(&args->stack.rrc.ue_category_str)->default_value(SRSRAN_UE_CATEGORY_DEFAULT), "UE Category (1 to 10)") ("rrc.ue_category_dl", bpo::value(&args->stack.rrc.ue_category_dl)->default_value(-1), "UE Category DL v12 (valid values: 0, 4, 6, 7, 9 to 16)") ("rrc.ue_category_ul", bpo::value(&args->stack.rrc.ue_category_ul)->default_value(-1), "UE Category UL v12 (valid values: 0, 3, 5, 7, 8 and 13)") - ("rrc.release", bpo::value(&args->stack.rrc.release)->default_value(SRSRAN_RELEASE_DEFAULT), "UE Release (8 to 12)") + ("rrc.release", bpo::value(&args->stack.rrc.release)->default_value(SRSRAN_RELEASE_DEFAULT), "UE Release (8 to 15)") ("rrc.mbms_service_id", bpo::value(&args->stack.rrc.mbms_service_id)->default_value(-1), "MBMS service id for autostart (-1 means disabled)") ("rrc.mbms_service_port", bpo::value(&args->stack.rrc.mbms_service_port)->default_value(4321), "Port of the MBMS service") diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 2c0d52351..3632f9c05 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -148,7 +148,7 @@ imei = 353490069873319 # RRC configuration # # ue_category: Sets UE category (range 1-5). Default: 4 -# release: UE Release (8 to 10) +# release: UE Release (8 to 15) # feature_group: Hex value of the featureGroupIndicators field in the # UECapabilityInformation message. Default 0xe6041000 # mbms_service_id: MBMS service id for autostarting MBMS reception @@ -157,7 +157,7 @@ imei = 353490069873319 ##################################################################### [rrc] #ue_category = 4 -#release = 8 +#release = 15 #feature_group = 0xe6041000 #mbms_service_id = -1 #mbms_service_port = 4321 From 5700b090ea6e96a808b38e6a7c640dd0a8bb4714 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 19 Apr 2021 18:53:14 +0200 Subject: [PATCH 41/46] worker_pool: set log level for PHY-NR logger and use for PRACH log level for PHY-NR wasn't set so: 16:00:32.202953 [PHY-NR ] [I] [ 8024] Setting RAR Grant rnti=4602 dci=rar hop=0 f_alloc=0x32 t_alloc=0x1 mcs=4 tpc=3 csi=0 was always printed. Also use the logger for the PRACH --- srsue/src/phy/nr/worker_pool.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 9a3ab0191..b15b677a2 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -49,10 +49,11 @@ bool worker_pool::init(const phy_args_nr_t& args, phy_common* common, stack_inte } } + // Set PHY loglevel + logger.set_level(srslog::str_to_basic_level(args.log.phy_level)); + // Initialise PRACH - auto& prach_log = srslog::fetch_basic_logger("PRACH-NR"); - prach_log.set_level(srslog::str_to_basic_level(args.log.phy_level)); - prach_buffer = std::unique_ptr(new prach(prach_log)); + prach_buffer = std::unique_ptr(new prach(logger)); prach_buffer->init(phy_state.args.dl.nof_max_prb); return true; From 8fffbb34c2dc1cecc81031e2b42007b472ec931e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 19 Apr 2021 15:07:43 +0200 Subject: [PATCH 42/46] update changelog and version for 21.04 --- CHANGELOG | 12 ++++++++++++ README.md | 5 +++-- cmake/modules/SRSRANVersion.cmake | 6 +++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 728322820..0569c19bd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,18 @@ Change Log for Releases ======================= +## 21.04 + * Rename project from srsLTE to srsRAN + * Add initial 5G NSA support to srsUE (including x86-optimized FEC and PHY layer) + * Add PDCP discard support + * Add UL power control, measurement gaps and a new proportional fair scheduler to srsENB + * Extend GTP-U tunneling to support tunnel forwarding over S1 + * Optimize many data structures, remove dynamic memory allocations in data plane + * Improved S1AP error handling and enhanced event reporting + * Update ASN.1 packing/unpacking, RRC to Rel 15.11, S1AP to Rel 16.1 + * Update PCAP writer to use UDP framing + * Other bug-fixes and improved stability and performance in all parts + ## 20.10.1 * Fix bug in srsENB that effectively disabled UL HARQ diff --git a/README.md b/README.md index da526758c..381166fc5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ srsRAN is a 4G/5G software radio suite developed by SRS (www.softwareradiosystem See the srsRAN project pages (www.srsran.com) for documentation, guides and project news. It includes: - * srsUE - a complete SDR LTE UE application featuring all layers from PHY to IP + * srsUE - a complete SDR 4G/5G UE application featuring all layers from PHY to IP * srsENB - a complete SDR LTE eNodeB application * srsEPC - a light-weight LTE core network implementation with MME, HSS and S/P-GW * a highly modular set of common libraries for PHY, MAC, RLC, PDCP, RRC, NAS, S1AP and GW layers. @@ -58,7 +58,8 @@ srsENB Features --------------- * FDD configuration - * Round Robin MAC scheduler with FAPI-like C++ API + * IntraENB- and InterENB (S1) mobility support + * Proportional-fair and Round Robin MAC scheduler with FAPI-like C++ API * SR support * Periodic and Aperiodic CQI feedback support * Standard S1AP and GTP-U interfaces to the Core Network diff --git a/cmake/modules/SRSRANVersion.cmake b/cmake/modules/SRSRANVersion.cmake index 7843a6dfb..51559a0af 100644 --- a/cmake/modules/SRSRANVersion.cmake +++ b/cmake/modules/SRSRANVersion.cmake @@ -6,8 +6,8 @@ # the distribution. # -SET(SRSRAN_VERSION_MAJOR 20) -SET(SRSRAN_VERSION_MINOR 10) -SET(SRSRAN_VERSION_PATCH 1) +SET(SRSRAN_VERSION_MAJOR 21) +SET(SRSRAN_VERSION_MINOR 04) +SET(SRSRAN_VERSION_PATCH 0) SET(SRSRAN_VERSION_STRING "${SRSRAN_VERSION_MAJOR}.${SRSRAN_VERSION_MINOR}.${SRSRAN_VERSION_PATCH}") SET(SRSRAN_SOVERSION 0) From 6b41ae7e8b982af7cd00dd3814952dbfdd53b878 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Tue, 13 Apr 2021 15:56:51 +0200 Subject: [PATCH 43/46] Updated PDCP config struct for rat type --- .../srsran/interfaces/pdcp_interface_types.h | 7 +++++-- lib/include/srsran/upper/pdcp.h | 11 +++++++--- lib/include/srsran/upper/pdcp_entity_base.h | 3 ++- lib/src/asn1/rrc_nr_utils.cc | 3 ++- lib/src/asn1/rrc_utils.cc | 9 ++++++--- lib/src/upper/pdcp.cc | 20 ++++++++++++++++++- lib/test/upper/pdcp_lte_test.h | 3 ++- lib/test/upper/pdcp_lte_test_discard_sdu.cc | 6 ++++-- lib/test/upper/pdcp_lte_test_rx.cc | 3 ++- lib/test/upper/pdcp_lte_test_status_report.cc | 15 +++++++++----- lib/test/upper/pdcp_nr_test.h | 3 ++- lib/test/upper/pdcp_nr_test_discard_sdu.cc | 3 ++- lib/test/upper/pdcp_nr_test_rx.cc | 3 ++- lib/test/upper/pdcp_nr_test_tx.cc | 3 ++- srsenb/src/stack/rrc/rrc_nr.cc | 3 ++- srsue/src/stack/rrc/rrc_nr.cc | 3 ++- srsue/src/stack/ue_stack_lte.cc | 2 +- 17 files changed, 73 insertions(+), 27 deletions(-) diff --git a/lib/include/srsran/interfaces/pdcp_interface_types.h b/lib/include/srsran/interfaces/pdcp_interface_types.h index 399c3c534..f51e232a4 100644 --- a/lib/include/srsran/interfaces/pdcp_interface_types.h +++ b/lib/include/srsran/interfaces/pdcp_interface_types.h @@ -126,7 +126,8 @@ public: uint8_t sn_len_, pdcp_t_reordering_t t_reordering_, pdcp_discard_timer_t discard_timer_, - bool status_report_required_) : + bool status_report_required_, + srsran::srsran_rat_t rat_) : bearer_id(bearer_id_), rb_type(rb_type_), tx_direction(tx_direction_), @@ -134,7 +135,8 @@ public: sn_len(sn_len_), t_reordering(t_reordering_), discard_timer(discard_timer_), - status_report_required(status_report_required_) + status_report_required(status_report_required_), + rat(rat_) { hdr_len_bytes = ceilf((float)sn_len / 8); } @@ -148,6 +150,7 @@ public: pdcp_t_reordering_t t_reordering = pdcp_t_reordering_t::ms500; pdcp_discard_timer_t discard_timer = pdcp_discard_timer_t::infinity; + srsran::srsran_rat_t rat = srsran::srsran_rat_t::lte; bool status_report_required = false; diff --git a/lib/include/srsran/upper/pdcp.h b/lib/include/srsran/upper/pdcp.h index d101bf70d..a3b37c71d 100644 --- a/lib/include/srsran/upper/pdcp.h +++ b/lib/include/srsran/upper/pdcp.h @@ -26,6 +26,10 @@ class pdcp : public srsue::pdcp_interface_rlc, public srsue::pdcp_interface_rrc public: pdcp(srsran::task_sched_handle task_sched_, const char* logname); virtual ~pdcp(); + void init(srsue::rlc_interface_pdcp* rlc_, + srsue::rrc_interface_pdcp* rrc_, + srsue::rrc_interface_pdcp* rrc_nr_, + srsue::gw_interface_pdcp* gw_); void init(srsue::rlc_interface_pdcp* rlc_, srsue::rrc_interface_pdcp* rrc_, srsue::gw_interface_pdcp* gw_); void stop(); @@ -69,9 +73,10 @@ public: void reset_metrics(); private: - srsue::rlc_interface_pdcp* rlc = nullptr; - srsue::rrc_interface_pdcp* rrc = nullptr; - srsue::gw_interface_pdcp* gw = nullptr; + srsue::rlc_interface_pdcp* rlc = nullptr; + srsue::rrc_interface_pdcp* rrc = nullptr; + srsue::rrc_interface_pdcp* rrc_nr = nullptr; + srsue::gw_interface_pdcp* gw = nullptr; srsran::task_sched_handle task_sched; srslog::basic_logger& logger; diff --git a/lib/include/srsran/upper/pdcp_entity_base.h b/lib/include/srsran/upper/pdcp_entity_base.h index 29035197c..55b5d768e 100644 --- a/lib/include/srsran/upper/pdcp_entity_base.h +++ b/lib/include/srsran/upper/pdcp_entity_base.h @@ -151,7 +151,8 @@ protected: PDCP_SN_LEN_12, pdcp_t_reordering_t::ms500, pdcp_discard_timer_t::infinity, - false}; + false, + srsran_rat_t::lte}; srsran::as_security_config_t sec_cfg = {}; diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index f5965107c..70497e0b7 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -212,7 +212,8 @@ srsran::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue sn_len, t_reordering, discard_timer, - false); + false, + srsran_rat_t::nr); return cfg; } diff --git a/lib/src/asn1/rrc_utils.cc b/lib/src/asn1/rrc_utils.cc index d1428c407..d3a1dc382 100644 --- a/lib/src/asn1/rrc_utils.cc +++ b/lib/src/asn1/rrc_utils.cc @@ -207,7 +207,8 @@ srsran::pdcp_config_t make_srb_pdcp_config_t(const uint8_t bearer_id, bool is_ue PDCP_SN_LEN_5, pdcp_t_reordering_t::ms500, pdcp_discard_timer_t::infinity, - false); + false, + srsran_rat_t::lte); return cfg; } @@ -220,7 +221,8 @@ srsran::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue PDCP_SN_LEN_12, pdcp_t_reordering_t::ms500, pdcp_discard_timer_t::infinity, - false); + false, + srsran_rat_t::lte); return cfg; } @@ -325,7 +327,8 @@ srsran::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue sn_len, t_reordering, discard_timer, - status_report_required); + status_report_required, + srsran_rat_t::lte); return cfg; } diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 9bf1e1623..88bc1fa0c 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -30,6 +30,15 @@ pdcp::~pdcp() pdcp_array_mrb.clear(); } +void pdcp::init(srsue::rlc_interface_pdcp* rlc_, + srsue::rrc_interface_pdcp* rrc_, + srsue::rrc_interface_pdcp* rrc_nr_, + srsue::gw_interface_pdcp* gw_) +{ + init(rlc_, rrc_, gw_); + rrc_nr = rrc_nr_; +} + void pdcp::init(srsue::rlc_interface_pdcp* rlc_, srsue::rrc_interface_pdcp* rrc_, srsue::gw_interface_pdcp* gw_) { rlc = rlc_; @@ -95,7 +104,16 @@ void pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg) if (not valid_lcid(lcid)) { std::unique_ptr entity; // For now we create an pdcp entity lte for nr due to it's maturity - entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid}); + if (cfg.rat == srsran::srsran_rat_t::lte) { + entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_sched, logger, lcid}); + } else if (cfg.rat == srsran::srsran_rat_t::nr) { + if (rrc_nr == nullptr) { + logger.warning("Cannot add PDCP entity - missing rrc_nr parent pointer"); + return; + } + entity.reset(new pdcp_entity_lte{rlc, rrc_nr, gw, task_sched, logger, lcid}); + } + if (not entity->configure(cfg)) { logger.error("Can not configure PDCP entity"); return; diff --git a/lib/test/upper/pdcp_lte_test.h b/lib/test/upper/pdcp_lte_test.h index 733b686f3..a106b1001 100644 --- a/lib/test/upper/pdcp_lte_test.h +++ b/lib/test/upper/pdcp_lte_test.h @@ -92,7 +92,8 @@ srsran::unique_byte_buffer_t gen_expected_pdu(const srsran::unique_byte_buffer_t pdcp_sn_len, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::infinity, - false}; + false, + srsran::srsran_rat_t::lte}; pdcp_lte_test_helper pdcp_hlp(cfg, sec_cfg, logger); srsran::pdcp_entity_lte* pdcp = &pdcp_hlp.pdcp; diff --git a/lib/test/upper/pdcp_lte_test_discard_sdu.cc b/lib/test/upper/pdcp_lte_test_discard_sdu.cc index 0d230dd62..e869ee080 100644 --- a/lib/test/upper/pdcp_lte_test_discard_sdu.cc +++ b/lib/test/upper/pdcp_lte_test_discard_sdu.cc @@ -26,7 +26,8 @@ int test_tx_sdu_notify(const srsran::pdcp_lte_state_t& init_state, srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, discard_timeout, - false}; + false, + srsran::srsran_rat_t::lte}; pdcp_lte_test_helper pdcp_hlp(cfg, sec_cfg, logger); srsran::pdcp_entity_lte* pdcp = &pdcp_hlp.pdcp; @@ -75,7 +76,8 @@ int test_tx_sdu_discard(const srsran::pdcp_lte_state_t& init_state, srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, discard_timeout, - false}; + false, + srsran::srsran_rat_t::lte}; pdcp_lte_test_helper pdcp_hlp(cfg, sec_cfg, logger); srsran::pdcp_entity_lte* pdcp = &pdcp_hlp.pdcp; diff --git a/lib/test/upper/pdcp_lte_test_rx.cc b/lib/test/upper/pdcp_lte_test_rx.cc index 98fd28a4f..7138a981c 100644 --- a/lib/test/upper/pdcp_lte_test_rx.cc +++ b/lib/test/upper/pdcp_lte_test_rx.cc @@ -31,7 +31,8 @@ int test_rx(std::vector events, pdcp_sn_len, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::infinity, - false}; + false, + srsran::srsran_rat_t::lte}; pdcp_lte_test_helper pdcp_hlp_rx(cfg_rx, sec_cfg, logger); srsran::pdcp_entity_lte* pdcp_rx = &pdcp_hlp_rx.pdcp; diff --git a/lib/test/upper/pdcp_lte_test_status_report.cc b/lib/test/upper/pdcp_lte_test_status_report.cc index 69586d3d3..ab7cca77d 100644 --- a/lib/test/upper/pdcp_lte_test_status_report.cc +++ b/lib/test/upper/pdcp_lte_test_status_report.cc @@ -24,7 +24,8 @@ int test_tx_status_report(const srsran::pdcp_lte_state_t& init_state, srslog::ba srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::ms500, - true}; + true, + srsran::srsran_rat_t::lte}; srsran::pdcp_config_t cfg_rx = {1, srsran::PDCP_RB_IS_DRB, @@ -33,7 +34,8 @@ int test_tx_status_report(const srsran::pdcp_lte_state_t& init_state, srslog::ba srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::ms500, - true}; + true, + srsran::srsran_rat_t::lte}; // Setup TX pdcp_lte_test_helper pdcp_hlp_tx(cfg_tx, sec_cfg, logger); @@ -128,7 +130,8 @@ int test_tx_wraparound_status_report(const srsran::pdcp_lte_state_t& init_state, srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::ms500, - true}; + true, + srsran::srsran_rat_t::lte}; srsran::pdcp_config_t cfg_rx = {1, srsran::PDCP_RB_IS_DRB, @@ -137,7 +140,8 @@ int test_tx_wraparound_status_report(const srsran::pdcp_lte_state_t& init_state, srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::ms500, - true}; + true, + srsran::srsran_rat_t::lte}; // Setup TX pdcp_lte_test_helper pdcp_hlp_tx(cfg_tx, sec_cfg, logger); @@ -240,7 +244,8 @@ int test_rx_status_report(const srsran::pdcp_lte_state_t& init_state, srslog::ba srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::ms500, - true}; + true, + srsran::srsran_rat_t::lte}; pdcp_lte_test_helper pdcp_hlp(cfg, sec_cfg, logger); srsran::pdcp_entity_lte* pdcp = &pdcp_hlp.pdcp; diff --git a/lib/test/upper/pdcp_nr_test.h b/lib/test/upper/pdcp_nr_test.h index 88ab0c1c3..40fc24b7d 100644 --- a/lib/test/upper/pdcp_nr_test.h +++ b/lib/test/upper/pdcp_nr_test.h @@ -125,7 +125,8 @@ srsran::unique_byte_buffer_t gen_expected_pdu(const srsran::unique_byte_buffer_t pdcp_sn_len, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::infinity, - false}; + false, + srsran::srsran_rat_t::nr}; pdcp_nr_test_helper pdcp_hlp(cfg, sec_cfg, logger); srsran::pdcp_entity_nr* pdcp = &pdcp_hlp.pdcp; diff --git a/lib/test/upper/pdcp_nr_test_discard_sdu.cc b/lib/test/upper/pdcp_nr_test_discard_sdu.cc index 6b3da0944..bbd21bade 100644 --- a/lib/test/upper/pdcp_nr_test_discard_sdu.cc +++ b/lib/test/upper/pdcp_nr_test_discard_sdu.cc @@ -27,7 +27,8 @@ int test_tx_sdu_discard(const pdcp_initial_state& init_state, srsran::PDCP_SN_LEN_12, srsran::pdcp_t_reordering_t::ms500, discard_timeout, - false}; + false, + srsran::srsran_rat_t::nr}; pdcp_nr_test_helper pdcp_hlp(cfg, sec_cfg, logger); srsran::pdcp_entity_nr* pdcp = &pdcp_hlp.pdcp; diff --git a/lib/test/upper/pdcp_nr_test_rx.cc b/lib/test/upper/pdcp_nr_test_rx.cc index 414009891..3f5397f3a 100644 --- a/lib/test/upper/pdcp_nr_test_rx.cc +++ b/lib/test/upper/pdcp_nr_test_rx.cc @@ -30,7 +30,8 @@ int test_rx(std::vector events, pdcp_sn_len, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::infinity, - false}; + false, + srsran::srsran_rat_t::nr}; pdcp_nr_test_helper pdcp_hlp_rx(cfg_rx, sec_cfg, logger); srsran::pdcp_entity_nr* pdcp_rx = &pdcp_hlp_rx.pdcp; diff --git a/lib/test/upper/pdcp_nr_test_tx.cc b/lib/test/upper/pdcp_nr_test_tx.cc index acdfc7b19..452f72450 100644 --- a/lib/test/upper/pdcp_nr_test_tx.cc +++ b/lib/test/upper/pdcp_nr_test_tx.cc @@ -29,7 +29,8 @@ int test_tx(uint32_t n_packets, pdcp_sn_len, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::infinity, - false}; + false, + srsran::srsran_rat_t::nr}; pdcp_nr_test_helper pdcp_hlp(cfg, sec_cfg, logger); srsran::pdcp_entity_nr* pdcp = &pdcp_hlp.pdcp; diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 9ec9719da..e874cf35f 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -65,7 +65,8 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, srsran::PDCP_SN_LEN_18, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::infinity, - false}; + false, + srsran::srsran_rat_t::nr}; pdcp->add_bearer(cfg.coreless.rnti, cfg.coreless.drb_lcid, pdcp_cnfg); logger.info("Started"); diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index dd7e94ed6..556ba516c 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -79,7 +79,8 @@ void rrc_nr::init_core_less() srsran::PDCP_SN_LEN_18, srsran::pdcp_t_reordering_t::ms500, srsran::pdcp_discard_timer_t::ms100, - false}; + false, + srsran_rat_t::nr}; pdcp->add_bearer(args.coreless.drb_lcid, pdcp_cnfg); return; diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 5a92b142e..991d9697e 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -202,7 +202,7 @@ int ue_stack_lte::init(const stack_args_t& args_) mac.init(phy, &rlc, &rrc); rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); - pdcp.init(&rlc, &rrc, gw); + pdcp.init(&rlc, &rrc, &rrc_nr, gw); nas.init(usim.get(), &rrc, gw, args.nas); mac_nr_args_t mac_nr_args = {}; From 91ff8a2e6d3ed1a94330ca12d947e34f1dae1820 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Tue, 13 Apr 2021 14:23:00 +0200 Subject: [PATCH 44/46] Add rrc_nr to rlc init function --- .../interfaces/nr_common_interface_types.h | 73 ++++++++++- lib/include/srsran/upper/rlc.h | 10 +- lib/src/upper/rlc.cc | 115 +++++++++++------- srsue/hdr/stack/rrc/rrc_nr.h | 2 +- srsue/src/stack/rrc/rrc_nr.cc | 21 +++- srsue/src/stack/ue_stack_lte.cc | 2 +- 6 files changed, 170 insertions(+), 53 deletions(-) diff --git a/lib/include/srsran/interfaces/nr_common_interface_types.h b/lib/include/srsran/interfaces/nr_common_interface_types.h index 1e90fe9a1..7ebbf5d96 100644 --- a/lib/include/srsran/interfaces/nr_common_interface_types.h +++ b/lib/include/srsran/interfaces/nr_common_interface_types.h @@ -16,11 +16,80 @@ namespace srsran { // NR Radio Bearer Id +// maxDRB = 29 +enum rb_id_nr_t { + NR_SRB0, + NR_SRB1, + NR_SRB2, + NR_SRB3, + NR_DRB1, + NR_DRB2, + NR_DRB3, + NR_DRB4, + NR_DRB5, + NR_DRB6, + NR_DRB7, + NR_DRB8, + NR_DRB9, + NR_DRB10, + NR_DRB11, + NR_DRB12, + NR_DRB13, + NR_DRB14, + NR_DRB15, + NR_DRB16, + NR_DRB17, + NR_DRB18, + NR_DRB19, + NR_DRB20, + NR_DRB21, + NR_DRB22, + NR_DRB23, + NR_DRB24, + NR_DRB25, + NR_DRB26, + NR_DRB27, + NR_DRB28, + NR_DRB29, + RB_ID_NR_N_ITEMS +}; -enum rb_id_nr_t { NR_SRB0, NR_SRB1, NR_SRB2, NR_SRB3, NR_DRB1, RB_ID_NR_N_ITEMS }; inline const char* to_string(rb_id_nr_t rb_id) { - const static char* names[] = {"SRB0", "SRB1", "SRB2", "SRB3", "DRB1"}; + const static char* names[] = { + "SRB0", + "SRB1", + "SRB2", + "SRB3", + "DRB1", + "DRB2", + "DRB3", + "DRB4", + "DRB5", + "DRB6", + "DRB7", + "DRB8", + "DRB9", + "DRB10", + "DRB11", + "DRB13", + "DRB14", + "DRB15", + "DRB16", + "DRB17", + "DRB18", + "DRB19", + "DRB20", + "DRB21", + "DRB22", + "DRB23", + "DRB24", + "DRB25", + "DRB26", + "DRB27", + "DRB28", + "DRB29", + }; return (rb_id < rb_id_nr_t::RB_ID_NR_N_ITEMS) ? names[rb_id] : "invalid bearer id"; } inline bool is_srb(rb_id_nr_t lcid) diff --git a/lib/include/srsran/upper/rlc.h b/lib/include/srsran/upper/rlc.h index 533cd7a11..75fff9a98 100644 --- a/lib/include/srsran/upper/rlc.h +++ b/lib/include/srsran/upper/rlc.h @@ -39,6 +39,13 @@ public: srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_, uint32_t lcid_); + + void init(srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srsue::rrc_interface_rlc* rrc_nr_, + srsran::timer_handler* timers_, + uint32_t lcid_); + void init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_, @@ -87,10 +94,11 @@ public: private: void reset_metrics(); - byte_buffer_pool* pool = nullptr; srslog::basic_logger& logger; + byte_buffer_pool* pool = nullptr; srsue::pdcp_interface_rlc* pdcp = nullptr; srsue::rrc_interface_rlc* rrc = nullptr; + srsue::rrc_interface_rlc* rrc_nr = nullptr; srsran::timer_handler* timers = nullptr; typedef std::map rlc_map_t; diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index de922121c..030c28137 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -45,6 +45,16 @@ rlc::~rlc() pthread_rwlock_destroy(&rwlock); } +void rlc::init(srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srsue::rrc_interface_rlc* rrc_nr_, + srsran::timer_handler* timers_, + uint32_t lcid_) +{ + init(pdcp_, rrc_, timers_, lcid_); + rrc_nr = rrc_nr_; +} + void rlc::init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_, @@ -148,7 +158,7 @@ void rlc::reestablish() void rlc::reestablish(uint32_t lcid) { if (valid_lcid(lcid)) { - logger.info("Reestablishing %s", rrc->get_rb_name(lcid)); + logger.info("Reestablishing LCID %d", lcid); rlc_array.at(lcid)->reestablish(); } else { logger.warning("RLC LCID %d doesn't exist.", lcid); @@ -395,6 +405,12 @@ void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) rlc_common* rlc_entity = nullptr; + // Check this for later rrc_nr pointer access + if (cnfg.rat == srsran::srsran_rat_t::nr && rrc_nr == nullptr) { + logger.error("Cannot add/modify RLC entity - missing rrc_nr parent pointer for rat type nr"); + return; + } + if (cnfg.rlc_mode != rlc_mode_t::tm and rlc_array.find(lcid) != rlc_array.end()) { if (rlc_array[lcid]->get_mode() != cnfg.rlc_mode) { logger.info("Switching RLC entity type. Recreating it."); @@ -403,46 +419,51 @@ void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) } if (not valid_lcid(lcid)) { - if (cnfg.rat == srsran_rat_t::lte) { - switch (cnfg.rlc_mode) { - case rlc_mode_t::tm: - rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc); - break; - case rlc_mode_t::am: - rlc_entity = new rlc_am_lte(logger, lcid, pdcp, rrc, timers); - break; - case rlc_mode_t::um: - rlc_entity = new rlc_um_lte(logger, lcid, pdcp, rrc, timers); - break; - default: - logger.error("Cannot add RLC entity - invalid mode"); - return; - } - if (rlc_entity != nullptr) { - rlc_entity->set_bsr_callback(bsr_callback); - } - } else if (cnfg.rat == srsran_rat_t::nr) { - switch (cnfg.rlc_mode) { - case rlc_mode_t::tm: - rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc); - break; - case rlc_mode_t::um: - rlc_entity = new rlc_um_nr(logger, lcid, pdcp, rrc, timers); - break; - default: - logger.error("Cannot add RLC entity - invalid mode"); - return; - } - } else { - logger.error("RAT not supported"); - return; + switch (cnfg.rat) { + case srsran_rat_t::lte: + switch (cnfg.rlc_mode) { + case rlc_mode_t::tm: + rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc); + break; + case rlc_mode_t::am: + rlc_entity = new rlc_am_lte(logger, lcid, pdcp, rrc, timers); + break; + case rlc_mode_t::um: + rlc_entity = new rlc_um_lte(logger, lcid, pdcp, rrc, timers); + break; + default: + logger.error("Cannot add RLC entity - invalid mode"); + return; + } + if (rlc_entity != nullptr) { + rlc_entity->set_bsr_callback(bsr_callback); + } + break; + case srsran_rat_t::nr: + switch (cnfg.rlc_mode) { + case rlc_mode_t::tm: + rlc_entity = new rlc_tm(logger, lcid, pdcp, rrc_nr); + break; + case rlc_mode_t::um: + rlc_entity = new rlc_um_nr(logger, lcid, pdcp, rrc_nr, timers); + break; + default: + logger.error("Cannot add RLC entity - invalid mode"); + return; + } + break; + default: + logger.error("RAT not supported"); + return; } if (not rlc_array.insert(rlc_map_pair_t(lcid, rlc_entity)).second) { logger.error("Error inserting RLC entity in to array."); goto delete_and_exit; } - logger.info("Added radio bearer %s in %s", rrc->get_rb_name(lcid), to_string(cnfg.rlc_mode).c_str()); + + logger.info( + "Added %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode).c_str()); rlc_entity = NULL; } @@ -454,7 +475,8 @@ void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) } } - logger.info("Configured radio bearer %s in %s", rrc->get_rb_name(lcid), to_string(cnfg.rlc_mode).c_str()); + logger.info( + "Configured %s radio bearer with LCID %d in %s", to_string(cnfg.rat), lcid, to_string(cnfg.rlc_mode).c_str()); delete_and_exit: if (rlc_entity) { @@ -501,9 +523,9 @@ void rlc::del_bearer(uint32_t lcid) it->second->stop(); delete (it->second); rlc_array.erase(it); - logger.warning("Deleted RLC bearer %s", rrc->get_rb_name(lcid)); + logger.info("Deleted RLC bearer with LCID %d", lcid); } else { - logger.error("Can't delete bearer %s. Bearer doesn't exist.", rrc->get_rb_name(lcid)); + logger.error("Can't delete bearer with LCID %d. Bearer doesn't exist.", lcid); } } @@ -516,9 +538,9 @@ void rlc::del_bearer_mrb(uint32_t lcid) it->second->stop(); delete (it->second); rlc_array_mrb.erase(it); - logger.warning("Deleted RLC MRB bearer %s", rrc->get_rb_name(lcid)); + logger.warning("Deleted RLC MRB bearer with LCID %d", lcid); } else { - logger.error("Can't delete bearer %s. Bearer doesn't exist.", rrc->get_rb_name(lcid)); + logger.error("Can't delete bearer with LCID %d. Bearer doesn't exist.", lcid); } } @@ -544,8 +566,7 @@ void rlc::change_lcid(uint32_t old_lcid, uint32_t new_lcid) logger.error("Error during LCID change of RLC bearer from %d to %d", old_lcid, new_lcid); } } else { - logger.error("Can't change LCID of bearer %s from %d to %d. Bearer doesn't exist or new LCID already occupied.", - rrc->get_rb_name(old_lcid), + logger.error("Can't change LCID of bearer LCID %d to %d. Bearer doesn't exist or new LCID already occupied.", old_lcid, new_lcid); } @@ -556,26 +577,26 @@ void rlc::suspend_bearer(uint32_t lcid) { if (valid_lcid(lcid)) { if (rlc_array.at(lcid)->suspend()) { - logger.info("Suspended radio bearer %s", rrc->get_rb_name(lcid)); + logger.info("Suspended radio bearer with LCID %d", lcid); } else { logger.error("Error suspending RLC entity: bearer already suspended."); } } else { - logger.error("Suspending bearer: bearer %s not configured.", rrc->get_rb_name(lcid)); + logger.error("Suspending bearer: bearer with LCID %d not configured.", lcid); } } void rlc::resume_bearer(uint32_t lcid) { - logger.info("Resuming radio bearer %s", rrc->get_rb_name(lcid)); + logger.info("Resuming radio LCID %d", lcid); if (valid_lcid(lcid)) { if (rlc_array.at(lcid)->resume()) { - logger.info("Resumed radio bearer %s", rrc->get_rb_name(lcid)); + logger.info("Resumed radio LCID %d", lcid); } else { logger.error("Error resuming RLC entity: bearer not suspended."); } } else { - logger.error("Resuming bearer: bearer %s not configured.", rrc->get_rb_name(lcid)); + logger.error("Resuming bearer: bearer with LCID %d not configured.", lcid); } } diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 0dc3a35bf..b69d1a9c5 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -173,7 +173,7 @@ private: // RRC constants and timers srsran::timer_handler* timers = nullptr; - const char* get_rb_name(uint32_t lcid) final { return srsran::to_string((srsran::rb_id_nr_t)lcid); } + const char* get_rb_name(uint32_t lcid) final; typedef enum { Srb = 0, Drb } rb_type_t; typedef struct { diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 556ba516c..569aafbe1 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -87,6 +87,25 @@ void rrc_nr::init_core_less() } void rrc_nr::get_metrics(rrc_nr_metrics_t& m) {} +const char* rrc_nr::get_rb_name(uint32_t lcid) +{ + uint32_t offset; + if (lcid_rb.find(lcid) != lcid_rb.end()) { + // Calulate offset for rb_id table + if (lcid_rb[lcid].rb_type == Srb) { + // SRB start at 0 + offset = NR_SRB0 + lcid_rb[lcid].rb_id; + } else { + // DRB start at 1 + offset = NR_SRB3 + lcid_rb[lcid].rb_id; + } + } else { + logger.warning("Unable to find lcid: %d. Return guessed rb name."); + offset = lcid; + } + return srsran::to_string((srsran::rb_id_nr_t)offset); +} + // Timeout callback interface void rrc_nr::timer_expired(uint32_t timeout_id) { @@ -161,7 +180,7 @@ void rrc_nr::log_rrc_message(const std::string& source, bool rrc_nr::add_lcid_rb(uint32_t lcid, rb_type_t rb_type, uint32_t rbid) { if (lcid_rb.find(lcid) != lcid_rb.end()) { - logger.error("Couldn't add RB to LCID. RB %d does exist.", rbid); + logger.error("Couldn't add RB to LCID (%d). RB %d already does exist.", lcid, rbid); return false; } else { logger.info("Adding lcid %d and radio bearer ID %d with type %s ", lcid, rbid, (rb_type == Srb) ? "SRB" : "DRB"); diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 991d9697e..2b44b71b8 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -201,7 +201,7 @@ int ue_stack_lte::init(const stack_args_t& args_) sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); mac.init(phy, &rlc, &rrc); - rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); + rlc.init(&pdcp, &rrc, &rrc_nr, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */); pdcp.init(&rlc, &rrc, &rrc_nr, gw); nas.init(usim.get(), &rrc, gw, args.nas); From 81ad72b0ff00ebda12ac4d0cf65a582b91dad9c1 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Apr 2021 17:19:57 +0200 Subject: [PATCH 45/46] Refactor srb and drb handling --- lib/include/srsran/common/common_nr.h | 99 ++++++++++++++++ .../srsran/interfaces/gnb_interfaces.h | 7 +- .../interfaces/nr_common_interface_types.h | 110 ------------------ srsenb/hdr/stack/rrc/rrc_nr.h | 6 +- srsenb/src/stack/rrc/rrc_nr.cc | 16 +-- srsenb/src/stack/upper/pdcp_nr.cc | 1 - srsenb/src/stack/upper/rlc_nr.cc | 9 +- srsue/hdr/stack/rrc/rrc_nr.h | 16 +-- srsue/src/stack/rrc/rrc_nr.cc | 51 ++++---- 9 files changed, 143 insertions(+), 172 deletions(-) create mode 100644 lib/include/srsran/common/common_nr.h delete mode 100644 lib/include/srsran/interfaces/nr_common_interface_types.h diff --git a/lib/include/srsran/common/common_nr.h b/lib/include/srsran/common/common_nr.h new file mode 100644 index 000000000..0257938e3 --- /dev/null +++ b/lib/include/srsran/common/common_nr.h @@ -0,0 +1,99 @@ + +/** + * + * \section COPYRIGHT + * + * Copyright 2012-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_COMMON_NR_H +#define SRSRAN_COMMON_NR_H + +#include +#include + +namespace srsran { + +// Radio Bearers +enum class nr_srb { srb0, srb1, srb2, srb3, count }; +const uint32_t MAX_NR_SRB_ID = 3; +enum class nr_drb { + drb1 = 1, + drb2, + drb3, + drb4, + drb5, + drb6, + drb7, + drb8, + drb9, + drb10, + drb11, + drb12, + drb13, + drb14, + drb15, + drb16, + drb17, + drb18, + drb19, + drb20, + drb21, + drb22, + drb23, + drb24, + drb25, + drb26, + drb27, + drb28, + drb29, + invalid +}; +const uint32_t MAX_NR_DRB_ID = 29; +const uint32_t MAX_NR_NOF_BEARERS = MAX_NR_DRB_ID + MAX_NR_SRB_ID; + +constexpr bool is_nr_lcid(uint32_t lcid) +{ + return lcid < MAX_NR_NOF_BEARERS; +} +constexpr bool is_nr_srb(uint32_t srib) +{ + return srib <= MAX_NR_SRB_ID; +} +inline const char* get_srb_name(nr_srb srb_id) +{ + static const char* names[] = {"SRB0", "SRB1", "SRB2", "SRB3", "invalid SRB id"}; + return names[(uint32_t)(srb_id < nr_srb::count ? srb_id : nr_srb::count)]; +} +constexpr uint32_t srb_to_lcid(nr_srb srb_id) +{ + return static_cast(srb_id); +} +constexpr nr_srb nr_lcid_to_srb(uint32_t lcid) +{ + return static_cast(lcid); +} +constexpr nr_drb nr_drb_id_to_drb(uint32_t drb_id) +{ + return static_cast(drb_id); +} +constexpr bool is_nr_drb(uint32_t drib) +{ + return drib > MAX_NR_SRB_ID and is_nr_lcid(drib); +} +inline const char* get_drb_name(nr_drb drb_id) +{ + static const char* names[] = {"DRB1", "DRB2", "DRB3", "DRB4", "DRB5", "DRB6", "DRB7", "DRB8", + "DRB9", "DRB10", "DRB11", "DRB12", "DRB13", "DRB14", "DRB15", "DRB16", + "DRB17", "DRB18", "DRB19", "DRB20", "DRB21", "DRB22", "DRB23", "DRB24", + "DRB25", "DRB26", "DRB27", "DRB28", "DRB29", "invalid DRB id"}; + return names[(uint32_t)(drb_id < nr_drb::invalid ? drb_id : nr_drb::invalid) - 1]; +} +} // namespace srsran + +#endif // SRSRAN_COMMON_NR_H \ No newline at end of file diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 3a3be7e30..31681a9be 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -149,9 +149,10 @@ public: class rrc_interface_rlc_nr { public: - virtual void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) = 0; - virtual void max_retx_attempted(uint16_t rnti) = 0; - virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0; + virtual void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) = 0; + virtual void max_retx_attempted(uint16_t rnti) = 0; + virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) = 0; + virtual const char* get_rb_name(uint32_t lcid) = 0; }; class rrc_interface_pdcp_nr { diff --git a/lib/include/srsran/interfaces/nr_common_interface_types.h b/lib/include/srsran/interfaces/nr_common_interface_types.h deleted file mode 100644 index 7ebbf5d96..000000000 --- a/lib/include/srsran/interfaces/nr_common_interface_types.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSRAN_COMMON_NR_H -#define SRSRAN_COMMON_NR_H - -namespace srsran { - -// NR Radio Bearer Id -// maxDRB = 29 -enum rb_id_nr_t { - NR_SRB0, - NR_SRB1, - NR_SRB2, - NR_SRB3, - NR_DRB1, - NR_DRB2, - NR_DRB3, - NR_DRB4, - NR_DRB5, - NR_DRB6, - NR_DRB7, - NR_DRB8, - NR_DRB9, - NR_DRB10, - NR_DRB11, - NR_DRB12, - NR_DRB13, - NR_DRB14, - NR_DRB15, - NR_DRB16, - NR_DRB17, - NR_DRB18, - NR_DRB19, - NR_DRB20, - NR_DRB21, - NR_DRB22, - NR_DRB23, - NR_DRB24, - NR_DRB25, - NR_DRB26, - NR_DRB27, - NR_DRB28, - NR_DRB29, - RB_ID_NR_N_ITEMS -}; - -inline const char* to_string(rb_id_nr_t rb_id) -{ - const static char* names[] = { - "SRB0", - "SRB1", - "SRB2", - "SRB3", - "DRB1", - "DRB2", - "DRB3", - "DRB4", - "DRB5", - "DRB6", - "DRB7", - "DRB8", - "DRB9", - "DRB10", - "DRB11", - "DRB13", - "DRB14", - "DRB15", - "DRB16", - "DRB17", - "DRB18", - "DRB19", - "DRB20", - "DRB21", - "DRB22", - "DRB23", - "DRB24", - "DRB25", - "DRB26", - "DRB27", - "DRB28", - "DRB29", - }; - return (rb_id < rb_id_nr_t::RB_ID_NR_N_ITEMS) ? names[rb_id] : "invalid bearer id"; -} -inline bool is_srb(rb_id_nr_t lcid) -{ - return lcid <= rb_id_nr_t::NR_SRB3; -} -inline bool is_drb(rb_id_nr_t lcid) -{ - return not is_srb(lcid) and lcid <= rb_id_nr_t::RB_ID_NR_N_ITEMS; -} -inline int get_drb_id(rb_id_nr_t rb_id) -{ - return is_drb(rb_id) ? (rb_id - 3) : -1; -} - -} // namespace srsran - -#endif // SRSRAN_NR_COMMON_INTERFACE_TYPES_H diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 278a83066..0e2f3b944 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -84,9 +84,9 @@ public: // RLC interface // TODO - void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) {} - void max_retx_attempted(uint16_t rnti) {} - + void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) {} + void max_retx_attempted(uint16_t rnti) {} + const char* get_rb_name(uint32_t lcid) { return "invalid"; } // PDCP interface void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) final; diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index e874cf35f..d6be8ccef 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -10,10 +10,10 @@ * */ +#include "srsran/common/common_nr.h" +#include "srsran/asn1/rrc_nr_utils.h" #include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/common/common_enb.h" -#include "srsran/asn1/rrc_nr_utils.h" -#include "srsran/interfaces/nr_common_interface_types.h" using namespace asn1::rrc_nr; @@ -312,16 +312,16 @@ void rrc_nr::get_metrics(srsenb::rrc_metrics_t& m) void rrc_nr::handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) { if (pdu) { - logger.info(pdu->msg, pdu->N_bytes, "Rx %s PDU", srsran::to_string(static_cast(lcid))); + logger.info(pdu->msg, pdu->N_bytes, "Rx %s PDU", get_rb_name(lcid)); } if (users.count(rnti) == 1) { - switch (static_cast(lcid)) { - case srsran::rb_id_nr_t::NR_SRB0: + switch (static_cast(lcid)) { + case srsran::nr_srb::srb0: // parse_ul_ccch(rnti, std::move(pdu)); break; - case srsran::rb_id_nr_t::NR_SRB1: - case srsran::rb_id_nr_t::NR_SRB2: + case srsran::nr_srb::srb1: + case srsran::nr_srb::srb2: // parse_ul_dcch(p.rnti, p.lcid, std::move(p.pdu)); break; default: @@ -397,7 +397,7 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) char buf[32] = {}; sprintf(buf, "SRB0 - rnti=0x%x", rnti); parent->log_rrc_message(buf, Tx, pdu.get(), *dl_ccch_msg); - parent->rlc->write_sdu(rnti, srsran::NR_SRB0, std::move(pdu)); + parent->rlc->write_sdu(rnti, (uint32_t)srsran::nr_srb::srb0, std::move(pdu)); } } // namespace srsenb diff --git a/srsenb/src/stack/upper/pdcp_nr.cc b/srsenb/src/stack/upper/pdcp_nr.cc index c3e0d5df1..540efdbce 100644 --- a/srsenb/src/stack/upper/pdcp_nr.cc +++ b/srsenb/src/stack/upper/pdcp_nr.cc @@ -11,7 +11,6 @@ */ #include "srsenb/hdr/stack/upper/pdcp_nr.h" -#include "lib/include/srsran/interfaces/nr_common_interface_types.h" #include "srsenb/hdr/common/common_enb.h" namespace srsenb { diff --git a/srsenb/src/stack/upper/rlc_nr.cc b/srsenb/src/stack/upper/rlc_nr.cc index e23e0dcb0..67d079457 100644 --- a/srsenb/src/stack/upper/rlc_nr.cc +++ b/srsenb/src/stack/upper/rlc_nr.cc @@ -11,8 +11,7 @@ */ #include "srsenb/hdr/stack/upper/rlc_nr.h" -#include "srsran/interfaces/nr_common_interface_types.h" - +#include "srsran/common/common_nr.h" namespace srsenb { rlc_nr::rlc_nr(const char* logname) : logger(srslog::fetch_basic_logger(logname)) {} @@ -46,7 +45,7 @@ void rlc_nr::add_user(uint16_t rnti) user_itf.parent = this; user_itf.m_rlc.reset(new srsran::rlc(logger.id().c_str())); users[rnti] = std::move(user_itf); - users[rnti].m_rlc->init(&users[rnti], &users[rnti], timers, (int)srsran::rb_id_nr_t::NR_SRB0); + users[rnti].m_rlc->init(&users[rnti], &users[rnti], timers, (int)srsran::nr_srb::srb0); } } @@ -180,7 +179,7 @@ void rlc_nr::user_interface::max_retx_attempted() void rlc_nr::user_interface::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { - if (lcid == (int)srsran::rb_id_nr_t::NR_SRB0) { + if (lcid == (int)srsran::nr_srb::srb0) { m_rrc->write_pdu(rnti, lcid, std::move(sdu)); } else { m_pdcp->write_pdu(rnti, lcid, std::move(sdu)); @@ -204,7 +203,7 @@ void rlc_nr::user_interface::write_pdu_pcch(srsran::unique_byte_buffer_t sdu) const char* rlc_nr::user_interface::get_rb_name(uint32_t lcid) { - return srsran::to_string(static_cast(lcid)); + return m_rrc->get_rb_name(lcid); } void rlc_nr::user_interface::notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index b69d1a9c5..50830b008 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -16,12 +16,12 @@ #include "srsran/asn1/rrc_nr.h" #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/block_queue.h" +#include "srsran/common/common_nr.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/stack_procedure.h" #include "srsran/common/task_scheduler.h" -#include "srsran/interfaces/nr_common_interface_types.h" -#include "srsran/interfaces/ue_nr_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/interfaces/ue_nr_interfaces.h" #include "srsue/hdr/stack/upper/gw.h" namespace srsue { @@ -175,16 +175,10 @@ private: const char* get_rb_name(uint32_t lcid) final; - typedef enum { Srb = 0, Drb } rb_type_t; - typedef struct { - uint32_t rb_id; - rb_type_t rb_type; - } rb_t; - - bool add_lcid_rb(uint32_t lcid, rb_type_t rb_type, uint32_t rbid); - uint32_t get_lcid_for_rbid(uint32_t rdid); + bool add_lcid_drb(uint32_t lcid, uint32_t drb_id); + uint32_t get_lcid_for_drbid(uint32_t rdid); - std::map lcid_rb; // Map of lcid to radio bearer (type and rb id) + std::map lcid_drb; // Map of lcid to drb std::map drb_eps_bearer_id; // Map of drb id to eps_bearer_id diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 569aafbe1..24f55f3af 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -89,21 +89,14 @@ void rrc_nr::get_metrics(rrc_nr_metrics_t& m) {} const char* rrc_nr::get_rb_name(uint32_t lcid) { - uint32_t offset; - if (lcid_rb.find(lcid) != lcid_rb.end()) { - // Calulate offset for rb_id table - if (lcid_rb[lcid].rb_type == Srb) { - // SRB start at 0 - offset = NR_SRB0 + lcid_rb[lcid].rb_id; - } else { - // DRB start at 1 - offset = NR_SRB3 + lcid_rb[lcid].rb_id; - } - } else { - logger.warning("Unable to find lcid: %d. Return guessed rb name."); - offset = lcid; + if (is_nr_srb(lcid)) { + return get_srb_name(nr_lcid_to_srb(lcid)); } - return srsran::to_string((srsran::rb_id_nr_t)offset); + if (lcid_drb.find(lcid) != lcid_drb.end()) { + return get_drb_name(lcid_drb[lcid]); + } + logger.warning("Unable to find lcid: %d. Return invalid LCID"); + return "invalid LCID"; } // Timeout callback interface @@ -177,27 +170,26 @@ void rrc_nr::log_rrc_message(const std::string& source, } } -bool rrc_nr::add_lcid_rb(uint32_t lcid, rb_type_t rb_type, uint32_t rbid) +bool rrc_nr::add_lcid_drb(uint32_t lcid, uint32_t drb_id) { - if (lcid_rb.find(lcid) != lcid_rb.end()) { - logger.error("Couldn't add RB to LCID (%d). RB %d already does exist.", lcid, rbid); + if (lcid_drb.find(lcid) != lcid_drb.end()) { + logger.error("Couldn't add DRB to LCID (%d). DRB %d already exists.", lcid, drb_id); return false; } else { - logger.info("Adding lcid %d and radio bearer ID %d with type %s ", lcid, rbid, (rb_type == Srb) ? "SRB" : "DRB"); - lcid_rb[lcid].rb_id = rbid; - lcid_rb[lcid].rb_type = rb_type; + logger.info("Adding lcid %d and radio bearer ID %d", lcid, drb_id); + lcid_drb[lcid] = nr_drb_id_to_drb(drb_id); } return true; } -uint32_t rrc_nr::get_lcid_for_rbid(uint32_t rb_id) +uint32_t rrc_nr::get_lcid_for_drbid(uint32_t drb_id) { - for (auto& rb : lcid_rb) { - if (rb.second.rb_id == rb_id) { + for (auto& rb : lcid_drb) { + if (rb.second == nr_drb_id_to_drb(drb_id)) { return rb.first; } } - logger.error("Couldn't find LCID for rb LCID. RB %d does exist.", rb_id); + logger.error("Couldn't find LCID for DRB. DRB %d does exist.", drb_id); return 0; } @@ -457,10 +449,7 @@ bool rrc_nr::apply_rlc_add_mod(const rlc_bearer_cfg_s& rlc_bearer_cfg) if (rlc_bearer_cfg.served_radio_bearer_present == true) { if (rlc_bearer_cfg.served_radio_bearer.type() == rlc_bearer_cfg_s::served_radio_bearer_c_::types::drb_id) { drb_id = rlc_bearer_cfg.served_radio_bearer.drb_id(); - add_lcid_rb(lc_ch_id, Drb, drb_id); - } else { - srb_id = rlc_bearer_cfg.served_radio_bearer.srb_id(); - add_lcid_rb(lc_ch_id, Srb, srb_id); + add_lcid_drb(lc_ch_id, drb_id); } } else { logger.warning("In RLC bearer cfg does not contain served radio bearer"); @@ -1255,7 +1244,7 @@ bool rrc_nr::apply_cell_group_cfg(const cell_group_cfg_s& cell_group_cfg) bool rrc_nr::apply_drb_release(const uint8_t drb) { - uint32_t lcid = get_lcid_for_rbid(drb); + uint32_t lcid = get_lcid_for_drbid(drb); if(lcid == 0){ logger.warning("Can not release bearer with lcid %d and drb %d", lcid, drb); return false; @@ -1276,7 +1265,7 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) return false; } - uint32_t lcid = get_lcid_for_rbid(drb_cfg.drb_id); + uint32_t lcid = get_lcid_for_drbid(drb_cfg.drb_id); // Setup PDCP if (!(drb_cfg.pdcp_cfg.drb_present == true)) { @@ -1363,7 +1352,7 @@ bool rrc_nr::apply_security_cfg(const security_cfg_s& security_cfg) } // Apply security config for all known NR lcids - for (auto& lcid : lcid_rb) { + for (auto& lcid : lcid_drb) { pdcp->config_security(lcid.first, sec_cfg); pdcp->enable_encryption(lcid.first); } From a064e85c54de2d4f808cb2d47d91c37f87548d9e Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Apr 2021 17:35:12 +0200 Subject: [PATCH 46/46] rename common lte header --- lib/include/srsran/common/{lte_common.h => common_lte.h} | 6 +++--- lib/src/upper/rlc_tm.cc | 2 +- srsenb/hdr/common/common_enb.h | 2 +- srsenb/test/mac/sched_benchmark.cc | 2 +- srsenb/test/mac/sched_ca_test.cc | 2 +- srsenb/test/mac/sched_dci_test.cc | 2 +- srsenb/test/mac/sched_grid_test.cc | 2 +- srsenb/test/mac/sched_test_rand.cc | 2 +- srsue/hdr/stack/rrc/rrc.h | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) rename lib/include/srsran/common/{lte_common.h => common_lte.h} (96%) diff --git a/lib/include/srsran/common/lte_common.h b/lib/include/srsran/common/common_lte.h similarity index 96% rename from lib/include/srsran/common/lte_common.h rename to lib/include/srsran/common/common_lte.h index 788c2b1da..f650dc2e3 100644 --- a/lib/include/srsran/common/lte_common.h +++ b/lib/include/srsran/common/common_lte.h @@ -10,8 +10,8 @@ * */ -#ifndef SRSRAN_LTE_COMMON_H -#define SRSRAN_LTE_COMMON_H +#ifndef SRSRAN_COMMON_LTE_H +#define SRSRAN_COMMON_LTE_H #include #include @@ -88,4 +88,4 @@ inline const char* get_drb_name(lte_drb drb_id) } // namespace srsran -#endif // SRSRAN_LTE_COMMON_H +#endif // SRSRAN_COMMON_LTE_H diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 3ff1d7cee..08478a6bc 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -11,7 +11,7 @@ */ #include "srsran/upper/rlc_tm.h" -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" diff --git a/srsenb/hdr/common/common_enb.h b/srsenb/hdr/common/common_enb.h index 7ed9cf72b..4c87f8f39 100644 --- a/srsenb/hdr/common/common_enb.h +++ b/srsenb/hdr/common/common_enb.h @@ -17,7 +17,7 @@ INCLUDES *******************************************************************************/ -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include namespace srsenb { diff --git a/srsenb/test/mac/sched_benchmark.cc b/srsenb/test/mac/sched_benchmark.cc index d70b16a4f..606013a1f 100644 --- a/srsenb/test/mac/sched_benchmark.cc +++ b/srsenb/test/mac/sched_benchmark.cc @@ -13,7 +13,7 @@ #include "sched_test_common.h" #include "srsenb/hdr/stack/mac/sched.h" #include "srsran/adt/accumulators.h" -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include namespace srsenb { diff --git a/srsenb/test/mac/sched_ca_test.cc b/srsenb/test/mac/sched_ca_test.cc index 9e5946e22..f0d925aa8 100644 --- a/srsenb/test/mac/sched_ca_test.cc +++ b/srsenb/test/mac/sched_ca_test.cc @@ -13,7 +13,7 @@ #include "sched_test_common.h" #include "sched_test_utils.h" #include "srsenb/hdr/stack/mac/sched.h" -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include "srsran/mac/pdu.h" using namespace srsenb; diff --git a/srsenb/test/mac/sched_dci_test.cc b/srsenb/test/mac/sched_dci_test.cc index a42713bfc..6f78e615b 100644 --- a/srsenb/test/mac/sched_dci_test.cc +++ b/srsenb/test/mac/sched_dci_test.cc @@ -13,7 +13,7 @@ #include "sched_test_utils.h" #include "srsenb/hdr/stack/mac/sched_common.h" #include "srsenb/hdr/stack/mac/sched_phy_ch/sched_dci.h" -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include "srsran/common/test_common.h" namespace srsenb { diff --git a/srsenb/test/mac/sched_grid_test.cc b/srsenb/test/mac/sched_grid_test.cc index 776c9888b..ec366b055 100644 --- a/srsenb/test/mac/sched_grid_test.cc +++ b/srsenb/test/mac/sched_grid_test.cc @@ -12,7 +12,7 @@ #include "sched_test_common.h" #include "srsenb/hdr/stack/mac/sched_grid.h" -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include "srsran/common/test_common.h" using namespace srsenb; diff --git a/srsenb/test/mac/sched_test_rand.cc b/srsenb/test/mac/sched_test_rand.cc index 4904bff72..c1ff6b4e1 100644 --- a/srsenb/test/mac/sched_test_rand.cc +++ b/srsenb/test/mac/sched_test_rand.cc @@ -25,7 +25,7 @@ #include "sched_common_test_suite.h" #include "sched_test_common.h" #include "sched_test_utils.h" -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include "srsran/common/test_common.h" namespace srsenb { diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index a6e474742..48a168974 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -21,7 +21,7 @@ #include "srsran/common/block_queue.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" -#include "srsran/common/lte_common.h" +#include "srsran/common/common_lte.h" #include "srsran/common/security.h" #include "srsran/common/stack_procedure.h" #include "srsran/interfaces/ue_interfaces.h"