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.

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::string encode_commands(const std::vector<Command> &cmds)

encodes a vector of commands into a json array

Parameters:
  • fid -- the reply fid

  • cmds -- vector of Command structures cdescribing commands

Returns:

an std::string containin the command json array

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.

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 &regmap, 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 &reg_name)

read a register.

Parameters:

reg_name -- register name.

Returns:

the register value

void set_register(const std::string &reg_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 &reg_name)
Returns:

whether the register is readable

inline bool can_write(const std::string &reg_name)
Returns:

whether the register is writable

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

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.