30#define TRACE_NAME "TimingHardwareManagerBase"
63 m_params = mod_config->get_configuration();
66 for (
auto con : mod_config->get_inputs()) {
67 if (con->get_data_type() == datatype_to_string<timingcmd::TimingHwCmd>()) {
95 TLOG_DEBUG(3) << fanout->get_device() <<
": device, slot: " << fanout->get_fanout_slot() << std::endl;
116 auto time_of_scrap = std::chrono::high_resolution_clock::now();
118 auto now = std::chrono::high_resolution_clock::now();
119 auto ms_since_scrap = std::chrono::duration_cast<std::chrono::milliseconds>(now - time_of_scrap);
121 <<
" command threads to finish...";
122 std::this_thread::sleep_for(std::chrono::microseconds(250000));
141 if (!device_name.compare(
"")) {
142 std::stringstream message;
143 message <<
"UHAL device name is an empty string";
144 throw UHALDeviceNameIssue(
ERS_HERE, message.str());
148 return dynamic_cast<const timing::TimingNode*
>(&hw_device_entry->second->getNode(
""));
150 TLOG_DEBUG(0) << get_name() <<
": hw device interface for: " << device_name
151 <<
" does not exist. I will try to create it.";
157 }
catch (
const uhal::exception::ConnectionUIDDoesNotExist& exception) {
158 std::stringstream message;
159 message <<
"UHAL device name not " << device_name <<
" in connections file";
160 throw UHALDeviceNameIssue(
ERS_HERE, message.str(), exception);
163 TLOG_DEBUG(0) << get_name() <<
": hw device interface for: " << device_name <<
" successfully created.";
172 auto device_name = gatherer.get_device_name();
174 while (gatherer.run_gathering()) {
180 gatherer.collect_info_from_device(*design);
181 }
catch (
const std::exception& excpt) {
185 auto prev_gather_time = std::chrono::steady_clock::now();
186 auto next_gather_time = prev_gather_time + std::chrono::microseconds(gatherer.get_gather_interval());
189 auto slice_period = std::chrono::microseconds(10000);
190 auto next_slice_gather_time = prev_gather_time + slice_period;
192 bool break_flag =
false;
193 while (next_gather_time > next_slice_gather_time + slice_period) {
194 if (!gatherer.run_gathering()) {
195 TLOG_DEBUG(0) <<
"while waiting to gather data, negative run gatherer flag detected.";
199 std::this_thread::sleep_until(next_slice_gather_time);
200 next_slice_gather_time = next_slice_gather_time + slice_period;
202 if (break_flag ==
false) {
203 std::this_thread::sleep_until(next_gather_time);
210 const std::string& device_name,
213 std::string gatherer_name = device_name +
"_level_" + std::to_string(op_mon_level);
215 std::unique_ptr<InfoGatherer> gatherer = std::make_unique<InfoGatherer>(
221 TLOG_DEBUG(0) <<
"Registering info gatherer: " << gatherer_name;
222 m_info_gatherers.emplace(std::make_pair(gatherer_name, std::move(gatherer)));
224 TLOG() <<
"Skipping registration of " << gatherer_name <<
". Already exists.";
232 if (!device_name.compare(
"")) {
233 TLOG_DEBUG(0) << get_name() <<
" Starting all info gatherers";
235 it->second.get()->start_gathering_thread();
238 bool gatherer_found =
false;
240 TLOG_DEBUG(0) << get_name() <<
" Starting info gatherer: " << it->first;
241 it->second.get()->start_gathering_thread();
242 gatherer_found =
true;
253 if (!device_name.compare(
"")) {
254 TLOG_DEBUG(0) << get_name() <<
" Stopping all info gatherers";
256 it->second.get()->stop_gathering_thread();
259 bool gatherer_found =
false;
261 TLOG_DEBUG(0) << get_name() <<
" Stopping info gatherer: " << it->first;
262 it->second.get()->stop_gathering_thread();
263 gatherer_found =
true;
270std::vector<std::string>
273 std::vector<std::string> running_gatherers;
275 TLOG_DEBUG(0) << get_name() <<
" Checking run state of info gatherer: " << it->first <<
", and the state is "
276 << it->second.get()->run_gathering();
277 if (it->second.get()->run_gathering()) {
278 running_gatherers.push_back(it->first);
281 return running_gatherers;
289 std::ostringstream starting_stream;
290 starting_stream <<
": Executing process_hardware_command() callback.";
291 TLOG_DEBUG(0) << get_name() << starting_stream.str();
296 <<
", it is of type: " << timing_hw_cmd.
id <<
", targeting device: " << timing_hw_cmd.
device
297 <<
", with payload: " << timing_hw_cmd.
payload.dump();
299 std::string hw_cmd_name = timing_hw_cmd.
id;
304 TLOG_DEBUG(0) <<
"Found hw cmd: " << hw_cmd_name;
306 std::invoke(cmd->second, timing_hw_cmd);
307 }
catch (
const std::exception& exception) {
316 std::ostringstream exiting_stream;
317 exiting_stream <<
": Finished executing process_hardware_command() callback. Received "
319 TLOG_DEBUG(0) << get_name() << exiting_stream.str();
333 for (
auto& gatherer : running_hw_gatherers) {
339 if (cmd_payload.
soft) {
341 design->soft_reset_io();
344 <<
" io reset, with supplied clk file: " << cmd_payload.
clock_config;
348 <<
" io reset, with supplied clk source: " << cmd_payload.
clock_source;
353 for (
auto& gatherer : running_hw_gatherers) {
364 TLOG() << std::endl << design->get_status();
375 <<
" set timestamp, with supplied ts source: " << cmd_payload.
timestamp_source;
384 TLOG_DEBUG(0) << get_name() <<
": " << hw_cmd.
device <<
" master_endpoint_scan";
386 std::stringstream command_thread_uid;
387 auto t = std::time(
nullptr);
388 auto tm = *std::localtime(&t);
389 command_thread_uid <<
"enpoint_scan_cmd_at_" << std::put_time(&tm,
"%d-%m-%Y %H-%M-%S") <<
"_cmd_num_"
395 TLOG_DEBUG(1) <<
"Queuing: " << command_thread_uid.str();
397 auto thread_key = command_thread_uid.str();
412 for (
auto& endpoint_location : cmd_payload.
endpoints) {
413 auto endpoint_address = endpoint_location.address;
414 auto fanout_slot = endpoint_location.fanout_slot;
415 auto sfp_slot = endpoint_location.sfp_slot;
420 <<
" master_endpoint_scan starting: ept adr: " << endpoint_address <<
", ept sfp: " << sfp_slot
421 <<
", fanout slot: " << fanout_slot;
428 if (fanout_slot >= 0) {
432 ->switch_mux(sfp_slot);
433 }
catch (
const UHALDeviceClassIssue& e) {
439 if (fanout_slot != 0) {
443 }
catch (
const UHALDeviceClassIssue& e) {
453 auto scan_result = master_design->get_master_node_plain()->scan_endpoint(endpoint_address,
true);
454 if (scan_result.alive) {
455 auto current_rtt = scan_result.round_trip_time;
456 ers::info(EndpointRTTMeasurement(
ERS_HERE, fanout_slot, sfp_slot, endpoint_address, current_rtt));
459 if (previous_rtt != current_rtt) {
463 ERS_HERE, fanout_slot, sfp_slot, endpoint_address, current_rtt, previous_rtt));
474 }
catch (std::exception& e) {
476 master_design->get_master_node_plain()->switch_endpoint_sfp(endpoint_address,
false);
484 TLOG_DEBUG(0) <<
"Entering clean_endpoint_scan_threads()";
485 bool break_flag =
false;
486 while (!break_flag) {
488 if (
thread.second->joinable()) {
496 auto prev_clean_time = std::chrono::steady_clock::now();
497 auto next_clean_time = prev_clean_time + std::chrono::milliseconds(30);
500 auto flag_check_period = std::chrono::milliseconds(1);
501 auto next_flag_check_time = prev_clean_time + flag_check_period;
503 while (next_clean_time > next_flag_check_time + flag_check_period) {
505 TLOG_DEBUG(2) <<
"while waiting to clean up endpoint scan threads, negative run gatherer flag detected.";
509 std::this_thread::sleep_until(next_flag_check_time);
510 next_flag_check_time = next_flag_check_time + flag_check_period;
512 if (break_flag ==
false) {
513 std::this_thread::sleep_until(next_clean_time);
516 TLOG_DEBUG(0) <<
"Exiting clean_endpoint_scan_threads()";
523 TLOG_DEBUG(0) << get_name() <<
": " << hw_cmd.
device <<
" set endpoint delay";
529 design->apply_endpoint_delay(cmd_payload.
address,
545 <<
", parsed data: " << cmd_payload.
fl_cmd_id <<
", " << cmd_payload.
channel <<
", "
549 design->get_master_node_plain()->send_fl_cmd(
576 design->get_endpoint_node_plain(cmd_payload.
endpoint_id)->disable();
599 design->get_hsi_node().reset_hsi();
624 design->get_hsi_node().start_hsi();
633 design->get_hsi_node().stop_hsi();
639 TLOG_DEBUG(0) << get_name() <<
": " << hw_cmd.
device <<
" hsi print status";
642 TLOG() << std::endl << design->get_hsi_node().get_status();
#define DUNE_DAQ_SERIALIZABLE(Type, typestring)
Macro to define a type as serializable, so it can be sent over the network.
static std::shared_ptr< IOManager > get()
Base class for timing endpoint design nodes.
Base class for timing nodes.
std::unique_ptr< uhal::ConnectionManager > m_connection_manager
void configure_uhal(const dunedaq::timinglibs::dal::TimingHardwareInterfaceConf *mdal)
std::atomic< bool > m_run_endpoint_scan_cleanup_thread
const timing::TimingNode * get_timing_device_plain(const std::string &device_name)
void hsi_stop(const timingcmd::TimingHwCmd &hw_cmd)
std::atomic< uint64_t > m_accepted_hw_commands_counter
void io_reset(const timingcmd::TimingHwCmd &hw_cmd)
void print_status(const timingcmd::TimingHwCmd &hw_cmd)
void register_info_gatherer(uint gather_interval, const std::string &device_name, int op_mon_level)
TIMING_DEV get_timing_device(const std::string &device_name)
std::map< std::string, std::unique_ptr< uhal::HwInterface > > m_hw_device_map
virtual void perform_endpoint_scan(const timingcmd::TimingHwCmd &hw_cmd)
virtual void conf(const CommandData_t &data)
std::atomic< uint64_t > m_received_hw_commands_counter
std::map< uint, std::string > m_monitored_device_names_fanout
virtual void clean_endpoint_scan_threads()
void endpoint_reset(const timingcmd::TimingHwCmd &hw_cmd)
void init(std::shared_ptr< appfwk::ConfigurationManager > mcfg) override
std::shared_ptr< source_t > m_hw_command_receiver
uint m_gather_interval_debug
void hsi_reset(const timingcmd::TimingHwCmd &hw_cmd)
void set_endpoint_delay(const timingcmd::TimingHwCmd &hw_cmd)
virtual void process_hardware_command(timingcmd::TimingHwCmd &timing_hw_cmd)
std::unique_ptr< dunedaq::utilities::ReusableThread > m_endpoint_scan_threads_clean_up_thread
std::atomic< uint64_t > m_rejected_hw_commands_counter
std::atomic< uint64_t > m_failed_hw_commands_counter
void gather_monitor_data(InfoGatherer &gatherer)
void hsi_configure(const timingcmd::TimingHwCmd &hw_cmd)
std::string m_monitored_device_name_endpoint
void set_timestamp(const timingcmd::TimingHwCmd &hw_cmd)
std::map< uint, int > m_monitored_endpoints_round_trip_times
virtual void start_hw_mon_gathering(const std::string &device_name="")
std::string m_monitored_device_name_master
virtual void stop_hw_mon_gathering(const std::string &device_name="")
void hsi_print_status(const timingcmd::TimingHwCmd &hw_cmd)
void send_fl_cmd(const timingcmd::TimingHwCmd &hw_cmd)
std::mutex m_hw_device_map_mutex
std::string m_monitored_device_name_hsi
std::mutex master_sfp_mutex
void hsi_start(const timingcmd::TimingHwCmd &hw_cmd)
std::map< std::string, std::unique_ptr< std::thread > > m_command_threads
std::map< timingcmd::TimingHwCmdId, std::function< void(const timingcmd::TimingHwCmd &)> > m_timing_hw_cmd_map_
std::mutex m_command_threads_map_mutex
std::string m_hw_cmd_connection
void endpoint_enable(const timingcmd::TimingHwCmd &hw_cmd)
virtual void do_scrap(const CommandData_t &)
TimingHardwareManagerBase(const std::string &name)
TimingHardwareManagerBase Constructor.
void endpoint_disable(const timingcmd::TimingHwCmd &hw_cmd)
const timinglibs::dal::TimingHardwareManagerConf * m_params
virtual std::vector< std::string > check_hw_mon_gatherer_is_running(const std::string &device_name)
void master_endpoint_scan(const timingcmd::TimingHwCmd &hw_cmd)
std::map< std::string, std::unique_ptr< InfoGatherer > > m_info_gatherers
uint32_t get_gather_interval() const
Get "gather_interval" attribute value. Hardware device data gather interval [us].
const std::string & get_monitored_device_name_hsi() const
Get "monitored_device_name_hsi" attribute value. Name of hsi device to be monitored.
const std::string & get_monitored_device_name_endpoint() const
Get "monitored_device_name_endpoint" attribute value. Name of timing endpoint device to be monitored.
uint32_t get_gather_interval_debug() const
Get "gather_interval_debug" attribute value. Hardware device data gather debug interval [us].
const std::string & get_monitored_device_name_master() const
Get "monitored_device_name_master" attribute value. Name of timing master device to be monitored.
const std::vector< const dunedaq::timinglibs::dal::TimingFanoutDevice * > & get_monitored_device_names_fanout() const
Get "monitored_device_names_fanout" relationship value. Timing fanout devices to be monitored.
Base class for any user define issue.
#define TLOG_DEBUG(lvl,...)
void from_json(const data_t &j, EndpointLocation &obj)
void warning(const Issue &issue)
void info(const Issue &issue)
void error(const Issue &issue)
UintData timestamp_source
TimingHwCmdPayload payload
TimingEndpointLocations endpoints
UintData number_of_commands_to_send