DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
HSINode.cpp
Go to the documentation of this file.
1
9#include "timing/HSINode.hpp"
10
12#include "timing/toolbox.hpp"
13#include "logging/Logging.hpp"
14
15#include <string>
16#include <utility>
17#include <vector>
18
19namespace dunedaq {
20namespace timing {
21
22UHAL_REGISTER_DERIVED_NODE(HSINode)
23
24//-----------------------------------------------------------------------------
25HSINode::HSINode(const uhal::Node& node)
26 : TimingNode(node)
27{}
28//-----------------------------------------------------------------------------
29
30//-----------------------------------------------------------------------------
32//-----------------------------------------------------------------------------
33
34//-----------------------------------------------------------------------------
35std::string
36HSINode::get_status(bool print_out) const
37{
38
39 std::stringstream status;
40
41 std::vector<std::pair<std::string, std::string>> ept_summary;
42 std::vector<std::pair<std::string, std::string>> hsi_summary;
43
44 // auto lEPTimestamp = getNode("tstamp").readBlock(2);
45
46 auto hsi_control = read_sub_nodes(getNode("csr.ctrl"), false);
47 auto hsi_state = read_sub_nodes(getNode("csr.stat"), false);
48
49 auto hsi_buffer_count = getNode("buf.count").read();
50
51 auto hsi_re_mask = getNode("csr.re_mask").read();
52 auto hsi_fe_mask = getNode("csr.fe_mask").read();
53 auto hsi_inv_mask = getNode("csr.inv_mask").read();
54
55 getClient().dispatch();
56
57 hsi_summary.push_back(std::make_pair("Source", format_reg_value(hsi_control.find("src")->second.value(), 16)));
58 hsi_summary.push_back(std::make_pair("Enabled", format_reg_value(hsi_control.find("en")->second.value(), 16)));
59 hsi_summary.push_back(std::make_pair("Rising edge mask", format_reg_value(hsi_re_mask.value(), 16)));
60 hsi_summary.push_back(std::make_pair("Falling edge mask", format_reg_value(hsi_fe_mask.value(), 16)));
61 hsi_summary.push_back(std::make_pair("Invert mask", format_reg_value(hsi_inv_mask.value(), 16)));
62 hsi_summary.push_back(
63 std::make_pair("Buffer enabled", format_reg_value(hsi_control.find("buf_en")->second.value(), 16)));
64 hsi_summary.push_back(
65 std::make_pair("Buffer error", format_reg_value(hsi_state.find("buf_err")->second.value(), 16)));
66 hsi_summary.push_back(
67 std::make_pair("Buffer warning", format_reg_value(hsi_state.find("buf_warn")->second.value(), 16)));
68 hsi_summary.push_back(std::make_pair("Buffer occupancy", to_string(hsi_buffer_count.value())));
69
70 status << format_reg_table(hsi_summary, "HSI summary", { "", "" }) << std::endl;
71
72 if (print_out)
73 TLOG() << status.str();
74 return status.str();
75}
76//-----------------------------------------------------------------------------
77
78//-----------------------------------------------------------------------------
79uint32_t // NOLINT(build/unsigned)
81{
82 auto buffer_count = getNode("buf.count").read();
83 getClient().dispatch();
84 return buffer_count.value();
85}
86//-----------------------------------------------------------------------------
87
88//-----------------------------------------------------------------------------
89uhal::ValVector<uint32_t> // NOLINT(build/unsigned)
90HSINode::read_data_buffer(uint16_t& n_words, bool read_all, bool fail_on_error) const // NOLINT(build/unsigned)
91{
92
93 uint32_t buffer_state = read_buffer_state(); // NOLINT(build/unsigned)
94
95 uint16_t n_hsi_words = buffer_state >> 0x10; // NOLINT(build/unsigned)
96
97 n_words = n_hsi_words;
98
99 TLOG_DEBUG(5) << "Words available in readout buffer: " << format_reg_value(n_hsi_words);
100
101 uhal::ValVector<uint32_t> buffer_data; // NOLINT(build/unsigned)
102
103 if (buffer_state & 0x2) {
104 ers::warning(HSIBufferIssue(ERS_HERE, "WARNING"));
105 }
106
107 if (buffer_state & 0x1) {
108 ers::error(HSIBufferIssue(ERS_HERE, "ERROR"));
109 if (fail_on_error)
110 return buffer_data;
111 }
112
113 // this is bad
114 if (n_hsi_words > 1024) {
115 ers::error(HSIBufferIssue(ERS_HERE, "OVERFLOW"));
116 if (fail_on_error)
117 return buffer_data;
118 n_hsi_words = 1024;
119 }
120
121 uint32_t events_to_read = n_hsi_words / hsi_buffer_event_words_number; // NOLINT(build/unsigned)
122
123 TLOG_DEBUG(5) << "Events available in readout buffer: " << format_reg_value(events_to_read);
124
125 uint32_t words_to_read = read_all ? n_hsi_words : events_to_read * hsi_buffer_event_words_number; // NOLINT(build/unsigned)
126
127 TLOG_DEBUG(5) << "Words to be read out in readout buffer: " << format_reg_value(words_to_read);
128
129 if (!words_to_read) {
130 TLOG_DEBUG(5) << "No words to be read out.";
131 }
132
133 buffer_data = getNode("buf.data").readBlock(words_to_read);
134 getClient().dispatch();
135
136 return buffer_data;
137}
138//-----------------------------------------------------------------------------
139
140//-----------------------------------------------------------------------------
141uhal::ValVector<uint32_t> // NOLINT(build/unsigned)
142HSINode::read_data_buffer(bool read_all, bool fail_on_error) const
143{
144 uint16_t words; // NOLINT(build/unsigned)
145 return read_data_buffer(words, read_all, fail_on_error);
146}
147
148//-----------------------------------------------------------------------------
149std::string
150HSINode::get_data_buffer_table(bool read_all, bool print_out) const
151{
152
153 std::stringstream table;
154 auto buffer_data = read_data_buffer(read_all);
155
156 std::vector<std::pair<std::string, uint32_t>> buffer_table; // NOLINT(build/unsigned)
157
158 uint32_t i = 0; // NOLINT(build/unsigned)
159 for (auto it = buffer_data.begin(); it != buffer_data.end(); ++it, ++i) {
160 std::stringstream index_stream;
161 index_stream << std::setfill('0') << std::setw(4) << i;
162 buffer_table.push_back(std::make_pair(index_stream.str(), *it));
163 }
164 table << format_reg_table(buffer_table, "HSI buffer", { "Word", "Data" });
165
166 if (print_out)
167 TLOG() << table.str();
168 return table.str();
169}
170//-----------------------------------------------------------------------------
171
172//-----------------------------------------------------------------------------
173void
174HSINode::configure_hsi(uint32_t src, // NOLINT(build/unsigned)
175 uint32_t re_mask, // NOLINT(build/unsigned)
176 uint32_t fe_mask, // NOLINT(build/unsigned)
177 uint32_t inv_mask, // NOLINT(build/unsigned)
178 double rate,
179 uint32_t clock_frequency_hz, // NOLINT(build/unsigned)
180 bool dispatch) const
181{
182
183 getNode("csr.ctrl.src").write(src);
184 getNode("csr.re_mask").write(re_mask);
185 getNode("csr.fe_mask").write(fe_mask);
186 getNode("csr.inv_mask").write(inv_mask);
187
188 // Configures the internal hsi signal generator to produce triggers at a defined frequency.
189 // Rate = (clock_frequency_hz / 2^(d+8)) / p where n in [0,15] and p in [1,256]
190
191 // DIVIDER (int): Frequency divider.
192
193 // The division from clock_frequency_hz to the desired rate is done in three steps:
194 // a) A pre-division by 256
195 // b) Division by a power of two set by n = 2 ^ rate_div_d (ranging from 2^0 -> 2^15)
196 // c) 1-in-n prescaling set by n = rate_div_p
197
198 try
199 {
200 uint32_t divisor;
201 uint32_t prescale;
202 double actual_rate;
203
204 FLCmdGeneratorNode::parse_periodic_fl_cmd_rate(rate, clock_frequency_hz, actual_rate, divisor, prescale);
205
206 TLOG() << "Requested rate, actual rate: " << rate << ", " << actual_rate;
207 TLOG() << "prescale, divisor: " << prescale << ", " << divisor;
208
209 std::stringstream trig_stream;
210 trig_stream << "> Random trigger rate for HSI set to " << std::setprecision(3) << std::scientific << actual_rate << " Hz. d: " << divisor << " p: " << prescale;
211 TLOG() << trig_stream.str();
212
213 getNode("csr.ctrl.rate_div_p").write(prescale);
214 getNode("csr.ctrl.rate_div_d").write(divisor);
215 }
216 catch (const timing::BadRequestedFakeTriggerRate& e)
217 {
218 ers::error(FailedToUpdateHSIRandomRate(ERS_HERE,e));
219 }
220
221 if (dispatch)
222 getClient().dispatch();
223}
224//-----------------------------------------------------------------------------
225
226//-----------------------------------------------------------------------------
227void
228HSINode::start_hsi(bool dispatch) const
229{
230 getNode("csr.ctrl.en").write(0x1);
231 if (dispatch)
232 getClient().dispatch();
233}
234//-----------------------------------------------------------------------------
235
236//-----------------------------------------------------------------------------
237void
238HSINode::stop_hsi(bool dispatch) const
239{
240 getNode("csr.ctrl.en").write(0x0);
241 if (dispatch)
242 getClient().dispatch();
243}
244//-----------------------------------------------------------------------------
245
246//-----------------------------------------------------------------------------
247void
248HSINode::reset_hsi(bool dispatch) const
249{
250 getNode("csr.ctrl.en").write(0x0);
251
252 getNode("csr.ctrl.buf_en").write(0x0);
253 getNode("csr.ctrl.buf_en").write(0x1);
254
255 getNode("csr.re_mask").write(0x0);
256 getNode("csr.fe_mask").write(0x0);
257 getNode("csr.inv_mask").write(0x0);
258 getNode("csr.ctrl.src").write(0x0);
259
260 if (dispatch)
261 getClient().dispatch();
262}
263//-----------------------------------------------------------------------------
264
265//-----------------------------------------------------------------------------
266bool
268{
269 auto buf_warning = getNode("csr.stat.buf_warn").read();
270 getClient().dispatch();
271 return buf_warning.value();
272}
273//-----------------------------------------------------------------------------
274
275//-----------------------------------------------------------------------------
276bool
278{
279 auto buf_error = getNode("csr.stat.buf_err").read();
280 getClient().dispatch();
281 return buf_error.value();
282}
283//-----------------------------------------------------------------------------
284
285//-----------------------------------------------------------------------------
286uint32_t // NOLINT(build/unsigned)
288{
289
290 auto buf_state = read_sub_nodes(getNode("csr.stat"), false);
291 auto hsi_buffer_count = getNode("buf.count").read();
292 getClient().dispatch();
293
294 uint8_t buffer_error = static_cast<uint8_t>(buf_state.find("buf_err")->second.value()); // NOLINT(build/unsigned)
295 uint8_t buffer_warning = static_cast<uint8_t>(buf_state.find("buf_warn")->second.value()); // NOLINT(build/unsigned)
296
297 uint32_t buffer_state = buffer_error | (buffer_warning << 1); // NOLINT(build/unsigned)
298 buffer_state = buffer_state | static_cast<uint32_t>(hsi_buffer_count.value()) << 0x10; // NOLINT(build/unsigned)
299 return buffer_state;
300}
301//-----------------------------------------------------------------------------
302
303//-----------------------------------------------------------------------------
304uint32_t // NOLINT(build/unsigned)
306{
307 auto source = getNode("csr.ctrl.src").read();
308 getClient().dispatch();
309 return source.value();
310}
311//-----------------------------------------------------------------------------
312
313//-----------------------------------------------------------------------------
314void
316{
317 auto hsi_control = read_sub_nodes(getNode("csr.ctrl"), false);
318 auto hsi_state = read_sub_nodes(getNode("csr.stat"), false);
319
320 auto hsi_buffer_count = getNode("buf.count").read();
321
322 auto hsi_re_mask = getNode("csr.re_mask").read();
323 auto hsi_fe_mask = getNode("csr.fe_mask").read();
324 auto hsi_inv_mask = getNode("csr.inv_mask").read();
325
326 getClient().dispatch();
327
328 mon_data.source = hsi_control.find("src")->second.value();
329 mon_data.re_mask = hsi_re_mask.value();
330 mon_data.fe_mask = hsi_fe_mask.value();
331 mon_data.inv_mask = hsi_inv_mask.value();
332 mon_data.buffer_enabled = hsi_control.find("buf_en")->second.value();
333 mon_data.buffer_error = hsi_state.find("buf_err")->second.value();
334 mon_data.buffer_warning = hsi_state.find("buf_warn")->second.value();
335 mon_data.buffer_occupancy = hsi_buffer_count.value();
336 mon_data.enabled = hsi_control.find("en")->second.value();
337}
338// //-----------------------------------------------------------------------------
339
340} // namespace timing
341} // namespace dunedaq
#define ERS_HERE
static void parse_periodic_fl_cmd_rate(double requested_rate, uint32_t clock_frequency_hz, double &actual_rate, uint32_t &divisor, uint32_t &prescale)
Class for HSI nodes.
Definition HSINode.hpp:37
void get_info(timingfirmwareinfo::HSIFirmwareMonitorData &mon_data) const
Collect monitoring information for timing endpoint.
Definition HSINode.cpp:315
bool read_buffer_warning() const
Read butffer warning flag.
Definition HSINode.cpp:267
std::string get_status(bool print_out=false) const override
Print the status of the timing node.
Definition HSINode.cpp:36
void stop_hsi(bool dispatch=true) const
Stop HSI triggering.
Definition HSINode.cpp:238
bool read_buffer_error() const
Read butffer error flag.
Definition HSINode.cpp:277
void configure_hsi(uint32_t src, uint32_t re_mask, uint32_t fe_mask, uint32_t inv_mask, double rate, uint32_t clock_frequency_hz, bool dispatch=true) const
Configure HSI triggering.
Definition HSINode.cpp:174
uhal::ValVector< uint32_t > read_data_buffer(uint16_t &n_words, bool read_all=false, bool fail_on_error=false) const
Read the contents of the endpoint data buffer.
Definition HSINode.cpp:90
uint32_t read_buffer_state() const
Read butffer error/warning/word count.
Definition HSINode.cpp:287
void start_hsi(bool dispatch=true) const
Start HSI triggering.
Definition HSINode.cpp:228
std::string get_data_buffer_table(bool read_all=false, bool print_out=false) const
Print the contents of the endpoint data buffer.
Definition HSINode.cpp:150
uint32_t read_buffer_count() const
Read the number of words in the data buffer.
Definition HSINode.cpp:80
uint32_t read_signal_source_mode() const
Read signal source, 0 - hardware, 1 - internal emulation.
Definition HSINode.cpp:305
void reset_hsi(bool dispatch=true) const
Reset HSI.
Definition HSINode.cpp:248
Base class for timing nodes.
std::map< std::string, uhal::ValWord< uint32_t > > read_sub_nodes(const uhal::Node &node, bool dispatch=true) const
Read subnodes.
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
#define TLOG(...)
Definition macro.hpp:22
std::string format_reg_table(T data, std::string title, std::vector< std::string > headers)
Format reg-value table.
Definition toolbox.hxx:166
std::string to_string(const T &v)
Definition toolbox.hxx:49
std::string format_reg_value(T reg_value, uint32_t base)
Definition toolbox.hxx:117
Including Qt Headers.
void warning(const Issue &issue)
Definition ers.hpp:115
void error(const Issue &issue)
Definition ers.hpp:81