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 <memory>
30 : #include <string>
31 : #include <vector>
32 : #include <fstream>
33 : #include <shared_mutex>
34 : #include <map>
35 : #include <deque>
36 :
37 : #include <boost/asio.hpp>
38 : #include <boost/array.hpp>
39 :
40 :
41 : namespace dunedaq {
42 : namespace ctbmodules {
43 :
44 : typedef std::pair<uint64_t,uint64_t> ts_payload; // NOLINT
45 :
46 : /**
47 : * @brief CTBModule provides the command and readout interface to the Central Trigger Board hardware
48 : */
49 : class CTBModule : public dunedaq::hsilibs::HSIEventSender
50 : {
51 : public:
52 : /**
53 : * @brief CTBModule Constructor
54 : * @param name Instance name for this CTBModule instance
55 : */
56 : explicit CTBModule(const std::string& name);
57 : ~CTBModule();
58 :
59 : CTBModule(const CTBModule&) = delete; ///< CTBModule is not copy-constructible
60 : CTBModule& operator=(const CTBModule&) = delete; ///< CTBModule is not copy-assignable
61 : CTBModule(CTBModule&&) = delete; ///< CTBModule is not move-constructible
62 : CTBModule& operator=(CTBModule&&) = delete; ///< CTBModule is not move-assignable
63 :
64 : void init(std::shared_ptr<appfwk::ConfigurationManager> cfgMgr) override;
65 :
66 : static bool IsTSWord( const content::word::word_t &w ) noexcept;
67 : static bool IsFeedbackWord( const content::word::word_t &w ) noexcept;
68 : bool ErrorState() const { return m_error_state.load() ; }
69 :
70 : protected:
71 : void generate_opmon_data() override;
72 :
73 : private:
74 :
75 : // control and monitoring variables
76 :
77 : std::atomic<bool> m_is_running;
78 : std::atomic<bool> m_stop_requested;
79 : std::atomic<bool> m_is_configured;
80 :
81 : unsigned int m_receiver_port;
82 : std::chrono::microseconds m_timeout;
83 : std::atomic<bool> m_error_state;
84 :
85 : boost::asio::io_service m_control_ios;
86 : boost::asio::io_service m_receiver_ios;
87 : boost::asio::ip::tcp::socket m_control_socket;
88 : boost::asio::ip::tcp::socket m_receiver_socket;
89 : boost::asio::ip::tcp::endpoint m_endpoint;
90 :
91 : std::shared_ptr<dunedaq::hsilibs::HSIEventSender::raw_sender_ct> m_llt_hsi_data_sender;
92 : std::shared_ptr<dunedaq::hsilibs::HSIEventSender::raw_sender_ct> m_hlt_hsi_data_sender;
93 :
94 : ts_payload last_popped_llt, last_popped_chstatus;
95 :
96 :
97 : // Commands
98 : void do_configure(const CommandData_t& obj) override;
99 : void do_start(const CommandData_t& startobj) override;
100 : void do_stop(const CommandData_t& obj) override;
101 0 : void do_scrap(const CommandData_t& /*obj*/) override{};
102 :
103 : void send_reset() ;
104 : void send_config(const std::string & config);
105 : bool send_message(const std::string & msg);
106 :
107 : // Configuration
108 : std::shared_ptr<appfwk::ConfigurationManager> m_cfg;
109 : using conf_t = appmodel::CTBModule;
110 : const conf_t* m_module = nullptr;
111 :
112 : std::atomic<daqdataformats::run_number_t> m_run_number;
113 :
114 : // Threading
115 : dunedaq::utilities::WorkerThread m_thread_;
116 : void do_hsi_work(std::atomic<bool>&);
117 : // variables for geo_id to construct the HSI frame
118 : // These are defined as uint32 in the schema, but given the way the HSI frame is consctructed from this it is unsusable.
119 : // THe HSI frame uses 4 Bits for the slot and 10 Bits for the crate and 6 for the DetID. So here I'm overiding the types
120 : uint16_t m_det; // NOLINT
121 : uint16_t m_crate; // NOLINT
122 : uint16_t m_slot; // NOLINT
123 :
124 : // Generate HSI Frame/Event
125 : void send_matched_trigger_word(const content::word::trigger_t&, uint64_t); // NOLINT
126 : void match_between_buffers(std::queue<content::word::trigger_t>&, std::queue<ts_payload>&, uint64_t, content::word::word_type); // NOLINT
127 :
128 : static bool check_repeated_word(ts_payload&, ts_payload&, uint64_t); // NOLINT
129 :
130 : template<typename T>
131 : bool read(T &obj);
132 :
133 : // members related to calibration stream
134 :
135 : void update_calibration_file();
136 : void init_calibration_file();
137 : bool SetCalibrationStream( const std::string &prefix = "" );
138 :
139 : bool m_has_calibration_stream = false;
140 : std::string m_calibration_dir = "";
141 : std::string m_calibration_prefix = "";
142 : std::chrono::minutes m_calibration_file_interval;
143 : std::ofstream m_calibration_file;
144 : std::chrono::steady_clock::time_point m_last_calibration_file_update;
145 :
146 : // metric utilities
147 : using general_metric_t = dunedaq::ctbmodules::opmon::CTBModuleInfo;
148 : using channel_metric_t = dunedaq::ctbmodules::opmon::TriggerInfo;
149 :
150 : using const_total_hlt_counter_t = std::invoke_result<decltype(&general_metric_t::total_hlt_count),
151 : general_metric_t>::type;
152 : std::atomic<std::remove_const<const_total_hlt_counter_t>::type> m_total_hlt_counter;
153 :
154 : using const_ts_word_counter_t = std::invoke_result<decltype(&general_metric_t::ts_word_count),
155 : general_metric_t>::type;
156 : std::atomic<std::remove_const<const_ts_word_counter_t>::type> m_ts_word_counter;
157 :
158 : size_t m_hlt_range = 20;
159 : size_t m_llt_range = 25;
160 : using const_trigger_counter_t = std::invoke_result<decltype(&channel_metric_t::count),
161 : 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 = std::invoke_result<decltype(&general_metric_t::num_control_messages_sent),
177 : 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 : };
184 : } // namespace ctbmodules
185 : } // namespace dunedaq
186 :
187 : #endif // CTBMODULES_PLUGINS_CTBMODULE_HPP_
188 :
189 : // Local Variables:
190 : // c-basic-offset: 2
191 : // End:
|