Merge branch 'next' into agpl_next

master
Codebot 4 years ago committed by Your Name
commit 887f1da10c

@ -65,11 +65,13 @@ struct cells results[1024];
float rf_gain = 70.0; float rf_gain = 70.0;
char* rf_args = ""; char* rf_args = "";
char* rf_dev = "";
void usage(char* prog) void usage(char* prog)
{ {
printf("Usage: %s [agsendtvb] -b band\n", prog); printf("Usage: %s [agsendtvb] -b band\n", prog);
printf("\t-a RF args [Default %s]\n", rf_args); printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-d RF devicename [Default %s]\n", rf_dev);
printf("\t-g RF gain [Default %.2f dB]\n", rf_gain); printf("\t-g RF gain [Default %.2f dB]\n", rf_gain);
printf("\t-s earfcn_start [Default All]\n"); printf("\t-s earfcn_start [Default All]\n");
printf("\t-e earfcn_end [Default All]\n"); printf("\t-e earfcn_end [Default All]\n");
@ -88,6 +90,9 @@ void parse_args(int argc, char** argv)
case 'b': case 'b':
band = (int)strtol(argv[optind], NULL, 10); band = (int)strtol(argv[optind], NULL, 10);
break; break;
case 'd':
rf_dev = argv[optind];
break;
case 's': case 's':
earfcn_start = (int)strtol(argv[optind], NULL, 10); earfcn_start = (int)strtol(argv[optind], NULL, 10);
break; break;
@ -151,7 +156,8 @@ int main(int argc, char** argv)
parse_args(argc, argv); parse_args(argc, argv);
printf("Opening RF device...\n"); printf("Opening RF device...\n");
if (srsran_rf_open(&rf, rf_args)) {
if (srsran_rf_open_devname(&rf, rf_dev, rf_args, 1)) {
ERROR("Error opening rf"); ERROR("Error opening rf");
exit(-1); exit(-1);
} }

@ -551,7 +551,7 @@ int main(int argc, char** argv)
system_frame_number = (mib.sfn + sfn_offset) % 1024; system_frame_number = (mib.sfn + sfn_offset) % 1024;
cell.mode = mib.mode; cell.mode = mib.mode;
// set number of ports of base cell to that of NB-IoT cell (FIXME: read eutra-NumCRS-Ports-r13) // set number of ports of base cell to that of NB-IoT cell (TODO: read eutra-NumCRS-Ports-r13)
cell.base.nof_ports = cell.nof_ports; cell.base.nof_ports = cell.nof_ports;
if (cell.mode == SRSRAN_NBIOT_MODE_INBAND_SAME_PCI) { if (cell.mode == SRSRAN_NBIOT_MODE_INBAND_SAME_PCI) {

@ -374,7 +374,6 @@ srsran_ue_sync_t ue_sync;
prog_args_t prog_args; prog_args_t prog_args;
uint32_t pkt_errors = 0, pkt_total = 0, nof_detected = 0, pmch_pkt_errors = 0, pmch_pkt_total = 0, nof_trials = 0; uint32_t pkt_errors = 0, pkt_total = 0, nof_detected = 0, pmch_pkt_errors = 0, pmch_pkt_total = 0, nof_trials = 0;
double evm = 0.0;
srsran_netsink_t net_sink, net_sink_signal; srsran_netsink_t net_sink, net_sink_signal;
/* Useful macros for printing lines which will disappear */ /* Useful macros for printing lines which will disappear */

@ -253,7 +253,7 @@ int main(int argc, char** argv)
if (!prog_args.input_file_name) { if (!prog_args.input_file_name) {
printf("Opening RF device...\n"); printf("Opening RF device...\n");
if (srsran_rf_open_multi(&radio, prog_args.rf_args, prog_args.nof_rx_antennas)) { if (srsran_rf_open_devname(&radio, prog_args.rf_dev, prog_args.rf_args, prog_args.nof_rx_antennas)) {
ERROR("Error opening rf"); ERROR("Error opening rf");
exit(-1); exit(-1);
} }

@ -48,7 +48,7 @@ public:
bool empty() const { return stop_ == start_; } bool empty() const { return stop_ == start_; }
auto length() -> decltype(std::declval<T>() - std::declval<T>()) const { return stop_ - start_; } auto length() const -> decltype(std::declval<T>() - std::declval<T>()) { return stop_ - start_; }
void set(T start_point, T stop_point) void set(T start_point, T stop_point)
{ {

@ -59,7 +59,7 @@ public:
{ {
for (mem_block_elem_t& elem : pools) { for (mem_block_elem_t& elem : pools) {
std::unique_lock<std::mutex> lock(elem.mutex); std::unique_lock<std::mutex> lock(elem.mutex);
srsran_assert(elem.count == 0, "There are missing deallocations for stack id=%zd", elem.key); srsran_expect(elem.count == 0, "There are missing deallocations for stack id=%zd", elem.key);
if (elem.alloc.is_init()) { if (elem.alloc.is_init()) {
void* ptr = elem.alloc.memblock_ptr(); void* ptr = elem.alloc.memblock_ptr();
elem.alloc.clear(); elem.alloc.clear();

@ -295,7 +295,7 @@ public:
using iterator = T*; using iterator = T*;
using const_iterator = const T*; using const_iterator = const T*;
explicit bounded_array(uint32_t size_ = 0) : current_size(size_) {} explicit bounded_array(uint32_t size_ = 0) : data_(), current_size(size_) {}
static uint32_t capacity() { return MAX_N; } static uint32_t capacity() { return MAX_N; }
uint32_t size() const { return current_size; } uint32_t size() const { return current_size; }
T& operator[](uint32_t idx) { return data_[idx]; } T& operator[](uint32_t idx) { return data_[idx]; }

@ -4159,7 +4159,7 @@ public:
#elif defined(__aarch64__) #elif defined(__aarch64__)
#if defined(__APPLE__) #if defined(__APPLE__)
error_addr = reinterpret_cast<void *>(uctx->uc_mcontext->__ss.__pc); error_addr = reinterpret_cast<void *>(uctx->uc_mcontext->__ss.__pc);
#elif #else
error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.pc); error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.pc);
#endif #endif
#elif defined(__mips__) #elif defined(__mips__)

@ -80,7 +80,7 @@ private:
// Elements of Table 5.4.2.3-1 in TS 38.104 // Elements of Table 5.4.2.3-1 in TS 38.104
struct nr_band { struct nr_band {
uint8_t band; uint16_t band;
delta_f_raster_t delta_f_raster; delta_f_raster_t delta_f_raster;
uint32_t ul_nref_first; uint32_t ul_nref_first;
uint32_t ul_nref_step; uint32_t ul_nref_step;
@ -92,12 +92,45 @@ private:
// List of NR bands for FR1 (Table 5.4.2.3-1) // List of NR bands for FR1 (Table 5.4.2.3-1)
// bands with more than one raster offset have multiple entries // bands with more than one raster offset have multiple entries
// TODO: add remaining bands static const uint32_t nof_nr_bands_fr1 = 36;
static const uint32_t nof_nr_bands_fr1 = 7;
static constexpr std::array<nr_band, nof_nr_bands_fr1> nr_band_table_fr1 = {{ static constexpr std::array<nr_band, nof_nr_bands_fr1> nr_band_table_fr1 = {{
// clang-format off // clang-format off
{1, KHZ_100, 384000, 20, 396000, 422000, 20, 434000},
{2, KHZ_100, 370000, 20, 382000, 386000, 20, 398000},
{3, KHZ_100, 342000, 20, 357000, 361000, 20, 376000},
{5, KHZ_100, 164800, 20, 169800, 173800, 20, 178800},
{7, KHZ_100, 500000, 20, 514000, 524000, 20, 538000},
{8, KHZ_100, 176000, 20, 183000, 185000, 20, 192000},
{12, KHZ_100, 139800, 20, 143200, 145800, 20, 149200},
{20, KHZ_100, 166400, 20, 172400, 158200, 20, 164200},
{25, KHZ_100, 370000, 20, 383000, 386000, 20, 399000},
{28, KHZ_100, 140600, 20, 149600, 151600, 20, 160600},
{34, KHZ_100, 402000, 20, 405000, 402000, 20, 405000},
{38, KHZ_100, 514000, 20, 524000, 514000, 20, 524000},
{39, KHZ_100, 376000, 20, 384000, 376000, 20, 384000},
{40, KHZ_100, 460000, 20, 480000, 460000, 20, 480000},
{41, KHZ_15, 499200, 3, 537999, 499200, 3, 537999},
{41, KHZ_30, 499200, 6, 537996, 499200, 6, 537996},
{50, KHZ_100, 286400, 20, 303400, 286400, 20, 303400},
{51, KHZ_100, 285400, 20, 286400, 285400, 20, 286400},
{66, KHZ_100, 342000, 20, 356000, 422000, 20, 440000},
{70, KHZ_100, 339000, 20, 342000, 399000, 20, 404000},
{71, KHZ_100, 132600, 20, 139600, 123400, 20, 130400},
{74, KHZ_100, 285400, 20, 294000, 295000, 20, 303600}, {74, KHZ_100, 285400, 20, 294000, 295000, 20, 303600},
// n75+n76 missing
{75, KHZ_100, 0, 0, 0, 286400, 20, 303400},
{76, KHZ_100, 0, 0, 0, 285400, 20, 286400},
{77, KHZ_15, 620000, 1, 680000, 620000, 1, 680000}, {77, KHZ_15, 620000, 1, 680000, 620000, 1, 680000},
{77, KHZ_30, 620000, 2, 680000, 620000, 2, 680000}, {77, KHZ_30, 620000, 2, 680000, 620000, 2, 680000},
@ -105,9 +138,31 @@ private:
{78, KHZ_30, 620000, 2, 653332, 620000, 2, 653332}, {78, KHZ_30, 620000, 2, 653332, 620000, 2, 653332},
{79, KHZ_15, 693334, 2, 733333, 693334, 2, 733333}, {79, KHZ_15, 693334, 2, 733333, 693334, 2, 733333},
{79, KHZ_30, 693334, 2, 733332, 693334, 2, 733332} {79, KHZ_30, 693334, 2, 733332, 693334, 2, 733332},
{80, KHZ_100, 342000, 20, 357000, 0, 0, 0},
{81, KHZ_100, 176000, 20, 183000, 0, 0, 0},
{82, KHZ_100, 166400, 20, 172400, 0, 0, 0},
{83, KHZ_100, 140600, 20, 149600, 0, 0, 0},
{84, KHZ_100, 384000, 20, 396000, 0, 0, 0},
{86, KHZ_100, 342000, 20, 356000, 0, 0, 0}
// clang-format on // clang-format on
}}; }};
static const uint32_t nof_nr_bands_fr2 = 36;
static constexpr std::array<nr_band, nof_nr_bands_fr2> nr_band_table_fr2 = {{
{257, KHZ_60, 2054166, 1, 2104165, 2054166, 1, 2104165},
{257, KHZ_120, 2054167, 2, 2104165, 2054167, 20, 2104165},
{258, KHZ_60, 2016667, 1, 2070832, 2016667, 1, 2070832},
{258, KHZ_120, 2016667, 2, 2070831, 2016667, 2, 2070832},
{260, KHZ_60, 2229166, 1, 2279165, 2229166, 1, 2279165},
{260, KHZ_120, 2229167, 2, 2279165, 2229167, 2, 2279165},
{261, KHZ_60, 2070833, 1, 2084999, 2070833, 1, 2084999},
{261, KHZ_120, 2070833, 2, 2084999, 2070833, 2, 2084999}
}};
}; };
} // namespace srsran } // namespace srsran

@ -202,7 +202,7 @@ private:
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - tti_start_time) std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - tti_start_time)
.count(); .count();
// FIXME: add averaging // TODO: add averaging
metrics.avg_rtt_us = rtt; metrics.avg_rtt_us = rtt;
} }
}; };

@ -164,7 +164,7 @@ public:
const uint8_t* data() const { return msg; } const uint8_t* data() const { return msg; }
uint32_t size() const { return N_bytes; } uint32_t size() const { return N_bytes; }
iterator begin() { return msg; } iterator begin() { return msg; }
const iterator begin() const { return msg; } const_iterator begin() const { return msg; }
iterator end() { return msg + N_bytes; } iterator end() { return msg + N_bytes; }
const_iterator end() const { return msg + N_bytes; } const_iterator end() const { return msg + N_bytes; }

@ -65,7 +65,8 @@ struct cell_cfg_t {
double dl_freq_hz; double dl_freq_hz;
uint32_t ul_earfcn; uint32_t ul_earfcn;
double ul_freq_hz; double ul_freq_hz;
int target_ul_sinr_db; int target_pucch_sinr_db;
int target_pusch_sinr_db;
uint32_t initial_dl_cqi; uint32_t initial_dl_cqi;
bool enable_phr_handling; bool enable_phr_handling;
std::vector<scell_cfg_t> scell_list; std::vector<scell_cfg_t> scell_list;

@ -35,6 +35,7 @@ struct s1ap_args_t {
uint16_t mnc; // BCD-coded with 0xF filler uint16_t mnc; // BCD-coded with 0xF filler
std::string mme_addr; std::string mme_addr;
std::string gtp_bind_addr; std::string gtp_bind_addr;
std::string gtp_advertise_addr;
std::string s1c_bind_addr; std::string s1c_bind_addr;
std::string enb_name; std::string enb_name;
}; };

@ -74,9 +74,12 @@ public:
cell_cfg_sib_t sibs[MAX_SIBS]; cell_cfg_sib_t sibs[MAX_SIBS];
uint32_t si_window_ms; uint32_t si_window_ms;
/* pucch configuration */
float target_pucch_ul_sinr;
/* pusch configuration */ /* pusch configuration */
srsran_pusch_hopping_cfg_t pusch_hopping_cfg; srsran_pusch_hopping_cfg_t pusch_hopping_cfg;
float target_ul_sinr; float target_pusch_ul_sinr;
bool enable_phr_handling; bool enable_phr_handling;
bool enable_64qam; bool enable_64qam;

@ -91,7 +91,7 @@ public:
tb_ul_t tb; // only single TB in UL tb_ul_t tb; // only single TB in UL
} tb_action_ul_t; } tb_action_ul_t;
virtual int sf_indication(const uint32_t tti) = 0; ///< FIXME: rename to slot indication virtual int sf_indication(const uint32_t tti) = 0; ///< TODO: rename to slot indication
// Query the MAC for the current RNTI to look for // Query the MAC for the current RNTI to look for
struct sched_rnti_t { struct sched_rnti_t {

@ -44,9 +44,7 @@ struct phy_args_t {
std::vector<uint32_t> dl_earfcn_list = {3400}; // vectorized version of dl_earfcn that gets populated during init std::vector<uint32_t> dl_earfcn_list = {3400}; // vectorized version of dl_earfcn that gets populated during init
std::map<uint32_t, uint32_t> ul_earfcn_map; // Map linking DL EARFCN and UL EARFCN std::map<uint32_t, uint32_t> ul_earfcn_map; // Map linking DL EARFCN and UL EARFCN
std::string dl_nr_arfcn = "632628"; // comma-separated list of DL NR ARFCNs int force_N_id_2 = -1; // Cell identity within the identity group (PSS) to filter.
std::vector<uint32_t> dl_nr_arfcn_list = {
632628}; // vectorized version of dl_nr_arfcn that gets populated during init
float dl_freq = -1.0f; float dl_freq = -1.0f;
float ul_freq = -1.0f; float ul_freq = -1.0f;
@ -63,7 +61,6 @@ struct phy_args_t {
uint32_t nof_lte_carriers = 1; uint32_t nof_lte_carriers = 1;
uint32_t nof_nr_carriers = 0; uint32_t nof_nr_carriers = 0;
uint32_t nr_max_nof_prb = 106; uint32_t nr_max_nof_prb = 106;
double nr_freq_hz = 2630e6;
uint32_t nof_rx_ant = 1; uint32_t nof_rx_ant = 1;
std::string equalizer_mode = "mmse"; std::string equalizer_mode = "mmse";
int cqi_max = 15; int cqi_max = 15;

@ -289,6 +289,7 @@ typedef struct SRSRAN_API {
uint32_t pci; uint32_t pci;
uint32_t absolute_frequency_ssb; uint32_t absolute_frequency_ssb;
uint32_t absolute_frequency_point_a; uint32_t absolute_frequency_point_a;
uint32_t offset_to_carrier; ///< Offset between point A and the lowest subcarrier of the lowest RB
srsran_subcarrier_spacing_t scs; srsran_subcarrier_spacing_t scs;
uint32_t nof_prb; ///< @brief See TS 38.101-1 Table 5.3.2-1 for more details uint32_t nof_prb; ///< @brief See TS 38.101-1 Table 5.3.2-1 for more details
uint32_t start; uint32_t start;

@ -56,7 +56,7 @@ static const uint16_t NMAX = 1024;
/*! /*!
* \brief Base 2 logarithm of maximum codeword length * \brief Base 2 logarithm of maximum codeword length
*/ */
static const uint16_t NMAX_LOG = 10; #define NMAX_LOG 10U
/*! /*!
* \brief \f$log_2(EMAX)\f$ * \brief \f$log_2(EMAX)\f$

@ -237,7 +237,7 @@ typedef struct SRSRAN_API {
* @remark Implemented according TS 38.212 section 7.3.1.0 DCI size alignment * @remark Implemented according TS 38.212 section 7.3.1.0 DCI size alignment
* @param[in,out] dci DCI object * @param[in,out] dci DCI object
* @param[in] cfg NR-DCI configuration * @param[in] cfg NR-DCI configuration
* @return SRSLTE_SUCCESS if the configuration is valid, SRSLTE_ERROR code otherwise * @return SRSRAN_SUCCESS if the configuration is valid, SRSRAN_ERROR code otherwise
*/ */
SRSRAN_API int srsran_dci_nr_set_cfg(srsran_dci_nr_t* dci, const srsran_dci_cfg_nr_t* cfg); SRSRAN_API int srsran_dci_nr_set_cfg(srsran_dci_nr_t* dci, const srsran_dci_cfg_nr_t* cfg);
@ -266,7 +266,7 @@ SRSRAN_API bool srsran_dci_nr_valid_direction(const srsran_dci_msg_nr_t* dci);
* @param q NR DCI object with precomputed DCI parameters * @param q NR DCI object with precomputed DCI parameters
* @param dci DL NR DCI to pack (serialize) * @param dci DL NR DCI to pack (serialize)
* @param[out] msg Resultant packed DCI message * @param[out] msg Resultant packed DCI message
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise * @return SRSRAN_SUCCESS if provided arguments are valid, SRSRAN_ERROR code otherwise
*/ */
SRSRAN_API int srsran_dci_nr_dl_pack(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, srsran_dci_msg_nr_t* msg); SRSRAN_API int srsran_dci_nr_dl_pack(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, srsran_dci_msg_nr_t* msg);
@ -275,7 +275,7 @@ SRSRAN_API int srsran_dci_nr_dl_pack(const srsran_dci_nr_t* q, const srsran_dci_
* @param q NR DCI object with precomputed DCI parameters * @param q NR DCI object with precomputed DCI parameters
* @param msg DCI message to unpack (deserialize) * @param msg DCI message to unpack (deserialize)
* @param[out] dci Resultant unpacked DL DCI * @param[out] dci Resultant unpacked DL DCI
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise * @return SRSRAN_SUCCESS if provided arguments are valid, SRSRAN_ERROR code otherwise
*/ */
SRSRAN_API int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_dl_nr_t* dci); SRSRAN_API int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_dl_nr_t* dci);
@ -284,7 +284,7 @@ SRSRAN_API int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_
* @param q NR DCI object with precomputed DCI parameters * @param q NR DCI object with precomputed DCI parameters
* @param dci UL NR DCI to pack (serialize) * @param dci UL NR DCI to pack (serialize)
* @param[out] msg resultant DCI message * @param[out] msg resultant DCI message
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise * @return SRSRAN_SUCCESS if provided arguments are valid, SRSRAN_ERROR code otherwise
*/ */
SRSRAN_API int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, srsran_dci_msg_nr_t* msg); SRSRAN_API int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, srsran_dci_msg_nr_t* msg);
@ -293,7 +293,7 @@ SRSRAN_API int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_
* @param q NR DCI object with precomputed DCI parameters * @param q NR DCI object with precomputed DCI parameters
* @param msg DCI message to unpack (deserialize) * @param msg DCI message to unpack (deserialize)
* @param[out] dci Resultant unpacked UL DCI * @param[out] dci Resultant unpacked UL DCI
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise * @return SRSRAN_SUCCESS if provided arguments are valid, SRSRAN_ERROR code otherwise
*/ */
SRSRAN_API int srsran_dci_nr_ul_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_ul_nr_t* dci); SRSRAN_API int srsran_dci_nr_ul_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_ul_nr_t* dci);

@ -88,7 +88,7 @@ SRSRAN_API int srsran_re_pattern_merge(srsran_re_pattern_list_t* list, const srs
* @brief Checks collision between a RE pattern list and a RE pattern * @brief Checks collision between a RE pattern list and a RE pattern
* @param list Provides pattern list * @param list Provides pattern list
* @param p Provides a pattern * @param p Provides a pattern
* @return SRSLTE_SUCCESS if no collision is detected, SRSLTE_ERROR code otherwise * @return SRSRAN_SUCCESS if no collision is detected, SRSRAN_ERROR code otherwise
*/ */
SRSRAN_API int srsran_re_pattern_check_collision(const srsran_re_pattern_list_t* list, const srsran_re_pattern_t* p); SRSRAN_API int srsran_re_pattern_check_collision(const srsran_re_pattern_list_t* list, const srsran_re_pattern_t* p);

@ -66,8 +66,8 @@ public:
pdcp_entity_base(pdcp_entity_base&&) = default; pdcp_entity_base(pdcp_entity_base&&) = default;
virtual ~pdcp_entity_base(); virtual ~pdcp_entity_base();
virtual bool configure(const pdcp_config_t& cnfg_) = 0; virtual bool configure(const pdcp_config_t& cnfg_) = 0;
virtual void reset() = 0; virtual void reset() = 0;
virtual void reestablish() = 0; virtual void reestablish() = 0;
bool is_active() { return active; } bool is_active() { return active; }
bool is_srb() { return cfg.rb_type == PDCP_RB_IS_SRB; } bool is_srb() { return cfg.rb_type == PDCP_RB_IS_SRB; }
@ -115,7 +115,7 @@ public:
} }
} }
void config_security(as_security_config_t sec_cfg_); void config_security(const as_security_config_t& sec_cfg_);
// GW/SDAP/RRC interface // GW/SDAP/RRC interface
virtual void write_sdu(unique_byte_buffer_t sdu, int sn = -1) = 0; virtual void write_sdu(unique_byte_buffer_t sdu, int sn = -1) = 0;

@ -459,7 +459,7 @@ bool make_phy_csi_report(const csi_report_cfg_s& csi_report_cfg,
return false; return false;
} }
if (srsran_csi_hl_report_cfg.type = SRSRAN_CSI_REPORT_TYPE_PERIODIC) { if (srsran_csi_hl_report_cfg.type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) {
srsran_csi_hl_report_cfg.periodic.period = srsran_csi_hl_report_cfg.periodic.period =
csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.type().to_number(); csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.type().to_number();
switch (csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.type()) { switch (csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.type()) {
@ -586,7 +586,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) 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_t srsran_coreset = {};
srsran_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) { switch (ctrl_res_set.precoder_granularity) {
case ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle: case ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle:
srsran_coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; srsran_coreset.precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle;
@ -949,77 +949,76 @@ bool make_phy_zp_csi_rs_resource(const asn1::rrc_nr::zp_csi_rs_res_s& zp_csi_rs_
} }
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.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; 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){ if (zp_csi_rs_res.periodicity_and_offset_present) {
switch (zp_csi_rs_res.periodicity_and_offset.type()) switch (zp_csi_rs_res.periodicity_and_offset.type()) {
{ case csi_res_periodicity_and_offset_c::types_opts::options::slots4:
case csi_res_periodicity_and_offset_c::types_opts::options::slots4: zp_csi_rs_resource.periodicity.period = 4;
zp_csi_rs_resource.periodicity.period = 4; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots4();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots4(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots5:
case csi_res_periodicity_and_offset_c::types_opts::options::slots5: zp_csi_rs_resource.periodicity.period = 5;
zp_csi_rs_resource.periodicity.period = 5; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots5();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots5(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots8:
case csi_res_periodicity_and_offset_c::types_opts::options::slots8: zp_csi_rs_resource.periodicity.period = 8;
zp_csi_rs_resource.periodicity.period = 8; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots8();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots8(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots10:
case csi_res_periodicity_and_offset_c::types_opts::options::slots10: zp_csi_rs_resource.periodicity.period = 10;
zp_csi_rs_resource.periodicity.period = 10; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots10();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots10(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots16:
case csi_res_periodicity_and_offset_c::types_opts::options::slots16: zp_csi_rs_resource.periodicity.period = 16;
zp_csi_rs_resource.periodicity.period = 16; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots16();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots16(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots20:
case csi_res_periodicity_and_offset_c::types_opts::options::slots20: zp_csi_rs_resource.periodicity.period = 20;
zp_csi_rs_resource.periodicity.period = 20; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots20();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots20(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots32:
case csi_res_periodicity_and_offset_c::types_opts::options::slots32: zp_csi_rs_resource.periodicity.period = 32;
zp_csi_rs_resource.periodicity.period = 32; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots32();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots32(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots40:
case csi_res_periodicity_and_offset_c::types_opts::options::slots40: zp_csi_rs_resource.periodicity.period = 40;
zp_csi_rs_resource.periodicity.period = 40; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots40();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots40(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots64:
case csi_res_periodicity_and_offset_c::types_opts::options::slots64: zp_csi_rs_resource.periodicity.period = 64;
zp_csi_rs_resource.periodicity.period = 64; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots64();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots64(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots80:
case csi_res_periodicity_and_offset_c::types_opts::options::slots80: zp_csi_rs_resource.periodicity.period = 80;
zp_csi_rs_resource.periodicity.period = 80; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots80();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots80(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots160:
case csi_res_periodicity_and_offset_c::types_opts::options::slots160: zp_csi_rs_resource.periodicity.period = 160;
zp_csi_rs_resource.periodicity.period = 160; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots160();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots160(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots320:
case csi_res_periodicity_and_offset_c::types_opts::options::slots320: zp_csi_rs_resource.periodicity.period = 320;
zp_csi_rs_resource.periodicity.period = 320; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots320();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots320(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots640:
case csi_res_periodicity_and_offset_c::types_opts::options::slots640: zp_csi_rs_resource.periodicity.period = 640;
zp_csi_rs_resource.periodicity.period = 640; zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots640();
zp_csi_rs_resource.periodicity.offset = zp_csi_rs_res.periodicity_and_offset.slots640(); break;
break; default:
default: asn1::log_warning("Invalid option for periodicity_and_offset %s",
asn1::log_warning("Invalid option for periodicity_and_offset %s", zp_csi_rs_res.periodicity_and_offset.type().to_string());
zp_csi_rs_res.periodicity_and_offset.type().to_string()); return false;
return false;
} }
} else { } else {
asn1::log_warning("Option periodicity_and_offset not present"); asn1::log_warning("Option periodicity_and_offset not present");
return false; return false;
} }
*out_zp_csi_rs_resource = zp_csi_rs_resource; *out_zp_csi_rs_resource = zp_csi_rs_resource;
return true; return true;
} }
bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nzp_csi_rs_res, 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* out_csi_rs_nzp_resource)
{ {
srsran_csi_rs_nzp_resource_t 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; csi_rs_nzp_resource.id = asn1_nzp_csi_rs_res.nzp_csi_rs_res_id;
@ -1028,24 +1027,24 @@ bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nz
csi_rs_nzp_resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1; 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++) { 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] = 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() - asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row1().get(
1 - i); asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row1().length() - 1 - i);
} }
break; break;
case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row2: 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; 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++) { 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] = 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() - asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row2().get(
1 - i); asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row2().length() - 1 - i);
} }
break; break;
case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::row4: 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; 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++) { 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] = 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() - asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row4().get(
1 - i); asn1_nzp_csi_rs_res.res_map.freq_domain_alloc.row4().length() - 1 - i);
} }
break; break;
case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::other: case csi_rs_res_map_s::freq_domain_alloc_c_::types_opts::options::other:
@ -1113,69 +1112,68 @@ bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nz
csi_rs_nzp_resource.power_control_offset_ss = asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss.to_number(); 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){ if (asn1_nzp_csi_rs_res.periodicity_and_offset_present) {
switch (asn1_nzp_csi_rs_res.periodicity_and_offset.type()) switch (asn1_nzp_csi_rs_res.periodicity_and_offset.type()) {
{ case csi_res_periodicity_and_offset_c::types_opts::options::slots4:
case csi_res_periodicity_and_offset_c::types_opts::options::slots4: csi_rs_nzp_resource.periodicity.period = 4;
csi_rs_nzp_resource.periodicity.period = 4; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots4();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots4(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots5:
case csi_res_periodicity_and_offset_c::types_opts::options::slots5: csi_rs_nzp_resource.periodicity.period = 5;
csi_rs_nzp_resource.periodicity.period = 5; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots5();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots5(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots8:
case csi_res_periodicity_and_offset_c::types_opts::options::slots8: csi_rs_nzp_resource.periodicity.period = 8;
csi_rs_nzp_resource.periodicity.period = 8; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots8();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots8(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots10:
case csi_res_periodicity_and_offset_c::types_opts::options::slots10: csi_rs_nzp_resource.periodicity.period = 10;
csi_rs_nzp_resource.periodicity.period = 10; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots10();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots10(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots16:
case csi_res_periodicity_and_offset_c::types_opts::options::slots16: csi_rs_nzp_resource.periodicity.period = 16;
csi_rs_nzp_resource.periodicity.period = 16; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots16();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots16(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots20:
case csi_res_periodicity_and_offset_c::types_opts::options::slots20: csi_rs_nzp_resource.periodicity.period = 20;
csi_rs_nzp_resource.periodicity.period = 20; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots20();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots20(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots32:
case csi_res_periodicity_and_offset_c::types_opts::options::slots32: csi_rs_nzp_resource.periodicity.period = 32;
csi_rs_nzp_resource.periodicity.period = 32; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots32();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots32(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots40:
case csi_res_periodicity_and_offset_c::types_opts::options::slots40: csi_rs_nzp_resource.periodicity.period = 40;
csi_rs_nzp_resource.periodicity.period = 40; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots40();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots40(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots64:
case csi_res_periodicity_and_offset_c::types_opts::options::slots64: csi_rs_nzp_resource.periodicity.period = 64;
csi_rs_nzp_resource.periodicity.period = 64; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots64();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots64(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots80:
case csi_res_periodicity_and_offset_c::types_opts::options::slots80: csi_rs_nzp_resource.periodicity.period = 80;
csi_rs_nzp_resource.periodicity.period = 80; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots80();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots80(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots160:
case csi_res_periodicity_and_offset_c::types_opts::options::slots160: csi_rs_nzp_resource.periodicity.period = 160;
csi_rs_nzp_resource.periodicity.period = 160; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots160();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots160(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots320:
case csi_res_periodicity_and_offset_c::types_opts::options::slots320: csi_rs_nzp_resource.periodicity.period = 320;
csi_rs_nzp_resource.periodicity.period = 320; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots320();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots320(); break;
break; case csi_res_periodicity_and_offset_c::types_opts::options::slots640:
case csi_res_periodicity_and_offset_c::types_opts::options::slots640: csi_rs_nzp_resource.periodicity.period = 640;
csi_rs_nzp_resource.periodicity.period = 640; csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots640();
csi_rs_nzp_resource.periodicity.offset = asn1_nzp_csi_rs_res.periodicity_and_offset.slots640(); break;
break; default:
default: asn1::log_warning("Invalid option for periodicity_and_offset %s",
asn1::log_warning("Invalid option for periodicity_and_offset %s", asn1_nzp_csi_rs_res.periodicity_and_offset.type().to_string());
asn1_nzp_csi_rs_res.periodicity_and_offset.type().to_string()); return false;
return false;
} }
} else { } else {
asn1::log_warning("Option periodicity_and_offset not present"); asn1::log_warning("Option periodicity_and_offset not present");
return false; return false;
} }
csi_rs_nzp_resource.scrambling_id = asn1_nzp_csi_rs_res.scrambling_id; csi_rs_nzp_resource.scrambling_id = asn1_nzp_csi_rs_res.scrambling_id;
@ -1193,14 +1191,12 @@ bool make_phy_carrier_cfg(const freq_info_dl_s& asn1_freq_info_dl, srsran_carrie
asn1::log_warning("Option absolute_freq_ssb not present"); asn1::log_warning("Option absolute_freq_ssb not present");
return false; return false;
} }
uint32_t absolute_frequency_point_a = asn1_freq_info_dl.absolute_freq_point_a;
if (asn1_freq_info_dl.scs_specific_carrier_list.size() != 1) { if (asn1_freq_info_dl.scs_specific_carrier_list.size() != 1) {
asn1::log_warning("Option absolute_freq_ssb not present"); asn1::log_warning("Option absolute_freq_ssb not present");
return false; return false;
} }
uint32_t nof_prb = asn1_freq_info_dl.scs_specific_carrier_list[0].carrier_bw; srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_15kHz;
srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_15kHz;
switch (asn1_freq_info_dl.scs_specific_carrier_list[0].subcarrier_spacing) { switch (asn1_freq_info_dl.scs_specific_carrier_list[0].subcarrier_spacing) {
case subcarrier_spacing_opts::options::khz15: case subcarrier_spacing_opts::options::khz15:
scs = srsran_subcarrier_spacing_15kHz; scs = srsran_subcarrier_spacing_15kHz;
@ -1222,8 +1218,9 @@ bool make_phy_carrier_cfg(const freq_info_dl_s& asn1_freq_info_dl, srsran_carrie
} }
// As the carrier structure requires parameters from different objects, set fields separately // As the carrier structure requires parameters from different objects, set fields separately
out_carrier_nr->absolute_frequency_ssb = absolute_frequency_ssb; out_carrier_nr->absolute_frequency_ssb = absolute_frequency_ssb;
out_carrier_nr->absolute_frequency_point_a = absolute_frequency_point_a; out_carrier_nr->absolute_frequency_point_a = asn1_freq_info_dl.absolute_freq_point_a;
out_carrier_nr->nof_prb = nof_prb; out_carrier_nr->offset_to_carrier = asn1_freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier;
out_carrier_nr->nof_prb = asn1_freq_info_dl.scs_specific_carrier_list[0].carrier_bw;
out_carrier_nr->scs = scs; out_carrier_nr->scs = scs;
return true; return true;
} }

@ -269,7 +269,7 @@ int srsran_basic_vnf::dl_config_request(const srsenb::phy_interface_stack_nr::dl
dl_conf.header.msg_len = sizeof(dl_conf) - sizeof(basic_vnf_api::msg_header_t); dl_conf.header.msg_len = sizeof(dl_conf) - sizeof(basic_vnf_api::msg_header_t);
dl_conf.t1 = last_sf_indication_time; // play back the time dl_conf.t1 = last_sf_indication_time; // play back the time
dl_conf.t2 = 0xaa; // FIXME: add timestamp dl_conf.t2 = 0xaa; // TODO: add timestamp
dl_conf.tti = request.tti; dl_conf.tti = request.tti;
dl_conf.beam_id = request.beam_id; dl_conf.beam_id = request.beam_id;

@ -129,7 +129,9 @@ int open_socket(net_utils::addr_family ip_type, net_utils::socket_type socket_ty
evnts.sctp_address_event = 1; evnts.sctp_address_event = 1;
if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts)) != 0) { if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts)) != 0) {
srslog::fetch_basic_logger(LOGSERVICE).error("Failed to subscribe to SCTP_SHUTDOWN event: %s", strerror(errno)); srslog::fetch_basic_logger(LOGSERVICE).error("Failed to subscribe to SCTP_SHUTDOWN event: %s", strerror(errno));
perror("Could not regiester socket to SCTP events\n"); perror("Could not register socket to SCTP events\n");
close(fd);
return -1;
} }
/* /*
@ -143,6 +145,7 @@ int open_socket(net_utils::addr_family ip_type, net_utils::socket_type socket_ty
rto_opts.srto_assoc_id = 0; rto_opts.srto_assoc_id = 0;
if (getsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, &rto_sz) < 0) { if (getsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, &rto_sz) < 0) {
printf("Error getting RTO_INFO sockopts\n"); printf("Error getting RTO_INFO sockopts\n");
close(fd);
return -1; return -1;
} }
@ -158,6 +161,7 @@ int open_socket(net_utils::addr_family ip_type, net_utils::socket_type socket_ty
if (setsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, rto_sz) < 0) { if (setsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, rto_sz) < 0) {
perror("Error setting RTO_INFO sockopts\n"); perror("Error setting RTO_INFO sockopts\n");
close(fd);
return -1; return -1;
} }
@ -166,6 +170,8 @@ int open_socket(net_utils::addr_family ip_type, net_utils::socket_type socket_ty
socklen_t init_sz = sizeof(sctp_initmsg); socklen_t init_sz = sizeof(sctp_initmsg);
if (getsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, &init_sz) < 0) { if (getsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, &init_sz) < 0) {
printf("Error getting sockopts\n"); printf("Error getting sockopts\n");
close(fd);
return -1;
} }
init_opts.sinit_max_attempts = 3; init_opts.sinit_max_attempts = 3;
@ -177,6 +183,7 @@ int open_socket(net_utils::addr_family ip_type, net_utils::socket_type socket_ty
init_opts.sinit_max_init_timeo); init_opts.sinit_max_init_timeo);
if (setsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, init_sz) < 0) { if (setsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, init_sz) < 0) {
perror("Error setting SCTP_INITMSG sockopts\n"); perror("Error setting SCTP_INITMSG sockopts\n");
close(fd);
return -1; return -1;
} }
} }

@ -27,6 +27,8 @@ int bands_test_nr()
srsran::srsran_band_helper bands; srsran::srsran_band_helper bands;
TESTASSERT(bands.nr_arfcn_to_freq(632628) == 3489.42e6); TESTASSERT(bands.nr_arfcn_to_freq(632628) == 3489.42e6);
TESTASSERT(bands.nr_arfcn_to_freq(633928) == 3508.92e6); // default refPointA
TESTASSERT(bands.nr_arfcn_to_freq(634240) == 3513.6e6); // default ARFCN with freq divisible by 11.52 MHz
const uint32_t max_valid_nr_arfcn = 3279165; const uint32_t max_valid_nr_arfcn = 3279165;

@ -474,24 +474,42 @@ static void interpolate_pilots(srsran_chest_dl_t* q,
(fidx_offset) ? 1 : 2); (fidx_offset) ? 1 : 2);
} }
} else { } else {
if (cfg->estimator_alg == SRSRAN_ESTIMATOR_ALG_AVERAGE && nsymbols > 1) { if (cfg->estimator_alg == SRSRAN_ESTIMATOR_ALG_AVERAGE) {
fidx_offset = q->cell.id % 3; if (nsymbols > 1) {
srsran_interp_linear_offset( fidx_offset = q->cell.id % 3;
&q->srsran_interp_lin_3, pilot_estimates, ce, fidx_offset, SRSRAN_NRE / 4 - fidx_offset); srsran_interp_linear_offset(
&q->srsran_interp_lin_3, pilot_estimates, ce, fidx_offset, SRSRAN_NRE / 4 - fidx_offset);
} else {
fidx_offset = srsran_refsignal_cs_fidx(q->cell, l, port_id, 0);
srsran_interp_linear_offset(&q->srsran_interp_lin,
&pilot_estimates[2 * q->cell.nof_prb * l],
ce,
fidx_offset,
SRSRAN_NRE / 2 - fidx_offset);
}
} else { } else {
fidx_offset = srsran_refsignal_cs_fidx(q->cell, l, port_id, 0); if (nsymbols < 2) {
srsran_interp_linear_offset( fidx_offset = srsran_refsignal_cs_fidx(q->cell, l, port_id, 0);
&q->srsran_interp_lin, srsran_interp_linear_offset(&q->srsran_interp_lin,
&pilot_estimates[2 * q->cell.nof_prb * l], &pilot_estimates[2 * q->cell.nof_prb * l],
&ce[srsran_refsignal_cs_nsymbol(l, q->cell.cp, port_id) * q->cell.nof_prb * SRSRAN_NRE], ce,
fidx_offset, fidx_offset,
SRSRAN_NRE / 2 - fidx_offset); SRSRAN_NRE / 2 - fidx_offset);
} else {
fidx_offset = srsran_refsignal_cs_fidx(q->cell, l, port_id, 0);
srsran_interp_linear_offset(
&q->srsran_interp_lin,
&pilot_estimates[2 * q->cell.nof_prb * l],
&ce[srsran_refsignal_cs_nsymbol(l, q->cell.cp, port_id) * q->cell.nof_prb * SRSRAN_NRE],
fidx_offset,
SRSRAN_NRE / 2 - fidx_offset);
}
} }
} }
} }
/* Now interpolate in the time domain between symbols */ /* Now interpolate in the time domain between symbols */
if (sf->sf_type == SRSRAN_SF_NORM && (cfg->estimator_alg == SRSRAN_ESTIMATOR_ALG_AVERAGE || nsymbols < 3)) { if (sf->sf_type == SRSRAN_SF_NORM && (cfg->estimator_alg == SRSRAN_ESTIMATOR_ALG_AVERAGE || nsymbols < 2)) {
// If we average per subframe, just copy the estimates in the time domain // If we average per subframe, just copy the estimates in the time domain
for (uint32_t l = 1; l < 2 * SRSRAN_CP_NSYMB(q->cell.cp); l++) { for (uint32_t l = 1; l < 2 * SRSRAN_CP_NSYMB(q->cell.cp); l++) {
memcpy(&ce[l * SRSRAN_NRE * q->cell.nof_prb], ce, sizeof(cf_t) * SRSRAN_NRE * q->cell.nof_prb); memcpy(&ce[l * SRSRAN_NRE * q->cell.nof_prb], ce, sizeof(cf_t) * SRSRAN_NRE * q->cell.nof_prb);
@ -504,7 +522,7 @@ static void interpolate_pilots(srsran_chest_dl_t* q,
srsran_interp_linear_vector2(&q->srsran_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(10), &cesymb(11), 4, 1); srsran_interp_linear_vector2(&q->srsran_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(10), &cesymb(11), 4, 1);
} else { } else {
if (SRSRAN_CP_ISNORM(q->cell.cp)) { if (SRSRAN_CP_ISNORM(q->cell.cp)) {
if (port_id <= 2) { if (port_id < 2) {
srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3); srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3);
srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2); srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2);
if (nsymbols == 4) { if (nsymbols == 4) {
@ -521,7 +539,7 @@ static void interpolate_pilots(srsran_chest_dl_t* q,
srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5); srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5);
} }
} else { } else {
if (port_id <= 2) { if (port_id < 2) {
// TODO: TDD and extended cyclic prefix // TODO: TDD and extended cyclic prefix
srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2); srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2);
srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2); srsran_interp_linear_vector(&q->srsran_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2);

@ -27,13 +27,14 @@
#include <stdlib.h> #include <stdlib.h>
static srsran_carrier_nr_t carrier = { static srsran_carrier_nr_t carrier = {
1, // pci 1, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
srsran_subcarrier_spacing_15kHz, // scs 0, // offset_to_carrier
50, // nof_prb srsran_subcarrier_spacing_15kHz, // scs
0, // start 50, // nof_prb
1 // max_mimo_layers 0, // start
1 // max_mimo_layers
}; };
static float snr_dB = 20.0; static float snr_dB = 20.0;

@ -29,15 +29,15 @@
#include <strings.h> #include <strings.h>
#include <unistd.h> #include <unistd.h>
static srsran_carrier_nr_t carrier = { static srsran_carrier_nr_t carrier = {
1, // pci 1, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
srsran_subcarrier_spacing_15kHz, // scs 0, // offset_to_carrier
50, // nof_prb srsran_subcarrier_spacing_15kHz, // scs
0, // start 50, // nof_prb
1 // max_mimo_layers 0, // start
1 // max_mimo_layers
}; };
typedef struct { typedef struct {

@ -244,11 +244,27 @@ int srsran_enb_ul_get_pucch(srsran_enb_ul_t* q,
// If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // If we are looking for SR and ACK at the same time and ret=0, means there is no SR.
// try again to decode ACK only // try again to decode ACK only
if (cfg->uci_cfg.is_scheduling_request_tti && srsran_uci_cfg_total_ack(&cfg->uci_cfg) && !res->detected) { if (cfg->uci_cfg.is_scheduling_request_tti && srsran_uci_cfg_total_ack(&cfg->uci_cfg)) {
// Disable SR
cfg->uci_cfg.is_scheduling_request_tti = false; cfg->uci_cfg.is_scheduling_request_tti = false;
if (get_pucch(q, ul_sf, cfg, res)) {
// Init PUCCH result without SR
srsran_pucch_res_t res_no_sr = {};
// Actual decode without SR
if (get_pucch(q, ul_sf, cfg, &res_no_sr)) {
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
// Override PUCCH result if PUCCH without SR was detected, and
// - no PUCCH with SR was detected; or
// - PUCCH without SR has better correlation
if (res_no_sr.detected && (!res->detected || res_no_sr.correlation > res->correlation)) {
*res = res_no_sr;
} else {
// If the PUCCH decode result is not overridden, flag SR
cfg->uci_cfg.is_scheduling_request_tti = true;
}
} }
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;

@ -93,7 +93,7 @@ void* create_ldpc_dec_c(uint8_t bgN, uint8_t bgM, uint16_t ls, float scaling_fct
uint16_t liftN = bgN * ls; uint16_t liftN = bgN * ls;
uint16_t hrrN = (bgK + 4) * ls; uint16_t hrrN = (bgK + 4) * ls;
if ((vp = malloc(sizeof(struct ldpc_regs_c))) == NULL) { if ((vp = SRSRAN_MEM_ALLOC(struct ldpc_regs_c, 1)) == NULL) {
return NULL; return NULL;
} }
@ -177,13 +177,13 @@ int init_ldpc_dec_c(void* p, const int8_t* llrs, uint16_t ls)
return -1; return -1;
} }
bzero(vp->soft_bits, skip * sizeof(int8_t)); srsran_vec_i8_zero(vp->soft_bits, skip);
for (i = skip; i < vp->liftN; i++) { for (i = skip; i < vp->liftN; i++) {
vp->soft_bits[i] = llrs[i - skip]; vp->soft_bits[i] = llrs[i - skip];
} }
bzero(vp->check_to_var, (vp->hrrN + vp->ls) * vp->bgM * sizeof(int8_t)); srsran_vec_i8_zero(vp->check_to_var, (vp->hrrN + vp->ls) * (uint32_t)vp->bgM);
bzero(vp->var_to_check, (vp->hrrN + vp->ls) * sizeof(int8_t)); srsran_vec_i8_zero(vp->var_to_check, vp->hrrN + vp->ls);
return 0; return 0;
} }
@ -258,7 +258,7 @@ int update_ldpc_check_to_var_c(void* p,
vp->prod_v2c[index] *= (vp->var_to_check[i_v2c] >= 0) ? 1 : -1; vp->prod_v2c[index] *= (vp->var_to_check[i_v2c] >= 0) ? 1 : -1;
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
int8_t* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls); int8_t* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls);
@ -277,7 +277,7 @@ int update_ldpc_check_to_var_c(void* p,
this_check_to_var[i_v2c] *= vp->prod_v2c[index] * ((vp->var_to_check[i_v2c] >= 0) ? 1 : -1); this_check_to_var[i_v2c] *= vp->prod_v2c[index] * ((vp->var_to_check[i_v2c] >= 0) ? 1 : -1);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -314,7 +314,7 @@ int update_ldpc_soft_bits_c(void* p, int i_layer, const int8_t (*these_var_indic
} }
vp->soft_bits[i_bit] = (int8_t)tmp; vp->soft_bits[i_bit] = (int8_t)tmp;
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -56,8 +56,8 @@
* \brief Represents a node of the base factor graph. * \brief Represents a node of the base factor graph.
*/ */
typedef union bg_node_t { typedef union bg_node_t {
int8_t c[SRSRAN_AVX2_B_SIZE]; /*!< Each base node may contain up to \ref SRSRAN_AVX2_B_SIZE lifted nodes. */ int8_t* c; /*!< Each base node may contain up to \ref SRSRAN_AVX2_B_SIZE lifted nodes. */
__m256i v; /*!< All the lifted nodes of the current base node as a 256-bit line. */ __m256i* v; /*!< All the lifted nodes of the current base node as a 256-bit line. */
} bg_node_t; } bg_node_t;
/*! /*!
@ -72,10 +72,10 @@ static const int8_t infinity7 = (1U << 6U) - 1;
struct ldpc_regs_c_avx2 { struct ldpc_regs_c_avx2 {
__m256i scaling_fctr; /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */ __m256i scaling_fctr; /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */
bg_node_t* soft_bits; /*!< \brief A-posteriori log-likelihood ratios. */ bg_node_t soft_bits; /*!< \brief A-posteriori log-likelihood ratios. */
__m256i* check_to_var; /*!< \brief Check-to-variable messages. */ __m256i* check_to_var; /*!< \brief Check-to-variable messages. */
__m256i* var_to_check; /*!< \brief Variable-to-check messages. */ __m256i* var_to_check; /*!< \brief Variable-to-check messages. */
__m256i* rotated_v2c; /*!< \brief To store a rotated version of the variable-to-check messages. */ __m256i* rotated_v2c; /*!< \brief To store a rotated version of the variable-to-check messages. */
uint16_t ls; /*!< \brief Lifting size. */ uint16_t ls; /*!< \brief Lifting size. */
uint8_t hrr; /*!< \brief Number of variable nodes in the high-rate region (before lifting). */ uint8_t hrr; /*!< \brief Number of variable nodes in the high-rate region (before lifting). */
@ -154,33 +154,28 @@ void* create_ldpc_dec_c_avx2(uint8_t bgN, uint8_t bgM, uint16_t ls, float scalin
uint8_t bgK = bgN - bgM; uint8_t bgK = bgN - bgM;
uint16_t hrr = bgK + 4; uint16_t hrr = bgK + 4;
if ((vp = srsran_vec_malloc(sizeof(struct ldpc_regs_c_avx2))) == NULL) { if ((vp = SRSRAN_MEM_ALLOC(struct ldpc_regs_c_avx2, 1)) == NULL) {
return NULL; return NULL;
} }
SRSRAN_MEM_ZERO(vp, struct ldpc_regs_c_avx2, 1);
if ((vp->soft_bits = srsran_vec_malloc(bgN * sizeof(bg_node_t))) == NULL) { if ((vp->soft_bits.v = SRSRAN_MEM_ALLOC(__m256i, bgN)) == NULL) {
free(vp); delete_ldpc_dec_c_avx2(vp);
return NULL; return NULL;
} }
if ((vp->check_to_var = srsran_vec_malloc((hrr + 1) * bgM * sizeof(__m256i))) == NULL) { if ((vp->check_to_var = SRSRAN_MEM_ALLOC(__m256i, (hrr + 1) * (uint32_t)bgM)) == NULL) {
free(vp->soft_bits); delete_ldpc_dec_c_avx2(vp);
free(vp);
return NULL; return NULL;
} }
if ((vp->var_to_check = srsran_vec_malloc((hrr + 1) * sizeof(__m256i))) == NULL) { if ((vp->var_to_check = SRSRAN_MEM_ALLOC(__m256i, hrr + 1)) == NULL) {
free(vp->check_to_var); delete_ldpc_dec_c_avx2(vp);
free(vp->soft_bits);
free(vp);
return NULL; return NULL;
} }
if ((vp->rotated_v2c = srsran_vec_malloc((hrr + 1) * sizeof(__m256i))) == NULL) { if ((vp->rotated_v2c = SRSRAN_MEM_ALLOC(__m256i, hrr + 1)) == NULL) {
free(vp->var_to_check); delete_ldpc_dec_c_avx2(vp);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp);
return NULL; return NULL;
} }
@ -199,13 +194,22 @@ void delete_ldpc_dec_c_avx2(void* p)
{ {
struct ldpc_regs_c_avx2* vp = p; struct ldpc_regs_c_avx2* vp = p;
if (vp != NULL) { if (vp == NULL) {
return;
}
if (vp->rotated_v2c) {
free(vp->rotated_v2c); free(vp->rotated_v2c);
}
if (vp->var_to_check) {
free(vp->var_to_check); free(vp->var_to_check);
}
if (vp->check_to_var) {
free(vp->check_to_var); free(vp->check_to_var);
free(vp->soft_bits);
free(vp);
} }
if (vp->soft_bits.v) {
free(vp->soft_bits.v);
}
free(vp);
} }
int init_ldpc_dec_c_avx2(void* p, const int8_t* llrs, uint16_t ls) int init_ldpc_dec_c_avx2(void* p, const int8_t* llrs, uint16_t ls)
@ -219,17 +223,17 @@ int init_ldpc_dec_c_avx2(void* p, const int8_t* llrs, uint16_t ls)
} }
// the first 2 x LS bits of the codeword are not sent // the first 2 x LS bits of the codeword are not sent
vp->soft_bits[0].v = _mm256_set1_epi8(0); vp->soft_bits.v[0] = _mm256_set1_epi8(0);
vp->soft_bits[1].v = _mm256_set1_epi8(0); vp->soft_bits.v[1] = _mm256_set1_epi8(0);
for (i = 2; i < vp->bgN; i++) { for (i = 2; i < vp->bgN; i++) {
for (j = 0; j < ls; j++) { for (j = 0; j < ls; j++) {
vp->soft_bits[i].c[j] = llrs[(i - 2) * ls + j]; vp->soft_bits.c[i * SRSRAN_AVX2_B_SIZE + j] = llrs[(i - 2) * ls + j];
} }
bzero(&(vp->soft_bits[i].c[ls]), (SRSRAN_AVX2_B_SIZE - ls) * sizeof(int8_t)); SRSRAN_MEM_ZERO(&(vp->soft_bits.c[i * SRSRAN_AVX2_B_SIZE + ls]), int8_t, SRSRAN_AVX2_B_SIZE - ls);
} }
bzero(vp->check_to_var, (vp->hrr + 1) * vp->bgM * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->check_to_var, __m256i, (vp->hrr + 1) * (uint32_t)vp->bgM);
bzero(vp->var_to_check, (vp->hrr + 1) * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->var_to_check, __m256i, vp->hrr + 1);
return 0; return 0;
} }
@ -244,15 +248,12 @@ int update_ldpc_var_to_check_c_avx2(void* p, int i_layer)
__m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1); __m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1);
// Update the high-rate region. // Update the high-rate region.
inner_var_to_check_c_avx2(&(vp->soft_bits[0].v), this_check_to_var, vp->var_to_check, infinity7, vp->hrr); inner_var_to_check_c_avx2(vp->soft_bits.v, this_check_to_var, vp->var_to_check, infinity7, vp->hrr);
if (i_layer >= 4) { if (i_layer >= 4) {
// Update the extension region. // Update the extension region.
inner_var_to_check_c_avx2(&(vp->soft_bits[0].v) + vp->hrr + i_layer - 4, inner_var_to_check_c_avx2(
this_check_to_var + vp->hrr, vp->soft_bits.v + vp->hrr + i_layer - 4, this_check_to_var + vp->hrr, vp->var_to_check + vp->hrr, infinity7, 1);
vp->var_to_check + vp->hrr,
infinity7,
1);
} }
return 0; return 0;
@ -313,7 +314,7 @@ int update_ldpc_check_to_var_c_avx2(void* p,
mask_min_epi8 = _mm256_cmpgt_epi8(mins_v2c_epi8, this_abs_v2c_epi8); mask_min_epi8 = _mm256_cmpgt_epi8(mins_v2c_epi8, this_abs_v2c_epi8);
mins_v2c_epi8 = _mm256_blendv_epi8(mins_v2c_epi8, help_min_epi8, mask_min_epi8); mins_v2c_epi8 = _mm256_blendv_epi8(mins_v2c_epi8, help_min_epi8, mask_min_epi8);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
__m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1); __m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1);
@ -342,7 +343,7 @@ int update_ldpc_check_to_var_c_avx2(void* p,
this_check_to_var[i_v2c_base] = rotate_node_left(this_c2v_epi8, shift, vp->ls); this_check_to_var[i_v2c_base] = rotate_node_left(this_c2v_epi8, shift, vp->ls);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -375,9 +376,9 @@ int update_ldpc_soft_bits_c_avx2(void* p, int i_layer, const int8_t (*these_var_
// tmp = (tmp < -infty7) : -infty8 ? tmp // tmp = (tmp < -infty7) : -infty8 ? tmp
mask_epi8 = _mm256_cmpgt_epi8(neg_infty7_epi8, tmp_epi8); mask_epi8 = _mm256_cmpgt_epi8(neg_infty7_epi8, tmp_epi8);
vp->soft_bits[current_var_index].v = _mm256_blendv_epi8(tmp_epi8, neg_infty8_epi8, mask_epi8); vp->soft_bits.v[current_var_index] = _mm256_blendv_epi8(tmp_epi8, neg_infty8_epi8, mask_epi8);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -395,7 +396,7 @@ int extract_ldpc_message_c_avx2(void* p, uint8_t* message, uint16_t liftK)
for (int i = 0; i < liftK / vp->ls; i++) { for (int i = 0; i < liftK / vp->ls; i++) {
for (j = 0; j < vp->ls; j++) { for (j = 0; j < vp->ls; j++) {
message[i * vp->ls + j] = (vp->soft_bits[i].c[j] < 0); message[i * vp->ls + j] = (vp->soft_bits.c[i * SRSRAN_AVX2_B_SIZE + j] < 0);
} }
} }

@ -56,8 +56,8 @@
* \brief Represents a node of the base factor graph. * \brief Represents a node of the base factor graph.
*/ */
typedef union bg_node_t { typedef union bg_node_t {
int8_t c[SRSRAN_AVX2_B_SIZE]; /*!< Each base node may contain up to \ref SRSRAN_AVX2_B_SIZE lifted nodes. */ int8_t* c; /*!< Each base node may contain up to \ref SRSRAN_AVX2_B_SIZE lifted nodes. */
__m256i v; /*!< All the lifted nodes of the current base node as a 256-bit line. */ __m256i* v; /*!< All the lifted nodes of the current base node as a 256-bit line. */
} bg_node_t; } bg_node_t;
/*! /*!
@ -72,11 +72,11 @@ static const int8_t infinity7 = (1U << 6U) - 1;
struct ldpc_regs_c_avx2_flood { struct ldpc_regs_c_avx2_flood {
__m256i scaling_fctr; /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */ __m256i scaling_fctr; /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */
bg_node_t* soft_bits; /*!< \brief A-posteriori log-likelihood ratios. */ bg_node_t soft_bits; /*!< \brief A-posteriori log-likelihood ratios. */
__m256i* llrs; /*!< \brief A-priori log-likelihood ratios. */ __m256i* llrs; /*!< \brief A-priori log-likelihood ratios. */
__m256i* check_to_var; /*!< \brief Check-to-variable messages. */ __m256i* check_to_var; /*!< \brief Check-to-variable messages. */
__m256i* var_to_check; /*!< \brief Variable-to-check messages. */ __m256i* var_to_check; /*!< \brief Variable-to-check messages. */
__m256i* rotated_v2c; /*!< \brief To store a rotated version of the variable-to-check messages. */ __m256i* rotated_v2c; /*!< \brief To store a rotated version of the variable-to-check messages. */
uint16_t ls; /*!< \brief Lifting size. */ uint16_t ls; /*!< \brief Lifting size. */
uint8_t hrr; /*!< \brief Number of variable nodes in the high-rate region (before lifting). */ uint8_t hrr; /*!< \brief Number of variable nodes in the high-rate region (before lifting). */
@ -155,42 +155,34 @@ void* create_ldpc_dec_c_avx2_flood(uint8_t bgN, uint8_t bgM, uint16_t ls, float
uint8_t bgK = bgN - bgM; uint8_t bgK = bgN - bgM;
uint16_t hrr = bgK + 4; uint16_t hrr = bgK + 4;
if ((vp = srsran_vec_malloc(sizeof(struct ldpc_regs_c_avx2_flood))) == NULL) { if ((vp = SRSRAN_MEM_ALLOC(struct ldpc_regs_c_avx2_flood, 1)) == NULL) {
return NULL; return NULL;
} }
SRSRAN_MEM_ZERO(vp, struct ldpc_regs_c_avx2_flood, 1);
if ((vp->llrs = srsran_vec_malloc(bgN * sizeof(__m256i))) == NULL) { if ((vp->llrs = SRSRAN_MEM_ALLOC(__m256i, bgN)) == NULL) {
free(vp); delete_ldpc_dec_c_avx2_flood(vp);
return NULL; return NULL;
} }
if ((vp->soft_bits = srsran_vec_malloc(bgN * sizeof(bg_node_t))) == NULL) { if ((vp->soft_bits.v = SRSRAN_MEM_ALLOC(__m256i, bgN)) == NULL) {
free(vp->llrs); delete_ldpc_dec_c_avx2_flood(vp);
free(vp);
return NULL; return NULL;
} }
if ((vp->check_to_var = srsran_vec_malloc((hrr + 1) * bgM * sizeof(__m256i))) == NULL) { uint32_t sz = (uint32_t)(hrr + 1) * (uint32_t)bgM;
free(vp->soft_bits); if ((vp->check_to_var = SRSRAN_MEM_ALLOC(__m256i, sz)) == NULL) {
free(vp->llrs); delete_ldpc_dec_c_avx2_flood(vp);
free(vp);
return NULL; return NULL;
} }
if ((vp->var_to_check = srsran_vec_malloc((hrr + 1) * bgM * sizeof(__m256i))) == NULL) { if ((vp->var_to_check = SRSRAN_MEM_ALLOC(__m256i, sz)) == NULL) {
free(vp->check_to_var); delete_ldpc_dec_c_avx2_flood(vp);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
if ((vp->rotated_v2c = srsran_vec_malloc((hrr + 1) * sizeof(__m256i))) == NULL) { if ((vp->rotated_v2c = SRSRAN_MEM_ALLOC(__m256i, hrr + 1)) == NULL) {
free(vp->var_to_check); delete_ldpc_dec_c_avx2_flood(vp);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
@ -209,14 +201,25 @@ void delete_ldpc_dec_c_avx2_flood(void* p)
{ {
struct ldpc_regs_c_avx2_flood* vp = p; struct ldpc_regs_c_avx2_flood* vp = p;
if (vp != NULL) { if (vp == NULL) {
return;
}
if (vp->rotated_v2c) {
free(vp->rotated_v2c); free(vp->rotated_v2c);
}
if (vp->var_to_check) {
free(vp->var_to_check); free(vp->var_to_check);
}
if (vp->check_to_var) {
free(vp->check_to_var); free(vp->check_to_var);
free(vp->soft_bits); }
if (vp->soft_bits.v) {
free(vp->soft_bits.v);
}
if (vp->llrs) {
free(vp->llrs); free(vp->llrs);
free(vp);
} }
free(vp);
} }
int init_ldpc_dec_c_avx2_flood(void* p, const int8_t* llrs, uint16_t ls) int init_ldpc_dec_c_avx2_flood(void* p, const int8_t* llrs, uint16_t ls)
@ -230,20 +233,20 @@ int init_ldpc_dec_c_avx2_flood(void* p, const int8_t* llrs, uint16_t ls)
} }
// the first 2 x LS bits of the codeword are not sent // the first 2 x LS bits of the codeword are not sent
vp->soft_bits[0].v = _mm256_set1_epi8(0); vp->soft_bits.v[0] = _mm256_set1_epi8(0);
vp->soft_bits[1].v = _mm256_set1_epi8(0); vp->soft_bits.v[1] = _mm256_set1_epi8(0);
vp->llrs[0] = _mm256_set1_epi8(0); vp->llrs[0] = _mm256_set1_epi8(0);
vp->llrs[1] = _mm256_set1_epi8(0); vp->llrs[1] = _mm256_set1_epi8(0);
for (i = 2; i < vp->bgN; i++) { for (i = 2; i < vp->bgN; i++) {
for (j = 0; j < ls; j++) { for (j = 0; j < ls; j++) {
vp->soft_bits[i].c[j] = llrs[(i - 2) * ls + j]; vp->soft_bits.c[i * SRSRAN_AVX2_B_SIZE + j] = llrs[(i - 2) * ls + j];
} }
bzero(&(vp->soft_bits[i].c[ls]), (SRSRAN_AVX2_B_SIZE - ls) * sizeof(int8_t)); srsran_vec_i8_zero(&(vp->soft_bits.c[i * SRSRAN_AVX2_B_SIZE + ls]), SRSRAN_AVX2_B_SIZE - ls);
vp->llrs[i] = vp->soft_bits[i].v; vp->llrs[i] = vp->soft_bits.v[i];
} }
bzero(vp->check_to_var, (vp->hrr + 1) * vp->bgM * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->check_to_var, __m256i, (vp->hrr + 1) * (uint32_t)vp->bgM);
bzero(vp->var_to_check, (vp->hrr + 1) * vp->bgM * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->var_to_check, __m256i, (vp->hrr + 1) * (uint32_t)vp->bgM);
return 0; return 0;
} }
@ -259,11 +262,11 @@ int update_ldpc_var_to_check_c_avx2_flood(void* p, int i_layer)
__m256i* this_var_to_check = vp->var_to_check + i_layer * (vp->hrr + 1); __m256i* this_var_to_check = vp->var_to_check + i_layer * (vp->hrr + 1);
// Update the high-rate region. // Update the high-rate region.
inner_var_to_check_c_avx2(&(vp->soft_bits[0].v), this_check_to_var, this_var_to_check, infinity7, vp->hrr); inner_var_to_check_c_avx2(&(vp->soft_bits.v[0]), this_check_to_var, this_var_to_check, infinity7, vp->hrr);
if (i_layer >= 4) { if (i_layer >= 4) {
// Update the extension region. // Update the extension region.
inner_var_to_check_c_avx2(&(vp->soft_bits[0].v) + vp->hrr + i_layer - 4, inner_var_to_check_c_avx2(&(vp->soft_bits.v[0]) + vp->hrr + i_layer - 4,
this_check_to_var + vp->hrr, this_check_to_var + vp->hrr,
this_var_to_check + vp->hrr, this_var_to_check + vp->hrr,
infinity7, infinity7,
@ -328,7 +331,7 @@ int update_ldpc_check_to_var_c_avx2_flood(void* p,
mask_min_epi8 = _mm256_cmpgt_epi8(mins_v2c_epi8, this_abs_v2c_epi8); mask_min_epi8 = _mm256_cmpgt_epi8(mins_v2c_epi8, this_abs_v2c_epi8);
mins_v2c_epi8 = _mm256_blendv_epi8(mins_v2c_epi8, help_min_epi8, mask_min_epi8); mins_v2c_epi8 = _mm256_blendv_epi8(mins_v2c_epi8, help_min_epi8, mask_min_epi8);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
__m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1); __m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1);
@ -357,7 +360,7 @@ int update_ldpc_check_to_var_c_avx2_flood(void* p,
this_check_to_var[i_v2c_base] = rotate_node_left(this_c2v_epi8, shift, vp->ls); this_check_to_var[i_v2c_base] = rotate_node_left(this_c2v_epi8, shift, vp->ls);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -381,7 +384,7 @@ int update_ldpc_soft_bits_c_avx2_flood(void* p, const int8_t (*these_var_indices
__m256i mask_epi8; __m256i mask_epi8;
for (i = 0; i < vp->bgN; i++) { for (i = 0; i < vp->bgN; i++) {
vp->soft_bits[i].v = vp->llrs[i]; vp->soft_bits.v[i] = vp->llrs[i];
} }
for (i_layer = 0; i_layer < vp->bgM; i_layer++) { for (i_layer = 0; i_layer < vp->bgM; i_layer++) {
@ -391,7 +394,7 @@ int update_ldpc_soft_bits_c_avx2_flood(void* p, const int8_t (*these_var_indices
for (i = 0; (current_var_index != -1) && (i < MAX_CNCT); i++) { for (i = 0; (current_var_index != -1) && (i < MAX_CNCT); i++) {
i_bit_tmp_base = (current_var_index <= vp->hrr) ? current_var_index : vp->hrr; i_bit_tmp_base = (current_var_index <= vp->hrr) ? current_var_index : vp->hrr;
tmp_epi8 = _mm256_adds_epi8(this_check_to_var[i_bit_tmp_base], vp->soft_bits[current_var_index].v); tmp_epi8 = _mm256_adds_epi8(this_check_to_var[i_bit_tmp_base], vp->soft_bits.v[current_var_index]);
// tmp = (tmp > infty7) : infty8 ? tmp // tmp = (tmp > infty7) : infty8 ? tmp
mask_epi8 = _mm256_cmpgt_epi8(tmp_epi8, infty7_epi8); mask_epi8 = _mm256_cmpgt_epi8(tmp_epi8, infty7_epi8);
@ -399,7 +402,7 @@ int update_ldpc_soft_bits_c_avx2_flood(void* p, const int8_t (*these_var_indices
// tmp = (tmp < -infty7) : -infty8 ? tmp // tmp = (tmp < -infty7) : -infty8 ? tmp
mask_epi8 = _mm256_cmpgt_epi8(neg_infty7_epi8, tmp_epi8); mask_epi8 = _mm256_cmpgt_epi8(neg_infty7_epi8, tmp_epi8);
vp->soft_bits[current_var_index].v = _mm256_blendv_epi8(tmp_epi8, neg_infty8_epi8, mask_epi8); vp->soft_bits.v[current_var_index] = _mm256_blendv_epi8(tmp_epi8, neg_infty8_epi8, mask_epi8);
current_var_index = these_var_indices[i_layer][i + 1]; current_var_index = these_var_indices[i_layer][i + 1];
} }
@ -420,7 +423,7 @@ int extract_ldpc_message_c_avx2_flood(void* p, uint8_t* message, uint16_t liftK)
for (int i = 0; i < liftK / vp->ls; i++) { for (int i = 0; i < liftK / vp->ls; i++) {
for (j = 0; j < vp->ls; j++) { for (j = 0; j < vp->ls; j++) {
message[i * vp->ls + j] = (vp->soft_bits[i].c[j] < 0); message[i * vp->ls + j] = (vp->soft_bits.c[i * SRSRAN_AVX2_B_SIZE + j] < 0);
} }
} }

@ -368,7 +368,7 @@ int update_ldpc_check_to_var_c_avx2long(void* p,
vp->mins_v2c_epi8[j] = _mm256_blendv_epi8(vp->mins_v2c_epi8[j], help_min_epi8, mask_min_epi8); vp->mins_v2c_epi8[j] = _mm256_blendv_epi8(vp->mins_v2c_epi8[j], help_min_epi8, mask_min_epi8);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
__m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes; __m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes;
@ -403,7 +403,7 @@ int update_ldpc_check_to_var_c_avx2long(void* p,
// rotating right LS - shift positions is the same as rotating left shift positions // rotating right LS - shift positions is the same as rotating left shift positions
rotate_node_right(vp->this_c2v_epi8, this_check_to_var + i_v2c_base, vp->ls - shift, vp->ls, vp->n_subnodes); rotate_node_right(vp->this_c2v_epi8, this_check_to_var + i_v2c_base, vp->ls - shift, vp->ls, vp->n_subnodes);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -445,7 +445,7 @@ int update_ldpc_soft_bits_c_avx2long(void* p, int i_layer, const int8_t (*these_
vp->soft_bits[current_var_index_subnode + j].v = _mm256_blendv_epi8(tmp_epi8, neg_infty8_epi8, mask_epi8); vp->soft_bits[current_var_index_subnode + j].v = _mm256_blendv_epi8(tmp_epi8, neg_infty8_epi8, mask_epi8);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -137,107 +137,63 @@ void* create_ldpc_dec_c_avx2long_flood(uint8_t bgN, uint8_t bgM, uint16_t ls, fl
uint8_t bgK = bgN - bgM; uint8_t bgK = bgN - bgM;
uint16_t hrr = bgK + 4; uint16_t hrr = bgK + 4;
if ((vp = srsran_vec_malloc(sizeof(struct ldpc_regs_c_avx2long_flood))) == NULL) { if ((vp = SRSRAN_MEM_ALLOC(struct ldpc_regs_c_avx2long_flood, 1)) == NULL) {
return NULL; return NULL;
} }
SRSRAN_MEM_ZERO(vp, struct ldpc_regs_c_avx2long_flood, 1);
// compute number of subnodes // compute number of subnodes
int left_out = ls % SRSRAN_AVX2_B_SIZE; int left_out = ls % SRSRAN_AVX2_B_SIZE;
int n_subnodes = ls / SRSRAN_AVX2_B_SIZE + (left_out > 0); int n_subnodes = ls / SRSRAN_AVX2_B_SIZE + (left_out > 0);
if ((vp->llrs = srsran_vec_malloc(bgN * n_subnodes * sizeof(__m256i))) == NULL) { if ((vp->llrs = SRSRAN_MEM_ALLOC(__m256i, bgN * n_subnodes)) == NULL) {
free(vp); delete_ldpc_dec_c_avx2long_flood(vp);
return NULL; return NULL;
} }
if ((vp->soft_bits = srsran_vec_malloc(bgN * n_subnodes * sizeof(bg_node_t))) == NULL) { if ((vp->soft_bits = SRSRAN_MEM_ALLOC(bg_node_t, bgN * n_subnodes)) == NULL) {
free(vp->llrs); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp);
return NULL; return NULL;
} }
if ((vp->check_to_var = srsran_vec_malloc((hrr + 1) * bgM * n_subnodes * sizeof(__m256i))) == NULL) { if ((vp->check_to_var = SRSRAN_MEM_ALLOC(__m256i, (hrr + 1) * (uint32_t)bgM * n_subnodes)) == NULL) {
free(vp->soft_bits); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
if ((vp->var_to_check_to_free = srsran_vec_malloc(((hrr + 1) * bgM * n_subnodes + 2) * sizeof(__m256i))) == NULL) { if ((vp->var_to_check_to_free = SRSRAN_MEM_ALLOC(__m256i, (hrr + 1) * (uint32_t)bgM * n_subnodes + 2)) == NULL) {
free(vp->check_to_var); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
vp->var_to_check = &vp->var_to_check_to_free[1]; vp->var_to_check = &vp->var_to_check_to_free[1];
if ((vp->minp_v2c_epi8 = srsran_vec_malloc(n_subnodes * sizeof(__m256i))) == NULL) { if ((vp->minp_v2c_epi8 = SRSRAN_MEM_ALLOC(__m256i, n_subnodes)) == NULL) {
free(vp->var_to_check_to_free); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
if ((vp->mins_v2c_epi8 = srsran_vec_malloc(n_subnodes * sizeof(__m256i))) == NULL) { if ((vp->mins_v2c_epi8 = SRSRAN_MEM_ALLOC(__m256i, n_subnodes)) == NULL) {
free(vp->minp_v2c_epi8); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->var_to_check_to_free);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
if ((vp->prod_v2c_epi8 = srsran_vec_malloc(n_subnodes * sizeof(__m256i))) == NULL) { if ((vp->prod_v2c_epi8 = SRSRAN_MEM_ALLOC(__m256i, n_subnodes)) == NULL) {
free(vp->mins_v2c_epi8); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->minp_v2c_epi8);
free(vp->var_to_check_to_free);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
if ((vp->min_ix_epi8 = srsran_vec_malloc(n_subnodes * sizeof(__m256i))) == NULL) { if ((vp->min_ix_epi8 = SRSRAN_MEM_ALLOC(__m256i, n_subnodes)) == NULL) {
free(vp->prod_v2c_epi8); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->mins_v2c_epi8);
free(vp->minp_v2c_epi8);
free(vp->var_to_check_to_free);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
if ((vp->rotated_v2c = srsran_vec_malloc((hrr + 1) * n_subnodes * sizeof(__m256i))) == NULL) { if ((vp->rotated_v2c = SRSRAN_MEM_ALLOC(__m256i, (hrr + 1) * (uint32_t)n_subnodes)) == NULL) {
free(vp->min_ix_epi8); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->prod_v2c_epi8);
free(vp->mins_v2c_epi8);
free(vp->minp_v2c_epi8);
free(vp->var_to_check_to_free);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
if ((vp->this_c2v_epi8_to_free = srsran_vec_malloc((n_subnodes + 2) * sizeof(__m256i))) == NULL) { if ((vp->this_c2v_epi8_to_free = SRSRAN_MEM_ALLOC(__m256i, n_subnodes + 2)) == NULL) {
free(vp->rotated_v2c); delete_ldpc_dec_c_avx2long_flood(vp);
free(vp->min_ix_epi8);
free(vp->prod_v2c_epi8);
free(vp->mins_v2c_epi8);
free(vp->minp_v2c_epi8);
free(vp->var_to_check_to_free);
free(vp->check_to_var);
free(vp->soft_bits);
free(vp->llrs);
free(vp);
return NULL; return NULL;
} }
vp->this_c2v_epi8 = &vp->this_c2v_epi8_to_free[1]; vp->this_c2v_epi8 = &vp->this_c2v_epi8_to_free[1];
@ -259,19 +215,40 @@ void delete_ldpc_dec_c_avx2long_flood(void* p)
{ {
struct ldpc_regs_c_avx2long_flood* vp = p; struct ldpc_regs_c_avx2long_flood* vp = p;
if (vp != NULL) { if (vp == NULL) {
return;
}
if (vp->this_c2v_epi8_to_free) {
free(vp->this_c2v_epi8_to_free); free(vp->this_c2v_epi8_to_free);
}
if (vp->rotated_v2c) {
free(vp->rotated_v2c); free(vp->rotated_v2c);
}
if (vp->min_ix_epi8) {
free(vp->min_ix_epi8); free(vp->min_ix_epi8);
}
if (vp->prod_v2c_epi8) {
free(vp->prod_v2c_epi8); free(vp->prod_v2c_epi8);
}
if (vp->mins_v2c_epi8) {
free(vp->mins_v2c_epi8); free(vp->mins_v2c_epi8);
}
if (vp->minp_v2c_epi8) {
free(vp->minp_v2c_epi8); free(vp->minp_v2c_epi8);
}
if (vp->var_to_check_to_free) {
free(vp->var_to_check_to_free); free(vp->var_to_check_to_free);
}
if (vp->check_to_var) {
free(vp->check_to_var); free(vp->check_to_var);
}
if (vp->soft_bits) {
free(vp->soft_bits); free(vp->soft_bits);
}
if (vp->llrs) {
free(vp->llrs); free(vp->llrs);
free(vp);
} }
free(vp);
} }
int init_ldpc_dec_c_avx2long_flood(void* p, const int8_t* llrs, uint16_t ls) int init_ldpc_dec_c_avx2long_flood(void* p, const int8_t* llrs, uint16_t ls)
@ -302,8 +279,8 @@ int init_ldpc_dec_c_avx2long_flood(void* p, const int8_t* llrs, uint16_t ls)
bzero((int8_t*)(vp->llrs + i * vp->n_subnodes + j - 1) + k, (SRSRAN_AVX2_B_SIZE - k) * sizeof(int8_t)); bzero((int8_t*)(vp->llrs + i * vp->n_subnodes + j - 1) + k, (SRSRAN_AVX2_B_SIZE - k) * sizeof(int8_t));
} }
bzero(vp->check_to_var, (vp->hrr + 1) * vp->bgM * vp->n_subnodes * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->check_to_var, __m256i, (vp->hrr + 1) * (uint32_t)vp->bgM * (uint32_t)vp->n_subnodes);
bzero(vp->var_to_check, (vp->hrr + 1) * vp->bgM * vp->n_subnodes * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->var_to_check, __m256i, (vp->hrr + 1) * (uint32_t)vp->bgM * (uint32_t)vp->n_subnodes);
return 0; return 0;
} }
@ -396,7 +373,7 @@ int update_ldpc_check_to_var_c_avx2long_flood(void* p,
vp->mins_v2c_epi8[j] = _mm256_blendv_epi8(vp->mins_v2c_epi8[j], help_min_epi8, mask_min_epi8); vp->mins_v2c_epi8[j] = _mm256_blendv_epi8(vp->mins_v2c_epi8[j], help_min_epi8, mask_min_epi8);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
__m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes; __m256i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes;
@ -428,7 +405,7 @@ int update_ldpc_check_to_var_c_avx2long_flood(void* p,
// rotating right LS - shift positions is the same as rotating left shift positions // rotating right LS - shift positions is the same as rotating left shift positions
rotate_node_right(vp->this_c2v_epi8, this_check_to_var + i_v2c_base, vp->ls - shift, vp->ls, vp->n_subnodes); rotate_node_right(vp->this_c2v_epi8, this_check_to_var + i_v2c_base, vp->ls - shift, vp->ls, vp->n_subnodes);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -324,7 +324,7 @@ int update_ldpc_check_to_var_c_avx512(void* p,
mask_min_epi8 = _mm512_cmpgt_epi8_mask(mins_v2c_epi8, this_abs_v2c_epi8); mask_min_epi8 = _mm512_cmpgt_epi8_mask(mins_v2c_epi8, this_abs_v2c_epi8);
mins_v2c_epi8 = _mm512_mask_blend_epi8(mask_min_epi8, mins_v2c_epi8, help_min_epi8); mins_v2c_epi8 = _mm512_mask_blend_epi8(mask_min_epi8, mins_v2c_epi8, help_min_epi8);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
__m512i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1); __m512i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1);
@ -356,7 +356,7 @@ int update_ldpc_check_to_var_c_avx512(void* p,
// rotating right LS - shift positions is the same as rotating left shift positions // rotating right LS - shift positions is the same as rotating left shift positions
rotate_node_right((uint8_t*)vp->this_c2v_epi8, this_check_to_var + i_v2c_base, (vp->ls - shift) % vp->ls, vp->ls); rotate_node_right((uint8_t*)vp->this_c2v_epi8, this_check_to_var + i_v2c_base, (vp->ls - shift) % vp->ls, vp->ls);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -390,7 +390,7 @@ int update_ldpc_soft_bits_c_avx512(void* p, int i_layer, const int8_t (*these_va
vp->soft_bits.v[current_var_index] = _mm512_mask_blend_epi8(mask_epi8, tmp_epi8, _mm512_neg_infty8_epi8); vp->soft_bits.v[current_var_index] = _mm512_mask_blend_epi8(mask_epi8, tmp_epi8, _mm512_neg_infty8_epi8);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -391,7 +391,7 @@ int update_ldpc_check_to_var_c_avx512long(void* p,
vp->mins_v2c_epi8[j] = _mm512_mask_blend_epi8(mask_min_epi8, vp->mins_v2c_epi8[j], help_min_epi8); vp->mins_v2c_epi8[j] = _mm512_mask_blend_epi8(mask_min_epi8, vp->mins_v2c_epi8[j], help_min_epi8);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
__m512i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes; __m512i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes;
@ -426,7 +426,7 @@ int update_ldpc_check_to_var_c_avx512long(void* p,
// rotating right LS - shift positions is the same as rotating left shift positions // rotating right LS - shift positions is the same as rotating left shift positions
rotate_node_right((uint8_t*)vp->this_c2v_epi8, this_check_to_var + i_v2c_base, (vp->ls - shift) % vp->ls, vp->ls); rotate_node_right((uint8_t*)vp->this_c2v_epi8, this_check_to_var + i_v2c_base, (vp->ls - shift) % vp->ls, vp->ls);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -469,7 +469,7 @@ int update_ldpc_soft_bits_c_avx512long(void* p, int i_layer, const int8_t (*thes
_mm512_mask_blend_epi8(mask_epi8, tmp_epi8, _mm512_neg_infty8_epi8); _mm512_mask_blend_epi8(mask_epi8, tmp_epi8, _mm512_neg_infty8_epi8);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -302,8 +302,8 @@ int init_ldpc_dec_c_avx512long_flood(void* p, const int8_t* llrs, uint16_t ls)
bzero((int8_t*)(vp->llrs + i * vp->n_subnodes + j - 1) + k, (SRSRAN_AVX512_B_SIZE - k) * sizeof(int8_t)); bzero((int8_t*)(vp->llrs + i * vp->n_subnodes + j - 1) + k, (SRSRAN_AVX512_B_SIZE - k) * sizeof(int8_t));
} }
bzero(vp->check_to_var, (vp->hrr + 1) * vp->bgM * vp->n_subnodes * sizeof(__m512i)); SRSRAN_MEM_ZERO(vp->check_to_var, __m512i, (vp->hrr + 1) * (uint32_t)vp->bgM * (uint32_t)vp->n_subnodes);
bzero(vp->var_to_check, (vp->hrr + 1) * vp->bgM * vp->n_subnodes * sizeof(__m512i)); SRSRAN_MEM_ZERO(vp->var_to_check, __m512i, (vp->hrr + 1) * (uint32_t)vp->bgM * (uint32_t)vp->n_subnodes);
return 0; return 0;
} }
@ -393,7 +393,7 @@ int update_ldpc_check_to_var_c_avx512long_flood(void* p,
vp->mins_v2c_epi8[j] = _mm512_mask_blend_epi8(mask_min_epi8, vp->mins_v2c_epi8[j], help_min_epi8); vp->mins_v2c_epi8[j] = _mm512_mask_blend_epi8(mask_min_epi8, vp->mins_v2c_epi8[j], help_min_epi8);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
__m512i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes; __m512i* this_check_to_var = vp->check_to_var + i_layer * (vp->hrr + 1) * vp->n_subnodes;
@ -427,7 +427,7 @@ int update_ldpc_check_to_var_c_avx512long_flood(void* p,
// rotating right LS - shift positions is the same as rotating left shift positions // rotating right LS - shift positions is the same as rotating left shift positions
rotate_node_right((uint8_t*)vp->this_c2v_epi8, this_check_to_var + i_v2c_base, (vp->ls - shift) % vp->ls, vp->ls); rotate_node_right((uint8_t*)vp->this_c2v_epi8, this_check_to_var + i_v2c_base, (vp->ls - shift) % vp->ls, vp->ls);
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -190,15 +190,15 @@ int init_ldpc_dec_c_flood(void* p, const int8_t* llrs, uint16_t ls)
return -1; return -1;
} }
bzero(vp->llrs, skip * sizeof(int8_t)); srsran_vec_i8_zero(vp->llrs, skip);
bzero(vp->soft_bits, skip * sizeof(int8_t)); srsran_vec_i8_zero(vp->soft_bits, skip);
for (i = skip; i < vp->liftN; i++) { for (i = skip; i < vp->liftN; i++) {
vp->llrs[i] = llrs[i - skip]; vp->llrs[i] = llrs[i - skip];
vp->soft_bits[i] = llrs[i - skip]; vp->soft_bits[i] = llrs[i - skip];
} }
bzero(vp->check_to_var, (vp->hrrN + vp->ls) * vp->bgM * sizeof(int8_t)); srsran_vec_i8_zero(vp->check_to_var, (vp->hrrN + vp->ls) * (uint32_t)vp->bgM);
bzero(vp->var_to_check, (vp->hrrN + vp->ls) * vp->bgM * sizeof(int8_t)); srsran_vec_i8_zero(vp->var_to_check, (vp->hrrN + vp->ls) * (uint32_t)vp->bgM);
return 0; return 0;
} }
@ -276,7 +276,7 @@ int update_ldpc_check_to_var_c_flood(void* p,
vp->prod_v2c[index] *= (this_var_to_check[i_v2c] >= 0) ? 1 : -1; vp->prod_v2c[index] *= (this_var_to_check[i_v2c] >= 0) ? 1 : -1;
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
int8_t* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls); int8_t* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls);
@ -295,7 +295,7 @@ int update_ldpc_check_to_var_c_flood(void* p,
this_check_to_var[i_v2c] *= vp->prod_v2c[index] * ((this_var_to_check[i_v2c] >= 0) ? 1 : -1); this_check_to_var[i_v2c] *= vp->prod_v2c[index] * ((this_var_to_check[i_v2c] >= 0) ? 1 : -1);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -156,8 +156,8 @@ int init_ldpc_dec_f(void* p, const float* llrs, uint16_t ls)
vp->soft_bits[i] = llrs[i - skip]; vp->soft_bits[i] = llrs[i - skip];
} }
bzero(vp->check_to_var, (vp->hrrN + vp->ls) * vp->bgM * sizeof(float)); srsran_vec_f_zero(vp->check_to_var, (vp->hrrN + vp->ls) * (uint32_t)vp->bgM);
bzero(vp->var_to_check, (vp->hrrN + vp->ls) * sizeof(float)); srsran_vec_f_zero(vp->var_to_check, vp->hrrN + vp->ls);
return 0; return 0;
} }
@ -232,7 +232,7 @@ int update_ldpc_check_to_var_f(void* p,
vp->prod_v2c[index] *= (vp->var_to_check[i_v2c] >= 0) ? 1 : -1; vp->prod_v2c[index] *= (vp->var_to_check[i_v2c] >= 0) ? 1 : -1;
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
float* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls); float* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls);
@ -251,7 +251,7 @@ int update_ldpc_check_to_var_f(void* p,
this_check_to_var[i_v2c] *= (float)vp->prod_v2c[index] * ((vp->var_to_check[i_v2c] >= 0) ? 1.F : -1.F); this_check_to_var[i_v2c] *= (float)vp->prod_v2c[index] * ((vp->var_to_check[i_v2c] >= 0) ? 1.F : -1.F);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -280,7 +280,7 @@ int update_ldpc_soft_bits_f(void* p, int i_layer, const int8_t (*these_var_indic
vp->soft_bits[i_bit] = this_check_to_var[i_bit_tmp] + this_var_to_check[i_bit_tmp]; vp->soft_bits[i_bit] = this_check_to_var[i_bit_tmp] + this_var_to_check[i_bit_tmp];
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -177,13 +177,13 @@ int init_ldpc_dec_s(void* p, const int16_t* llrs, uint16_t ls)
return -1; return -1;
} }
bzero(vp->soft_bits, skip * sizeof(int16_t)); srsran_vec_i16_zero(vp->soft_bits, skip);
for (i = skip; i < vp->liftN; i++) { for (i = skip; i < vp->liftN; i++) {
vp->soft_bits[i] = llrs[i - skip]; vp->soft_bits[i] = llrs[i - skip];
} }
bzero(vp->check_to_var, (vp->hrrN + vp->ls) * vp->bgM * sizeof(int16_t)); srsran_vec_i16_zero(vp->check_to_var, (vp->hrrN + vp->ls) * (uint32_t)vp->bgM);
bzero(vp->var_to_check, (vp->hrrN + vp->ls) * sizeof(int16_t)); srsran_vec_i16_zero(vp->var_to_check, vp->hrrN + vp->ls);
return 0; return 0;
} }
@ -258,7 +258,7 @@ int update_ldpc_check_to_var_s(void* p,
vp->prod_v2c[index] *= (vp->var_to_check[i_v2c] >= 0) ? 1 : -1; vp->prod_v2c[index] *= (vp->var_to_check[i_v2c] >= 0) ? 1 : -1;
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
int16_t* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls); int16_t* this_check_to_var = vp->check_to_var + i_layer * (vp->hrrN + vp->ls);
@ -277,7 +277,7 @@ int update_ldpc_check_to_var_s(void* p,
this_check_to_var[i_v2c] *= vp->prod_v2c[index] * ((vp->var_to_check[i_v2c] >= 0) ? 1 : -1); this_check_to_var[i_v2c] *= vp->prod_v2c[index] * ((vp->var_to_check[i_v2c] >= 0) ? 1 : -1);
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;
@ -315,7 +315,7 @@ int update_ldpc_soft_bits_s(void* p, int i_layer, const int8_t (*these_var_indic
} }
vp->soft_bits[i_bit] = (int16_t)tmp; vp->soft_bits[i_bit] = (int16_t)tmp;
} }
current_var_index = (*these_var_indices)[i + 1]; current_var_index = (*these_var_indices)[(i + 1) % MAX_CNCT];
} }
return 0; return 0;

@ -145,7 +145,7 @@ int load_avx2long(void* p, const uint8_t* input, const uint8_t msg_len, const ui
ini = ini + node_size; ini = ini + node_size;
} }
bzero(vp->codeword + msg_len * vp->n_subnodes, (cdwd_len - msg_len) * vp->n_subnodes * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->codeword + msg_len * vp->n_subnodes, bg_node_t, (cdwd_len - msg_len) * (uint32_t)vp->n_subnodes);
return 0; return 0;
} }
@ -212,8 +212,8 @@ void preprocess_systematic_bits_avx2long(srsran_ldpc_encoder_t* q)
int N = q->bgN; int N = q->bgN;
int K = q->bgK; int K = q->bgK;
int M = q->bgM;
int ls = q->ls; int ls = q->ls;
uint32_t M = q->bgM;
uint16_t* pcm = q->pcm; uint16_t* pcm = q->pcm;
int k = 0; int k = 0;
@ -223,7 +223,7 @@ void preprocess_systematic_bits_avx2long(srsran_ldpc_encoder_t* q)
__m256i tmp_epi8; __m256i tmp_epi8;
bzero(vp->aux, M * vp->n_subnodes * sizeof(__m256i)); SRSRAN_MEM_ZERO(vp->aux, __m256i, M * vp->n_subnodes);
// split the input message into K chunks of ls bits each and, for all chunks // split the input message into K chunks of ls bits each and, for all chunks
for (k = 0; k < K; k++) { for (k = 0; k < K; k++) {

@ -134,6 +134,12 @@ static int init_rm(srsran_ldpc_rm_t* p,
return -1; return -1;
} }
// Protect zero modulo
if (mod_order == 0) {
ERROR("Invalid modulation order");
return -1;
}
// check out_len is multiple of mod_order // check out_len is multiple of mod_order
if ((E % mod_order) != 0) { // N can only be a multiple of either BASEN[0] or BASEN[1], but not both if ((E % mod_order) != 0) { // N can only be a multiple of either BASEN[0] or BASEN[1], but not both
ERROR("Wrong RM codeword length (E) = %d. It must be a multiple of modulation order = %d", E, mod_order); ERROR("Wrong RM codeword length (E) = %d. It must be a multiple of modulation order = %d", E, mod_order);

@ -651,11 +651,23 @@ int main(int argc, char** argv)
void print_decoder(char* title, int n_batches, int n_errors, double elapsed_time) void print_decoder(char* title, int n_batches, int n_errors, double elapsed_time)
{ {
double wer = NAN;
if (n_batches != 0 && batch_size != 0) {
wer = (double)n_errors / n_batches / batch_size;
}
printf("\n**** %s ****", title); printf("\n**** %s ****", title);
printf("\nEstimated word error rate:\n %e (%d errors)\n", (double)n_errors / n_batches / batch_size, n_errors); printf("\nEstimated word error rate:\n %e (%d errors)\n", wer, n_errors);
double w_rate = NAN;
double k_rate = NAN;
double n_rate = NAN;
if (elapsed_time != 0) {
w_rate = n_batches * batch_size / elapsed_time;
k_rate = n_batches * batch_size * finalK / elapsed_time;
n_rate = n_batches * batch_size * finalN / elapsed_time;
}
printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n", printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
n_batches * batch_size / elapsed_time, w_rate,
n_batches * batch_size * finalK / elapsed_time, k_rate,
n_batches * batch_size * finalN / elapsed_time); n_rate);
} }

@ -104,7 +104,7 @@ void get_examples(uint8_t* messages, //
sprintf(cstr, "ls%dcwds", lift_size); sprintf(cstr, "ls%dcwds", lift_size);
do { do {
do { do {
tmp[0] = fgetc(ex_file); tmp[0] = (char)fgetc(ex_file);
} while (tmp[0] != 'l'); } while (tmp[0] != 'l');
fscanf(ex_file, "%[^\n]", tmp + 1); fscanf(ex_file, "%[^\n]", tmp + 1);
fgetc(ex_file); // discard newline fgetc(ex_file); // discard newline

@ -91,7 +91,7 @@ void srsran_polar_chanalloc_rx(const uint8_t* output_decoder,
uint16_t i_o = 0; uint16_t i_o = 0;
uint16_t iPC = 0; uint16_t iPC = 0;
uint16_t iK = 0; uint16_t iK = 0;
for (uint16_t iKPC = 0; iKPC < K + nPC; iKPC++) { for (uint16_t iKPC = 0; iKPC < K + (uint16_t)nPC; iKPC++) {
i_o = K_set[iKPC]; // includes parity bits i_o = K_set[iKPC]; // includes parity bits
if (i_o == PC_set[iPC]) { // skip if (i_o == PC_set[iPC]) { // skip
iPC = iPC + 1; iPC = iPC + 1;

@ -34,6 +34,7 @@
#include "polar_decoder_ssc_c_avx2.h" #include "polar_decoder_ssc_c_avx2.h"
#include "../utils_avx2.h" #include "../utils_avx2.h"
#include "polar_decoder_vector_avx2.h" #include "polar_decoder_vector_avx2.h"
#include "srsran/phy/fec/polar/polar_code.h"
#include "srsran/phy/fec/polar/polar_encoder.h" #include "srsran/phy/fec/polar/polar_encoder.h"
#include "srsran/phy/utils/vector.h" #include "srsran/phy/utils/vector.h"
@ -51,13 +52,13 @@ struct StateAVX2 {
* \brief Describes an SSC polar decoder (8-bit version). * \brief Describes an SSC polar decoder (8-bit version).
*/ */
struct pSSC_c_avx2 { struct pSSC_c_avx2 {
int8_t** llr0; /*!< \brief Pointers to the upper half of LLRs values at all stages. */ int8_t* llr0[NMAX_LOG + 1]; /*!< \brief Pointers to the upper half of LLRs values at all stages. */
int8_t** llr1; /*!< \brief Pointers to the lower half of LLRs values at all stages. */ int8_t* llr1[NMAX_LOG + 1]; /*!< \brief Pointers to the lower half of LLRs values at all stages. */
uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */ uint8_t* est_bit; /*!< \brief Pointers to the temporary estimated bits. */
struct Params* param; /*!< \brief Pointer to a Params structure. */ struct Params* param; /*!< \brief Pointer to a Params structure. */
struct StateAVX2* state; /*!< \brief Pointer to a State. */ struct StateAVX2* state; /*!< \brief Pointer to a State. */
void* tmp_node_type; /*!< \brief Pointer to a Tmp_node_type. */ void* tmp_node_type; /*!< \brief Pointer to a Tmp_node_type. */
srsran_polar_encoder_t* enc; /*!< \brief Pointer to a srsran_polar_encoder_t. */ srsran_polar_encoder_t* enc; /*!< \brief Pointer to a srsran_polar_encoder_t. */
void (*f)(const int8_t* x, const int8_t* y, int8_t* z, const uint16_t len); /*!< \brief Pointer to the function-f. */ void (*f)(const int8_t* x, const int8_t* y, int8_t* z, const uint16_t len); /*!< \brief Pointer to the function-f. */
void (*g)(const uint8_t* b, void (*g)(const uint8_t* b,
const int8_t* x, const int8_t* x,
@ -109,12 +110,6 @@ void delete_polar_decoder_ssc_c_avx2(void* p)
if (pp->llr0[0]) { if (pp->llr0[0]) {
free(pp->llr0[0]); // remove LLR buffer. free(pp->llr0[0]); // remove LLR buffer.
} }
if (pp->llr0) {
free(pp->llr0);
}
if (pp->llr1) {
free(pp->llr1);
}
if (pp->param) { if (pp->param) {
if (pp->param->node_type[0]) { if (pp->param->node_type[0]) {
free(pp->param->node_type[0]); free(pp->param->node_type[0]);
@ -200,10 +195,6 @@ void* create_polar_decoder_ssc_c_avx2(const uint8_t nMax)
pp->est_bit = srsran_vec_u8_malloc(est_bit_size); // every 32 chars are aligned pp->est_bit = srsran_vec_u8_malloc(est_bit_size); // every 32 chars are aligned
// allocate memory for LLR pointers.
pp->llr0 = malloc((nMax + 1) * sizeof(int8_t*));
pp->llr1 = malloc((nMax + 1) * sizeof(int8_t*));
// LLR MEMORY NOT ALIGNED FOR LLR_BUFFERS_SIZE < SRSRAN_SIMB_LLR_ALIGNED // LLR MEMORY NOT ALIGNED FOR LLR_BUFFERS_SIZE < SRSRAN_SIMB_LLR_ALIGNED
// We do not align the memory at lower stages, as if done, after each function f and function g // We do not align the memory at lower stages, as if done, after each function f and function g
@ -312,7 +303,6 @@ int init_polar_decoder_ssc_c_avx2(void* p,
int polar_decoder_ssc_c_avx2(void* p, uint8_t* data_decoded) int polar_decoder_ssc_c_avx2(void* p, uint8_t* data_decoded)
{ {
if (p == NULL) { if (p == NULL) {
return -1; return -1;
} }
@ -331,7 +321,6 @@ int polar_decoder_ssc_c_avx2(void* p, uint8_t* data_decoded)
static void simplified_node(struct pSSC_c_avx2* p) static void simplified_node(struct pSSC_c_avx2* p)
{ {
struct pSSC_c_avx2* pp = p; struct pSSC_c_avx2* pp = p;
pp->state->stage--; // to child node. pp->state->stage--; // to child node.
@ -345,7 +334,6 @@ static void simplified_node(struct pSSC_c_avx2* p)
uint16_t stage_half_size = 0; uint16_t stage_half_size = 0;
switch (pp->param->node_type[stage][bit_pos]) { switch (pp->param->node_type[stage][bit_pos]) {
case RATE_1: case RATE_1:
pp->hard_bit(pp->llr0[stage], pp->est_bit + pp->state->bit_pos, stage_size); pp->hard_bit(pp->llr0[stage], pp->est_bit + pp->state->bit_pos, stage_size);

@ -129,7 +129,6 @@ static inline void srsran_vec_polar_encoder_32_avx2(const uint8_t* x, uint8_t* z
*/ */
static inline void srsran_vec_xor_bbb_avx2(const uint8_t* x, const uint8_t* y, uint8_t* z, uint16_t len) static inline void srsran_vec_xor_bbb_avx2(const uint8_t* x, const uint8_t* y, uint8_t* z, uint16_t len)
{ {
for (int i = 0; i < len; i += SRSRAN_AVX2_B_SIZE) { for (int i = 0; i < len; i += SRSRAN_AVX2_B_SIZE) {
__m256i simd_x = _mm256_loadu_si256((__m256i*)&x[i]); __m256i simd_x = _mm256_loadu_si256((__m256i*)&x[i]);
__m256i simd_y = _mm256_loadu_si256((__m256i*)&y[i]); __m256i simd_y = _mm256_loadu_si256((__m256i*)&y[i]);
@ -142,19 +141,18 @@ static inline void srsran_vec_xor_bbb_avx2(const uint8_t* x, const uint8_t* y, u
int polar_encoder_encode_avx2(void* p, const uint8_t* input, uint8_t* output, const uint8_t code_size_log) int polar_encoder_encode_avx2(void* p, const uint8_t* input, uint8_t* output, const uint8_t code_size_log)
{ {
struct pAVX2* q = p; struct pAVX2* q = p;
if (q == NULL) {
return -1;
}
uint8_t* tmp = q->tmp; uint8_t* tmp = q->tmp;
uint8_t* x = NULL; uint8_t* x = NULL;
uint8_t* y = NULL; uint8_t* y = NULL;
uint8_t* z = NULL; uint8_t* z = NULL;
if (q == NULL) {
return -1;
}
// load data // load data
uint32_t code_size = 1U << code_size_log; uint32_t code_size = 1U << code_size_log;

@ -51,6 +51,16 @@ void srsran_polar_code_sets_free(srsran_polar_sets_t* c)
} }
} }
#define SAFE_READ(PTR, SIZE, N, FILE) \
do { \
size_t nbytes = SIZE * N; \
if (nbytes != fread(PTR, SIZE, N, FILE)) { \
perror("read"); \
fclose(FILE); \
exit(1); \
} \
} while (false)
int srsran_polar_code_sets_read(srsran_polar_sets_t* c, int srsran_polar_code_sets_read(srsran_polar_sets_t* c,
const uint16_t message_size, const uint16_t message_size,
const uint8_t code_size_log, const uint8_t code_size_log,
@ -109,10 +119,10 @@ int srsran_polar_code_sets_read(srsran_polar_sets_t* c,
exit(1); exit(1);
} }
fread(c->info_set, sizeof(uint16_t), c->info_set_size, fptr); SAFE_READ(c->info_set, sizeof(uint16_t), c->info_set_size, fptr);
fread(c->message_set, sizeof(uint16_t), c->message_set_size, fptr); SAFE_READ(c->message_set, sizeof(uint16_t), c->message_set_size, fptr);
fread(c->parity_set, sizeof(uint16_t), c->parity_set_size, fptr); SAFE_READ(c->parity_set, sizeof(uint16_t), c->parity_set_size, fptr);
fread(c->frozen_set, sizeof(uint16_t), c->frozen_set_size, fptr); SAFE_READ(c->frozen_set, sizeof(uint16_t), c->frozen_set_size, fptr);
fclose(fptr); fclose(fptr);
return 0; return 0;

@ -70,7 +70,11 @@ int main(int argc, char** argv)
uint32_t st = 0, end = 187; uint32_t st = 0, end = 187;
if (long_cb) { if (long_cb) {
st = srsran_cbsegm_cbindex(long_cb); int n = srsran_cbsegm_cbindex(long_cb);
if (n < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
st = (uint32_t)n;
end = st; end = st;
} }

@ -120,7 +120,6 @@ int main(int argc, char** argv)
short* llr_s; short* llr_s;
uint8_t* llr_c; uint8_t* llr_c;
uint8_t * data_tx, *data_rx, *data_rx_bytes, *symbols; uint8_t * data_tx, *data_rx, *data_rx_bytes, *symbols;
uint32_t i, j;
float var[SNR_POINTS]; float var[SNR_POINTS];
uint32_t snr_points; uint32_t snr_points;
uint32_t errors = 0; uint32_t errors = 0;
@ -140,7 +139,11 @@ int main(int argc, char** argv)
if (test_known_data) { if (test_known_data) {
frame_length = KNOWN_DATA_LEN; frame_length = KNOWN_DATA_LEN;
} else { } else {
frame_length = srsran_cbsegm_cbsize(srsran_cbsegm_cbindex(frame_length)); int n = srsran_cbsegm_cbsize(srsran_cbsegm_cbindex(frame_length));
if (n < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
frame_length = (uint32_t)n;
} }
coded_length = 3 * (frame_length) + SRSRAN_TCOD_TOTALTAIL; coded_length = 3 * (frame_length) + SRSRAN_TCOD_TOTALTAIL;
@ -209,7 +212,7 @@ int main(int argc, char** argv)
ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS; ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS;
if (ebno_db == 100.0) { if (ebno_db == 100.0) {
snr_points = SNR_POINTS; snr_points = SNR_POINTS;
for (i = 0; i < snr_points; i++) { for (uint32_t i = 0; i < snr_points; i++) {
ebno_db = SNR_MIN + i * ebno_inc; ebno_db = SNR_MIN + i * ebno_inc;
esno_db = ebno_db + srsran_convert_power_to_dB(1.0f / 3.0f); esno_db = ebno_db + srsran_convert_power_to_dB(1.0f / 3.0f);
var[i] = srsran_convert_dB_to_amplitude(-esno_db); var[i] = srsran_convert_dB_to_amplitude(-esno_db);
@ -219,13 +222,13 @@ int main(int argc, char** argv)
var[0] = srsran_convert_dB_to_amplitude(-esno_db); var[0] = srsran_convert_dB_to_amplitude(-esno_db);
snr_points = 1; snr_points = 1;
} }
for (i = 0; i < snr_points; i++) { for (uint32_t i = 0; i < snr_points; i++) {
mean_usec = 0; mean_usec = 0;
errors = 0; errors = 0;
frame_cnt = 0; frame_cnt = 0;
while (frame_cnt < nof_frames) { while (frame_cnt < nof_frames) {
/* generate data_tx */ /* generate data_tx */
for (j = 0; j < frame_length; j++) { for (uint32_t j = 0; j < frame_length; j++) {
if (test_known_data) { if (test_known_data) {
data_tx[j] = known_data[j]; data_tx[j] = known_data[j];
} else { } else {
@ -235,19 +238,19 @@ int main(int argc, char** argv)
/* coded BER */ /* coded BER */
if (test_known_data) { if (test_known_data) {
for (j = 0; j < coded_length; j++) { for (uint32_t j = 0; j < coded_length; j++) {
symbols[j] = known_data_encoded[j]; symbols[j] = known_data_encoded[j];
} }
} else { } else {
srsran_tcod_encode(&tcod, data_tx, symbols, frame_length); srsran_tcod_encode(&tcod, data_tx, symbols, frame_length);
} }
for (j = 0; j < coded_length; j++) { for (uint32_t j = 0; j < coded_length; j++) {
llr[j] = symbols[j] ? 1 : -1; llr[j] = symbols[j] ? 1 : -1;
} }
srsran_ch_awgn_f(llr, llr, var[i], coded_length); srsran_ch_awgn_f(llr, llr, var[i], coded_length);
for (j = 0; j < coded_length; j++) { for (uint32_t j = 0; j < coded_length; j++) {
llr_s[j] = (int16_t)(100 * llr[j]); llr_s[j] = (int16_t)(100 * llr[j]);
} }

@ -461,7 +461,7 @@ static void tdec_iteration_8(srsran_tdec_t* h, int8_t* input)
if (h->dec_type == SRSRAN_TDEC_AUTO) { if (h->dec_type == SRSRAN_TDEC_AUTO) {
h->current_llr_type = SRSRAN_TDEC_8; h->current_llr_type = SRSRAN_TDEC_8;
h->current_dec = tdec_sb_idx_8(h->current_long_cb); h->current_dec = tdec_sb_idx_8(h->current_long_cb);
h->current_inter_idx = interleaver_idx(h->nof_blocks8[h->current_dec]); h->current_inter_idx = interleaver_idx(h->nof_blocks8[h->current_dec % SRSRAN_TDEC_NOF_AUTO_MODES_8]);
// If long_cb is not multiple of any 8-bit decoder, use a 16-bit decoder and do type conversion // If long_cb is not multiple of any 8-bit decoder, use a 16-bit decoder and do type conversion
if (h->current_dec >= 10) { if (h->current_dec >= 10) {

@ -54,42 +54,43 @@ inline static uint8x16_t v_load_s8(int i15,
#define int8x16_to_8x8x2(v) ((int8x8x2_t){{vget_low_s8(v), vget_high_s8(v)}}) #define int8x16_to_8x8x2(v) ((int8x8x2_t){{vget_low_s8(v), vget_high_s8(v)}})
inline static void vshuff_s32_even(int32x4_t a, int imm, int32x4_t* res) #define vshuff_s32_even(a, imm, res) \
{ do { \
*res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> 2) & 0x3), *res, 1); *res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> 2) & 0x3), *res, 1); \
*res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> 6) & 0x3), *res, 3); *res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> 6) & 0x3), *res, 3); \
} } while (0)
inline static void vshuff_s32_odd(int32x4_t a, int imm, int32x4_t* res)
{ #define vshuff_s32_odd(a, imm, res) \
*res = vsetq_lane_s32(vgetq_lane_s32((a), (imm)&0x3), *res, 0); do { \
*res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> 4) & 0x3), *res, 2); *res = vsetq_lane_s32(vgetq_lane_s32((a), (imm)&0x3), *res, 0); \
} *res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> 4) & 0x3), *res, 2); \
} while (0)
inline static void vshuff_s32_idx(int32x4_t a, int imm, int32x4_t* res, int idx)
{ #define vshuff_s32_idx(a, imm, res, idx) \
*res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> idx * 2) & 0x3), *res, idx); do { \
} *res = vsetq_lane_s32(vgetq_lane_s32((a), ((imm) >> idx * 2) & 0x3), *res, idx); \
} while (0)
inline static void vshuff_s16_idx(int16x8_t a, int imm, int16x8_t* res, int idx)
{ #define vshuff_s16_idx(a, imm, res, idx) \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> (idx * 4)) & 0xF), *res, idx); do { \
} *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> (idx * 4)) & 0xF), *res, idx); \
} while (0)
inline static void vshuff_s16_even(int16x8_t a, int imm, int16x8_t* res)
{ #define vshuff_s16_even(a, imm, res) \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 4) & 0xF), *res, 1); do { \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 12) & 0xF), *res, 3); *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 4) & 0xF), *res, 1); \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 20) & 0xF), *res, 5); *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 12) & 0xF), *res, 3); \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 28) & 0xF), *res, 7); *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 20) & 0xF), *res, 5); \
} *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 28) & 0xF), *res, 7); \
} while (0)
inline static void vshuff_s16_odd(int16x8_t a, int imm, int16x8_t* res)
{ #define vshuff_s16_odd(a, imm, res) \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm)) & 0xF), *res, 0); do { \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 8) & 0xF), *res, 2); *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm)) & 0xF), *res, 0); \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 16) & 0xF), *res, 4); *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 8) & 0xF), *res, 2); \
*res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 24) & 0xF), *res, 6); *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 16) & 0xF), *res, 4); \
} *res = vsetq_lane_s16(vgetq_lane_s16((a), ((imm) >> 24) & 0xF), *res, 6); \
} while (0)
#endif #endif

@ -283,12 +283,13 @@ int srsran_npdcch_decode_msg(srsran_npdcch_t* q,
} else { } else {
DEBUG("Skipping DCI: nCCE=%d, L=%d, msg_len=%d, mean=%f", location->ncce, location->L, nof_bits, mean); DEBUG("Skipping DCI: nCCE=%d, L=%d, msg_len=%d, mean=%f", location->ncce, location->L, nof_bits, mean);
} }
q->num_decoded_symbols = num_decoded_symbols;
ret = SRSRAN_SUCCESS; ret = SRSRAN_SUCCESS;
} else { } else {
fprintf(stderr, "Invalid parameters, location=%d,%d\n", location->ncce, location->L); fprintf(stderr, "Invalid parameters, location=%d,%d\n", location->ncce, location->L);
} }
q->num_decoded_symbols = num_decoded_symbols;
return ret; return ret;
} }

@ -194,8 +194,13 @@ int srsran_pdcch_nr_init_tx(srsran_pdcch_nr_t* q, const srsran_pdcch_nr_args_t*
} }
q->is_tx = true; q->is_tx = true;
srsran_polar_encoder_type_t encoder_type = srsran_polar_encoder_type_t encoder_type = SRSRAN_POLAR_ENCODER_PIPELINED;
(args->disable_simd) ? SRSRAN_POLAR_ENCODER_PIPELINED : SRSRAN_POLAR_ENCODER_AVX2;
#ifdef LV_HAVE_AVX2
if (!args->disable_simd) {
encoder_type = SRSRAN_POLAR_ENCODER_AVX2;
}
#endif // LV_HAVE_AVX2
if (srsran_polar_encoder_init(&q->encoder, encoder_type, NMAX_LOG) < SRSRAN_SUCCESS) { if (srsran_polar_encoder_init(&q->encoder, encoder_type, NMAX_LOG) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR; return SRSRAN_ERROR;
@ -214,8 +219,13 @@ int srsran_pdcch_nr_init_rx(srsran_pdcch_nr_t* q, const srsran_pdcch_nr_args_t*
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
srsran_polar_decoder_type_t decoder_type = srsran_polar_decoder_type_t decoder_type = SRSRAN_POLAR_DECODER_SSC_C;
(args->disable_simd) ? SRSRAN_POLAR_DECODER_SSC_C : SRSRAN_POLAR_DECODER_SSC_C_AVX2;
#ifdef LV_HAVE_AVX2
if (!args->disable_simd) {
decoder_type = SRSRAN_POLAR_DECODER_SSC_C_AVX2;
}
#endif // LV_HAVE_AVX2
if (srsran_polar_decoder_init(&q->decoder, decoder_type, NMAX_LOG) < SRSRAN_SUCCESS) { if (srsran_polar_decoder_init(&q->decoder, decoder_type, NMAX_LOG) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR; return SRSRAN_ERROR;
@ -334,9 +344,9 @@ static uint32_t pdcch_nr_cp(const srsran_pdcch_nr_t* q,
static uint32_t pdcch_nr_c_init(const srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_msg) static uint32_t pdcch_nr_c_init(const srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_msg)
{ {
uint32_t n_id = (dci_msg->ctx.ss_type == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present) 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->coreset.dmrs_scrambling_id
: q->carrier.pci; : q->carrier.pci;
uint32_t n_rnti = (dci_msg->ctx.ss_type == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present) uint32_t n_rnti = (dci_msg->ctx.ss_type == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present)
? dci_msg->ctx.rnti ? dci_msg->ctx.rnti
: 0U; : 0U;

@ -591,8 +591,6 @@ static uint32_t pdsch_nr_grant_info(const srsran_pdsch_nr_t* q,
if (res != NULL) { if (res != NULL) {
if (grant->tb[i].enabled && !isnan(res->evm[i])) { if (grant->tb[i].enabled && !isnan(res->evm[i])) {
len = srsran_print_check(str, str_len, len, "evm=%.2f ", res->evm[i]); len = srsran_print_check(str, str_len, len, "evm=%.2f ", res->evm[i]);
if (i < SRSRAN_MAX_CODEWORDS - 1) {
}
} }
} }
} }

@ -1027,8 +1027,6 @@ static uint32_t pusch_nr_grant_info(const srsran_pusch_nr_t* q,
if (res != NULL) { if (res != NULL) {
if (grant->tb[i].enabled && !isnan(res->evm[i])) { if (grant->tb[i].enabled && !isnan(res->evm[i])) {
len = srsran_print_check(str, str_len, len, "evm=%.2f ", res->evm[i]); len = srsran_print_check(str, str_len, len, "evm=%.2f ", res->evm[i]);
if (i < SRSRAN_MAX_CODEWORDS - 1) {
}
} }
} }
} }

@ -28,6 +28,7 @@ static srsran_carrier_nr_t carrier = {
1, // pci 1, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
0, // offset_to_carrier
srsran_subcarrier_spacing_15kHz, // scs srsran_subcarrier_spacing_15kHz, // scs
50, // nof_prb 50, // nof_prb
0, // start 0, // start

@ -30,16 +30,16 @@
#include <math.h> #include <math.h>
static srsran_carrier_nr_t carrier = { static srsran_carrier_nr_t carrier = {
1, // pci 1, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
srsran_subcarrier_spacing_15kHz, // scs 0, // offset_to_carrier
SRSRAN_MAX_PRB_NR, // nof_prb srsran_subcarrier_spacing_15kHz, // scs
0, // start SRSRAN_MAX_PRB_NR, // nof_prb
1 // max_mimo_layers 0, // start
1 // max_mimo_layers
}; };
static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t n_prb = 0; // Set to 0 for steering
static uint32_t mcs = 30; // Set to 30 for steering static uint32_t mcs = 30; // Set to 30 for steering
static srsran_sch_cfg_nr_t pdsch_cfg = {}; static srsran_sch_cfg_nr_t pdsch_cfg = {};

@ -35,6 +35,7 @@ static srsran_carrier_nr_t carrier = {
1, // pci 1, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
0, // offset_to_carrier
srsran_subcarrier_spacing_15kHz, // scs srsran_subcarrier_spacing_15kHz, // scs
6, // nof_prb 6, // nof_prb
0, // start 0, // start

@ -29,13 +29,14 @@
#include <getopt.h> #include <getopt.h>
static srsran_carrier_nr_t carrier = { static srsran_carrier_nr_t carrier = {
1, // pci 1, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
srsran_subcarrier_spacing_15kHz, // scs 0, // offset_to_carrier
SRSRAN_MAX_PRB_NR, // nof_prb srsran_subcarrier_spacing_15kHz, // scs
0, // start SRSRAN_MAX_PRB_NR, // nof_prb
1 // max_mimo_layers 0, // start
1 // max_mimo_layers
}; };
static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t n_prb = 0; // Set to 0 for steering

@ -28,13 +28,14 @@
#include <srsran/phy/utils/random.h> #include <srsran/phy/utils/random.h>
static srsran_carrier_nr_t carrier = { static srsran_carrier_nr_t carrier = {
1, // pci 1, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
srsran_subcarrier_spacing_15kHz, // scs 0, // offset_to_carrier
SRSRAN_MAX_PRB_NR, // nof_prb srsran_subcarrier_spacing_15kHz, // scs
0, // start SRSRAN_MAX_PRB_NR, // nof_prb
1 // max_mimo_layers 0, // start
1 // max_mimo_layers
}; };
static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t n_prb = 0; // Set to 0 for steering

@ -1070,13 +1070,13 @@ int srsran_uci_nr_encode_pusch_ack(srsran_uci_nr_t* q,
const srsran_uci_value_nr_t* value, const srsran_uci_value_nr_t* value,
uint8_t* o) uint8_t* o)
{ {
int A = cfg->o_ack;
// Check inputs // Check inputs
if (q == NULL || cfg == NULL || value == NULL || o == NULL) { if (q == NULL || cfg == NULL || value == NULL || o == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS; return SRSRAN_ERROR_INVALID_INPUTS;
} }
int A = cfg->o_ack;
// 6.3.2.1 UCI bit sequence generation // 6.3.2.1 UCI bit sequence generation
// 6.3.2.1.1 HARQ-ACK // 6.3.2.1.1 HARQ-ACK
bool has_csi_part2 = srsran_csi_has_part2(cfg->csi, cfg->nof_csi); bool has_csi_part2 = srsran_csi_has_part2(cfg->csi, cfg->nof_csi);

@ -296,26 +296,16 @@ int rf_soapy_open_multi(char* args, void** h, uint32_t num_requested_channels)
SoapySDRKwargsList_clear(soapy_args, length); SoapySDRKwargsList_clear(soapy_args, length);
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
char* devname = DEVNAME_NONE;
// Print connected devices
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
printf("Soapy has found device #%d: ", (int)i); printf("Soapy has found device #%d: ", (int)i);
for (size_t j = 0; j < soapy_args[i].size; j++) { for (size_t j = 0; j < soapy_args[i].size; j++) {
printf("%s=%s, ", soapy_args[i].keys[j], soapy_args[i].vals[j]); printf("%s=%s, ", soapy_args[i].keys[j], soapy_args[i].vals[j]);
if (!strcmp(soapy_args[i].keys[j], "name") && !strcmp(soapy_args[i].vals[j], "LimeSDR-USB")) {
devname = DEVNAME_LIME;
} else if (!strcmp(soapy_args[i].keys[j], "name") && !strcmp(soapy_args[i].vals[j], "LimeSDR Mini")) {
devname = DEVNAME_LIME_MINI;
}
} }
printf("\n"); printf("\n");
} }
// With the Lime we are better off using LTE sample rates
if (strcmp(devname, "Lime") && srsran_symbol_size_is_standard() == false) {
printf("\033[0;31mConsider using LTE sample rates for better RF performance.\nEither compile with "
"\'-DUSE_LTE_RATES=True\' or start srsENB or srsUE with \'--expert.lte_sample_rates=true\'\033[0m\n");
}
// Select Soapy device by id // Select Soapy device by id
int dev_id = 0; int dev_id = 0;
if (args != NULL) { if (args != NULL) {
@ -338,6 +328,14 @@ int rf_soapy_open_multi(char* args, void** h, uint32_t num_requested_channels)
dev_id = SRSRAN_MIN(dev_id, length - 1); dev_id = SRSRAN_MIN(dev_id, length - 1);
printf("Selecting Soapy device: %d\n", dev_id); printf("Selecting Soapy device: %d\n", dev_id);
// With the Lime we are better off using LTE sample rates
const char* devname = SoapySDRKwargs_get(&soapy_args[dev_id], "name");
if (devname != NULL && strstr(devname, "Lime") != NULL && srsran_symbol_size_is_standard() == false) {
printf("\033[0;31mDetected LimeSDR. Consider using LTE rates for better RF performance.\nEither compile with "
"\'-DUSE_LTE_RATES=True\' or start srsENB/srsUE with \'--expert.lte_sample_rates=true\'\033[0m\n");
}
// Now make the device
SoapySDRDevice* sdr = SoapySDRDevice_make(&(soapy_args[dev_id])); SoapySDRDevice* sdr = SoapySDRDevice_make(&(soapy_args[dev_id]));
if (sdr == NULL) { if (sdr == NULL) {
printf("Failed to create Soapy object\n"); printf("Failed to create Soapy object\n");
@ -352,7 +350,7 @@ int rf_soapy_open_multi(char* args, void** h, uint32_t num_requested_channels)
handler->device = sdr; handler->device = sdr;
handler->tx_stream_active = false; handler->tx_stream_active = false;
handler->rx_stream_active = false; handler->rx_stream_active = false;
handler->devname = devname; handler->devname = DEVNAME_SOAPY;
// create stream args from device args // create stream args from device args
SoapySDRKwargs stream_args = {}; SoapySDRKwargs stream_args = {};

@ -26,9 +26,7 @@
#include "srsran/phy/rf/rf.h" #include "srsran/phy/rf/rf.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#define DEVNAME_NONE "none" #define DEVNAME_SOAPY "soapy"
#define DEVNAME_LIME "lime"
#define DEVNAME_LIME_MINI "lime_mini"
SRSRAN_API int rf_soapy_open(char* args, void** handler); SRSRAN_API int rf_soapy_open(char* args, void** handler);

@ -46,22 +46,25 @@
* - BURST: A burst has started * - BURST: A burst has started
* - END_OF_BURST: An underflow, overflow or late has been detected, the next transmission shall be aborted and an end * - END_OF_BURST: An underflow, overflow or late has been detected, the next transmission shall be aborted and an end
* of burst will be send in the next transmission; * of burst will be send in the next transmission;
* - WAIT_EOB_ACK: Waits for either an end of burst ACK event or a transmission after EOB_ACK_TIMEOUT_S the
* Late/Underflow occurred.
* - START_BURST: The next transmission will be flagged as start of burst. * - START_BURST: The next transmission will be flagged as start of burst.
* *
* +-------+ L/O/U detected +--------------+ EoB Sent +-------------+ * +-------+ L/O/U detected +--------------+ EoB Sent +--------------+ EOB ACK Rx +-------------+
* | Burst |--------------->| End-of-burst |------------->| Start burst |<--- Initial state * | Burst |--------------->| End-of-burst |------------>| Wait EOB ACK |------------>| Start burst |<-- Initial state
* +-------+ | +--------------+ ^ +-------------+ * +-------+ +--------------+ +--------------+ +-------------+
* ^ | | | * ^ | |
* | | Burst ACK | | * | | New Transmission | New Transmission
* | +-------------------------------------+ | * | | (TS timed out) |
* | | * | | |
* | Start of burst is transmitted | * | Start of burst is transmitted | |
* +----------------------------------------------------------+ * +---------------------------------------------------------+----------------------------+
*/ */
typedef enum { typedef enum {
RF_UHD_IMP_TX_STATE_START_BURST = 0, RF_UHD_IMP_TX_STATE_START_BURST = 0,
RF_UHD_IMP_TX_STATE_BURST, RF_UHD_IMP_TX_STATE_BURST,
RF_UHD_IMP_TX_STATE_END_OF_BURST, RF_UHD_IMP_TX_STATE_END_OF_BURST,
RF_UHD_IMP_TX_STATE_WAIT_EOB_ACK ///< Wait for enb-of-burst ACK
} rf_uhd_imp_underflow_state_t; } rf_uhd_imp_underflow_state_t;
/** /**
@ -77,6 +80,11 @@ const std::set<std::string> RF_UHD_IMP_PROHIBITED_STREAM_REMAKE = {DEVNAME_X300,
DEVNAME_E3X0, DEVNAME_E3X0,
DEVNAME_B200}; DEVNAME_B200};
/**
* List of devices that do NOT support end of burst flushing
*/
const std::set<std::string> RF_UHD_IMP_PROHIBITED_EOB_FLUSH = {DEVNAME_X300, DEVNAME_N300};
/** /**
* List of devices that do NOT require/support to restart streaming after rate changes/timeouts * List of devices that do NOT require/support to restart streaming after rate changes/timeouts
*/ */
@ -119,6 +127,11 @@ static const std::chrono::milliseconds RF_UHD_IMP_ASYNCH_MSG_SLEEP_MS = std::chr
*/ */
static const uint32_t RF_UHD_IMP_MAX_RX_TRIALS = 100; static const uint32_t RF_UHD_IMP_MAX_RX_TRIALS = 100;
/**
* Timeout for end of burst ack.
*/
static const double RF_UHD_IMP_WAIT_EOB_ACK_TIMEOUT_S = 2.0;
struct rf_uhd_handler_t { struct rf_uhd_handler_t {
size_t id; size_t id;
@ -139,6 +152,7 @@ struct rf_uhd_handler_t {
srsran_rf_error_handler_t uhd_error_handler = nullptr; srsran_rf_error_handler_t uhd_error_handler = nullptr;
void* uhd_error_handler_arg = nullptr; void* uhd_error_handler_arg = nullptr;
rf_uhd_imp_underflow_state_t tx_state = RF_UHD_IMP_TX_STATE_START_BURST; rf_uhd_imp_underflow_state_t tx_state = RF_UHD_IMP_TX_STATE_START_BURST;
uhd::time_spec_t eob_ack_timeout = {}; //< Set when a Underflow/Late happens
double current_master_clock = 0.0; double current_master_clock = 0.0;
@ -250,8 +264,10 @@ static void log_rx_error(rf_uhd_handler_t* h)
#if HAVE_ASYNC_THREAD #if HAVE_ASYNC_THREAD
static void* async_thread(void* h) static void* async_thread(void* h)
{ {
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
uhd::async_metadata_t md; uhd::async_metadata_t md = {};
uhd::time_spec_t last_underflow_ts = {};
uhd::time_spec_t last_late_ts = {};
while (handler->async_thread_running) { while (handler->async_thread_running) {
std::unique_lock<std::mutex> lock(handler->async_mutex); std::unique_lock<std::mutex> lock(handler->async_mutex);
@ -273,12 +289,20 @@ static void* async_thread(void* h)
const uhd::async_metadata_t::event_code_t& event_code = md.event_code; const uhd::async_metadata_t::event_code_t& event_code = md.event_code;
if (event_code == uhd::async_metadata_t::EVENT_CODE_UNDERFLOW || if (event_code == uhd::async_metadata_t::EVENT_CODE_UNDERFLOW ||
event_code == uhd::async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) { event_code == uhd::async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) {
log_underflow(handler); if (md.time_spec != last_underflow_ts) {
last_underflow_ts = md.time_spec;
handler->eob_ack_timeout = md.time_spec + RF_UHD_IMP_WAIT_EOB_ACK_TIMEOUT_S;
log_underflow(handler);
}
} else if (event_code == uhd::async_metadata_t::EVENT_CODE_TIME_ERROR) { } else if (event_code == uhd::async_metadata_t::EVENT_CODE_TIME_ERROR) {
log_late(handler, false); if (md.time_spec != last_late_ts) {
last_late_ts = md.time_spec;
handler->eob_ack_timeout = md.time_spec + RF_UHD_IMP_WAIT_EOB_ACK_TIMEOUT_S;
log_late(handler, false);
}
} else if (event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK) { } else if (event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK) {
// Makes sure next block will be start of burst // Makes sure next block will be start of burst
if (handler->tx_state == RF_UHD_IMP_TX_STATE_BURST) { if (handler->tx_state == RF_UHD_IMP_TX_STATE_WAIT_EOB_ACK) {
handler->tx_state = RF_UHD_IMP_TX_STATE_START_BURST; handler->tx_state = RF_UHD_IMP_TX_STATE_START_BURST;
} }
} else { } else {
@ -979,8 +1003,8 @@ static inline int rf_uhd_imp_end_burst(rf_uhd_handler_t* handler)
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
// Update TX state // Update TX state to wait for end of burst ACK
handler->tx_state = RF_UHD_IMP_TX_STATE_START_BURST; handler->tx_state = RF_UHD_IMP_TX_STATE_WAIT_EOB_ACK;
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
@ -1296,7 +1320,7 @@ int rf_uhd_recv_with_time_multi(void* h,
} }
// Receive stream in multiple blocks // Receive stream in multiple blocks
while (rxd_samples_total < nsamples && trials < RF_UHD_IMP_MAX_RX_TRIALS) { while (rxd_samples_total < nsamples and trials < RF_UHD_IMP_MAX_RX_TRIALS) {
void* buffs_ptr[SRSRAN_MAX_CHANNELS] = {}; void* buffs_ptr[SRSRAN_MAX_CHANNELS] = {};
for (uint32_t i = 0; i < handler->nof_rx_channels; i++) { for (uint32_t i = 0; i < handler->nof_rx_channels; i++) {
cf_t* data_c = (cf_t*)data[i]; cf_t* data_c = (cf_t*)data[i];
@ -1389,36 +1413,14 @@ int rf_uhd_send_timed_multi(void* h,
std::unique_lock<std::mutex> lock(handler->tx_mutex); std::unique_lock<std::mutex> lock(handler->tx_mutex);
uhd::tx_metadata_t md; uhd::tx_metadata_t md;
void* buffs_ptr[SRSRAN_MAX_CHANNELS] = {}; void* buffs_ptr[SRSRAN_MAX_CHANNELS] = {};
size_t txd_samples = 0; int n = 0; //< Counts transmitted samples
int n = 0;
// Check Tx stream has been created // Check Tx stream has been created
if (not handler->uhd->is_tx_ready()) { if (not handler->uhd->is_tx_ready()) {
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
// Run Underflow recovery state machine // Set Tx timestamp
switch (handler->tx_state) {
case RF_UHD_IMP_TX_STATE_BURST:
// Normal case, do nothing
break;
case RF_UHD_IMP_TX_STATE_END_OF_BURST:
// Send end of burst and ignore transmission
if (rf_uhd_imp_end_burst(handler) != SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
// Flush receiver
rf_uhd_flush_buffer(h);
return SRSRAN_ERROR;
case RF_UHD_IMP_TX_STATE_START_BURST:
// Set tart of burst to false if recovering from the Underflow
is_start_of_burst = true;
handler->tx_state = RF_UHD_IMP_TX_STATE_BURST;
break;
}
if (not has_time_spec) { if (not has_time_spec) {
// If it the beginning of a burst, set timestamp // If it the beginning of a burst, set timestamp
if (is_start_of_burst) { if (is_start_of_burst) {
@ -1450,15 +1452,40 @@ int rf_uhd_send_timed_multi(void* h,
do { do {
size_t tx_samples = handler->tx_nof_samples; size_t tx_samples = handler->tx_nof_samples;
// Set start of burst. Time spec only for the first packet in the burst // If an Underflow or a Late has been detected, end the burst immediately
md.start_of_burst = is_start_of_burst; if (handler->tx_state == RF_UHD_IMP_TX_STATE_END_OF_BURST) {
// Send end of burst and ignore transmission
if (rf_uhd_imp_end_burst(handler) != SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
// Flush receiver only if allowed
if (RF_UHD_IMP_PROHIBITED_EOB_FLUSH.count(handler->devname) == 0) {
rf_uhd_flush_buffer(h);
}
return SRSRAN_ERROR;
}
// If the state is waiting for EOB ACK and the metadata of the current packet has passed the timeout, then start the
// burst
if (handler->tx_state == RF_UHD_IMP_TX_STATE_WAIT_EOB_ACK and md.time_spec >= handler->eob_ack_timeout) {
Info("Tx while waiting for EOB, timed out... " << md.time_spec.get_real_secs()
<< " >= " << handler->eob_ack_timeout.get_real_secs()
<< ". Starting new burst...");
handler->tx_state = RF_UHD_IMP_TX_STATE_START_BURST;
}
// Set start of burst, ignore function argument and set the flag based on the current Tx state
md.start_of_burst = (handler->tx_state == RF_UHD_IMP_TX_STATE_START_BURST);
// some devices don't like timestamps in each call // Time spec only for the first packet in the burst, some devices are not capable of handling like timestamps for
// each baseband packet
if (RF_UHD_IMP_TIMESPEC_AT_BURST_START_ONLY.count(handler->devname) == 0) { if (RF_UHD_IMP_TIMESPEC_AT_BURST_START_ONLY.count(handler->devname) == 0) {
md.has_time_spec = is_start_of_burst or has_time_spec; md.has_time_spec = md.start_of_burst or has_time_spec;
} else { } else {
// only set time for start // only set time for start
md.has_time_spec = is_start_of_burst and has_time_spec; md.has_time_spec = md.start_of_burst and has_time_spec;
} }
// middle packets are never end of burst, last one as defined // middle packets are never end of burst, last one as defined
@ -1469,20 +1496,35 @@ int rf_uhd_send_timed_multi(void* h,
md.end_of_burst = is_end_of_burst; md.end_of_burst = is_end_of_burst;
} }
// Update data pointers
for (int i = 0; i < SRSRAN_MAX_CHANNELS; i++) { for (int i = 0; i < SRSRAN_MAX_CHANNELS; i++) {
void* buff = (void*)&data_c[i][n]; void* buff = (void*)&data_c[i][n];
buffs_ptr[i] = buff; buffs_ptr[i] = buff;
} }
if (handler->uhd->send(buffs_ptr, tx_samples, md, RF_UHD_IMP_TRX_TIMEOUT_S, txd_samples) != UHD_ERROR_NONE) { size_t txd_samples = tx_samples; //< Stores the number of transmitted samples in this packet
print_usrp_error(handler);
return SRSRAN_ERROR; // Skip baseband packet transmission if it is waiting for the enb of burst ACK
if (handler->tx_state != RF_UHD_IMP_TX_STATE_WAIT_EOB_ACK) {
// Actual transmission
if (handler->uhd->send(buffs_ptr, tx_samples, md, RF_UHD_IMP_TRX_TIMEOUT_S, txd_samples) != UHD_ERROR_NONE) {
print_usrp_error(handler);
return SRSRAN_ERROR;
}
// Tx state is now in burst
if (md.start_of_burst) {
handler->tx_state = RF_UHD_IMP_TX_STATE_BURST;
}
} else {
Debug("Tx while waiting for EOB, aborting block... " << md.time_spec.get_real_secs() << " < "
<< handler->eob_ack_timeout.get_real_secs());
} }
// Next packets are not start of burst // Increase the metadata transmit time
is_start_of_burst = false;
md.time_spec += txd_samples / handler->tx_rate; md.time_spec += txd_samples / handler->tx_rate;
// Increase number of transmitted samples
n += txd_samples; n += txd_samples;
} while (n < nsamples); } while (n < nsamples);

@ -32,7 +32,7 @@ pdcp_entity_base::pdcp_entity_base(task_sched_handle task_sched_, srslog::basic_
pdcp_entity_base::~pdcp_entity_base() {} pdcp_entity_base::~pdcp_entity_base() {}
void pdcp_entity_base::config_security(as_security_config_t sec_cfg_) void pdcp_entity_base::config_security(const as_security_config_t& sec_cfg_)
{ {
sec_cfg = sec_cfg_; sec_cfg = sec_cfg_;

@ -148,7 +148,7 @@ void pdcp_entity_nr::write_pdu(unique_byte_buffer_t pdu)
// Extract RCVD_SN from header // Extract RCVD_SN from header
uint32_t rcvd_sn = read_data_header(pdu); uint32_t rcvd_sn = read_data_header(pdu);
discard_data_header(pdu); // FIXME Check wheather the header is part of integrity check. discard_data_header(pdu); // TODO: Check wheather the header is part of integrity check.
// Extract MAC // Extract MAC
uint8_t mac[4]; uint8_t mac[4];

@ -469,7 +469,7 @@ int make_phy_sr_resource_test()
sched_request_res_cfg.periodicity_and_offset_present = true; sched_request_res_cfg.periodicity_and_offset_present = true;
sched_request_res_cfg.periodicity_and_offset.set_sl40(); sched_request_res_cfg.periodicity_and_offset.set_sl40();
sched_request_res_cfg.periodicity_and_offset.sl40() = 8; sched_request_res_cfg.periodicity_and_offset.sl40() = 8;
sched_request_res_cfg.res_present = true; sched_request_res_cfg.res_present = true;
sched_request_res_cfg.res = 16; sched_request_res_cfg.res = 16;
srsran_pucch_nr_sr_resource_t srsran_pucch_nr_sr_resource; srsran_pucch_nr_sr_resource_t srsran_pucch_nr_sr_resource;
@ -551,30 +551,30 @@ int make_phy_pusch_scaling_test()
uci_on_pusch.scaling = uci_on_pusch_s::scaling_opts::f1; uci_on_pusch.scaling = uci_on_pusch_s::scaling_opts::f1;
float scaling; float scaling;
TESTASSERT(make_phy_pusch_scaling(uci_on_pusch, &scaling) == true); TESTASSERT(make_phy_pusch_scaling(uci_on_pusch, &scaling) == true);
TESTASSERT(scaling = 1.0); TESTASSERT(scaling == 1.0);
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
int make_phy_zp_csi_rs_resource_test() int make_phy_zp_csi_rs_resource_test()
{ {
srsran_csi_rs_zp_resource_t zp_csi_rs_resource0 = {}; srsran_csi_rs_zp_resource_t zp_csi_rs_resource0 = {};
// Item 0 // Item 0
// ZP-CSI-RS-Resource // ZP-CSI-RS-Resource
// zp-CSI-RS-ResourceId: 0 // zp-CSI-RS-ResourceId: 0
// resourceMapping // resourceMapping
// frequencyDomainAllocation: row4 (2) // frequencyDomainAllocation: row4 (2)
// row4: 80 [bit length 3, 5 LSB pad bits, 100. .... // row4: 80 [bit length 3, 5 LSB pad bits, 100. ....
// decimal value 4] // decimal value 4]
// nrofPorts: p4 (2) // nrofPorts: p4 (2)
// firstOFDMSymbolInTimeDomain: 8 // firstOFDMSymbolInTimeDomain: 8
// cdm-Type: fd-CDM2 (1) // cdm-Type: fd-CDM2 (1)
// density: one (1) // density: one (1)
// one: NULL // one: NULL
// freqBand // freqBand
// startingRB: 0 // startingRB: 0
// nrofRBs: 52 // nrofRBs: 52
// periodicityAndOffset: slots80 (9) // periodicityAndOffset: slots80 (9)
// slots80: 1 // slots80: 1
asn1::rrc_nr::zp_csi_rs_res_s zp_csi_rs_res0; 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.set_row4();
@ -583,9 +583,9 @@ int make_phy_zp_csi_rs_resource_test()
zp_csi_rs_res0.res_map.first_ofdm_symbol_in_time_domain = 8; 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.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.density.set_one();
zp_csi_rs_res0.res_map.freq_band.start_rb = 0; 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.res_map.freq_band.nrof_rbs = 52;
zp_csi_rs_res0.periodicity_and_offset_present = true; zp_csi_rs_res0.periodicity_and_offset_present = true;
zp_csi_rs_res0.periodicity_and_offset.set_slots80() = 1; 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(make_phy_zp_csi_rs_resource(zp_csi_rs_res0, &zp_csi_rs_resource0) == true);
@ -632,7 +632,7 @@ int make_phy_nzp_csi_rs_resource_test()
nzp_csi_rs_res.nzp_csi_rs_res_id = 0; 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.set_row2();
nzp_csi_rs_res.res_map.freq_domain_alloc.row2().from_string("100000000000"); 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.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.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.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.density.set_one();
@ -644,7 +644,7 @@ int make_phy_nzp_csi_rs_resource_test()
nzp_csi_rs_res.scrambling_id = 0; nzp_csi_rs_res.scrambling_id = 0;
nzp_csi_rs_res.periodicity_and_offset_present = true; nzp_csi_rs_res.periodicity_and_offset_present = true;
nzp_csi_rs_res.periodicity_and_offset.set_slots80() = 1; nzp_csi_rs_res.periodicity_and_offset.set_slots80() = 1;
srsran_csi_rs_nzp_resource_t nzp_resource_0; 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(make_phy_nzp_csi_rs_resource(nzp_csi_rs_res, &nzp_resource_0) == true);

@ -32,13 +32,15 @@ struct rx_thread_tester {
std::thread t; std::thread t;
rx_thread_tester() : rx_thread_tester() :
task_queue(task_sched.make_task_queue()), t([this]() { task_queue(task_sched.make_task_queue()),
t([this]() {
stop_token.store(false); stop_token.store(false);
while (not stop_token.load(std::memory_order_relaxed)) { while (not stop_token.load(std::memory_order_relaxed)) {
task_sched.run_pending_tasks(); task_sched.run_pending_tasks();
std::this_thread::sleep_for(std::chrono::microseconds(100)); std::this_thread::sleep_for(std::chrono::microseconds(100));
} }
}) }),
stop_token(false)
{} {}
~rx_thread_tester() ~rx_thread_tester()
{ {

@ -29,13 +29,14 @@
#include <getopt.h> #include <getopt.h>
static srsran_carrier_nr_t carrier = { static srsran_carrier_nr_t carrier = {
501, // pci 501, // pci
0, // absolute_frequency_ssb 0, // absolute_frequency_ssb
0, // absolute_frequency_point_a 0, // absolute_frequency_point_a
srsran_subcarrier_spacing_15kHz, // scs 0, // offset_to_carrier
52, // nof_prb srsran_subcarrier_spacing_15kHz, // scs
0, // start 52, // nof_prb
1 // max_mimo_layers 0, // start
1 // max_mimo_layers
}; };
static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t n_prb = 0; // Set to 0 for steering
@ -275,7 +276,6 @@ int main(int argc, char** argv)
if (srsran_ue_dl_nr_set_carrier(&ue_dl, &carrier)) { if (srsran_ue_dl_nr_set_carrier(&ue_dl, &carrier)) {
ERROR("Error setting SCH NR carrier"); ERROR("Error setting SCH NR carrier");
goto clean_exit; goto clean_exit;
goto clean_exit;
} }
srsran_dci_cfg_nr_t dci_cfg = {}; srsran_dci_cfg_nr_t dci_cfg = {};

@ -5,15 +5,16 @@
##################################################################### #####################################################################
# eNB configuration # eNB configuration
# #
# enb_id: 20-bit eNB identifier. # enb_id: 20-bit eNB identifier.
# mcc: Mobile Country Code # mcc: Mobile Country Code
# mnc: Mobile Network Code # mnc: Mobile Network Code
# mme_addr: IP address of MME for S1 connnection # mme_addr: IP address of MME for S1 connnection
# gtp_bind_addr: Local IP address to bind for GTP connection # gtp_bind_addr: Local IP address to bind for GTP connection
# s1c_bind_addr: Local IP address to bind for S1AP connection # gtp_advertise_addr: IP address of eNB to advertise for DL GTP-U Traffic
# n_prb: Number of Physical Resource Blocks (6,15,25,50,75,100) # s1c_bind_addr: Local IP address to bind for S1AP connection
# tm: Transmission mode 1-4 (TM1 default) # n_prb: Number of Physical Resource Blocks (6,15,25,50,75,100)
# nof_ports: Number of Tx ports (1 port default, set to 2 for TM2/3/4) # tm: Transmission mode 1-4 (TM1 default)
# nof_ports: Number of Tx ports (1 port default, set to 2 for TM2/3/4)
# #
##################################################################### #####################################################################
[enb] [enb]

@ -43,7 +43,8 @@ class stack_interface_phy_lte;
class prach_worker : srsran::thread class prach_worker : srsran::thread
{ {
public: public:
prach_worker(uint32_t cc_idx_, srslog::basic_logger& logger) : buffer_pool(8), thread("PRACH_WORKER"), logger(logger) prach_worker(uint32_t cc_idx_, srslog::basic_logger& logger) :
buffer_pool(8), thread("PRACH_WORKER"), logger(logger), running(false)
{ {
cc_idx = cc_idx_; cc_idx = cc_idx_;
} }

@ -44,15 +44,23 @@ public:
static constexpr uint32_t PUSCH_CODE = 0, PUCCH_CODE = 1; static constexpr uint32_t PUSCH_CODE = 0, PUCCH_CODE = 1;
static constexpr int PHR_NEG_NOF_PRB = 1; static constexpr int PHR_NEG_NOF_PRB = 1;
explicit tpc(uint32_t cell_nof_prb, float target_snr_dB_ = -1.0, bool phr_handling_flag_ = false) : explicit tpc(uint32_t cell_nof_prb,
float target_pucch_snr_dB_ = -1.0,
float target_pusch_sn_dB_ = -1.0,
bool phr_handling_flag_ = false) :
nof_prb(cell_nof_prb), nof_prb(cell_nof_prb),
target_snr_dB(target_snr_dB_), target_pucch_snr_dB(target_pucch_snr_dB_),
snr_estim_list({ul_ch_snr_estim{target_snr_dB_}, ul_ch_snr_estim{target_snr_dB_}}), target_pusch_snr_dB(target_pusch_sn_dB_),
snr_estim_list({ul_ch_snr_estim{target_pusch_snr_dB}, ul_ch_snr_estim{target_pucch_snr_dB}}),
phr_handling_flag(phr_handling_flag_) phr_handling_flag(phr_handling_flag_)
{ {
max_prbs_cached = nof_prb; max_prbs_cached = nof_prb;
} }
void set_cfg(float target_snr_dB_) { target_snr_dB = target_snr_dB_; } void set_cfg(float target_pusch_snr_dB_, float target_pucch_snr_dB_)
{
target_pucch_snr_dB = target_pucch_snr_dB_;
target_pusch_snr_dB = target_pusch_snr_dB_;
}
void set_snr(float snr, uint32_t ul_ch_code) void set_snr(float snr, uint32_t ul_ch_code)
{ {
@ -81,7 +89,9 @@ public:
void new_tti() void new_tti()
{ {
for (auto& ch_snr : snr_estim_list) { for (size_t chidx = 0; chidx < 2; ++chidx) {
float target_snr_dB = chidx == PUSCH_CODE ? target_pusch_snr_dB : target_pucch_snr_dB;
auto& ch_snr = snr_estim_list[chidx];
if (target_snr_dB < 0) { if (target_snr_dB < 0) {
ch_snr.pending_delta = 0; ch_snr.pending_delta = 0;
continue; continue;
@ -139,7 +149,8 @@ private:
} }
uint8_t enconde_tpc(uint32_t cc) uint8_t enconde_tpc(uint32_t cc)
{ {
auto& ch_snr = snr_estim_list[cc]; float target_snr_dB = cc == PUSCH_CODE ? target_pusch_snr_dB : target_pucch_snr_dB;
auto& ch_snr = snr_estim_list[cc];
assert(ch_snr.pending_delta == 0); // ensure called once per {cc,tti} assert(ch_snr.pending_delta == 0); // ensure called once per {cc,tti}
if (target_snr_dB < 0) { if (target_snr_dB < 0) {
// undefined target SINR case. Increase Tx power once per PHR, considering the number of allocable PRBs remains // undefined target SINR case. Increase Tx power once per PHR, considering the number of allocable PRBs remains
@ -167,7 +178,7 @@ private:
} }
uint32_t nof_prb; uint32_t nof_prb;
float target_snr_dB; float target_pucch_snr_dB, target_pusch_snr_dB;
bool phr_handling_flag; bool phr_handling_flag;
// PHR-related variables // PHR-related variables

@ -124,9 +124,9 @@ private:
std::map<uint32_t, user_interface> users; std::map<uint32_t, user_interface> users;
rlc_interface_pdcp* rlc; rlc_interface_pdcp* rlc = nullptr;
rrc_interface_pdcp* rrc; rrc_interface_pdcp* rrc = nullptr;
gtpu_interface_pdcp* gtpu; gtpu_interface_pdcp* gtpu = nullptr;
srsran::task_sched_handle task_sched; srsran::task_sched_handle task_sched;
srslog::basic_logger& logger; srslog::basic_logger& logger;
}; };

@ -48,7 +48,7 @@ class rlc : public rlc_interface_mac, public rlc_interface_rrc, public rlc_inter
public: public:
explicit rlc(srslog::basic_logger& logger) : logger(logger) {} explicit rlc(srslog::basic_logger& logger) : logger(logger) {}
void void
init(pdcp_interface_rlc* pdcp_, rrc_interface_rlc* rrc_, mac_interface_rlc* mac_, srsran::timer_handler* timers_); init(pdcp_interface_rlc* pdcp_, rrc_interface_rlc* rrc_, mac_interface_rlc* mac_, srsran::timer_handler* timers_);
void stop(); void stop();
void get_metrics(rlc_metrics_t& m, const uint32_t nof_tti); void get_metrics(rlc_metrics_t& m, const uint32_t nof_tti);
@ -104,11 +104,11 @@ private:
std::map<uint32_t, user_interface> users; std::map<uint32_t, user_interface> users;
std::vector<mch_service_t> mch_services; std::vector<mch_service_t> mch_services;
mac_interface_rlc* mac; mac_interface_rlc* mac = nullptr;
pdcp_interface_rlc* pdcp; pdcp_interface_rlc* pdcp = nullptr;
rrc_interface_rlc* rrc; rrc_interface_rlc* rrc = nullptr;
srslog::basic_logger& logger; srslog::basic_logger& logger;
srsran::timer_handler* timers; srsran::timer_handler* timers = nullptr;
}; };
} // namespace srsenb } // namespace srsenb

@ -288,7 +288,7 @@ private:
srsran::unique_timer ts1_reloc_overall; ///< TS1_{RELOCOverall} srsran::unique_timer ts1_reloc_overall; ///< TS1_{RELOCOverall}
// Procedure state // Procedure state
s1ap_proc_id_t current_state; s1ap_proc_id_t current_state = s1ap_proc_id_t::nulltype;
erab_id_list updated_erabs; erab_id_list updated_erabs;
srsran::bounded_vector<asn1::s1ap::erab_item_s, ASN1_S1AP_MAXNOOF_ERABS> failed_cfg_erabs; srsran::bounded_vector<asn1::s1ap::erab_item_s, ASN1_S1AP_MAXNOOF_ERABS> failed_cfg_erabs;

@ -62,7 +62,9 @@ cell_list =
//ul_earfcn = 21400; //ul_earfcn = 21400;
ho_active = false; ho_active = false;
//meas_gap_period = 0; // 0 (inactive), 40 or 80 //meas_gap_period = 0; // 0 (inactive), 40 or 80
//allowed_meas_bw = 6; // target_pusch_sinr = -1;
// target_pucch_sinr = -1;
// allowed_meas_bw = 6;
// CA cells // CA cells
scell_list = ( scell_list = (

@ -758,7 +758,8 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
cell_cfg.root_seq_idx, cellroot, "root_seq_idx", rrc_cfg->sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx); cell_cfg.root_seq_idx, cellroot, "root_seq_idx", rrc_cfg->sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx);
parse_default_field(cell_cfg.initial_dl_cqi, cellroot, "initial_dl_cqi", 5u); parse_default_field(cell_cfg.initial_dl_cqi, cellroot, "initial_dl_cqi", 5u);
parse_default_field(cell_cfg.meas_cfg.meas_gap_period, cellroot, "meas_gap_period", 0u); parse_default_field(cell_cfg.meas_cfg.meas_gap_period, cellroot, "meas_gap_period", 0u);
HANDLEPARSERCODE(parse_default_field(cell_cfg.target_ul_sinr_db, cellroot, "target_ul_sinr", -1)); HANDLEPARSERCODE(parse_default_field(cell_cfg.target_pusch_sinr_db, cellroot, "target_pusch_sinr", -1));
HANDLEPARSERCODE(parse_default_field(cell_cfg.target_pucch_sinr_db, cellroot, "target_pucch_sinr", -1));
HANDLEPARSERCODE(parse_default_field(cell_cfg.enable_phr_handling, cellroot, "enable_phr_handling", false)); HANDLEPARSERCODE(parse_default_field(cell_cfg.enable_phr_handling, cellroot, "enable_phr_handling", false));
parse_default_field(cell_cfg.meas_cfg.allowed_meas_bw, cellroot, "allowed_meas_bw", 6u); parse_default_field(cell_cfg.meas_cfg.allowed_meas_bw, cellroot, "allowed_meas_bw", 6u);
srsran_assert(srsran::is_lte_cell_nof_prb(cell_cfg.meas_cfg.allowed_meas_bw), "Invalid measurement Bandwidth"); srsran_assert(srsran::is_lte_cell_nof_prb(cell_cfg.meas_cfg.allowed_meas_bw), "Invalid measurement Bandwidth");

@ -73,18 +73,19 @@ void parse_args(all_args_t* args, int argc, char* argv[])
bpo::options_description common("Configuration options"); bpo::options_description common("Configuration options");
common.add_options() common.add_options()
("enb.stack", bpo::value<string>(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]") ("enb.stack", bpo::value<string>(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]")
("enb.enb_id", bpo::value<string>(&enb_id)->default_value("0x0"), "eNodeB ID") ("enb.enb_id", bpo::value<string>(&enb_id)->default_value("0x0"), "eNodeB ID")
("enb.name", bpo::value<string>(&args->stack.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name") ("enb.name", bpo::value<string>(&args->stack.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name")
("enb.mcc", bpo::value<string>(&mcc)->default_value("001"), "Mobile Country Code") ("enb.mcc", bpo::value<string>(&mcc)->default_value("001"), "Mobile Country Code")
("enb.mnc", bpo::value<string>(&mnc)->default_value("01"), "Mobile Network Code") ("enb.mnc", bpo::value<string>(&mnc)->default_value("01"), "Mobile Network Code")
("enb.mme_addr", bpo::value<string>(&args->stack.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connection") ("enb.mme_addr", bpo::value<string>(&args->stack.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connection")
("enb.gtp_bind_addr", bpo::value<string>(&args->stack.s1ap.gtp_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for GTP connection") ("enb.gtp_bind_addr", bpo::value<string>(&args->stack.s1ap.gtp_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for GTP connection")
("enb.s1c_bind_addr", bpo::value<string>(&args->stack.s1ap.s1c_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for S1AP connection") ("enb.gtp_advertise_addr", bpo::value<string>(&args->stack.s1ap.gtp_advertise_addr)->default_value(""), "IP address of eNB to advertise for DL GTP-U Traffic")
("enb.n_prb", bpo::value<uint32_t>(&args->enb.n_prb)->default_value(25), "Number of PRB") ("enb.s1c_bind_addr", bpo::value<string>(&args->stack.s1ap.s1c_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for S1AP connection")
("enb.nof_ports", bpo::value<uint32_t>(&args->enb.nof_ports)->default_value(1), "Number of ports") ("enb.n_prb", bpo::value<uint32_t>(&args->enb.n_prb)->default_value(25), "Number of PRB")
("enb.tm", bpo::value<uint32_t>(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)") ("enb.nof_ports", bpo::value<uint32_t>(&args->enb.nof_ports)->default_value(1), "Number of ports")
("enb.p_a", bpo::value<float>(&args->enb.p_a)->default_value(0.0f), "Power allocation rho_a (-6, -4.77, -3, -1.77, 0, 1, 2, 3)") ("enb.tm", bpo::value<uint32_t>(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)")
("enb.p_a", bpo::value<float>(&args->enb.p_a)->default_value(0.0f), "Power allocation rho_a (-6, -4.77, -3, -1.77, 0, 1, 2, 3)")
("enb_files.sib_config", bpo::value<string>(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files") ("enb_files.sib_config", bpo::value<string>(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files")
("enb_files.rr_config", bpo::value<string>(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files") ("enb_files.rr_config", bpo::value<string>(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files")

@ -139,8 +139,12 @@ int phy::init(const phy_args_t& args,
parse_common_config(cfg); parse_common_config(cfg);
// Add workers to workers pool and start threads // Add workers to workers pool and start threads
lte_workers.init(args, &workers_common, log_sink, WORKERS_THREAD_PRIO); if (not cfg.phy_cell_cfg.empty()) {
nr_workers.init(args, &workers_common, log_sink, WORKERS_THREAD_PRIO); lte_workers.init(args, &workers_common, log_sink, WORKERS_THREAD_PRIO);
}
if (not cfg.phy_cell_cfg_nr.empty()) {
nr_workers.init(args, &workers_common, log_sink, WORKERS_THREAD_PRIO);
}
// For each carrier, initialise PRACH worker // For each carrier, initialise PRACH worker
for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) { for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) {

@ -43,7 +43,7 @@ using namespace std;
namespace srsenb { namespace srsenb {
txrx::txrx(srslog::basic_logger& logger) : thread("TXRX"), logger(logger) txrx::txrx(srslog::basic_logger& logger) : thread("TXRX"), logger(logger), running(false)
{ {
/* Do nothing */ /* Do nothing */
} }

@ -36,7 +36,10 @@ sched_ue_cell::sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg
cell_cfg(&cell_cfg_), cell_cfg(&cell_cfg_),
dci_locations(generate_cce_location_table(rnti_, cell_cfg_)), dci_locations(generate_cce_location_table(rnti_, cell_cfg_)),
harq_ent(SCHED_MAX_HARQ_PROC, SCHED_MAX_HARQ_PROC), harq_ent(SCHED_MAX_HARQ_PROC, SCHED_MAX_HARQ_PROC),
tpc_fsm(cell_cfg->nof_prb(), cell_cfg->cfg.target_ul_sinr, cell_cfg->cfg.enable_phr_handling), tpc_fsm(cell_cfg->nof_prb(),
cell_cfg->cfg.target_pucch_ul_sinr,
cell_cfg->cfg.target_pusch_ul_sinr,
cell_cfg->cfg.enable_phr_handling),
fixed_mcs_dl(cell_cfg_.sched_cfg->pdsch_mcs), fixed_mcs_dl(cell_cfg_.sched_cfg->pdsch_mcs),
fixed_mcs_ul(cell_cfg_.sched_cfg->pusch_mcs), fixed_mcs_ul(cell_cfg_.sched_cfg->pusch_mcs),
current_tti(current_tti_), current_tti(current_tti_),

@ -733,16 +733,17 @@ void rrc::config_mac()
item.si_window_ms = cfg.sib1.si_win_len.to_number(); item.si_window_ms = cfg.sib1.si_win_len.to_number();
item.prach_rar_window = item.prach_rar_window =
cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.ra_supervision_info.ra_resp_win_size.to_number(); cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.ra_supervision_info.ra_resp_win_size.to_number();
item.prach_freq_offset = cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset; item.prach_freq_offset = cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.prach_cfg_info.prach_freq_offset;
item.maxharq_msg3tx = cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.max_harq_msg3_tx; item.maxharq_msg3tx = cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.max_harq_msg3_tx;
item.enable_64qam = cfg.sibs[1].sib2().rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam; item.enable_64qam = cfg.sibs[1].sib2().rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam;
item.initial_dl_cqi = cfg.cell_list[ccidx].initial_dl_cqi; item.initial_dl_cqi = cfg.cell_list[ccidx].initial_dl_cqi;
item.target_ul_sinr = cfg.cell_list[ccidx].target_ul_sinr_db; item.target_pucch_ul_sinr = cfg.cell_list[ccidx].target_pucch_sinr_db;
item.enable_phr_handling = cfg.cell_list[ccidx].enable_phr_handling; item.target_pusch_ul_sinr = cfg.cell_list[ccidx].target_pusch_sinr_db;
item.delta_pucch_shift = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.delta_pucch_shift.to_number(); item.enable_phr_handling = cfg.cell_list[ccidx].enable_phr_handling;
item.ncs_an = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.ncs_an; item.delta_pucch_shift = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.delta_pucch_shift.to_number();
item.n1pucch_an = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.n1_pucch_an; item.ncs_an = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.ncs_an;
item.nrb_cqi = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.nrb_cqi; item.n1pucch_an = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.n1_pucch_an;
item.nrb_cqi = cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.nrb_cqi;
item.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb); item.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, cfg.cqi_cfg.nof_prb);
logger.info("Allocating %d PRBs for PUCCH", item.nrb_pucch); logger.info("Allocating %d PRBs for PUCCH", item.nrb_pucch);

@ -45,7 +45,7 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_,
gtpu = gtpu_; gtpu = gtpu_;
ngap = ngap_; ngap = ngap_;
// FIXME: overwriting because we are not passing config right now // TODO: overwriting because we are not passing config right now
cfg = update_default_cfg(cfg_); cfg = update_default_cfg(cfg_);
// config logging // config logging
@ -167,7 +167,7 @@ rrc_nr_cfg_t rrc_nr::update_default_cfg(const rrc_nr_cfg_t& current)
cfg_default.nof_sibs = 1; cfg_default.nof_sibs = 1;
sib2_s& sib2 = cfg_default.sibs[0].set_sib2(); sib2_s& sib2 = cfg_default.sibs[0].set_sib2();
sib2.cell_resel_info_common.q_hyst.value = sib2_s::cell_resel_info_common_s_::q_hyst_opts::db5; sib2.cell_resel_info_common.q_hyst.value = sib2_s::cell_resel_info_common_s_::q_hyst_opts::db5;
// FIXME: Fill SIB2 values // TODO: Fill SIB2 values
// set loglevel // set loglevel
cfg_default.log_level = "debug"; cfg_default.log_level = "debug";

@ -395,8 +395,10 @@ void rrc::ue::handle_rrc_con_req(rrc_conn_request_s* msg)
for (auto& user : parent->users) { for (auto& user : parent->users) {
if (user.first != rnti && user.second->has_tmsi && user.second->mmec == mmec && user.second->m_tmsi == m_tmsi) { if (user.first != rnti && user.second->has_tmsi && user.second->mmec == mmec && user.second->m_tmsi == m_tmsi) {
parent->logger.info("RRC connection request: UE context already exists. M-TMSI=%d", m_tmsi); parent->logger.info("RRC connection request: UE context already exists. M-TMSI=%d", m_tmsi);
parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::radio_conn_with_ue_lost); if (parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::radio_conn_with_ue_lost)) {
parent->rem_user_thread(user.first); // Do not wait for MME response
parent->rem_user_thread(user.first);
}
break; break;
} }
} }

@ -768,8 +768,7 @@ bool gtpu::send_end_marker(uint32_t teidin)
servaddr.sin_addr.s_addr = htonl(tx_tun->spgw_addr); servaddr.sin_addr.s_addr = htonl(tx_tun->spgw_addr);
servaddr.sin_port = htons(GTPU_PORT); servaddr.sin_port = htons(GTPU_PORT);
sendto(fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in)); return sendto(fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in)) > 0;
return true;
} }
/**************************************************************************** /****************************************************************************

@ -427,7 +427,7 @@ bool s1ap::user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_r
return false; return false;
} }
if (u->was_uectxtrelease_requested()) { if (u->was_uectxtrelease_requested() or not u->ctxt.mme_ue_s1ap_id.has_value()) {
logger.warning("UE context for RNTI:0x%x is in zombie state. Releasing...", rnti); logger.warning("UE context for RNTI:0x%x is in zombie state. Releasing...", rnti);
users.erase(u); users.erase(u);
rrc->release_ue(rnti); rrc->release_ue(rnti);
@ -437,10 +437,7 @@ bool s1ap::user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_r
cause_c cause; cause_c cause;
cause.set_radio_network().value = cause_radio.value; cause.set_radio_network().value = cause_radio.value;
if (u->ctxt.mme_ue_s1ap_id.has_value()) { return u->send_uectxtreleaserequest(cause);
return u->send_uectxtreleaserequest(cause);
}
return true;
} }
bool s1ap::user_exists(uint16_t rnti) bool s1ap::user_exists(uint16_t rnti)
@ -1172,7 +1169,11 @@ bool s1ap::send_ho_req_ack(const asn1::s1ap::ho_request_s& msg,
tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_HO_RES_ALLOC); tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_HO_RES_ALLOC);
ho_request_ack_ies_container& container = tx_pdu.successful_outcome().value.ho_request_ack().protocol_ies; ho_request_ack_ies_container& container = tx_pdu.successful_outcome().value.ho_request_ack().protocol_ies;
ue* ue_ptr = users.find_ue_mmeid(msg.protocol_ies.mme_ue_s1ap_id.value.value); ue* ue_ptr = users.find_ue_mmeid(msg.protocol_ies.mme_ue_s1ap_id.value.value);
if (ue_ptr == nullptr) {
logger.error("The MME-S1AP-UE-ID=%ld is not valid", msg.protocol_ies.mme_ue_s1ap_id.value.value);
return false;
}
ue_ptr->ctxt.rnti = rnti; ue_ptr->ctxt.rnti = rnti;
ue_ptr->ctxt.enb_cc_idx = enb_cc_idx; ue_ptr->ctxt.enb_cc_idx = enb_cc_idx;
@ -1183,9 +1184,13 @@ bool s1ap::send_ho_req_ack(const asn1::s1ap::ho_request_s& msg,
container.erab_admitted_list.value.resize(admitted_bearers.size()); container.erab_admitted_list.value.resize(admitted_bearers.size());
for (size_t i = 0; i < admitted_bearers.size(); ++i) { for (size_t i = 0; i < admitted_bearers.size(); ++i) {
container.erab_admitted_list.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_ADMITTED_ITEM); container.erab_admitted_list.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_ADMITTED_ITEM);
auto& c = container.erab_admitted_list.value[i].value.erab_admitted_item(); auto& c = container.erab_admitted_list.value[i].value.erab_admitted_item();
c = admitted_bearers[i]; c = admitted_bearers[i];
c.transport_layer_address = addr_to_asn1(args.gtp_bind_addr.c_str()); if (!args.gtp_advertise_addr.empty()) {
c.transport_layer_address = addr_to_asn1(args.gtp_advertise_addr.c_str());
} else {
c.transport_layer_address = addr_to_asn1(args.gtp_bind_addr.c_str());
}
// If E-RAB is proposed for forward tunneling // If E-RAB is proposed for forward tunneling
if (c.dl_g_tp_teid_present) { if (c.dl_g_tp_teid_present) {
@ -1678,7 +1683,11 @@ void s1ap::ue::get_erab_addr(uint16_t erab_id, transp_addr_t& transp_addr, asn1:
// Note: RRC does not yet update correctly gtpu transp_addr // Note: RRC does not yet update correctly gtpu transp_addr
transp_addr.resize(32); transp_addr.resize(32);
uint8_t addr[4]; uint8_t addr[4];
inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr); if (!s1ap_ptr->args.gtp_advertise_addr.empty()) {
inet_pton(AF_INET, s1ap_ptr->args.gtp_advertise_addr.c_str(), addr);
} else {
inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr);
}
for (uint32_t j = 0; j < 4; ++j) { for (uint32_t j = 0; j < 4; ++j) {
transp_addr.data()[j] = addr[3 - j]; transp_addr.data()[j] = addr[3 - j];
} }

@ -280,7 +280,8 @@ sched_sim_events rand_sim_params(uint32_t nof_ttis)
sched_sim_event_generator generator; sched_sim_event_generator generator;
sim_gen.sim_args.cell_cfg = {generate_default_cell_cfg(nof_prb)}; sim_gen.sim_args.cell_cfg = {generate_default_cell_cfg(nof_prb)};
sim_gen.sim_args.cell_cfg[0].target_ul_sinr = pick_random_uniform({10, 15, 20, -1}); sim_gen.sim_args.cell_cfg[0].target_pucch_ul_sinr = pick_random_uniform({10, 15, 20, -1});
sim_gen.sim_args.cell_cfg[0].target_pusch_ul_sinr = pick_random_uniform({10, 15, 20, -1});
sim_gen.sim_args.cell_cfg[0].enable_phr_handling = false; sim_gen.sim_args.cell_cfg[0].enable_phr_handling = false;
sim_gen.sim_args.default_ue_sim_cfg.ue_cfg = generate_default_ue_cfg(); sim_gen.sim_args.default_ue_sim_cfg.ue_cfg = generate_default_ue_cfg();
sim_gen.sim_args.default_ue_sim_cfg.periodic_cqi = true; sim_gen.sim_args.default_ue_sim_cfg.periodic_cqi = true;

@ -49,21 +49,22 @@ inline srsenb::sched_interface::cell_cfg_t generate_default_cell_cfg(uint32_t no
cell_cfg_phy.phich_length = SRSRAN_PHICH_NORM; cell_cfg_phy.phich_length = SRSRAN_PHICH_NORM;
cell_cfg_phy.phich_resources = SRSRAN_PHICH_R_1; cell_cfg_phy.phich_resources = SRSRAN_PHICH_R_1;
cell_cfg.sibs[0].len = 18; cell_cfg.sibs[0].len = 18;
cell_cfg.sibs[0].period_rf = 8; cell_cfg.sibs[0].period_rf = 8;
cell_cfg.sibs[1].len = 41; cell_cfg.sibs[1].len = 41;
cell_cfg.sibs[1].period_rf = 16; cell_cfg.sibs[1].period_rf = 16;
cell_cfg.si_window_ms = 40; cell_cfg.si_window_ms = 40;
cell_cfg.nrb_pucch = (cell_cfg_phy.nof_prb == 6) ? 1 : 2; cell_cfg.nrb_pucch = (cell_cfg_phy.nof_prb == 6) ? 1 : 2;
cell_cfg.prach_freq_offset = (cell_cfg_phy.nof_prb == 6) ? 0 : 4; cell_cfg.prach_freq_offset = (cell_cfg_phy.nof_prb == 6) ? 0 : 4;
cell_cfg.prach_rar_window = 3; cell_cfg.prach_rar_window = 3;
cell_cfg.maxharq_msg3tx = 3; cell_cfg.maxharq_msg3tx = 3;
cell_cfg.initial_dl_cqi = 6; cell_cfg.initial_dl_cqi = 6;
cell_cfg.target_ul_sinr = -1; cell_cfg.target_pusch_ul_sinr = -1;
cell_cfg.nrb_cqi = 1; cell_cfg.target_pucch_ul_sinr = -1;
cell_cfg.n1pucch_an = 12; cell_cfg.nrb_cqi = 1;
cell_cfg.delta_pucch_shift = 1; cell_cfg.n1pucch_an = 12;
cell_cfg.ncs_an = 0; cell_cfg.delta_pucch_shift = 1;
cell_cfg.ncs_an = 0;
return cell_cfg; return cell_cfg;
} }

@ -35,7 +35,7 @@ int test_finite_target_snr()
const uint32_t nof_prbs = 50; const uint32_t nof_prbs = 50;
const int target_snr = 15; const int target_snr = 15;
tpc tpcfsm(nof_prbs, 15, true); tpc tpcfsm(nof_prbs, 15, 15, true);
// TEST: While no SNR info is provided, no TPC commands are sent // TEST: While no SNR info is provided, no TPC commands are sent
for (uint32_t i = 0; i < 100; ++i) { for (uint32_t i = 0; i < 100; ++i) {
@ -82,7 +82,7 @@ int test_undefined_target_snr()
{ {
const uint32_t nof_prbs = 50; const uint32_t nof_prbs = 50;
tpc tpcfsm(nof_prbs, -1, true); tpc tpcfsm(nof_prbs, -1, -1, true);
TESTASSERT(tpcfsm.max_ul_prbs() == 50); TESTASSERT(tpcfsm.max_ul_prbs() == 50);
// TEST: While the PHR is not updated, a limited number of TPC commands should be sent // TEST: While the PHR is not updated, a limited number of TPC commands should be sent

@ -1180,8 +1180,8 @@ public:
private: private:
// Test constants // Test constants
static const uint32_t delta_pucch = 2; static const uint32_t delta_pucch = 1;
static const uint32_t N_pucch_1 = 2; static const uint32_t N_pucch_1 = 12;
// Private classes // Private classes
unique_dummy_radio_t radio; unique_dummy_radio_t radio;

@ -14,9 +14,9 @@
# mme_bind_addr: IP bind addr to listen for eNB S1-MME connnections # mme_bind_addr: IP bind addr to listen for eNB S1-MME connnections
# dns_addr: DNS server address for the UEs # dns_addr: DNS server address for the UEs
# encryption_algo: Preferred encryption algorithm for NAS layer # encryption_algo: Preferred encryption algorithm for NAS layer
# (default: EEA0, support: EEA1, EEA2) # (supported: EEA0 (default), EEA1, EEA2, EEA3)
# integrity_algo: Preferred integrity protection algorithm for NAS # integrity_algo: Preferred integrity protection algorithm for NAS
# (default: EIA1, support: EIA1, EIA2 (EIA0 not support) # (supported: EIA0 (rejected by most UEs), EIA1 (default), EIA2, EIA3
# paging_timer: Value of paging timer in seconds (T3413) # paging_timer: Value of paging timer in seconds (T3413)
# #
##################################################################### #####################################################################

@ -137,6 +137,8 @@ typedef struct {
uint16_t paging_timer; uint16_t paging_timer;
std::string apn; std::string apn;
std::string dns; std::string dns;
std::string full_net_name;
std::string short_net_name;
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
} nas_init_t; } nas_init_t;
@ -273,6 +275,8 @@ private:
uint16_t m_tac = 0; uint16_t m_tac = 0;
std::string m_apn; std::string m_apn;
std::string m_dns; std::string m_dns;
std::string m_full_net_name;
std::string m_short_net_name;
// Timers timeout values // Timers timeout values
uint16_t m_t3413 = 0; uint16_t m_t3413 = 0;

@ -44,6 +44,8 @@ typedef struct {
std::string mme_bind_addr; std::string mme_bind_addr;
std::string mme_name; std::string mme_name;
std::string dns_addr; std::string dns_addr;
std::string full_net_name;
std::string short_net_name;
std::string mme_apn; std::string mme_apn;
bool pcap_enable; bool pcap_enable;
std::string pcap_filename; std::string pcap_filename;

@ -87,6 +87,8 @@ void parse_args(all_args_t* args, int argc, char* argv[])
string sgi_if_addr; string sgi_if_addr;
string sgi_if_name; string sgi_if_name;
string dns_addr; string dns_addr;
string full_net_name;
string short_net_name;
string hss_db_file; string hss_db_file;
string hss_auth_algo; string hss_auth_algo;
string log_filename; string log_filename;
@ -110,6 +112,8 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("mme.mnc", bpo::value<string>(&mnc)->default_value("01"), "Mobile Network Code") ("mme.mnc", bpo::value<string>(&mnc)->default_value("01"), "Mobile Network Code")
("mme.mme_bind_addr", bpo::value<string>(&mme_bind_addr)->default_value("127.0.0.1"), "IP address of MME for S1 connection") ("mme.mme_bind_addr", bpo::value<string>(&mme_bind_addr)->default_value("127.0.0.1"), "IP address of MME for S1 connection")
("mme.dns_addr", bpo::value<string>(&dns_addr)->default_value("8.8.8.8"), "IP address of the DNS server for the UEs") ("mme.dns_addr", bpo::value<string>(&dns_addr)->default_value("8.8.8.8"), "IP address of the DNS server for the UEs")
("mme.full_net_name", bpo::value<string>(&full_net_name)->default_value("Software Radio Systems RAN"), "Full name of the network")
("mme.short_net_name", bpo::value<string>(&short_net_name)->default_value("srsRAN"), "Short name of the network")
("mme.apn", bpo::value<string>(&mme_apn)->default_value(""), "Set Access Point Name (APN) for data services") ("mme.apn", bpo::value<string>(&mme_apn)->default_value(""), "Set Access Point Name (APN) for data services")
("mme.encryption_algo", bpo::value<string>(&encryption_algo)->default_value("EEA0"), "Set preferred encryption algorithm for NAS layer ") ("mme.encryption_algo", bpo::value<string>(&encryption_algo)->default_value("EEA0"), "Set preferred encryption algorithm for NAS layer ")
("mme.integrity_algo", bpo::value<string>(&integrity_algo)->default_value("EIA1"), "Set preferred integrity protection algorithm for NAS") ("mme.integrity_algo", bpo::value<string>(&integrity_algo)->default_value("EIA1"), "Set preferred integrity protection algorithm for NAS")
@ -269,6 +273,8 @@ void parse_args(all_args_t* args, int argc, char* argv[])
args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr;
args->mme_args.s1ap_args.mme_name = mme_name; args->mme_args.s1ap_args.mme_name = mme_name;
args->mme_args.s1ap_args.dns_addr = dns_addr; args->mme_args.s1ap_args.dns_addr = dns_addr;
args->mme_args.s1ap_args.full_net_name = full_net_name;
args->mme_args.s1ap_args.short_net_name = short_net_name;
args->mme_args.s1ap_args.mme_apn = mme_apn; args->mme_args.s1ap_args.mme_apn = mme_apn;
args->mme_args.s1ap_args.paging_timer = paging_timer; args->mme_args.s1ap_args.paging_timer = paging_timer;
args->spgw_args.gtpu_bind_addr = spgw_bind_addr; args->spgw_args.gtpu_bind_addr = spgw_bind_addr;

@ -43,6 +43,8 @@ nas::nas(const nas_init_t& args, const nas_if_t& itf) :
m_tac(args.tac), m_tac(args.tac),
m_apn(args.apn), m_apn(args.apn),
m_dns(args.dns), m_dns(args.dns),
m_full_net_name(args.full_net_name),
m_short_net_name(args.short_net_name),
m_t3413(args.paging_timer) m_t3413(args.paging_timer)
{ {
m_sec_ctx.integ_algo = args.integ_algo; m_sec_ctx.integ_algo = args.integ_algo;
@ -1573,10 +1575,10 @@ bool nas::pack_emm_information(srsran::byte_buffer_t* nas_buffer)
LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info;
emm_info.full_net_name_present = true; emm_info.full_net_name_present = true;
strncpy(emm_info.full_net_name.name, "Software Radio Systems LTE", LIBLTE_STRING_LEN); memccpy(emm_info.full_net_name.name, m_full_net_name.c_str(), 0, LIBLTE_STRING_LEN);
emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD;
emm_info.short_net_name_present = true; emm_info.short_net_name_present = true;
strncpy(emm_info.short_net_name.name, "srsRAN", LIBLTE_STRING_LEN); memccpy(emm_info.short_net_name.name, m_short_net_name.c_str(), 0, LIBLTE_STRING_LEN);
emm_info.short_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; emm_info.short_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD;
emm_info.local_time_zone_present = false; emm_info.local_time_zone_present = false;

@ -75,6 +75,8 @@ void s1ap_nas_transport::init()
m_nas_init.tac = m_s1ap->m_s1ap_args.tac; m_nas_init.tac = m_s1ap->m_s1ap_args.tac;
m_nas_init.apn = m_s1ap->m_s1ap_args.mme_apn; m_nas_init.apn = m_s1ap->m_s1ap_args.mme_apn;
m_nas_init.dns = m_s1ap->m_s1ap_args.dns_addr; m_nas_init.dns = m_s1ap->m_s1ap_args.dns_addr;
m_nas_init.full_net_name = m_s1ap->m_s1ap_args.full_net_name;
m_nas_init.short_net_name = m_s1ap->m_s1ap_args.short_net_name;
m_nas_init.paging_timer = m_s1ap->m_s1ap_args.paging_timer; m_nas_init.paging_timer = m_s1ap->m_s1ap_args.paging_timer;
m_nas_init.integ_algo = m_s1ap->m_s1ap_args.integrity_algo; m_nas_init.integ_algo = m_s1ap->m_s1ap_args.integrity_algo;
m_nas_init.cipher_algo = m_s1ap->m_s1ap_args.encryption_algo; m_nas_init.cipher_algo = m_s1ap->m_s1ap_args.encryption_algo;

@ -244,7 +244,7 @@ void spgw::gtpu::handle_sgi_pdu(srsran::unique_byte_buffer_t msg)
m_gtpc->send_downlink_data_notification(spgw_teid); m_gtpc->send_downlink_data_notification(spgw_teid);
m_gtpc->queue_downlink_packet(spgw_teid, std::move(msg)); m_gtpc->queue_downlink_packet(spgw_teid, std::move(msg));
return; return;
} else if (usr_found == false && ctr_found == true) { } else if (usr_found == true && ctr_found == false) {
m_logger.error("User plane tunnel found without a control plane tunnel present."); m_logger.error("User plane tunnel found without a control plane tunnel present.");
} else { } else {
send_s1u_pdu(enb_fteid, msg.get()); send_s1u_pdu(enb_fteid, msg.get());

@ -51,13 +51,13 @@ public:
void stop(); void stop();
private: private:
void set_metrics_helper(const srsran::rf_metrics_t rf, void set_metrics_helper(const srsran::rf_metrics_t& rf,
const srsran::sys_metrics_t sys, const srsran::sys_metrics_t& sys,
const phy_metrics_t phy, const phy_metrics_t& phy,
const mac_metrics_t mac[SRSRAN_MAX_CARRIERS], const mac_metrics_t mac[SRSRAN_MAX_CARRIERS],
const rrc_metrics_t rrc, const rrc_metrics_t& rrc,
const uint32_t cc, const uint32_t cc,
const uint32_t r); const uint32_t r);
std::string float_to_string(float f, int digits, bool add_semicolon = true); std::string float_to_string(float f, int digits, bool add_semicolon = true);

@ -48,11 +48,11 @@ public:
private: private:
static const bool FORCE_NEIGHBOUR_CELL = false; // Set to true for printing always neighbour cells static const bool FORCE_NEIGHBOUR_CELL = false; // Set to true for printing always neighbour cells
void set_metrics_helper(const phy_metrics_t phy, void set_metrics_helper(const phy_metrics_t& phy,
const mac_metrics_t mac[SRSRAN_MAX_CARRIERS], const mac_metrics_t mac[SRSRAN_MAX_CARRIERS],
const rrc_metrics_t rrc, const rrc_metrics_t& rrc,
bool display_neighbours, bool display_neighbours,
const uint32_t r); const uint32_t r);
std::string float_to_string(float f, int digits); std::string float_to_string(float f, int digits);
std::string float_to_eng_string(float f, int digits); std::string float_to_eng_string(float f, int digits);
void print_table(const bool display_neighbours); void print_table(const bool display_neighbours);

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save