Program Listing for File register.hpp
↰ Return to documentation for file (register.hpp)
#include "log.hpp"
#include "config/config_register.hpp"
#include "device.hpp"
#include "regmap_manager.hpp"
#include "register_device_controller.hpp"
#include "hardware_monitor.hpp"
#include <sys/types.h>
#include <memory>
#include "network/netio_evloop.hpp"
template <class DEV>
class Register {
public:
explicit Register(const ConfigRegister & conf);
private:
RegmapManager m_regmap;
std::variant<NetioEventLoop> m_evt_loop;
std::map<int, std::shared_ptr<DEV>> m_devices;
std::map<int, std::shared_ptr<RegisterDeviceController<DEV>>> m_dev_registers;
std::unique_ptr<HwMonitor<DEV>> hw_mon;
void init_device(int dev_no);
int get_or_init_primary(int dev_no);
int get_or_init_secondary(int dev_no);
int get_primary(int dev_no);
};
template <class DEV>
Register<DEV>::Register(const ConfigRegister & c) : m_evt_loop{[&c](){
switch (c.evloop_type){
case EventLoopType::netio_next:
return std::variant<NetioEventLoop>{NetioEventLoop()};
case EventLoopType::netio3_native:
case EventLoopType::netio3_asio:
throw std::runtime_error("Netio3 not implemented");
default:
throw std::runtime_error("Unknown event loop type");
}
}()}
{
log_init(c.verbose);
for (const auto & dc : c.dconfs){
LOG_INFO("Opening device %d", dc.dev_no);
init_device(dc.dev_no);
}
unsigned int idx = 0; //to pass the single-device configuration to DeviceRegister
for (const auto & dc : c.dconfs) {
LOG_INFO("Device %u: send commands to fid 0x%lx, get reply from 0x%lx", dc.dev_no, dc.fid_cmd, dc.fid_reply);
int primary_no = get_or_init_primary(dc.dev_no);
m_dev_registers.emplace(std::piecewise_construct,
std::forward_as_tuple(dc.dev_no),
std::forward_as_tuple(
std::make_shared<RegisterDeviceController<DEV>>(
m_evt_loop, m_regmap, m_devices.at(dc.dev_no), m_devices.at(primary_no), c, idx))
);
++idx;
}
if (c.enable_mon){
using device_pair = std::pair<std::shared_ptr<DEV>, std::shared_ptr<DEV>>;
std::vector<device_pair> all_devices;
//make sure that that all requested devices are paired.
for (const auto & dc : c.dconfs) {
get_or_init_secondary(dc.dev_no);
}
//loop over all opened devices and match each primary with a secondary
for (const auto &[dev_no, dev_ptr] : m_devices) {
if (dev_ptr->is_primary()) {
int secondary = get_or_init_secondary(dev_no);
if (secondary != -1) {
all_devices.push_back({m_devices.at(dev_no), m_devices.at(secondary)});
} else {
all_devices.push_back({m_devices.at(dev_no), nullptr});
}
}
}
LOG_INFO("Monitoring info for all devices on fid 0x%lx", c.fid_mon);
hw_mon = std::make_unique<HwMonitor<DEV>>(all_devices, c);
}
std::visit([] (auto& evloop) { evloop.start(); }, m_evt_loop);
}
template <class DEV>
void Register<DEV>::init_device(int dev_no)
{
m_devices.emplace(dev_no, new DEV(dev_no));
unsigned int lock_mask = 0;
m_devices.at(dev_no)->open_device(lock_mask);
}
template <class DEV>
int Register<DEV>::get_or_init_primary(int dev_no)
{
int primary = get_primary(dev_no);
if (dev_no != primary and m_devices.count(primary) == 0){
LOG_INFO("Opening required primary device %d", primary);
init_device(primary);
}
return primary;
}
template <class DEV>
int Register<DEV>::get_or_init_secondary(int dev_no)
{
int secondary = -1;
if (m_devices.at(dev_no)->is_primary() and m_devices.at(dev_no)->get_card_endpoints() > 1){
secondary = dev_no + 1;
if (m_devices.count(secondary) == 0){
LOG_INFO("Opening required secondary device (for monitoring) %d", secondary);
init_device(secondary);
}
}
else if (not m_devices.at(dev_no)->is_primary()){
secondary = dev_no;
}
return secondary;
}
template <class DEV>
int Register<DEV>::get_primary(int dev_no)
{
int primary{-1};
if ( m_devices.at(dev_no)->is_primary() ){
primary = dev_no;
} else {
primary = dev_no - 1;
}
return primary;
}