PHY CC configuration is stashed and applied in the next TTI

This commit is contained in:
Xavier Arteaga 2021-05-28 15:29:00 +02:00 committed by Xavier Arteaga
parent 235a664120
commit 7185ec6beb
7 changed files with 91 additions and 20 deletions

View File

@ -40,8 +40,8 @@ public:
void reset_cell_unlocked();
bool set_cell_unlocked(srsran_cell_t cell_);
void set_tdd_config_unlocked(srsran_tdd_config_t config);
void set_config_unlocked(srsran::phy_cfg_t& phy_cfg);
void upd_config_dci_unlocked(srsran_dci_cfg_t& dci_cfg);
void set_config_unlocked(const srsran::phy_cfg_t& phy_cfg);
void upd_config_dci_unlocked(const srsran_dci_cfg_t& dci_cfg);
void set_uci_periodic_cqi(srsran_uci_data_t* uci_data);

View File

@ -48,7 +48,7 @@ public:
void set_cfo_unlocked(const uint32_t& cc_idx, float cfo);
void set_tdd_config_unlocked(srsran_tdd_config_t config);
void set_config_unlocked(uint32_t cc_idx, srsran::phy_cfg_t phy_cfg);
void set_config_unlocked(uint32_t cc_idx, const srsran::phy_cfg_t& phy_cfg);
///< Methods for plotting called from GUI thread
int read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna);

View File

@ -21,9 +21,25 @@ namespace lte {
class worker_pool
{
private:
srsran::thread_pool pool;
std::vector<std::unique_ptr<sf_worker> > workers;
class phy_cfg_stash_t
{
private:
std::vector<bool> pending; ///< Indicates for each SF worker if it has pending configuration
srsran::phy_cfg_t cfg; ///< Actual CC configuration
public:
phy_cfg_stash_t(uint32_t max_workers) : pending(max_workers) {}
void set_cfg(const srsran::phy_cfg_t& c);
bool is_pending(uint32_t sf_idx);
const srsran::phy_cfg_t& get_cfg(uint32_t sf_idx);
};
std::mutex phy_cfg_mutex; ///< Protects configuration stash
std::array<phy_cfg_stash_t, SRSRAN_MAX_CARRIERS> phy_cfg_stash; ///< Stores the latest worker configuration
public:
sf_worker* operator[](std::size_t pos) { return workers.at(pos).get(); }
@ -33,6 +49,14 @@ public:
sf_worker* wait_worker_id(uint32_t id);
void start_worker(sf_worker* w);
void stop();
/**
* @brief Sets a new configuration for a given CC, it copies the new configuration into the stash and it will be
* applied to the sf_worker at the time it is reserved.
* @param cc_idx CC index
* @param phy_cfg Actual PHY configuration
*/
void set_config_unlocked(uint32_t cc_idx, srsran::phy_cfg_t phy_cfg);
};
} // namespace lte

View File

@ -860,7 +860,7 @@ void cc_worker::set_uci_ack(srsran_uci_data_t* uci_data,
/* Translates RRC structs into PHY structs
*/
void cc_worker::set_config_unlocked(srsran::phy_cfg_t& phy_cfg)
void cc_worker::set_config_unlocked(const srsran::phy_cfg_t& phy_cfg)
{
// Save configuration
ue_dl_cfg.cfg = phy_cfg.dl_cfg;
@ -869,7 +869,7 @@ void cc_worker::set_config_unlocked(srsran::phy_cfg_t& phy_cfg)
phy->set_pdsch_cfg(&ue_dl_cfg.cfg.pdsch);
}
void cc_worker::upd_config_dci_unlocked(srsran_dci_cfg_t& dci_cfg)
void cc_worker::upd_config_dci_unlocked(const srsran_dci_cfg_t& dci_cfg)
{
ue_dl_cfg.cfg.dci = dci_cfg;
}

View File

@ -138,7 +138,7 @@ void sf_worker::set_tdd_config_unlocked(srsran_tdd_config_t config)
tdd_config = config;
}
void sf_worker::set_config_unlocked(uint32_t cc_idx, srsran::phy_cfg_t phy_cfg)
void sf_worker::set_config_unlocked(uint32_t cc_idx, const srsran::phy_cfg_t& phy_cfg)
{
if (cc_idx < cc_workers.size()) {
cc_workers[cc_idx]->set_config_unlocked(phy_cfg);

View File

@ -14,7 +14,34 @@
namespace srsue {
namespace lte {
worker_pool::worker_pool(uint32_t max_workers) : pool(max_workers) {}
void worker_pool::phy_cfg_stash_t::set_cfg(const srsran::phy_cfg_t& c)
{
for (auto it = pending.begin(); it < pending.end(); it++) {
*it = true;
}
cfg = c;
}
bool worker_pool::phy_cfg_stash_t::is_pending(uint32_t sf_idx)
{
if (sf_idx >= (uint32_t)pending.size()) {
return false;
}
return pending[sf_idx];
}
const srsran::phy_cfg_t& worker_pool::phy_cfg_stash_t::get_cfg(uint32_t sf_idx)
{
if (sf_idx < (uint32_t)pending.size()) {
pending[sf_idx] = false;
}
return cfg;
}
worker_pool::worker_pool(uint32_t max_workers) :
pool(max_workers), phy_cfg_stash{{max_workers, max_workers, max_workers, max_workers, max_workers}}
{}
bool worker_pool::init(phy_common* common, int prio)
{
@ -39,7 +66,23 @@ void worker_pool::start_worker(sf_worker* w)
sf_worker* worker_pool::wait_worker(uint32_t tti)
{
return (sf_worker*)pool.wait_worker(tti);
sf_worker* w = (sf_worker*)pool.wait_worker(tti);
if (w == nullptr) {
return w;
}
// Protect configuration
std::unique_lock<std::mutex> lock(phy_cfg_mutex);
// Iterate all CC searching for a pending configuration
uint32_t worker_id = w->get_id();
for (uint32_t cc_idx = 0; cc_idx < SRSRAN_MAX_CARRIERS; cc_idx++) {
if (phy_cfg_stash[cc_idx].is_pending(worker_id)) {
w->set_config_unlocked(cc_idx, phy_cfg_stash[cc_idx].get_cfg(worker_id));
}
}
return w;
}
sf_worker* worker_pool::wait_worker_id(uint32_t id)
@ -52,5 +95,16 @@ void worker_pool::stop()
pool.stop();
}
void worker_pool::set_config_unlocked(uint32_t cc_idx, srsran::phy_cfg_t phy_cfg)
{
// Protect CC index bounds
if (cc_idx >= SRSRAN_MAX_CARRIERS) {
return;
}
// Protect configuration
std::unique_lock<std::mutex> lock(phy_cfg_mutex);
phy_cfg_stash[cc_idx].set_cfg(phy_cfg);
}
}; // namespace lte
}; // namespace srsue

View File

@ -440,18 +440,10 @@ bool phy::set_config(const srsran::phy_cfg_t& config_, uint32_t cc_idx)
prach_cfg = config_.prach_cfg;
}
// Apply configuration after the worker is finished to avoid race conditions
// Apply configurations asynchronously to avoid race conditions
cmd_worker.add_cmd([this, config_, cc_idx]() {
logger_phy.info("Setting new PHY configuration cc_idx=%d...", cc_idx);
for (uint32_t i = 0; i < args.nof_phy_threads; i++) {
// set_cell is not protected so run when worker is finished
lte::sf_worker* w = lte_workers.wait_worker_id(i);
if (w) {
w->set_config_unlocked(cc_idx, config_);
w->release();
}
}
logger_phy.info("Finished setting new PHY configuration cc_idx=%d", cc_idx);
lte_workers.set_config_unlocked(cc_idx, config_);
// It is up to the PRACH component to detect whether the cell or the configuration have changed to reconfigure
configure_prach_params();
@ -497,7 +489,7 @@ bool phy::set_scell(srsran_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn)
// Component carrier index zero should be reserved for PCell
// Send configuration to workers
cmd_worker.add_cmd([this, cell_info, cc_idx, earfcn, earfcn_is_different]() {
logger_phy.info("Setting new SCell configuration cc_idx=%d, earfcn=%d...", cc_idx, earfcn);
logger_phy.info("Setting new SCell configuration cc_idx=%d, earfcn=%d, pci=%d...", cc_idx, earfcn, cell_info.id);
for (uint32_t i = 0; i < args.nof_phy_threads; i++) {
// set_cell is not protected so run when worker has finished to ensure no PHY processing is done at the time of
// cell setting
@ -526,7 +518,8 @@ bool phy::set_scell(srsran_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn)
// Set secondary serving cell synchronization
sfsync.scell_sync_set(cc_idx, cell_info);
logger_phy.info("Finished setting new SCell configuration cc_idx=%d, earfcn=%d", cc_idx, earfcn);
logger_phy.info(
"Finished setting new SCell configuration cc_idx=%d, earfcn=%d, pci=%d", cc_idx, earfcn, cell_info.id);
// Configure secondary serving cell, allows this component carrier to execute PHY processing
common.cell_state.configure(cc_idx, earfcn, cell_info.id);