Protect better the access to shared variables in phy_common and metrics (#1750)

master
Ismael Gomez 4 years ago committed by GitHub
parent eeb2b904aa
commit 5968157ea5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -44,7 +44,6 @@ public:
void set_tti(uint32_t tti);
void set_cfo(float cfo);
float get_ref_cfo() const;
void set_tdd_config(srslte_tdd_config_t config);
void set_config(srslte::phy_cfg_t& phy_cfg);
@ -61,7 +60,8 @@ public:
int read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna);
int read_pdsch_d(cf_t* pdsch_d);
void update_measurements();
void update_measurements(std::vector<rrc_interface_phy_lte::phy_meas_t>& serving_cells,
cf_t* rssi_power_buffer = nullptr);
private:
void dl_phy_to_mac_grant(srslte_pdsch_grant_t* phy_grant,
@ -117,10 +117,6 @@ private:
srslte_ue_ul_t ue_ul = {};
srslte_ue_ul_cfg_t ue_ul_cfg = {};
// Metrics
dl_metrics_t dl_metrics = {};
ul_metrics_t ul_metrics = {};
// Mutex, for protecting what matters most: ue_ul, ue_ul_cfg, ue_dl, ue_dl_cfg, cell, pmch_cfg
std::mutex mutex;
};

@ -39,7 +39,7 @@
namespace srsue {
class chest_feedback_itf
class rsrp_insync_itf
{
public:
virtual void in_sync() = 0;
@ -59,20 +59,6 @@ public:
srslte::phy_cfg_mbsfn_t mbsfn_config = {};
/* Power control variables */
float pathloss[SRSLTE_MAX_CARRIERS] = {};
float cur_pathloss = 0.0f;
float cur_pusch_power = 0.0f;
float avg_rsrp[SRSLTE_MAX_CARRIERS] = {};
float avg_rsrp_dbm[SRSLTE_MAX_CARRIERS] = {};
float avg_rsrq_db[SRSLTE_MAX_CARRIERS] = {};
float avg_rssi_dbm[SRSLTE_MAX_CARRIERS] = {};
float avg_cfo_hz[SRSLTE_MAX_CARRIERS] = {};
float rx_gain_offset = 0.0f;
float avg_snr_db_cqi[SRSLTE_MAX_CARRIERS] = {};
float avg_noise[SRSLTE_MAX_CARRIERS] = {};
uint32_t pcell_report_period = 0;
// SCell EARFCN, PCI, configured and enabled list
typedef struct {
uint32_t earfcn = 0;
@ -97,7 +83,11 @@ public:
~phy_common();
void init(phy_args_t* args, srslte::log* _log, srslte::radio_interface_phy* _radio, stack_interface_phy_lte* _stack);
void init(phy_args_t* args,
srslte::log* _log,
srslte::radio_interface_phy* _radio,
stack_interface_phy_lte* _stack,
rsrp_insync_itf* rsrp_insync);
uint32_t ul_pidof(uint32_t tti, srslte_tdd_config_t* tdd_config);
@ -157,10 +147,15 @@ public:
srslte::radio_interface_phy* get_radio();
void set_dl_metrics(dl_metrics_t m, uint32_t cc_idx);
void set_dl_metrics(uint32_t cc_idx, const dl_metrics_t& m);
void get_dl_metrics(dl_metrics_t m[SRSLTE_MAX_CARRIERS]);
void set_ul_metrics(ul_metrics_t m, uint32_t cc_idx);
void set_ch_metrics(uint32_t cc_idx, const ch_metrics_t& m);
void get_ch_metrics(ch_metrics_t m[SRSLTE_MAX_CARRIERS]);
void set_ul_metrics(uint32_t cc_idx, const ul_metrics_t& m);
void get_ul_metrics(ul_metrics_t m[SRSLTE_MAX_CARRIERS]);
void set_sync_metrics(const uint32_t& cc_idx, const sync_metrics_t& m);
void get_sync_metrics(sync_metrics_t m[SRSLTE_MAX_CARRIERS]);
@ -185,7 +180,58 @@ public:
*/
uint32_t get_ul_earfcn(uint32_t dl_earfcn);
void update_measurements(uint32_t cc_idx,
srslte_chest_dl_res_t chest_res,
srslte_dl_sf_cfg_t sf_cfg_dl,
float tx_crs_power,
std::vector<rrc_interface_phy_lte::phy_meas_t>& serving_cells,
cf_t* rssi_power_buffer = nullptr);
void update_cfo_measurement(uint32_t cc_idx, float cfo_hz);
float get_sinr_db(uint32_t cc_idx)
{
std::unique_lock<std::mutex> lock(meas_mutex);
return avg_snr_db_cqi[cc_idx];
}
float get_pusch_power()
{
std::unique_lock<std::mutex> lock(meas_mutex);
return cur_pusch_power;
}
float get_pathloss()
{
std::unique_lock<std::mutex> lock(meas_mutex);
return cur_pathloss;
}
float get_rx_gain_offset()
{
std::unique_lock<std::mutex> lock(meas_mutex);
return rx_gain_offset;
}
private:
std::mutex meas_mutex;
float pathloss[SRSLTE_MAX_CARRIERS] = {};
float cur_pathloss = 0.0f;
float cur_pusch_power = 0.0f;
float avg_rsrp[SRSLTE_MAX_CARRIERS] = {};
float avg_rsrp_dbm[SRSLTE_MAX_CARRIERS] = {};
float avg_rsrq_db[SRSLTE_MAX_CARRIERS] = {};
float avg_rssi_dbm[SRSLTE_MAX_CARRIERS] = {};
float avg_cfo_hz[SRSLTE_MAX_CARRIERS] = {};
float rx_gain_offset = 0.0f;
float avg_snr_db_cqi[SRSLTE_MAX_CARRIERS] = {};
float avg_noise[SRSLTE_MAX_CARRIERS] = {};
uint32_t pcell_report_period = 0;
uint32_t rssi_read_cnt = 0;
rsrp_insync_itf* insync_itf = nullptr;
bool have_mtch_stop = false;
std::mutex mtch_mutex;
std::condition_variable mtch_cvar;
@ -244,15 +290,16 @@ private:
srslte_cell_t cell = {};
std::mutex metrics_mutex;
ch_metrics_t ch_metrics[SRSLTE_MAX_CARRIERS] = {};
uint32_t ch_metrics_count[SRSLTE_MAX_CARRIERS] = {};
dl_metrics_t dl_metrics[SRSLTE_MAX_CARRIERS] = {};
uint32_t dl_metrics_count = 0;
bool dl_metrics_read = true;
uint32_t dl_metrics_count[SRSLTE_MAX_CARRIERS] = {};
ul_metrics_t ul_metrics[SRSLTE_MAX_CARRIERS] = {};
uint32_t ul_metrics_count = 0;
bool ul_metrics_read = true;
uint32_t ul_metrics_count[SRSLTE_MAX_CARRIERS] = {};
sync_metrics_t sync_metrics[SRSLTE_MAX_CARRIERS] = {};
uint32_t sync_metrics_count = 0;
bool sync_metrics_read = true;
uint32_t sync_metrics_count[SRSLTE_MAX_CARRIERS] = {};
// MBSFN
bool sib13_configured = false;

@ -37,19 +37,22 @@ struct sync_metrics_t {
float sfo;
};
struct dl_metrics_t {
struct ch_metrics_t {
float n;
float sinr;
float rsrp;
float rsrq;
float rssi;
float ri;
float turbo_iters;
float mcs;
float pathloss;
float sync_err;
};
struct dl_metrics_t {
float turbo_iters;
float mcs;
};
struct ul_metrics_t {
float mcs;
float power;
@ -58,6 +61,7 @@ struct ul_metrics_t {
struct phy_metrics_t {
info_metrics_t info[SRSLTE_MAX_CARRIERS];
sync_metrics_t sync[SRSLTE_MAX_CARRIERS];
ch_metrics_t ch[SRSLTE_MAX_CARRIERS];
dl_metrics_t dl[SRSLTE_MAX_CARRIERS];
ul_metrics_t ul[SRSLTE_MAX_CARRIERS];
uint32_t nof_active_cc;

@ -41,11 +41,7 @@ namespace srsue {
class sf_worker : public srslte::thread_pool::worker
{
public:
sf_worker(uint32_t max_prb,
phy_common* phy,
srslte::log* log,
srslte::log* log_phy_lib_h,
chest_feedback_itf* chest_loop);
sf_worker(uint32_t max_prb, phy_common* phy, srslte::log* log, srslte::log* log_phy_lib_h);
virtual ~sf_worker();
void reset();
@ -77,7 +73,6 @@ public:
}
uint32_t get_rx_nof_antennas() { return phy->args->nof_rx_ant; }
int read_pdsch_d(cf_t* pdsch_d);
float get_sync_error();
float get_cfo();
void start_plot();
@ -96,8 +91,6 @@ private:
srslte::log* log_phy_lib_h = nullptr;
chest_feedback_itf* chest_loop = nullptr;
srslte_cell_t cell = {};
std::mutex cell_mutex;
srslte_tdd_config_t tdd_config = {};
@ -111,7 +104,6 @@ private:
uint32_t tti = 0;
srslte::rf_timestamp_t tx_time = {};
uint32_t rssi_read_cnt = 0;
};
} // namespace srsue

@ -48,7 +48,7 @@ namespace srsue {
typedef _Complex float cf_t;
class sync : public srslte::thread, public chest_feedback_itf, public search_callback, public scell::sync_callback
class sync : public srslte::thread, public rsrp_insync_itf, public search_callback, public scell::sync_callback
{
public:
sync() : thread("SYNC"), sf_buffer(sync_nof_rx_subframes), dummy_buffer(sync_nof_rx_subframes){};

@ -98,8 +98,8 @@ void metrics_csv::set_metrics(const ue_metrics_t& metrics, const uint32_t period
file << metrics.phy.info[r].pci << ";";
// Print PHY metrics for first CC
file << float_to_string(metrics.phy.dl[r].rsrp, 2);
file << float_to_string(metrics.phy.dl[r].pathloss, 2);
file << float_to_string(metrics.phy.ch[r].rsrp, 2);
file << float_to_string(metrics.phy.ch[r].pathloss, 2);
file << float_to_string(metrics.phy.sync[r].cfo, 2);
// Find strongest neighbour for this EARFCN (cells are ordered)
@ -120,7 +120,7 @@ void metrics_csv::set_metrics(const ue_metrics_t& metrics, const uint32_t period
}
file << float_to_string(metrics.phy.dl[r].mcs, 2);
file << float_to_string(metrics.phy.dl[r].sinr, 2);
file << float_to_string(metrics.phy.ch[r].sinr, 2);
file << float_to_string(metrics.phy.dl[r].turbo_iters, 2);
if (metrics.stack.mac[r].rx_brate > 0) {

@ -118,8 +118,8 @@ void metrics_stdout::set_metrics(const ue_metrics_t& metrics, const uint32_t per
for (uint32_t r = 0; r < metrics.phy.nof_active_cc; r++) {
cout << std::setw(2) << r;
cout << std::setw(4) << metrics.phy.info[r].pci << std::setw(0);
cout << float_to_string(metrics.phy.dl[r].rsrp, 2);
cout << float_to_string(metrics.phy.dl[r].pathloss, 2);
cout << float_to_string(metrics.phy.ch[r].rsrp, 2);
cout << float_to_string(metrics.phy.ch[r].pathloss, 2);
cout << float_to_eng_string(metrics.phy.sync[r].cfo, 2);
// Find strongest neighbour for this EARFCN (cells are ordered)
@ -140,7 +140,7 @@ void metrics_stdout::set_metrics(const ue_metrics_t& metrics, const uint32_t per
}
cout << float_to_string(metrics.phy.dl[r].mcs, 2);
cout << float_to_string(metrics.phy.dl[r].sinr, 2);
cout << float_to_string(metrics.phy.ch[r].sinr, 2);
cout << float_to_string(metrics.phy.dl[r].turbo_iters, 2);
cout << float_to_eng_string((float)metrics.stack.mac[r].rx_brate / (metrics.stack.mac[r].nof_tti * 1e-3), 2);

@ -117,9 +117,6 @@ cc_worker::~cc_worker()
void cc_worker::reset()
{
bzero(&dl_metrics, sizeof(dl_metrics_t));
bzero(&ul_metrics, sizeof(ul_metrics_t));
// constructor sets defaults
srslte::phy_cfg_t empty_cfg;
set_config(empty_cfg);
@ -184,11 +181,6 @@ void cc_worker::set_cfo(float cfo)
ue_ul_cfg.cfo_value = cfo;
}
float cc_worker::get_ref_cfo() const
{
return ue_dl.chest_res.cfo;
}
void cc_worker::set_crnti(uint16_t rnti)
{
std::unique_lock<std::mutex> lock(mutex);
@ -476,8 +468,14 @@ int cc_worker::decode_pdsch(srslte_pdsch_ack_resource_t ack_resource,
if (decode_enable) {
// Metrics
dl_metrics_t dl_metrics = {};
if (ue_dl_cfg.cfg.pdsch.grant.nof_tb == 1) {
dl_metrics.mcs = ue_dl_cfg.cfg.pdsch.grant.tb[0].mcs_idx;
} else {
dl_metrics.mcs = (ue_dl_cfg.cfg.pdsch.grant.tb[0].mcs_idx + ue_dl_cfg.cfg.pdsch.grant.tb[1].mcs_idx) / 2;
}
dl_metrics.turbo_iters = pdsch_dec->avg_iterations_block / 2;
phy->set_dl_metrics(cc_idx, dl_metrics);
// Logging
if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
@ -508,7 +506,11 @@ int cc_worker::decode_pmch(mac_interface_phy_lte::tb_action_dl_t* action, srslte
}
// Store metrics
dl_metrics.mcs = pmch_cfg.pdsch_cfg.grant.tb[0].mcs_idx;
// Metrics
dl_metrics_t dl_metrics = {};
dl_metrics.mcs = ue_dl_cfg.cfg.pdsch.grant.tb[0].mcs_idx;
dl_metrics.turbo_iters = pmch_dec.avg_iterations_block / 2;
phy->set_dl_metrics(cc_idx, dl_metrics);
Info("PMCH: l_crb=%2d, tbs=%d, mcs=%d, crc=%s, snr=%.1f dB, n_iter=%.1f\n",
pmch_cfg.pdsch_cfg.grant.nof_prb,
@ -552,85 +554,11 @@ void cc_worker::decode_phich()
}
}
void cc_worker::update_measurements()
void cc_worker::update_measurements(std::vector<rrc_interface_phy_lte::phy_meas_t>& serving_cells,
cf_t* rssi_power_buffer)
{
std::unique_lock<std::mutex> lock(mutex);
float snr_ema_coeff = phy->args->snr_ema_coeff;
// In TDD, ignore special subframes without PDSCH
if (srslte_sfidx_tdd_type(sf_cfg_dl.tdd_config, CURRENT_SFIDX) == SRSLTE_TDD_SF_S &&
srslte_sfidx_tdd_nof_dw(sf_cfg_dl.tdd_config) < 4) {
return;
}
// Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC
float rsrq_db = ue_dl.chest_res.rsrq_db;
if (std::isnormal(rsrq_db)) {
if (!(CURRENT_TTI % phy->pcell_report_period) || !std::isnormal(phy->avg_rsrq_db[cc_idx])) {
phy->avg_rsrq_db[cc_idx] = rsrq_db;
} else {
phy->avg_rsrq_db[cc_idx] =
SRSLTE_VEC_CMA(rsrq_db, phy->avg_rsrq_db[cc_idx], CURRENT_TTI % phy->pcell_report_period);
}
}
// Average RSRP taken from CRS
float rsrp_lin = ue_dl.chest_res.rsrp;
if (std::isnormal(rsrp_lin)) {
if (!std::isnormal(phy->avg_rsrp[cc_idx])) {
phy->avg_rsrp[cc_idx] = rsrp_lin;
} else {
phy->avg_rsrp[cc_idx] = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp[cc_idx], snr_ema_coeff);
}
}
/* Correct absolute power measurements by RX gain offset */
float rsrp_dbm = ue_dl.chest_res.rsrp_dbm - phy->rx_gain_offset;
// Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC
if (std::isnormal(rsrp_dbm)) {
if (!(CURRENT_TTI % phy->pcell_report_period) || !std::isnormal(phy->avg_rsrp_dbm[cc_idx])) {
phy->avg_rsrp_dbm[cc_idx] = rsrp_dbm;
} else {
phy->avg_rsrp_dbm[cc_idx] =
SRSLTE_VEC_CMA(rsrp_dbm, phy->avg_rsrp_dbm[cc_idx], CURRENT_TTI % phy->pcell_report_period);
}
}
// Compute PL
float tx_crs_power = ue_dl_cfg.cfg.pdsch.rs_power;
phy->pathloss[cc_idx] = tx_crs_power - phy->avg_rsrp_dbm[cc_idx];
// Average noise
float cur_noise = ue_dl.chest_res.noise_estimate;
if (std::isnormal(cur_noise)) {
if (!std::isnormal(phy->avg_noise[cc_idx])) {
phy->avg_noise[cc_idx] = cur_noise;
} else {
phy->avg_noise[cc_idx] = SRSLTE_VEC_EMA(cur_noise, phy->avg_noise[cc_idx], snr_ema_coeff);
}
}
// Average snr in the log domain
if (std::isnormal(ue_dl.chest_res.snr_db)) {
if (!std::isnormal(phy->avg_snr_db_cqi[cc_idx])) {
phy->avg_snr_db_cqi[cc_idx] = ue_dl.chest_res.snr_db;
} else {
phy->avg_snr_db_cqi[cc_idx] = SRSLTE_VEC_EMA(ue_dl.chest_res.snr_db, phy->avg_snr_db_cqi[cc_idx], snr_ema_coeff);
}
}
// Store metrics
dl_metrics.n = phy->avg_noise[cc_idx];
dl_metrics.rsrp = phy->avg_rsrp_dbm[cc_idx];
dl_metrics.rsrq = phy->avg_rsrq_db[cc_idx];
dl_metrics.rssi = phy->avg_rssi_dbm[cc_idx];
dl_metrics.pathloss = phy->pathloss[cc_idx];
dl_metrics.sinr = phy->avg_snr_db_cqi[cc_idx];
dl_metrics.sync_err = ue_dl.chest_res.sync_error;
phy->set_dl_metrics(dl_metrics, cc_idx);
phy->set_ul_metrics(ul_metrics, cc_idx);
phy->update_measurements(
cc_idx, ue_dl.chest_res, sf_cfg_dl, ue_dl_cfg.cfg.pdsch.rs_power, serving_cells, rssi_power_buffer);
}
/************
@ -835,7 +763,10 @@ bool cc_worker::encode_uplink(mac_interface_phy_lte::tb_action_ul_t* action, srs
// Store metrics
if (action->tb.enabled) {
ul_metrics_t ul_metrics = {};
ul_metrics.mcs = ue_ul_cfg.ul_cfg.pusch.grant.tb.mcs_idx;
ul_metrics.power = 0;
phy->set_ul_metrics(cc_idx, ul_metrics);
}
// Logging
@ -866,7 +797,7 @@ uint32_t cc_worker::get_wideband_cqi()
int cqi_fixed = phy->args->cqi_fixed;
int cqi_max = phy->args->cqi_max;
uint32_t wb_cqi_value = srslte_cqi_from_snr(phy->avg_snr_db_cqi[cc_idx] + ue_dl_cfg.snr_to_cqi_offset);
uint32_t wb_cqi_value = srslte_cqi_from_snr(phy->get_sinr_db(cc_idx) + ue_dl_cfg.snr_to_cqi_offset);
if (cqi_fixed >= 0) {
wb_cqi_value = cqi_fixed;

@ -180,12 +180,12 @@ void phy::run_thread()
{
std::unique_lock<std::mutex> lock(config_mutex);
prach_buffer.init(SRSLTE_MAX_PRB, log_h);
common.init(&args, (srslte::log*)log_vec[0].get(), radio, stack);
common.init(&args, (srslte::log*)log_vec[0].get(), radio, stack, &sfsync);
// Add workers to workers pool and start threads
for (uint32_t i = 0; i < nof_workers; i++) {
auto w = std::unique_ptr<sf_worker>(new sf_worker(
SRSLTE_MAX_PRB, &common, (srslte::log*)log_vec[i].get(), (srslte::log*)log_vec[nof_workers].get(), &sfsync));
SRSLTE_MAX_PRB, &common, (srslte::log*)log_vec[i].get(), (srslte::log*)log_vec[nof_workers].get()));
workers_pool.init_worker(i, w.get(), WORKERS_THREAD_PRIO, args.worker_cpu_mask);
workers.push_back(std::move(w));
}
@ -248,6 +248,7 @@ void phy::get_metrics(phy_metrics_t* m)
m->info[i].pci = common.scell_cfg[i].pci;
}
common.get_ch_metrics(m->ch);
common.get_dl_metrics(m->dl);
common.get_ul_metrics(m->ul);
common.get_sync_metrics(m->sync);
@ -322,13 +323,13 @@ bool phy::cell_is_camping()
float phy::get_phr()
{
float phr = radio->get_info()->max_tx_gain - common.cur_pusch_power;
float phr = radio->get_info()->max_tx_gain - common.get_pusch_power();
return phr;
}
float phy::get_pathloss_db()
{
return common.cur_pathloss;
return common.get_pathloss();
}
void phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec)

@ -57,12 +57,14 @@ void phy_common::set_nof_workers(uint32_t nof_workers_)
void phy_common::init(phy_args_t* _args,
srslte::log* _log,
srslte::radio_interface_phy* _radio,
stack_interface_phy_lte* _stack)
stack_interface_phy_lte* _stack,
rsrp_insync_itf* _chest_loop)
{
log_h = _log;
radio_h = _radio;
stack = _stack;
args = _args;
insync_itf = _chest_loop;
sr_last_tx_tti = -1;
ta.set_logger(_log);
@ -603,75 +605,241 @@ void phy_common::set_cell(const srslte_cell_t& c)
}
}
void phy_common::set_dl_metrics(const dl_metrics_t m, uint32_t cc_idx)
void phy_common::update_cfo_measurement(uint32_t cc_idx, float cfo_hz)
{
if (dl_metrics_read) {
bzero(dl_metrics, sizeof(dl_metrics_t) * SRSLTE_MAX_CARRIERS);
dl_metrics_count = 0;
dl_metrics_read = false;
std::unique_lock<std::mutex> lock(meas_mutex);
// use SNR EMA coefficient for averaging
avg_cfo_hz[cc_idx] = SRSLTE_VEC_EMA(cfo_hz, avg_cfo_hz[cc_idx], args->snr_ema_coeff);
}
void phy_common::update_measurements(uint32_t cc_idx,
srslte_chest_dl_res_t chest_res,
srslte_dl_sf_cfg_t sf_cfg_dl,
float tx_crs_power,
std::vector<rrc_interface_phy_lte::phy_meas_t>& serving_cells,
cf_t* rssi_power_buffer)
{
std::unique_lock<std::mutex> lock(meas_mutex);
float snr_ema_coeff = args->snr_ema_coeff;
// In TDD, ignore special subframes without PDSCH
if (srslte_sfidx_tdd_type(sf_cfg_dl.tdd_config, sf_cfg_dl.tti % 10) == SRSLTE_TDD_SF_S &&
srslte_sfidx_tdd_nof_dw(sf_cfg_dl.tdd_config) < 4) {
return;
}
// Only worker 0 reads the RSSI sensor
if (rssi_power_buffer) {
if (!rssi_read_cnt) {
// Average RSSI over all symbols in antenna port 0 (make sure SF length is non-zero)
float rssi_dbm = SRSLTE_SF_LEN_PRB(cell.nof_prb) > 0 ? (srslte_convert_power_to_dB(srslte_vec_avg_power_cf(
rssi_power_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb))) +
30)
: 0;
if (std::isnormal(rssi_dbm)) {
avg_rssi_dbm[0] = SRSLTE_VEC_EMA(rssi_dbm, avg_rssi_dbm[0], args->snr_ema_coeff);
}
rx_gain_offset = get_radio()->get_rx_gain() + args->rx_gain_offset;
}
rssi_read_cnt++;
if (rssi_read_cnt == 1000) {
rssi_read_cnt = 0;
}
}
// Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC
float rsrq_db = chest_res.rsrq_db;
if (std::isnormal(rsrq_db)) {
if (!(sf_cfg_dl.tti % pcell_report_period) || !std::isnormal(avg_rsrq_db[cc_idx])) {
avg_rsrq_db[cc_idx] = rsrq_db;
} else {
avg_rsrq_db[cc_idx] = SRSLTE_VEC_CMA(rsrq_db, avg_rsrq_db[cc_idx], sf_cfg_dl.tti % pcell_report_period);
}
}
// Average RSRP taken from CRS
float rsrp_lin = chest_res.rsrp;
if (std::isnormal(rsrp_lin)) {
if (!std::isnormal(avg_rsrp[cc_idx])) {
avg_rsrp[cc_idx] = rsrp_lin;
} else {
avg_rsrp[cc_idx] = SRSLTE_VEC_EMA(rsrp_lin, avg_rsrp[cc_idx], snr_ema_coeff);
}
}
/* Correct absolute power measurements by RX gain offset */
float rsrp_dbm = chest_res.rsrp_dbm - rx_gain_offset;
// Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC
if (std::isnormal(rsrp_dbm)) {
if (!(sf_cfg_dl.tti % pcell_report_period) || !std::isnormal(avg_rsrp_dbm[cc_idx])) {
avg_rsrp_dbm[cc_idx] = rsrp_dbm;
} else {
avg_rsrp_dbm[cc_idx] = SRSLTE_VEC_CMA(rsrp_dbm, avg_rsrp_dbm[cc_idx], sf_cfg_dl.tti % pcell_report_period);
}
}
// Compute PL
pathloss[cc_idx] = tx_crs_power - avg_rsrp_dbm[cc_idx];
// Average noise
float cur_noise = chest_res.noise_estimate;
if (std::isnormal(cur_noise)) {
if (!std::isnormal(avg_noise[cc_idx])) {
avg_noise[cc_idx] = cur_noise;
} else {
avg_noise[cc_idx] = SRSLTE_VEC_EMA(cur_noise, avg_noise[cc_idx], snr_ema_coeff);
}
}
// Average snr in the log domain
if (std::isnormal(chest_res.snr_db)) {
if (!std::isnormal(avg_snr_db_cqi[cc_idx])) {
avg_snr_db_cqi[cc_idx] = chest_res.snr_db;
} else {
avg_snr_db_cqi[cc_idx] = SRSLTE_VEC_EMA(chest_res.snr_db, avg_snr_db_cqi[cc_idx], snr_ema_coeff);
}
}
dl_metrics_count++;
dl_metrics[cc_idx].mcs = dl_metrics[cc_idx].mcs + (m.mcs - dl_metrics[cc_idx].mcs) / dl_metrics_count;
dl_metrics[cc_idx].n = dl_metrics[cc_idx].n + (m.n - dl_metrics[cc_idx].n) / dl_metrics_count;
dl_metrics[cc_idx].rsrq = dl_metrics[cc_idx].rsrq + (m.rsrq - dl_metrics[cc_idx].rsrq) / dl_metrics_count;
dl_metrics[cc_idx].rssi = dl_metrics[cc_idx].rssi + (m.rssi - dl_metrics[cc_idx].rssi) / dl_metrics_count;
dl_metrics[cc_idx].rsrp = dl_metrics[cc_idx].rsrp + (m.rsrp - dl_metrics[cc_idx].rsrp) / dl_metrics_count;
dl_metrics[cc_idx].sinr = dl_metrics[cc_idx].sinr + (m.sinr - dl_metrics[cc_idx].sinr) / dl_metrics_count;
dl_metrics[cc_idx].sync_err =
dl_metrics[cc_idx].sync_err + (m.sync_err - dl_metrics[cc_idx].sync_err) / dl_metrics_count;
dl_metrics[cc_idx].pathloss =
dl_metrics[cc_idx].pathloss + (m.pathloss - dl_metrics[cc_idx].pathloss) / dl_metrics_count;
// Store metrics
ch_metrics_t ch = {};
ch.n = avg_noise[cc_idx];
ch.rsrp = avg_rsrp_dbm[cc_idx];
ch.rsrq = avg_rsrq_db[cc_idx];
ch.rssi = avg_rssi_dbm[cc_idx];
ch.pathloss = pathloss[cc_idx];
ch.sinr = avg_snr_db_cqi[cc_idx];
ch.sync_err = chest_res.sync_error;
set_ch_metrics(cc_idx, ch);
// Prepare measurements for serving cells
bool active = (cc_idx == 0 || scell_cfg[cc_idx].configured);
if (active && ((sf_cfg_dl.tti % pcell_report_period) == pcell_report_period - 1)) {
rrc_interface_phy_lte::phy_meas_t meas = {};
meas.rsrp = avg_rsrp_dbm[cc_idx];
meas.rsrq = avg_rsrq_db[cc_idx];
meas.cfo_hz = avg_cfo_hz[cc_idx];
// Save EARFCN and PCI for secondary cells, primary cell has earfcn=0
if (cc_idx > 0) {
meas.earfcn = scell_cfg[cc_idx].earfcn;
meas.pci = scell_cfg[cc_idx].pci;
}
serving_cells.push_back(meas);
}
// Check in-sync / out-sync conditions
if (avg_rsrp_dbm[0] > args->in_sync_rsrp_dbm_th && avg_snr_db_cqi[0] > args->in_sync_snr_db_th) {
log_h->debug(
"SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n", avg_snr_db_cqi[0], avg_rsrp_dbm[0]);
if (insync_itf) {
insync_itf->in_sync();
}
} else {
log_h->warning(
"SNR=%.1f dB RSRP=%.1f dBm, sync=out-of-sync from channel estimator\n", avg_snr_db_cqi[0], avg_rsrp_dbm[0]);
if (insync_itf) {
insync_itf->out_of_sync();
}
}
// Call feedback loop for chest
if (cc_idx == 0) {
if (insync_itf && ((1U << (sf_cfg_dl.tti % 10U)) & args->cfo_ref_mask)) {
insync_itf->set_cfo(chest_res.cfo);
}
}
}
void phy_common::set_dl_metrics(uint32_t cc_idx, const dl_metrics_t& m)
{
std::unique_lock<std::mutex> lock(metrics_mutex);
dl_metrics_count[cc_idx]++;
dl_metrics[cc_idx].mcs = dl_metrics[cc_idx].mcs + (m.mcs - dl_metrics[cc_idx].mcs) / dl_metrics_count[cc_idx];
dl_metrics[cc_idx].turbo_iters =
dl_metrics[cc_idx].turbo_iters + (m.turbo_iters - dl_metrics[cc_idx].turbo_iters) / dl_metrics_count;
dl_metrics[cc_idx].turbo_iters + (m.turbo_iters - dl_metrics[cc_idx].turbo_iters) / dl_metrics_count[cc_idx];
}
void phy_common::get_dl_metrics(dl_metrics_t m[SRSLTE_MAX_CARRIERS])
{
memcpy(m, dl_metrics, sizeof(dl_metrics_t) * SRSLTE_MAX_CARRIERS);
dl_metrics_read = true;
std::unique_lock<std::mutex> lock(metrics_mutex);
for (uint32_t i = 0; i < args->nof_carriers; i++) {
m[i] = dl_metrics[i];
dl_metrics[i] = {};
dl_metrics_count[i] = 0;
}
}
void phy_common::set_ch_metrics(uint32_t cc_idx, const ch_metrics_t& m)
{
std::unique_lock<std::mutex> lock(metrics_mutex);
ch_metrics_count[cc_idx]++;
ch_metrics[cc_idx].n = ch_metrics[cc_idx].n + (m.n - ch_metrics[cc_idx].n) / ch_metrics_count[cc_idx];
ch_metrics[cc_idx].rsrq = ch_metrics[cc_idx].rsrq + (m.rsrq - ch_metrics[cc_idx].rsrq) / ch_metrics_count[cc_idx];
ch_metrics[cc_idx].rssi = ch_metrics[cc_idx].rssi + (m.rssi - ch_metrics[cc_idx].rssi) / ch_metrics_count[cc_idx];
ch_metrics[cc_idx].rsrp = ch_metrics[cc_idx].rsrp + (m.rsrp - ch_metrics[cc_idx].rsrp) / ch_metrics_count[cc_idx];
ch_metrics[cc_idx].sinr = ch_metrics[cc_idx].sinr + (m.sinr - ch_metrics[cc_idx].sinr) / ch_metrics_count[cc_idx];
ch_metrics[cc_idx].sync_err =
ch_metrics[cc_idx].sync_err + (m.sync_err - ch_metrics[cc_idx].sync_err) / ch_metrics_count[cc_idx];
ch_metrics[cc_idx].pathloss =
ch_metrics[cc_idx].pathloss + (m.pathloss - ch_metrics[cc_idx].pathloss) / ch_metrics_count[cc_idx];
}
void phy_common::set_ul_metrics(const ul_metrics_t m, uint32_t cc_idx)
void phy_common::get_ch_metrics(ch_metrics_t m[SRSLTE_MAX_CARRIERS])
{
if (ul_metrics_read) {
bzero(ul_metrics, sizeof(ul_metrics_t) * SRSLTE_MAX_CARRIERS);
ul_metrics_count = 0;
ul_metrics_read = false;
std::unique_lock<std::mutex> lock(metrics_mutex);
for (uint32_t i = 0; i < args->nof_carriers; i++) {
m[i] = ch_metrics[i];
ch_metrics[i] = {};
ch_metrics_count[i] = 0;
}
ul_metrics_count++;
for (uint32_t r = 0; r < args->nof_carriers; r++) {
ul_metrics[cc_idx].mcs = ul_metrics[cc_idx].mcs + (m.mcs - ul_metrics[cc_idx].mcs) / ul_metrics_count;
ul_metrics[cc_idx].power = ul_metrics[cc_idx].power + (m.power - ul_metrics[cc_idx].power) / ul_metrics_count;
}
void phy_common::set_ul_metrics(uint32_t cc_idx, const ul_metrics_t& m)
{
std::unique_lock<std::mutex> lock(metrics_mutex);
ul_metrics_count[cc_idx]++;
ul_metrics[cc_idx].mcs = ul_metrics[cc_idx].mcs + (m.mcs - ul_metrics[cc_idx].mcs) / ul_metrics_count[cc_idx];
ul_metrics[cc_idx].power = ul_metrics[cc_idx].power + (m.power - ul_metrics[cc_idx].power) / ul_metrics_count[cc_idx];
}
void phy_common::get_ul_metrics(ul_metrics_t m[SRSLTE_MAX_CARRIERS])
{
memcpy(m, ul_metrics, sizeof(ul_metrics_t) * SRSLTE_MAX_CARRIERS);
ul_metrics_read = true;
std::unique_lock<std::mutex> lock(metrics_mutex);
for (uint32_t i = 0; i < args->nof_carriers; i++) {
m[i] = ul_metrics[i];
ul_metrics[i] = {};
ul_metrics_count[i] = 0;
}
}
void phy_common::set_sync_metrics(const uint32_t& cc_idx, const sync_metrics_t& m)
{
if (sync_metrics_read) {
sync_metrics[cc_idx] = m;
sync_metrics_count = 1;
if (cc_idx == 0)
sync_metrics_read = false;
} else {
if (cc_idx == 0)
sync_metrics_count++;
sync_metrics[cc_idx].cfo = sync_metrics[cc_idx].cfo + (m.cfo - sync_metrics[cc_idx].cfo) / sync_metrics_count;
sync_metrics[cc_idx].sfo = sync_metrics[cc_idx].sfo + (m.sfo - sync_metrics[cc_idx].sfo) / sync_metrics_count;
}
std::unique_lock<std::mutex> lock(metrics_mutex);
sync_metrics_count[cc_idx]++;
sync_metrics[cc_idx].cfo = sync_metrics[cc_idx].cfo + (m.cfo - sync_metrics[cc_idx].cfo) / sync_metrics_count[cc_idx];
sync_metrics[cc_idx].sfo = sync_metrics[cc_idx].sfo + (m.sfo - sync_metrics[cc_idx].sfo) / sync_metrics_count[cc_idx];
}
void phy_common::get_sync_metrics(sync_metrics_t m[SRSLTE_MAX_CARRIERS])
{
std::unique_lock<std::mutex> lock(metrics_mutex);
for (uint32_t i = 0; i < args->nof_carriers; i++) {
m[i] = sync_metrics[i];
sync_metrics[i] = {};
sync_metrics_count[i] = 0;
}
sync_metrics_read = true;
}
void phy_common::reset_radio()
@ -691,7 +859,6 @@ void phy_common::reset()
cur_pathloss = 0;
cur_pusch_power = 0;
sr_last_tx_tti = -1;
cur_pusch_power = 0;
pcell_report_period = 20;
ZERO_OBJECT(pathloss);

@ -55,16 +55,11 @@ static int plot_worker_id = -1;
namespace srsue {
sf_worker::sf_worker(uint32_t max_prb,
phy_common* phy_,
srslte::log* log_h_,
srslte::log* log_phy_lib_h_,
chest_feedback_itf* chest_loop_)
sf_worker::sf_worker(uint32_t max_prb, phy_common* phy_, srslte::log* log_h_, srslte::log* log_phy_lib_h_)
{
phy = phy_;
log_h = log_h_;
log_phy_lib_h = log_phy_lib_h_;
chest_loop = chest_loop_;
// ue_sync in phy.cc requires a buffer for 3 subframes
for (uint32_t r = 0; r < phy->args->nof_carriers; r++) {
@ -81,7 +76,6 @@ sf_worker::~sf_worker()
void sf_worker::reset()
{
rssi_read_cnt = 0;
for (auto& cc_worker : cc_workers) {
cc_worker->reset();
}
@ -270,11 +264,6 @@ void sf_worker::work_imp()
update_measurements();
}
// Call feedback loop for chest
if (chest_loop && ((1U << (tti % 10U)) & phy->args->cfo_ref_mask)) {
chest_loop->set_cfo(cc_workers[0]->get_ref_cfo());
}
/* Tell the plotting thread to draw the plots */
#ifdef ENABLE_GUI
if ((int)get_id() == plot_worker_id) {
@ -294,66 +283,20 @@ void sf_worker::reset_uci(srslte_uci_data_t* uci_data)
void sf_worker::update_measurements()
{
/* Only worker 0 reads the RSSI sensor every ~1-nof_cores s */
// Run measurements in all carriers, but only in one worker
if (get_id() == 0) {
// Average RSSI over all symbols in antenna port 0 (make sure SF length is non-zero)
float rssi_dbm = SRSLTE_SF_LEN_PRB(cell.nof_prb) > 0
? (srslte_convert_power_to_dB(srslte_vec_avg_power_cf(cc_workers[0]->get_rx_buffer(0),
SRSLTE_SF_LEN_PRB(cell.nof_prb))) +
30)
: 0;
if (std::isnormal(rssi_dbm)) {
phy->avg_rssi_dbm[0] = SRSLTE_VEC_EMA(rssi_dbm, phy->avg_rssi_dbm[0], phy->args->snr_ema_coeff);
}
if (!rssi_read_cnt) {
phy->rx_gain_offset = phy->get_radio()->get_rx_gain() + phy->args->rx_gain_offset;
}
rssi_read_cnt++;
if (rssi_read_cnt == 1000) {
rssi_read_cnt = 0;
}
}
// Run measurements in all carriers
std::vector<rrc_interface_phy_lte::phy_meas_t> serving_cells = {};
for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) {
bool active = (cc_idx == 0 || phy->scell_cfg[cc_idx].configured);
// Update measurement of the Component Carrier
cc_workers[cc_idx]->update_measurements();
// Send measurements for serving cells
if (active && ((tti % phy->pcell_report_period) == phy->pcell_report_period - 1)) {
rrc_interface_phy_lte::phy_meas_t meas = {};
meas.rsrp = phy->avg_rsrp_dbm[cc_idx];
meas.rsrq = phy->avg_rsrq_db[cc_idx];
meas.cfo_hz = phy->avg_cfo_hz[cc_idx];
// Save EARFCN and PCI for secondary cells, primary cell has earfcn=0
if (cc_idx > 0) {
meas.earfcn = phy->scell_cfg[cc_idx].earfcn;
meas.pci = phy->scell_cfg[cc_idx].pci;
}
serving_cells.push_back(meas);
cf_t* rssi_power_buffer = nullptr;
if (cc_idx == 0) {
rssi_power_buffer = cc_workers[0]->get_rx_buffer(0);
}
cc_workers[cc_idx]->update_measurements(serving_cells, rssi_power_buffer);
}
// Send report to stack
if (not serving_cells.empty()) {
phy->stack->new_cell_meas(serving_cells);
}
// Check in-sync / out-sync conditions
if (phy->avg_rsrp_dbm[0] > phy->args->in_sync_rsrp_dbm_th && phy->avg_snr_db_cqi[0] > phy->args->in_sync_snr_db_th) {
log_h->debug("SNR=%.1f dB, RSRP=%.1f dBm sync=in-sync from channel estimator\n",
phy->avg_snr_db_cqi[0],
phy->avg_rsrp_dbm[0]);
chest_loop->in_sync();
} else {
log_h->warning("SNR=%.1f dB RSRP=%.1f dBm, sync=out-of-sync from channel estimator\n",
phy->avg_snr_db_cqi[0],
phy->avg_rsrp_dbm[0]);
chest_loop->out_of_sync();
}
}
@ -387,12 +330,6 @@ int sf_worker::read_pdsch_d(cf_t* pdsch_d)
{
return cc_workers[0]->read_pdsch_d(pdsch_d);
}
float sf_worker::get_sync_error()
{
dl_metrics_t dl_metrics[SRSLTE_MAX_CARRIERS] = {};
phy->get_dl_metrics(dl_metrics);
return dl_metrics->sync_err;
}
float sf_worker::get_cfo()
{

@ -445,7 +445,7 @@ void sync::run_camping_in_sync_state(sf_worker* worker, srslte::rf_buffer_t& syn
// Set CFO for all Carriers
for (uint32_t cc = 0; cc < worker_com->args->nof_carriers; cc++) {
worker->set_cfo(cc, get_tx_cfo());
worker_com->avg_cfo_hz[cc] = srslte_ue_sync_get_cfo(&ue_sync);
worker_com->update_cfo_measurement(cc, srslte_ue_sync_get_cfo(&ue_sync));
}
worker->set_tti(tti);
@ -870,7 +870,7 @@ int sync::radio_recv_fnc(srslte::rf_buffer_t& data, srslte_timestamp_t* rx_time)
intra_freq_meas[i]->write(tti, data.get(i, 0, worker_com->args->nof_rx_ant), SRSLTE_SF_LEN_PRB(cell.nof_prb));
// Update RX gain
intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset);
intra_freq_meas[i]->set_rx_gain_offset(worker_com->get_rx_gain_offset());
}
}

@ -46,8 +46,8 @@ public:
bzero(m, sizeof(ue_metrics_t));
m->rf.rf_o = 10;
m->phy.nof_active_cc = 2;
m->phy.dl[0].rsrp = -10.0f;
m->phy.dl[0].pathloss = 74;
m->phy.ch[0].rsrp = -10.0f;
m->phy.ch[0].pathloss = 74;
m->stack.mac[0].rx_pkts = 100;
m->stack.mac[0].rx_errors = 0;

Loading…
Cancel
Save