rrc,nr,gnb: refactored rrc nr cfg default and derived param generation to be mostly independent of parser

master
Francisco 3 years ago committed by Francisco Paisana
parent f2a5f00bb3
commit fec97689a2

@ -32,7 +32,7 @@ void generate_default_pdcch_cfg_common(asn1::rrc_nr::pdcch_cfg_common_s& cfg, co
void generate_default_init_dl_bwp(asn1::rrc_nr::bwp_dl_common_s& cfg, const basic_cell_args_t& args = {}); void generate_default_init_dl_bwp(asn1::rrc_nr::bwp_dl_common_s& cfg, const basic_cell_args_t& args = {});
void generate_default_dl_cfg_common(asn1::rrc_nr::dl_cfg_common_s& cfg, const basic_cell_args_t& args = {}); void generate_default_dl_cfg_common(asn1::rrc_nr::dl_cfg_common_s& cfg, const basic_cell_args_t& args = {});
void generate_default_mib(const basic_cell_args_t& args, asn1::rrc_nr::mib_s& cfg); void generate_default_mib(uint32_t pdcch_scs, uint32_t coreset0_idx, asn1::rrc_nr::mib_s& cfg);
void generate_default_serv_cell_cfg_common_sib(const basic_cell_args_t& args, void generate_default_serv_cell_cfg_common_sib(const basic_cell_args_t& args,
asn1::rrc_nr::serving_cell_cfg_common_sib_s& cfg); asn1::rrc_nr::serving_cell_cfg_common_sib_s& cfg);

@ -172,14 +172,15 @@ void generate_default_serv_cell_cfg_common_sib(const basic_cell_args_t& args, se
cfg.ss_pbch_block_pwr = -16; cfg.ss_pbch_block_pwr = -16;
} }
void generate_default_mib(const basic_cell_args_t& args, mib_s& cfg) void generate_default_mib(uint32_t pdcch_scs, uint32_t coreset0_idx, mib_s& cfg)
{ {
asn1::number_to_enum(cfg.sub_carrier_spacing_common, args.scs); bool ret = asn1::number_to_enum(cfg.sub_carrier_spacing_common, pdcch_scs);
srsran_assert(ret, "Invalid SCS=%d kHz", pdcch_scs);
cfg.ssb_subcarrier_offset = 0; cfg.ssb_subcarrier_offset = 0;
cfg.intra_freq_resel.value = mib_s::intra_freq_resel_opts::allowed; cfg.intra_freq_resel.value = mib_s::intra_freq_resel_opts::allowed;
cfg.cell_barred.value = mib_s::cell_barred_opts::not_barred; cfg.cell_barred.value = mib_s::cell_barred_opts::not_barred;
cfg.pdcch_cfg_sib1.search_space_zero = 0; cfg.pdcch_cfg_sib1.search_space_zero = 0;
cfg.pdcch_cfg_sib1.ctrl_res_set_zero = 0; cfg.pdcch_cfg_sib1.ctrl_res_set_zero = coreset0_idx;
cfg.dmrs_type_a_position.value = mib_s::dmrs_type_a_position_opts::pos2; cfg.dmrs_type_a_position.value = mib_s::dmrs_type_a_position_opts::pos2;
cfg.sys_frame_num.from_number(0); cfg.sys_frame_num.from_number(0);
} }

@ -22,7 +22,7 @@ if (RPATH)
endif (RPATH) endif (RPATH)
add_library(enb_cfg_parser STATIC parser.cc enb_cfg_parser.cc) add_library(enb_cfg_parser STATIC parser.cc enb_cfg_parser.cc)
target_link_libraries(enb_cfg_parser srsran_common ${LIBCONFIGPP_LIBRARIES}) target_link_libraries(enb_cfg_parser srsran_common srsgnb_rrc_config_utils ${LIBCONFIGPP_LIBRARIES})
add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc) add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc)

@ -12,6 +12,7 @@
#include "enb_cfg_parser.h" #include "enb_cfg_parser.h"
#include "srsenb/hdr/enb.h" #include "srsenb/hdr/enb.h"
#include "srsgnb/hdr/stack/rrc/rrc_nr_config_utils.h"
#include "srsran/asn1/rrc_utils.h" #include "srsran/asn1/rrc_utils.h"
#include "srsran/common/band_helper.h" #include "srsran/common/band_helper.h"
#include "srsran/common/multiqueue.h" #include "srsran/common/multiqueue.h"
@ -961,8 +962,10 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
static int parse_nr_cell_list(all_args_t* args, rrc_nr_cfg_t* rrc_cfg_nr, rrc_cfg_t* rrc_cfg_eutra, Setting& root) static int parse_nr_cell_list(all_args_t* args, rrc_nr_cfg_t* rrc_cfg_nr, rrc_cfg_t* rrc_cfg_eutra, Setting& root)
{ {
for (uint32_t n = 0; n < (uint32_t)root.getLength(); ++n) { for (uint32_t n = 0; n < (uint32_t)root.getLength(); ++n) {
auto& cellroot = root[n];
rrc_cell_cfg_nr_t cell_cfg = {}; rrc_cell_cfg_nr_t cell_cfg = {};
auto& cellroot = root[n]; generate_default_nr_cell(cell_cfg);
parse_opt_field(cell_cfg.phy_cell.rf_port, cellroot, "rf_port"); parse_opt_field(cell_cfg.phy_cell.rf_port, cellroot, "rf_port");
HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.carrier.pci, cellroot, "pci")); HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.carrier.pci, cellroot, "pci"));
@ -1530,7 +1533,8 @@ int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_nr_cfg_, phy_cfg_t*
// Create NR dedicated cell configuration from RRC configuration // Create NR dedicated cell configuration from RRC configuration
for (auto it = rrc_nr_cfg_->cell_list.begin(); it != rrc_nr_cfg_->cell_list.end(); ++it) { for (auto it = rrc_nr_cfg_->cell_list.begin(); it != rrc_nr_cfg_->cell_list.end(); ++it) {
auto& cfg = *it; auto& cfg = *it;
cfg.phy_cell.carrier.max_mimo_layers = args_->enb.nof_ports; cfg.phy_cell.carrier.max_mimo_layers = args_->enb.nof_ports;
// NR cells have the same bandwidth as EUTRA cells, adjust PRB sizes // NR cells have the same bandwidth as EUTRA cells, adjust PRB sizes
@ -1548,130 +1552,22 @@ int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_nr_cfg_, phy_cfg_t*
ERROR("The only accepted number of PRB is: 25, 50, 100"); ERROR("The only accepted number of PRB is: 25, 50, 100");
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
// phy_cell_cfg.root_seq_idx = cfg.root_seq_idx;
cfg.phy_cell.num_ra_preambles = 52; // FIXME: read from config
if (cfg.phy_cell.dl_freq_hz == 0) {
cfg.phy_cell.dl_freq_hz = band_helper.nr_arfcn_to_freq(cfg.dl_arfcn);
}
if (cfg.phy_cell.ul_freq_hz == 0) { // Derive cross-dependent cell params
// auto-detect UL frequency if (set_derived_nr_cell_params(rrc_nr_cfg_->is_standalone, cfg) != SRSRAN_SUCCESS) {
if (cfg.ul_arfcn == 0) { ERROR("Failed to derive NR cell params.");
// derive UL ARFCN from given DL ARFCN return SRSRAN_ERROR;
cfg.ul_arfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_arfcn);
if (cfg.ul_arfcn == 0) {
ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_arfcn);
return SRSRAN_ERROR;
}
}
cfg.phy_cell.ul_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ul_arfcn);
} }
// duplex mode // phy_cell_cfg.root_seq_idx = cfg.root_seq_idx;
cfg.duplex_mode = band_helper.get_duplex_mode(cfg.band);
// PRACH // PRACH
cfg.phy_cell.prach.is_nr = true; cfg.phy_cell.prach.hs_flag = phy_cfg_->prach_cnfg.prach_cfg_info.high_speed_flag;
cfg.phy_cell.prach.config_idx = 8;
cfg.phy_cell.prach.root_seq_idx = 0;
cfg.phy_cell.prach.freq_offset = 1;
cfg.phy_cell.prach.num_ra_preambles = cfg.phy_cell.num_ra_preambles;
cfg.phy_cell.prach.hs_flag = phy_cfg_->prach_cnfg.prach_cfg_info.high_speed_flag;
cfg.phy_cell.prach.tdd_config.configured = (cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD);
// PDCCH
// Configure CORESET ID 1
cfg.phy_cell.pdcch.coreset_present[1] = true;
cfg.phy_cell.pdcch.coreset[1].id = 1;
cfg.phy_cell.pdcch.coreset[1].duration = 1;
cfg.phy_cell.pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved;
cfg.phy_cell.pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle;
// Generate frequency resources for the full BW
for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) {
cfg.phy_cell.pdcch.coreset[1].freq_resources[i] = i < SRSRAN_FLOOR(cfg.phy_cell.carrier.nof_prb, 6);
}
// Configure Search Space 1 as common
cfg.phy_cell.pdcch.search_space_present[1] = true;
cfg.phy_cell.pdcch.search_space[1].id = 1;
cfg.phy_cell.pdcch.search_space[1].coreset_id = 1;
cfg.phy_cell.pdcch.search_space[1].duration = 1;
cfg.phy_cell.pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH
cfg.phy_cell.pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH
cfg.phy_cell.pdcch.search_space[1].nof_formats = 2;
cfg.phy_cell.pdcch.search_space[1].type = srsran_search_space_type_common_3;
// Generate 1 candidate for each aggregation level if possible
for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) {
cfg.phy_cell.pdcch.search_space[1].nof_candidates[L] =
SRSRAN_MIN(2, srsran_pdcch_nr_max_candidates_coreset(&cfg.phy_cell.pdcch.coreset[1], L));
}
cfg.phy_cell.pdcch.ra_search_space_present = true;
cfg.phy_cell.pdcch.ra_search_space = cfg.phy_cell.pdcch.search_space[1];
cfg.phy_cell.pdcch.ra_search_space.type = srsran_search_space_type_common_1;
// PDSCH // PDSCH
cfg.phy_cell.pdsch.rs_power = phy_cfg_->pdsch_cnfg.ref_sig_pwr; cfg.phy_cell.pdsch.rs_power = phy_cfg_->pdsch_cnfg.ref_sig_pwr;
cfg.phy_cell.pdsch.p_b = phy_cfg_->pdsch_cnfg.p_b; cfg.phy_cell.pdsch.p_b = phy_cfg_->pdsch_cnfg.p_b;
// copy center frequencies
cfg.phy_cell.carrier.dl_center_frequency_hz = cfg.phy_cell.dl_freq_hz;
cfg.phy_cell.carrier.ul_center_frequency_hz = cfg.phy_cell.ul_freq_hz;
cfg.dl_absolute_freq_point_a = band_helper.get_abs_freq_point_a_arfcn(cfg.phy_cell.carrier.nof_prb, cfg.dl_arfcn);
cfg.ul_absolute_freq_point_a = band_helper.get_abs_freq_point_a_arfcn(cfg.phy_cell.carrier.nof_prb, cfg.ul_arfcn);
// Calculate SSB params depending on band/duplex
cfg.ssb_cfg.duplex_mode = band_helper.get_duplex_mode(cfg.band);
cfg.ssb_cfg.pattern = band_helper.get_ssb_pattern(cfg.band, srsran_subcarrier_spacing_15kHz);
if (cfg.ssb_cfg.pattern == SRSRAN_SSB_PATTERN_A) {
// 15kHz SSB SCS
cfg.ssb_cfg.scs = srsran_subcarrier_spacing_15kHz;
} else {
// try to optain SSB pattern for same band with 30kHz SCS
cfg.ssb_cfg.pattern = band_helper.get_ssb_pattern(cfg.band, srsran_subcarrier_spacing_30kHz);
if (cfg.ssb_cfg.pattern == SRSRAN_SSB_PATTERN_B || cfg.ssb_cfg.pattern == SRSRAN_SSB_PATTERN_C) {
// SSB SCS is 30 kHz
cfg.ssb_cfg.scs = srsran_subcarrier_spacing_30kHz;
} else {
ERROR("Can't derive SSB pattern for band %d", cfg.band);
return SRSRAN_ERROR;
}
}
// fill remaining SSB fields
int coreset0_rb_offset = 0;
if (rrc_nr_cfg_->is_standalone) {
const uint32_t coreset0_idx = 6; // See TS 38.331 - controlResourceSetZero / Table 13-1 index
cfg.phy_cell.pdcch.coreset_present[0] = true;
// Get offset in RBs between CORESET#0 and SSB
coreset0_rb_offset = srsran_coreset0_ssb_offset(coreset0_idx, cfg.ssb_cfg.scs, cfg.phy_cell.carrier.scs);
srsran_assert(coreset0_rb_offset >= 0, "Failed to compute RB offset between CORESET#0 and SSB");
}
cfg.ssb_absolute_freq_point =
band_helper.get_abs_freq_ssb_arfcn(cfg.band, cfg.ssb_cfg.scs, cfg.dl_absolute_freq_point_a, coreset0_rb_offset);
srsran_assert(cfg.ssb_absolute_freq_point > 0,
"Can't derive SSB freq point for dl_arfcn %d and band %d",
cfg.dl_arfcn,
cfg.band);
// Convert to frequency for PHY
cfg.phy_cell.carrier.ssb_center_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ssb_absolute_freq_point);
cfg.ssb_cfg.center_freq_hz = cfg.phy_cell.carrier.dl_center_frequency_hz;
cfg.ssb_cfg.ssb_freq_hz = cfg.phy_cell.carrier.ssb_center_freq_hz;
cfg.ssb_cfg.periodicity_ms = 10; // TODO: make a param
cfg.ssb_cfg.beta_pss = 0.0;
cfg.ssb_cfg.beta_sss = 0.0;
cfg.ssb_cfg.beta_pbch = 0.0;
cfg.ssb_cfg.beta_pbch_dmrs = 0.0;
// set by PHY layer in worker_pool::set_common_cfg
cfg.ssb_cfg.srate_hz = 0.0;
cfg.ssb_cfg.scaling = 0.0;
phy_cfg_->phy_cell_cfg_nr.push_back(cfg.phy_cell); phy_cfg_->phy_cell_cfg_nr.push_back(cfg.phy_cell);
} }

@ -13,7 +13,7 @@
#ifndef SRSRAN_CELL_ASN1_CONFIG_H #ifndef SRSRAN_CELL_ASN1_CONFIG_H
#define SRSRAN_CELL_ASN1_CONFIG_H #define SRSRAN_CELL_ASN1_CONFIG_H
#include "rrc_config_nr.h" #include "rrc_nr_config.h"
#include "srsran/asn1/rrc_nr.h" #include "srsran/asn1/rrc_nr.h"
namespace srsenb { namespace srsenb {

@ -16,7 +16,7 @@
#include "srsenb/hdr/stack/enb_stack_base.h" #include "srsenb/hdr/stack/enb_stack_base.h"
#include "srsenb/hdr/stack/rrc/rrc_config_common.h" #include "srsenb/hdr/stack/rrc/rrc_config_common.h"
#include "srsenb/hdr/stack/rrc/rrc_metrics.h" #include "srsenb/hdr/stack/rrc/rrc_metrics.h"
#include "srsgnb/hdr/stack/rrc/rrc_config_nr.h" #include "srsgnb/hdr/stack/rrc/rrc_nr_config.h"
#include "srsran/asn1/rrc_nr.h" #include "srsran/asn1/rrc_nr.h"
#include "srsran/common/block_queue.h" #include "srsran/common/block_queue.h"
#include "srsran/common/buffer_pool.h" #include "srsran/common/buffer_pool.h"

@ -10,8 +10,8 @@
* *
*/ */
#ifndef SRSRAN_RRC_CONFIG_NR_H #ifndef SRSRAN_RRC_NR_CONFIG_H
#define SRSRAN_RRC_CONFIG_NR_H #define SRSRAN_RRC_NR_CONFIG_H
#include "srsenb/hdr/phy/phy_interfaces.h" #include "srsenb/hdr/phy/phy_interfaces.h"
#include "srsenb/hdr/stack/rrc/rrc_config_common.h" #include "srsenb/hdr/stack/rrc/rrc_config_common.h"
@ -40,6 +40,7 @@ struct rrc_cell_cfg_nr_t {
uint32_t ul_absolute_freq_point_a; // derived from UL ARFCN uint32_t ul_absolute_freq_point_a; // derived from UL ARFCN
uint32_t ssb_absolute_freq_point; // derived from DL ARFCN uint32_t ssb_absolute_freq_point; // derived from DL ARFCN
uint32_t band; uint32_t band;
uint32_t coreset0_idx; // Table 13-{1,...15} row index
srsran_duplex_mode_t duplex_mode; srsran_duplex_mode_t duplex_mode;
srsran_ssb_cfg_t ssb_cfg; srsran_ssb_cfg_t ssb_cfg;
}; };
@ -61,4 +62,4 @@ struct rrc_nr_cfg_t {
} // namespace srsenb } // namespace srsenb
#endif // SRSRAN_RRC_CONFIG_NR_H #endif // SRSRAN_RRC_NR_CONFIG_H

@ -0,0 +1,28 @@
/**
*
* \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_RRC_NR_CONFIG_DEFAULT_H
#define SRSRAN_RRC_NR_CONFIG_DEFAULT_H
#include "rrc_nr_config.h"
namespace srsenb {
void generate_default_nr_cell(rrc_cell_cfg_nr_t& cell);
int set_derived_nr_cell_params(bool is_sa, rrc_cell_cfg_nr_t& cell);
int check_nr_cell_cfg_valid(const rrc_cell_cfg_nr_t& cell, bool is_sa);
} // namespace srsenb
#endif // SRSRAN_RRC_NR_CONFIG_DEFAULT_H

@ -6,9 +6,13 @@
# the distribution. # the distribution.
# #
set(SOURCES rrc_nr_config_utils.cc)
add_library(srsgnb_rrc_config_utils STATIC ${SOURCES})
target_link_libraries(srsgnb_rrc_config_utils srsran_rrc_nr srsran_phy)
set(SOURCES rrc_nr.cc rrc_nr_ue.cc cell_asn1_config.cc) set(SOURCES rrc_nr.cc rrc_nr_ue.cc cell_asn1_config.cc)
add_library(srsgnb_rrc STATIC ${SOURCES}) add_library(srsgnb_rrc STATIC ${SOURCES})
target_link_libraries(srsgnb_rrc srsran_rrc_nr) target_link_libraries(srsgnb_rrc srsran_rrc_nr srsgnb_rrc_config_utils)
include_directories(${PROJECT_SOURCE_DIR}) include_directories(${PROJECT_SOURCE_DIR})

@ -586,9 +586,9 @@ int fill_sp_cell_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, sp_cell_
int fill_mib_from_enb_cfg(const rrc_nr_cfg_t& cfg, asn1::rrc_nr::mib_s& mib) int fill_mib_from_enb_cfg(const rrc_nr_cfg_t& cfg, asn1::rrc_nr::mib_s& mib)
{ {
srsran::basic_cell_args_t args; uint32_t scs =
args.scs = cfg.cell_list[0].phy_cell.carrier.scs; subcarrier_spacing_e{(subcarrier_spacing_opts::options)cfg.cell_list[0].phy_cell.carrier.scs}.to_number();
srsran::generate_default_mib(args, mib); srsran::generate_default_mib(scs, cfg.cell_list[0].coreset0_idx, mib);
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -49,37 +49,6 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_,
rrc_eutra = rrc_eutra_; rrc_eutra = rrc_eutra_;
cfg = cfg_; cfg = cfg_;
if (cfg.is_standalone) {
// Generate parameters of Coreset#0 and SS#0
const uint32_t coreset0_idx = 6; // See TS 38.331 - controlResourceSetZero
cfg.cell_list[0].phy_cell.pdcch.coreset_present[0] = true;
// Get pointA and SSB absolute frequencies
double pointA_abs_freq_Hz = cfg.cell_list[0].phy_cell.carrier.dl_center_frequency_hz -
cfg.cell_list[0].phy_cell.carrier.nof_prb * SRSRAN_NRE *
SRSRAN_SUBC_SPACING_NR(cfg.cell_list[0].phy_cell.carrier.scs) / 2;
double ssb_abs_freq_Hz = cfg.cell_list[0].phy_cell.carrier.ssb_center_freq_hz;
// Calculate integer SSB to pointA frequency offset in Hz
uint32_t ssb_pointA_freq_offset_Hz =
(ssb_abs_freq_Hz > pointA_abs_freq_Hz) ? (uint32_t)(ssb_abs_freq_Hz - pointA_abs_freq_Hz) : 0;
int ret = srsran_coreset_zero(cfg.cell_list[0].phy_cell.cell_id,
ssb_pointA_freq_offset_Hz,
cfg.cell_list[0].ssb_cfg.scs,
cfg.cell_list[0].phy_cell.carrier.scs,
coreset0_idx,
&cfg.cell_list[0].phy_cell.pdcch.coreset[0]);
srsran_assert(ret == SRSRAN_SUCCESS, "Failed to generate CORESET#0");
cfg.cell_list[0].phy_cell.pdcch.search_space_present[0] = true;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].id = 0;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].coreset_id = 0;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].type = srsran_search_space_type_common_0;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_candidates[0] = 1;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_candidates[1] = 1;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_candidates[2] = 1;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].formats[0] = srsran_dci_format_nr_1_0;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_formats = 1;
cfg.cell_list[0].phy_cell.pdcch.search_space[0].duration = 1;
}
cell_ctxt.reset(new cell_ctxt_t{}); cell_ctxt.reset(new cell_ctxt_t{});
// derived // derived

@ -0,0 +1,292 @@
/**
*
* \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 "srsgnb/hdr/stack/rrc/rrc_nr_config_utils.h"
#include "srsran/common/band_helper.h"
#define INVALID_PARAM(x, fmt, ...) \
do { \
if (not(x)) { \
get_logger().error("ERROR: " fmt, ##__VA_ARGS__); \
return SRSRAN_ERROR; \
} \
} while (0)
namespace srsenb {
static srslog::basic_logger& get_logger()
{
static srslog::basic_logger& logger = srslog::fetch_basic_logger("ALL");
return logger;
}
/// Generate default phy cell configuration
void generate_default_nr_phy_cell(phy_cell_cfg_nr_t& phy_cell)
{
phy_cell = {};
phy_cell.carrier.scs = srsran_subcarrier_spacing_15kHz;
phy_cell.carrier.nof_prb = 52;
phy_cell.carrier.max_mimo_layers = 1;
phy_cell.dl_freq_hz = 0; // auto set
phy_cell.ul_freq_hz = 0;
phy_cell.num_ra_preambles = 52;
// PRACH
phy_cell.prach.is_nr = true;
phy_cell.prach.config_idx = 8;
phy_cell.prach.root_seq_idx = 0;
phy_cell.prach.freq_offset = 1;
phy_cell.prach.num_ra_preambles = phy_cell.num_ra_preambles;
phy_cell.prach.hs_flag = false;
phy_cell.prach.tdd_config.configured = false;
// PDCCH
// Configure CORESET ID 1
phy_cell.pdcch.coreset_present[1] = true;
phy_cell.pdcch.coreset[1].id = 1;
phy_cell.pdcch.coreset[1].duration = 1;
phy_cell.pdcch.coreset[1].mapping_type = srsran_coreset_mapping_type_non_interleaved;
phy_cell.pdcch.coreset[1].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle;
// Generate frequency resources for the full BW
for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) {
phy_cell.pdcch.coreset[1].freq_resources[i] = i < SRSRAN_FLOOR(phy_cell.carrier.nof_prb, 6);
}
// Configure Search Space 1 as common
phy_cell.pdcch.search_space_present[1] = true;
phy_cell.pdcch.search_space[1].id = 1;
phy_cell.pdcch.search_space[1].coreset_id = 1;
phy_cell.pdcch.search_space[1].duration = 1;
phy_cell.pdcch.search_space[1].formats[0] = srsran_dci_format_nr_0_0; // DCI format for PUSCH
phy_cell.pdcch.search_space[1].formats[1] = srsran_dci_format_nr_1_0; // DCI format for PDSCH
phy_cell.pdcch.search_space[1].nof_formats = 2;
phy_cell.pdcch.search_space[1].type = srsran_search_space_type_common_3;
// Generate 1 candidate for each aggregation level if possible
for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) {
phy_cell.pdcch.search_space[1].nof_candidates[L] =
SRSRAN_MIN(2, srsran_pdcch_nr_max_candidates_coreset(&phy_cell.pdcch.coreset[1], L));
}
phy_cell.pdcch.ra_search_space_present = true;
phy_cell.pdcch.ra_search_space = phy_cell.pdcch.search_space[1];
phy_cell.pdcch.ra_search_space.type = srsran_search_space_type_common_1;
// PDSCH
phy_cell.pdsch.rs_power = 0;
phy_cell.pdsch.p_b = 0;
}
/// Generate default rrc nr cell configuration
void generate_default_nr_cell(rrc_cell_cfg_nr_t& cell)
{
cell = {};
cell.coreset0_idx = 6;
cell.ssb_absolute_freq_point = 0; // auto derived
generate_default_nr_phy_cell(cell.phy_cell);
}
/// Generate CORESET#0 and SSB absolute frequency (if not specified)
int derive_coreset0_params(rrc_cell_cfg_nr_t& cell)
{
// Generate CORESET#0
cell.phy_cell.pdcch.coreset_present[0] = true;
// Get pointA and SSB absolute frequencies
double pointA_abs_freq_Hz =
cell.phy_cell.carrier.dl_center_frequency_hz -
cell.phy_cell.carrier.nof_prb * SRSRAN_NRE * SRSRAN_SUBC_SPACING_NR(cell.phy_cell.carrier.scs) / 2;
double ssb_abs_freq_Hz = cell.phy_cell.carrier.ssb_center_freq_hz;
// Calculate integer SSB to pointA frequency offset in Hz
uint32_t ssb_pointA_freq_offset_Hz =
(ssb_abs_freq_Hz > pointA_abs_freq_Hz) ? (uint32_t)(ssb_abs_freq_Hz - pointA_abs_freq_Hz) : 0;
int ret = srsran_coreset_zero(cell.phy_cell.cell_id,
ssb_pointA_freq_offset_Hz,
cell.ssb_cfg.scs,
cell.phy_cell.carrier.scs,
cell.coreset0_idx,
&cell.phy_cell.pdcch.coreset[0]);
INVALID_PARAM(ret == SRSRAN_SUCCESS, "Failed to generate CORESET#0");
return SRSRAN_SUCCESS;
}
int derive_ssb_params(bool is_sa,
uint32_t dl_arfcn,
uint32_t band,
srsran_subcarrier_spacing_t pdcch_scs,
uint32_t coreset0_idx,
uint32_t nof_prb,
srsran_ssb_cfg_t& ssb)
{
// Verify essential parameters are specified and valid
INVALID_PARAM(dl_arfcn > 0, "Invalid DL ARFCN=%d", dl_arfcn);
INVALID_PARAM(band > 0, "Band is a mandatory parameter");
INVALID_PARAM(pdcch_scs < srsran_subcarrier_spacing_invalid, "Invalid carrier SCS");
INVALID_PARAM(coreset0_idx < 15, "Invalid controlResourceSetZero");
INVALID_PARAM(nof_prb > 0, "Invalid DL number of PRBS=%d", nof_prb);
srsran::srsran_band_helper band_helper;
double dl_freq_hz = band_helper.nr_arfcn_to_freq(dl_arfcn);
uint32_t dl_absolute_freq_point_a = band_helper.get_abs_freq_point_a_arfcn(nof_prb, dl_arfcn);
ssb.center_freq_hz = dl_freq_hz;
ssb.duplex_mode = band_helper.get_duplex_mode(band);
// derive SSB pattern and scs
ssb.pattern = band_helper.get_ssb_pattern(band, srsran_subcarrier_spacing_15kHz);
if (ssb.pattern == SRSRAN_SSB_PATTERN_A) {
// 15kHz SSB SCS
ssb.scs = srsran_subcarrier_spacing_15kHz;
} else {
// try to optain SSB pattern for same band with 30kHz SCS
ssb.pattern = band_helper.get_ssb_pattern(band, srsran_subcarrier_spacing_30kHz);
if (ssb.pattern == SRSRAN_SSB_PATTERN_B || ssb.pattern == SRSRAN_SSB_PATTERN_C) {
// SSB SCS is 30 kHz
ssb.scs = srsran_subcarrier_spacing_30kHz;
} else {
srsran_terminate("Can't derive SSB pattern from band %d", band);
}
}
// derive SSB position
int coreset0_rb_offset = 0;
if (is_sa) {
// Get offset in RBs between CORESET#0 and SSB
coreset0_rb_offset = srsran_coreset0_ssb_offset(coreset0_idx, ssb.scs, pdcch_scs);
INVALID_PARAM(coreset0_rb_offset >= 0, "Failed to compute RB offset between CORESET#0 and SSB");
} else {
// TODO: Verify if specified SSB frequency is valid
}
uint32_t ssb_abs_freq_point =
band_helper.get_abs_freq_ssb_arfcn(band, ssb.scs, dl_absolute_freq_point_a, coreset0_rb_offset);
INVALID_PARAM(ssb_abs_freq_point > 0,
"Can't derive SSB freq point for dl_arfcn=%d and band %d",
band_helper.freq_to_nr_arfcn(dl_freq_hz),
band);
// Convert to frequency for PHY
ssb.ssb_freq_hz = band_helper.nr_arfcn_to_freq(ssb_abs_freq_point);
ssb.periodicity_ms = 10; // TODO: make a param
ssb.beta_pss = 0.0;
ssb.beta_sss = 0.0;
ssb.beta_pbch = 0.0;
ssb.beta_pbch_dmrs = 0.0;
// set by PHY layer in worker_pool::set_common_cfg
ssb.srate_hz = 0.0;
ssb.scaling = 0.0;
return SRSRAN_SUCCESS;
}
int derive_phy_cell_freq_params(uint32_t dl_arfcn, uint32_t ul_arfcn, phy_cell_cfg_nr_t& phy_cell)
{
// Verify essential parameters are specified and valid
INVALID_PARAM(dl_arfcn > 0, "DL ARFCN is a mandatory parameter");
// Use helper class to derive NR carrier parameters
srsran::srsran_band_helper band_helper;
// derive DL freq from ARFCN
if (phy_cell.dl_freq_hz == 0) {
phy_cell.dl_freq_hz = band_helper.nr_arfcn_to_freq(dl_arfcn);
}
// derive UL freq from ARFCN
if (phy_cell.ul_freq_hz == 0) {
// auto-detect UL frequency
if (ul_arfcn == 0) {
// derive UL ARFCN from given DL ARFCN
ul_arfcn = band_helper.get_ul_arfcn_from_dl_arfcn(dl_arfcn);
INVALID_PARAM(ul_arfcn > 0, "Can't derive UL ARFCN from DL ARFCN %d", dl_arfcn);
}
phy_cell.ul_freq_hz = band_helper.nr_arfcn_to_freq(ul_arfcn);
}
// copy center frequencies
phy_cell.carrier.dl_center_frequency_hz = phy_cell.dl_freq_hz;
phy_cell.carrier.ul_center_frequency_hz = phy_cell.ul_freq_hz;
return SRSRAN_SUCCESS;
}
int set_derived_nr_cell_params(bool is_sa, rrc_cell_cfg_nr_t& cell)
{
// Verify essential parameters are specified and valid
INVALID_PARAM(cell.dl_arfcn > 0, "DL ARFCN is a mandatory parameter");
INVALID_PARAM(cell.band > 0, "Band is a mandatory parameter");
INVALID_PARAM(cell.phy_cell.carrier.nof_prb > 0, "Number of PRBs is a mandatory parameter");
// Use helper class to derive NR carrier parameters
srsran::srsran_band_helper band_helper;
if (cell.ul_arfcn == 0) {
// derive UL ARFCN from given DL ARFCN
cell.ul_arfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cell.dl_arfcn);
INVALID_PARAM(cell.ul_arfcn > 0, "Can't derive UL ARFCN from DL ARFCN %d", cell.dl_arfcn);
}
// duplex mode
cell.duplex_mode = band_helper.get_duplex_mode(cell.band);
// PointA
cell.dl_absolute_freq_point_a = band_helper.get_abs_freq_point_a_arfcn(cell.phy_cell.carrier.nof_prb, cell.dl_arfcn);
cell.ul_absolute_freq_point_a = band_helper.get_abs_freq_point_a_arfcn(cell.phy_cell.carrier.nof_prb, cell.ul_arfcn);
// Derive phy_cell parameters that depend on ARFCNs
derive_phy_cell_freq_params(cell.dl_arfcn, cell.ul_arfcn, cell.phy_cell);
// Derive SSB params
derive_ssb_params(is_sa,
cell.dl_arfcn,
cell.band,
cell.phy_cell.carrier.scs,
cell.coreset0_idx,
cell.phy_cell.carrier.nof_prb,
cell.ssb_cfg);
cell.phy_cell.carrier.ssb_center_freq_hz = cell.ssb_cfg.ssb_freq_hz;
cell.ssb_absolute_freq_point = band_helper.freq_to_nr_arfcn(cell.ssb_cfg.ssb_freq_hz);
// Derive remaining config params
if (is_sa) {
derive_coreset0_params(cell);
cell.phy_cell.pdcch.search_space_present[0] = true;
cell.phy_cell.pdcch.search_space[0].id = 0;
cell.phy_cell.pdcch.search_space[0].coreset_id = 0;
cell.phy_cell.pdcch.search_space[0].type = srsran_search_space_type_common_0;
cell.phy_cell.pdcch.search_space[0].nof_candidates[0] = 1;
cell.phy_cell.pdcch.search_space[0].nof_candidates[1] = 1;
cell.phy_cell.pdcch.search_space[0].nof_candidates[2] = 1;
cell.phy_cell.pdcch.search_space[0].formats[0] = srsran_dci_format_nr_1_0;
cell.phy_cell.pdcch.search_space[0].nof_formats = 1;
cell.phy_cell.pdcch.search_space[0].duration = 1;
}
// Derive remaining PHY cell params
cell.phy_cell.prach.num_ra_preambles = cell.phy_cell.num_ra_preambles;
cell.phy_cell.prach.tdd_config.configured = (cell.duplex_mode == SRSRAN_DUPLEX_MODE_TDD);
return check_nr_cell_cfg_valid(cell, is_sa);
}
int check_nr_cell_cfg_valid(const rrc_cell_cfg_nr_t& cell, bool is_sa)
{
// verify SSB params are consistent
INVALID_PARAM(cell.ssb_cfg.center_freq_hz == cell.phy_cell.dl_freq_hz, "Invalid SSB param generation");
return SRSRAN_SUCCESS;
}
} // namespace srsenb

@ -9,5 +9,5 @@
add_library(rrc_nr_test_helpers rrc_nr_test_helpers.cc) add_library(rrc_nr_test_helpers rrc_nr_test_helpers.cc)
add_executable(rrc_nr_test rrc_nr_test.cc) add_executable(rrc_nr_test rrc_nr_test.cc)
target_link_libraries(rrc_nr_test srsgnb_rrc test_helpers rrc_nr_test_helpers ${ATOMIC_LIBS}) target_link_libraries(rrc_nr_test srsgnb_rrc srsgnb_rrc_config_utils test_helpers rrc_nr_test_helpers ${ATOMIC_LIBS})
add_test(rrc_nr_test rrc_nr_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) add_test(rrc_nr_test rrc_nr_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..)

@ -168,7 +168,7 @@ int main(int argc, char** argv)
auto& logger = srslog::fetch_basic_logger("ASN1"); auto& logger = srslog::fetch_basic_logger("ASN1");
logger.set_level(srslog::basic_levels::info); logger.set_level(srslog::basic_levels::info);
auto& rrc_logger = srslog::fetch_basic_logger("RRC-NR"); auto& rrc_logger = srslog::fetch_basic_logger("RRC-NR");
rrc_logger.set_level(srslog::basic_levels::info); rrc_logger.set_level(srslog::basic_levels::debug);
srslog::init(); srslog::init();

Loading…
Cancel
Save