Line data Source code
1 : /**
2 : * @file CTBModule.hpp
3 : *
4 : * CTBModule is a DAQModule implementation that reads that provides a command and readout
5 : * interface to the Central Trigger Board hardware.
6 : *
7 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
8 : * Licensing/copyright details are in the COPYING file that you should have
9 : * received with this code.
10 : */
11 :
12 : #ifndef CTBMODULES_PLUGINS_CTBMODULE_HPP_
13 : #define CTBMODULES_PLUGINS_CTBMODULE_HPP_
14 :
15 : #include "appfwk/DAQModule.hpp"
16 : #include "appmodel/CTBModule.hpp"
17 : #include "iomanager/Receiver.hpp"
18 : #include "iomanager/Sender.hpp"
19 : #include "utilities/WorkerThread.hpp"
20 :
21 : #include "hsilibs/HSIEventSender.hpp"
22 :
23 : #include <ers/Issue.hpp>
24 :
25 : #include "ctbmodules/opmon/CTBModule.pb.h"
26 :
27 : #include "CTBPacketContent.hpp"
28 :
29 : #include <deque>
30 : #include <fstream>
31 : #include <map>
32 : #include <memory>
33 : #include <shared_mutex>
34 : #include <string>
35 : #include <vector>
36 :
37 : #include <boost/array.hpp>
38 : #include <boost/asio.hpp>
39 :
40 : namespace dunedaq {
41 : namespace ctbmodules {
42 :
43 : typedef std::pair<uint64_t, uint64_t> ts_payload; // NOLINT
44 :
45 : /**
46 : * @brief CTBModule provides the command and readout interface to the Central Trigger Board hardware
47 : */
48 : class CTBModule : public dunedaq::hsilibs::HSIEventSender
49 : {
50 : public:
51 : /**
52 : * @brief CTBModule Constructor
53 : * @param name Instance name for this CTBModule instance
54 : */
55 : explicit CTBModule(const std::string& name);
56 : ~CTBModule();
57 :
58 : CTBModule(const CTBModule&) = delete; ///< CTBModule is not copy-constructible
59 : CTBModule& operator=(const CTBModule&) = delete; ///< CTBModule is not copy-assignable
60 : CTBModule(CTBModule&&) = delete; ///< CTBModule is not move-constructible
61 : CTBModule& operator=(CTBModule&&) = delete; ///< CTBModule is not move-assignable
62 :
63 : void init(std::shared_ptr<appfwk::ConfigurationManager> cfgMgr) override;
64 :
65 : static bool IsTSWord(const content::word::word_t& w) noexcept;
66 : static bool IsFeedbackWord(const content::word::word_t& w) noexcept;
67 : bool ErrorState() const { return m_error_state.load(); }
68 :
69 : protected:
70 : void generate_opmon_data() override;
71 :
72 : private:
73 : // control and monitoring variables
74 :
75 : std::atomic<bool> m_is_running;
76 : std::atomic<bool> m_stop_requested;
77 : std::atomic<bool> m_is_configured;
78 :
79 : unsigned int m_receiver_port;
80 : std::chrono::microseconds m_timeout;
81 : std::atomic<bool> m_error_state;
82 :
83 : boost::asio::io_service m_control_ios;
84 : boost::asio::io_service m_receiver_ios;
85 : boost::asio::ip::tcp::socket m_control_socket;
86 : boost::asio::ip::tcp::socket m_receiver_socket;
87 : boost::asio::ip::tcp::endpoint m_endpoint;
88 :
89 : std::shared_ptr<dunedaq::hsilibs::HSIEventSender::raw_sender_ct> m_llt_hsi_data_sender;
90 : std::shared_ptr<dunedaq::hsilibs::HSIEventSender::raw_sender_ct> m_hlt_hsi_data_sender;
91 :
92 : ts_payload last_popped_llt, last_popped_chstatus;
93 :
94 : // Commands
95 : void do_configure(const CommandData_t& obj) override;
96 : void do_start(const CommandData_t& startobj) override;
97 : void do_stop(const CommandData_t& obj) override;
98 0 : void do_scrap(const CommandData_t& /*obj*/) override {};
99 :
100 : void send_reset();
101 : void send_config(const std::string& config);
102 : bool send_message(const std::string& msg);
103 :
104 : // Configuration
105 : std::shared_ptr<appfwk::ConfigurationManager> m_cfg;
106 : using conf_t = appmodel::CTBModule;
107 : const conf_t* m_module = nullptr;
108 :
109 : std::atomic<daqdataformats::run_number_t> m_run_number;
110 :
111 : // Threading
112 : dunedaq::utilities::WorkerThread m_thread_;
113 : void do_hsi_work(std::atomic<bool>&);
114 : // variables for geo_id to construct the HSI frame
115 : // These are defined as uint32 in the schema, but given the way the HSI frame is consctructed from this it is
116 : // unsusable. THe HSI frame uses 4 Bits for the slot and 10 Bits for the crate and 6 for the DetID. So here I'm
117 : // overiding the types
118 : uint16_t m_det; // NOLINT
119 : uint16_t m_crate; // NOLINT
120 : uint16_t m_slot; // NOLINT
121 :
122 : // Generate HSI Frame/Event
123 : void send_matched_trigger_word(const content::word::trigger_t&, uint64_t); // NOLINT
124 : void match_between_buffers(std::queue<content::word::trigger_t>&,
125 : std::queue<ts_payload>&,
126 : uint64_t,
127 : content::word::word_type); // NOLINT
128 :
129 : static bool check_repeated_word(ts_payload&, ts_payload&, uint64_t); // NOLINT
130 :
131 : template<typename T>
132 : bool read(T& obj);
133 :
134 : // members related to calibration stream
135 :
136 : void update_calibration_file();
137 : void init_calibration_file();
138 : bool SetCalibrationStream(const std::string& prefix = "");
139 :
140 : bool m_has_calibration_stream = false;
141 : std::string m_calibration_dir = "";
142 : std::string m_calibration_prefix = "";
143 : std::chrono::minutes m_calibration_file_interval;
144 : std::ofstream m_calibration_file;
145 : std::chrono::steady_clock::time_point m_last_calibration_file_update;
146 :
147 : // metric utilities
148 : using general_metric_t = dunedaq::ctbmodules::opmon::CTBModuleInfo;
149 : using channel_metric_t = dunedaq::ctbmodules::opmon::TriggerInfo;
150 :
151 : using const_total_hlt_counter_t =
152 : std::invoke_result<decltype(&general_metric_t::total_hlt_count), general_metric_t>::type;
153 : std::atomic<std::remove_const<const_total_hlt_counter_t>::type> m_total_hlt_counter;
154 :
155 : using const_ts_word_counter_t =
156 : std::invoke_result<decltype(&general_metric_t::ts_word_count), general_metric_t>::type;
157 : std::atomic<std::remove_const<const_ts_word_counter_t>::type> m_ts_word_counter;
158 :
159 : size_t m_hlt_range = 20;
160 : size_t m_llt_range = 25;
161 : using const_trigger_counter_t = std::invoke_result<decltype(&channel_metric_t::count), channel_metric_t>::type;
162 : using trigger_counter_t = std::remove_const<const_ts_word_counter_t>::type;
163 : std::map<size_t, std::atomic<trigger_counter_t>> m_hlt_trigger_counter;
164 : std::map<size_t, std::atomic<trigger_counter_t>> m_llt_trigger_counter;
165 :
166 : std::atomic<trigger_counter_t> m_run_HLT_counter = 0;
167 : std::atomic<trigger_counter_t> m_run_LLT_counter = 0;
168 : std::atomic<trigger_counter_t> m_run_channel_status_counter = 0;
169 :
170 : // monitoring
171 : std::deque<uint> m_buffer_counts; // NOLINT(build/unsigned)
172 : std::shared_mutex m_buffer_counts_mutex;
173 : void update_buffer_counts(uint new_count); // NOLINT(build/unsigned)
174 : double read_average_buffer_counts();
175 :
176 : using const_message_counter_t =
177 : std::invoke_result<decltype(&general_metric_t::num_control_messages_sent), general_metric_t>::type;
178 : using message_counter_t = std::remove_const<const_message_counter_t>::type;
179 : std::atomic<message_counter_t> m_num_control_messages_sent = 0;
180 : std::atomic<message_counter_t> m_num_control_responses_received = 0;
181 : std::atomic<uint64_t> m_last_readout_hlt_timestamp = 0; // NOLINT(build/unsigned)
182 : };
183 : } // namespace ctbmodules
184 : } // namespace dunedaq
185 :
186 : #endif // CTBMODULES_PLUGINS_CTBMODULE_HPP_
187 :
188 : // Local Variables:
189 : // c-basic-offset: 2
190 : // End:
|