felix-register
Felix-register allows to edit registers from a remote endpoint. On the receiving side, felix-register advertises one command e-link per device whose identifier is built using a predefined value, the detector ID and the connector ID of the device. Messages bound to the command e-link are encoded in JSON and contain the command type (e.g. GET, SET) and the name of the register to act upon. Once the command has been executed, or an error occurred, a reply is sent over the reply e-link. The reply is also in JSON format.
In addition, felix-register publishes monitoring information regarding the hardware status of each card.
Note
The reception of commands uses the send/receive pattern. Replies are sent using the publish/subscribe pattern.
Top-level Class
The top-level class is Register, used to build two executables: felix-register that works with a FELIX card and felix-fileregister that emulates the hardware. Register is templated to support both use cases. Register supports multiple devices and runs two threads: one thread for the event loop shared by all the receivers and publishers for the register editing, and one run by the publisher of hardware monitoring information.
Important
Some registers are associated only to the primary device of a card as reported in the FELIX register map. Therefore, Register will make sure that both primary and secondary devices are open. If the primary is not, it will open it.
-
template<class DEV>
class Register felix-register main class to handle multiple devices as per run-time configuration. Each device is assigned a DeviceRegister. All DeviceRegisters share the same RegmapManager.
Public Functions
-
explicit Register(const ConfigRegister &conf)
the Register constructor opens all necessary devices, and initialises the network backed. The register-editing functionality does not spawn a new thread (uses the same that creates the object), the heardware monitor instead runs on a dedicated thread and event loop.
-
explicit Register(const ConfigRegister &conf)
Network Front-End
RegisterDeviceController is the class that owns a receiver and a publisher for each device associated to the event loop owned by Register. RegisterDeviceController's methods are registered as callbacks.
-
template<class DEV>
class RegisterDeviceController DeviceRegister implements the remote register read/write and remote monitoring for each device. Each DeviceRegisters has one receiver (cmd) and a publishers (reply).
Command Parser
Messages received by RegisterDeviceController are parsed by RegisterMsgParser. The same class encodes replies. Therefore defines the message serialisation and deserialisation.
-
class RegisterMsgParser
RegisterMsgParser de-serialises json-formatted commands (json string to struct) and serialises replies (struct to json string)
Public Functions
-
std::vector<ReqData> parse_commands(const char *msg, size_t len)
parses a char array containing a command in json format
- Parameters:
msg -- pointer to message C-string
len -- length of C-string message
- Returns:
a ReqData struct containing the command.
-
std::vector<ReqData> parse_commands(const std::string &cmd)
parses a string containing a command in json format
- Parameters:
cmd -- the command string
- Returns:
a ReqData struct containing the command.
-
std::string encode_replies(uint64_t fid, const std::vector<ReqData> &cmds)
encodes a reply in json
- Parameters:
fid -- the reply fid
cmds -- vector of ReqData structures containing the command execution data
- Returns:
an std::string containin the reply in serialised json.
-
std::vector<FelixClientThread::Reply> decode_replies(const std::string &r)
decode felix-register replies
- Parameters:
r -- the string containing the reply array in json format
- Returns:
a vector of FelixClientThread::Reply containing the decoded replies.
-
std::vector<ReqData> parse_commands(const char *msg, size_t len)
RegisterMap Manager
Provided that a command is well formatted, the legitimacy of the request is checked before interacting with the hardware. RegmapManager checks the register type (read or write) and PCIe endpoint. If the register can be written only from the primary device but the request came for the secondary, the command will have to be rerouted by the upper layers.
-
class RegmapManager
RegmapManager parses the YAML file that describes the register map, therefore it knows whether a register exists, it is readable, writable and whether it is attached to the secondary PCIe endpoint. RegmapManager does not interact with the FELIX card (real or emulated).
Public Functions
-
inline bool can_read(const std::string &name)
- Parameters:
name -- the register name.
- Returns:
whether the register is readable.
-
inline bool can_write(const std::string &name)
- Parameters:
name -- the register name.
- Returns:
whether the register is writable.
-
inline bool has_endpoint_1(const std::string &name)
- Parameters:
name -- the register name.
- Returns:
whether the register is used also by the secondary PCIe endpoint.
-
inline bool can_read(const std::string &name)
Device Interface
The interaction with the card happens via RegisterDeviceInterface. This class is templated such that is can act on a physical or emulated device.
-
template<class DEV>
class RegisterDeviceInterface Felix-register interface to a PCIe endpoint.
Public Functions
-
inline RegisterDeviceInterface(RegmapManager ®map, std::shared_ptr<DEV> main, std::shared_ptr<DEV> primary)
RegisterDeviceManager class constructor.
- Parameters:
regmap -- the owner of the the yaml register map.
main -- the PCIe endpoint for this RegisterDeviceManager.
primary -- the primary PCIe endpoint correspoding to "main".
-
uint64_t get_register(const std::string ®_name)
read a register.
- Parameters:
reg_name -- register name.
- Returns:
the register value
-
void set_register(const std::string ®_name, uint64_t value)
set a register.
- Parameters:
reg_name -- register name.
values -- the value to be set.
-
inline bool can_read(const std::string ®_name)
- Returns:
whether the register is readable
-
inline bool can_write(const std::string ®_name)
- Returns:
whether the register is writable
-
inline RegisterDeviceInterface(RegmapManager ®map, std::shared_ptr<DEV> main, std::shared_ptr<DEV> primary)
Hardware Monitoring
The hardware monitor is implemented by two classes, HwMonitor that owns the publisher and interacts with the network, and and HwMonBackend that gathers the data using the Device methods and prepares the message.
-
template<class DEV>
class HwMonitor HwMonFrontend published over the network hardware monitoring information for all requested devices using a single publisher. HwMonFrontend shall run on a dedicated thread as the retrieval of info can be blocking due to the regulation of concurrent access to the I2C bus.
Public Functions
-
HwMonitor(const std::vector<device_pair> &device_pairs, const ConfigRegister &c)
open the device.
- Parameters:
device_pairs -- pair of primary and secondary device of a card.
c -- configuration data structure.
-
bool publish_monitor_info()
publish monitoring information message over the network
-
HwMonitor(const std::vector<device_pair> &device_pairs, const ConfigRegister &c)
-
template<class DEV>
class HwMonBackend HwMonBackend retrieves the monitoring information for the requested number of cards. The monitored quantities are those available in FlxCard's monitoring_data_t. A custom set of registers to monitor can be passed by means of a file read at startup time. The monitoring information is returned in json format. No interaction with the network.
Public Functions
-
HwMonBackend(const std::vector<device_pair> &device_pairs, const std::string &extras_file)
- Parameters:
device_pairs -- pair of primary and secondary device of a card.
extras_file -- name of file containing additional registers to monitor.
-
std::string get_monitor_data()
- Returns:
string containing the monitoring information in JSON format.
-
HwMonBackend(const std::vector<device_pair> &device_pairs, const std::string &extras_file)