Add minimum NR SA logic in parent PHY class

master
Ismael Gomez 3 years ago
parent fb897d2998
commit 6947f87bcb

@ -58,14 +58,6 @@ struct rf_args_t {
std::array<rf_args_band_t, SRSRAN_MAX_CARRIERS> ch_tx_bands;
};
struct vnf_args_t {
std::string type;
std::string bind_addr;
uint16_t bind_port;
std::string log_level;
int log_hex_limit;
};
class srsran_gw_config_t
{
public:
@ -80,8 +72,6 @@ public:
virtual uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) = 0;
};
class stack_interface_phy_nr
{};
} // namespace srsran

@ -296,7 +296,7 @@ public:
virtual void rach_detected(const rach_info_t& rach_info) = 0;
};
class stack_interface_phy_nr : public mac_interface_phy_nr, public srsran::stack_interface_phy_nr
class stack_interface_phy_nr : public mac_interface_phy_nr
{};
} // namespace srsenb

@ -309,9 +309,7 @@ public:
};
// Combined interface for PHY to access stack (MAC and RRC)
class stack_interface_phy_nr : public mac_interface_phy_nr,
public rrc_interface_phy_nr,
public srsran::stack_interface_phy_nr
class stack_interface_phy_nr : public mac_interface_phy_nr, public rrc_interface_phy_nr
{};
// Combined interface for stack (MAC and RRC) to access PHY

@ -96,7 +96,6 @@ struct phy_args_t {
srsran::channel::args_t dl_channel_args;
srsran::channel::args_t ul_channel_args;
srsran::vnf_args_t vnf_args;
};
/* RAT agnostic Interface MAC -> PHY */

@ -56,8 +56,6 @@ struct phy_args_t {
bool extended_cp = false;
srsran::channel::args_t dl_channel_args;
srsran::channel::args_t ul_channel_args;
srsran::vnf_args_t vnf_args;
};
struct phy_cfg_t {

@ -261,13 +261,6 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("scheduler.nr_pdsch_mcs", bpo::value<int>(&args->nr_stack.mac.sched_cfg.fixed_dl_mcs)->default_value(28), "Fixed NR DL MCS (-1 for dynamic).")
("scheduler.nr_pusch_mcs", bpo::value<int>(&args->nr_stack.mac.sched_cfg.fixed_ul_mcs)->default_value(28), "Fixed NR UL MCS (-1 for dynamic).")
("expert.nr_pusch_max_its", bpo::value<uint32_t>(&args->phy.nr_pusch_max_its)->default_value(10), "Maximum number of LDPC iterations for NR.")
// VNF params
("vnf.type", bpo::value<string>(&args->phy.vnf_args.type)->default_value("gnb"), "VNF instance type [gnb,ue].")
("vnf.addr", bpo::value<string>(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface.")
("vnf.port", bpo::value<uint16_t>(&args->phy.vnf_args.bind_port)->default_value(3333), "Bind port.")
("log.vnf_level", bpo::value<string>(&args->phy.vnf_args.log_level), "VNF log level.")
("log.vnf_hex_limit", bpo::value<int>(&args->phy.vnf_args.log_hex_limit), "VNF log hex dump limit.")
;
// Positional options - config file location

@ -33,37 +33,6 @@ namespace srsue {
typedef _Complex float cf_t;
class phy_cmd_proc : public srsran::thread
{
public:
phy_cmd_proc() : thread("PHY_CMD") { start(); }
~phy_cmd_proc() { stop(); }
void add_cmd(std::function<void(void)> cmd) { cmd_queue.push(cmd); }
void stop()
{
if (running) {
add_cmd([this]() { running = false; });
wait_thread_finish();
}
}
private:
void run_thread()
{
std::function<void(void)> cmd;
while (running) {
cmd = cmd_queue.wait_pop();
cmd();
}
}
bool running = true;
// Queue for commands
srsran::block_queue<std::function<void(void)> > cmd_queue;
};
class phy final : public ue_lte_phy_base, public ue_nr_phy_base, public srsran::thread
{
public:
@ -80,16 +49,13 @@ public:
~phy() final { stop(); }
// Init defined in base class
int init(const phy_args_t& args_) final;
// Init for LTE PHYs
int init(const phy_args_t& args_, stack_interface_phy_lte* stack_, srsran::radio_interface_phy* radio_) final;
void stop() final;
void wait_initialize() final;
bool is_initiated();
bool is_initialized() final;
void get_metrics(const srsran::srsran_rat_t& rat, phy_metrics_t* m) final;
void srsran_phy_logger(phy_logger_level_t log_level, char* str);

@ -15,7 +15,9 @@
#include "phy_metrics.h"
#include "srsran/adt/circular_array.h"
#include "srsran/common/block_queue.h"
#include "srsran/common/gen_mch_tables.h"
#include "srsran/common/threads.h"
#include "srsran/common/tti_sempahore.h"
#include "srsran/interfaces/phy_common_interface.h"
#include "srsran/interfaces/phy_interface_types.h"
@ -46,6 +48,37 @@ public:
virtual void set_cfo(float cfo) = 0;
};
class phy_cmd_proc : public srsran::thread
{
public:
phy_cmd_proc() : thread("PHY_CMD") { start(); }
~phy_cmd_proc() { stop(); }
void add_cmd(std::function<void(void)> cmd) { cmd_queue.push(cmd); }
void stop()
{
if (running) {
add_cmd([this]() { running = false; });
wait_thread_finish();
}
}
private:
void run_thread()
{
std::function<void(void)> cmd;
while (running) {
cmd = cmd_queue.wait_pop();
cmd();
}
}
bool running = true;
// Queue for commands
srsran::block_queue<std::function<void(void)> > cmd_queue;
};
/* Subclass that manages variables common to all workers */
class phy_common : public srsran::phy_common_interface
{

@ -13,6 +13,7 @@
#ifndef SRSUE_PHY_NR_SA_H
#define SRSUE_PHY_NR_SA_H
#include "phy_common.h"
#include "srsran/interfaces/ue_nr_interfaces.h"
#include "srsue/hdr/phy/nr/sync_sa.h"
#include "srsue/hdr/phy/ue_nr_phy_base.h"
@ -28,38 +29,38 @@ public:
phy_nr_sa(const char* logname);
int init(const phy_args_nr_t& args_, stack_interface_phy_nr* stack_, srsran::radio_interface_phy* radio_) final;
void wait_initialize() final;
bool is_initialized() final;
void stop() final;
void reset_nr() final;
void start_plot() final {}
std::string get_type() final { return "nr_soft"; }
int set_rar_grant(uint32_t rar_slot_idx,
std::array<uint8_t, SRSRAN_RAR_UL_GRANT_NBITS> packed_ul_grant,
uint16_t rnti,
srsran_rnti_type_t rnti_type) final
{
return -1;
}
srsran_rnti_type_t rnti_type) final;
void send_prach(const uint32_t prach_occasion,
const int preamble_index,
const float preamble_received_target_power,
const float ta_base_sec) final
{}
const float ta_base_sec) final;
void set_earfcn(std::vector<uint32_t> earfcns) final{};
bool has_valid_sr_resource(uint32_t sr_id) final { return false; }
void clear_pending_grants() final {}
bool set_config(const srsran::phy_cfg_nr_t& cfg) final { return false; }
bool has_valid_sr_resource(uint32_t sr_id) final;
void clear_pending_grants() final;
bool set_config(const srsran::phy_cfg_nr_t& cfg) final;
phy_nr_state_t get_state() const final;
void reset_nr() final;
bool start_cell_search(const cell_search_args_t& req) final;
bool start_cell_select(const cell_search_args_t& req) final { return false; }
void stop() final { sync.stop(); }
void get_metrics(const srsran::srsran_rat_t& rat, phy_metrics_t* m) final{};
void srsran_phy_logger(phy_logger_level_t log_level, char* str);
private:
srslog::basic_logger& logger;
srslog::basic_logger& logger_phy_lib;
nr::worker_pool workers;
phy_common common;
@ -70,13 +71,25 @@ private:
phy_args_nr_t args = {};
srsran::radio_interface_phy* radio = nullptr;
stack_interface_phy_nr* stack = nullptr;
std::mutex config_mutex;
std::condition_variable config_cond;
std::atomic<bool> is_configured = {false};
// Since cell_search/cell_select operations take a lot of time, we use another queue to process the other commands
// in parallel and avoid accumulating in the queue
phy_cmd_proc cmd_worker_cell, cmd_worker;
// Run initialization functions in the background
void init_background();
std::thread init_thread;
const static int SF_RECV_THREAD_PRIO = 0;
const static int WORKERS_THREAD_PRIO = 2;
const static int MAX_WORKERS = 4;
const static int DEFAULT_WORKERS = 4;
static void set_default_args(phy_args_nr_t& args);
bool check_args(const phy_args_nr_t& args);
};
} // namespace srsue

@ -33,11 +33,9 @@ public:
virtual std::string get_type() = 0;
virtual int init(const phy_args_t& args_) = 0;
virtual int init(const phy_args_t& args_, stack_interface_phy_lte* stack_, srsran::radio_interface_phy* radio_) = 0;
virtual void stop() = 0;
virtual void wait_initialize() = 0;
virtual void start_plot() = 0;
virtual void get_metrics(const srsran::srsran_rat_t& rat, phy_metrics_t* m) = 0;

@ -24,7 +24,7 @@
namespace srsue {
class ue_nr_phy_base : public phy_interface_stack_nr
class ue_nr_phy_base : public ue_phy_base, public phy_interface_stack_nr
{
public:
ue_nr_phy_base(){};

@ -31,11 +31,10 @@ public:
virtual std::string get_type() = 0;
virtual int init(const phy_args_t& args_) = 0;
virtual void stop() = 0;
virtual void wait_initialize() = 0;
virtual bool is_initialized() = 0;
virtual void start_plot() = 0;
virtual void get_metrics(const srsran::srsran_rat_t& rat, phy_metrics_t* m) = 0;

@ -468,10 +468,6 @@ static int parse_args(all_args_t* args, int argc, char* argv[])
bpo::value<bool>(&args->stack.have_tti_time_stats)->default_value(true),
"Calculate TTI execution statistics")
// NR params
("vnf.type", bpo::value<string>(&args->phy.vnf_args.type)->default_value("ue"), "VNF instance type [gnb,ue]")
("vnf.addr", bpo::value<string>(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface")
("vnf.port", bpo::value<uint16_t>(&args->phy.vnf_args.bind_port)->default_value(3334), "Bind port")
;
// Positional options - config file location

@ -92,18 +92,11 @@ bool phy::check_args(const phy_args_t& args_)
int phy::init(const phy_args_t& args_, stack_interface_phy_lte* stack_, srsran::radio_interface_phy* radio_)
{
std::unique_lock<std::mutex> lock(config_mutex);
stack = stack_;
radio = radio_;
init(args_);
return SRSRAN_SUCCESS;
}
int phy::init(const phy_args_t& args_)
{
std::unique_lock<std::mutex> lock(config_mutex);
args = args_;
// Force frequency if given as argument
@ -159,7 +152,7 @@ void phy::wait_initialize()
}
}
bool phy::is_initiated()
bool phy::is_initialized()
{
return is_configured;
}
@ -448,7 +441,7 @@ void phy::start_plot()
bool phy::set_config(const srsran::phy_cfg_t& config_, uint32_t cc_idx)
{
if (!is_initiated()) {
if (!is_initialized()) {
fprintf(stderr, "Error calling set_config(): PHY not initialized\n");
return false;
}
@ -484,7 +477,7 @@ bool phy::set_config(const srsran::phy_cfg_t& config_, uint32_t cc_idx)
bool phy::set_scell(srsran_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn)
{
if (!is_initiated()) {
if (!is_initialized()) {
fprintf(stderr, "Error calling set_config(): PHY not initialized\n");
return false;
}

@ -9,12 +9,55 @@
* the distribution.
*
*/
#include "srsue/hdr/phy/phy_nr_sa.h"
#include "srsran/common/band_helper.h"
#include "srsran/common/standard_streams.h"
#include "srsran/srsran.h"
namespace srsue {
static void srsran_phy_handler(phy_logger_level_t log_level, void* ctx, char* str)
{
phy_nr_sa* r = (phy_nr_sa*)ctx;
r->srsran_phy_logger(log_level, str);
}
void phy_nr_sa::srsran_phy_logger(phy_logger_level_t log_level, char* str)
{
switch (log_level) {
case LOG_LEVEL_INFO_S:
logger_phy_lib.info(" %s", str);
break;
case LOG_LEVEL_DEBUG_S:
logger_phy_lib.debug(" %s", str);
break;
case LOG_LEVEL_ERROR_S:
logger_phy_lib.error(" %s", str);
break;
default:
break;
}
}
void phy_nr_sa::set_default_args(phy_args_nr_t& args_)
{
args_.nof_phy_threads = DEFAULT_WORKERS;
// TODO
}
bool phy_nr_sa::check_args(const phy_args_nr_t& args_)
{
if (args_.nof_phy_threads > MAX_WORKERS) {
srsran::console("Error in PHY args: nof_phy_threads must be 1, 2 or 3\n");
return false;
}
return true;
}
phy_nr_sa::phy_nr_sa(const char* logname) :
logger(srslog::fetch_basic_logger(logname)),
logger_phy_lib(srslog::fetch_basic_logger("PHY_LIB")),
sync(logger, workers),
workers(logger, 4),
common(logger),
@ -24,18 +67,67 @@ phy_nr_sa::phy_nr_sa(const char* logname) :
int phy_nr_sa::init(const phy_args_nr_t& args_, stack_interface_phy_nr* stack_, srsran::radio_interface_phy* radio_)
{
args = args_;
stack = stack_;
radio = radio_;
prach_buffer.init(SRSRAN_MAX_PRB);
// Add PHY lib log
auto lib_log_level = srslog::str_to_basic_level(args.log.phy_lib_level);
logger_phy_lib.set_level(lib_log_level);
logger_phy_lib.set_hex_dump_max_size(args.log.phy_hex_limit);
if (lib_log_level != srslog::basic_levels::none) {
srsran_phy_log_register_handler(this, srsran_phy_handler);
}
nr::sync_sa::args_t sync_args = {};
if (not sync.init(sync_args, stack_, radio_)) {
logger.error("Error initialising SYNC");
// set default logger
logger.set_level(srslog::str_to_basic_level(args.log.phy_level));
logger.set_hex_dump_max_size(args.log.phy_hex_limit);
if (!check_args(args)) {
return false;
}
is_configured = false;
std::thread t([this]() { init_background(); });
init_thread = std::move(t);
return true;
}
void phy_nr_sa::init_background()
{
nr::sync_sa::args_t sync_args = {};
if (not sync.init(sync_args, stack, radio)) {
logger.error("Error initialising SYNC");
return;
}
prach_buffer.init(SRSRAN_MAX_PRB);
workers.init(args, sync, stack, WORKERS_THREAD_PRIO);
is_configured = true;
}
void phy_nr_sa::stop()
{
cmd_worker.stop();
cmd_worker_cell.stop();
if (is_configured) {
sync.stop();
workers.stop();
prach_buffer.stop();
is_configured = false;
}
}
bool phy_nr_sa::is_initialized()
{
return is_configured;
}
void phy_nr_sa::wait_initialize()
{
init_thread.join();
}
phy_interface_rrc_nr::phy_nr_state_t phy_nr_sa::get_state() const
{
{
@ -71,4 +163,64 @@ bool phy_nr_sa::start_cell_search(const cell_search_args_t& req)
return sync.start_cell_search(cfg);
}
bool phy_nr_sa::has_valid_sr_resource(uint32_t sr_id)
{
return workers.has_valid_sr_resource(sr_id);
}
void phy_nr_sa::clear_pending_grants()
{
workers.clear_pending_grants();
}
void phy_nr_sa::send_prach(const uint32_t prach_occasion,
const int preamble_index,
const float preamble_received_target_power,
const float ta_base_sec)
{
workers.send_prach(prach_occasion, preamble_index, preamble_received_target_power);
}
int phy_nr_sa::set_rar_grant(uint32_t rar_slot_idx,
std::array<uint8_t, SRSRAN_RAR_UL_GRANT_NBITS> packed_ul_grant,
uint16_t rnti,
srsran_rnti_type_t rnti_type)
{
return workers.set_rar_grant(rar_slot_idx, packed_ul_grant, rnti, rnti_type);
}
bool phy_nr_sa::set_config(const srsran::phy_cfg_nr_t& cfg)
{
// Stash NR configuration
config_nr = cfg;
// Setup carrier configuration asynchronously
cmd_worker.add_cmd([this]() {
srsran::srsran_band_helper band_helper;
// tune radio
for (uint32_t i = 0; i < common.args->nof_nr_carriers; i++) {
logger.info("Tuning Rx channel %d to %.2f MHz",
i + common.args->nof_lte_carriers,
config_nr.carrier.dl_center_frequency_hz / 1e6);
radio->set_rx_freq(i + common.args->nof_lte_carriers, config_nr.carrier.dl_center_frequency_hz);
logger.info("Tuning Tx channel %d to %.2f MHz",
i + common.args->nof_lte_carriers,
config_nr.carrier.ul_center_frequency_hz / 1e6);
radio->set_tx_freq(i + common.args->nof_lte_carriers, config_nr.carrier.ul_center_frequency_hz);
}
// Set UE configuration
bool ret = workers.set_config(config_nr);
// Notify PHY config completion
if (stack != nullptr) {
stack->set_phy_config_complete(ret);
}
return ret;
});
return true;
}
} // namespace srsue

@ -44,8 +44,6 @@ public:
int init(const phy_args_t& args_, stack_interface_phy_lte* stack_, srsran::radio_interface_phy* radio_) override;
// ue_phy_base interface
int init(const phy_args_t& args_) override;
void stop() override;
void wait_initialize() override;
void start_plot() override;

@ -27,17 +27,16 @@ int lte_ttcn3_phy::init(const phy_args_t& args_, stack_interface_phy_lte* stack_
stack = stack_;
syssim = syssim_;
return init(args_);
logger.set_level(srslog::str_to_basic_level(args_.log.phy_level));
logger.set_hex_dump_max_size(-1);
return SRSRAN_SUCCESS;
}
int lte_ttcn3_phy::init(const phy_args_t& args_, stack_interface_phy_lte* stack_, srsran::radio_interface_phy* radio_)
{
return init(args_);
}
stack = stack_;
// ue_phy_base interface
int lte_ttcn3_phy::init(const phy_args_t& args_)
{
logger.set_level(srslog::str_to_basic_level(args_.log.phy_level));
logger.set_hex_dump_max_size(-1);

Loading…
Cancel
Save