Program Listing for File register.hpp
↰ Return to documentation for file (register.hpp)
#include "ers/ers.h"
#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 "netio3-backend/EventLoop/AsioEventLoop.hpp"
#include "netio3-backend/EventLoop/EpollEventLoop.hpp"
#include <format>
#include "network/netio3_evloop.hpp"
template <class DEV>
class Register {
public:
explicit Register(const ConfigRegister & conf);
private:
RegmapManager m_regmap;
Netio3EventLoop 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.network_mode) {
case NetworkMode::tcp:
return Netio3EventLoop{Netio3EventLoop::type_tag<netio3::AsioEventLoop>()};
case NetworkMode::rdma:
return Netio3EventLoop{Netio3EventLoop::type_tag<netio3::EpollEventLoop>()};
default:
throw std::runtime_error("Unknown network mode");
}
}()}
{
for (const auto & dc : c.dconfs){
ERS_INFO(std::format("Opening device {}", 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) {
ERS_INFO(std::format("Device {}: send commands to fid {:#x}, get reply from {:#x}", dc.dev_no, dc.fid_cmd, dc.fid_reply));
int primary_no = get_or_init_primary(dc.dev_no);
m_dev_registers.try_emplace(dc.dev_no, 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});
}
}
}
ERS_INFO(std::format("Monitoring info for all devices on fid {:#x}", c.fid_mon));
hw_mon = std::make_unique<HwMonitor<DEV>>(all_devices, c);
}
m_evt_loop.start();
}
template <class DEV>
void Register<DEV>::init_device(int dev_no)
{
m_devices.emplace(dev_no, std::make_unique<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){
ERS_INFO(std::format("Opening required primary device {}", 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){
ERS_INFO(std::format("Opening required secondary device (for monitoring) {}", 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;
}