DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
FLCmdGeneratorNode.cpp
Go to the documentation of this file.
1
10
11#include "timing/toolbox.hpp"
12#include "logging/Logging.hpp"
13
14#include <string>
15#include <vector>
16
17namespace dunedaq {
18namespace timing {
19
20UHAL_REGISTER_DERIVED_NODE(FLCmdGeneratorNode)
21
22//-----------------------------------------------------------------------------
24 : TimingNode(node)
25{}
26//-----------------------------------------------------------------------------
27
28//-----------------------------------------------------------------------------
30//-----------------------------------------------------------------------------
31
32//-----------------------------------------------------------------------------
33std::string
34FLCmdGeneratorNode::get_status(bool print_out) const
35{
36 std::stringstream status;
37 auto subnodes = read_sub_nodes(getNode("csr.stat"));
38 status << format_reg_table(subnodes, "FL Cmd gen state");
39 if (print_out)
40 TLOG() << status.str();
41 return status.str();
42}
43//-----------------------------------------------------------------------------
44
45//-----------------------------------------------------------------------------
46void
47FLCmdGeneratorNode::validate_command(uint32_t command) const // NOLINT(build/unsigned)
48{
49 if (command > 0xff)
50 {
51 throw InvalidFixedLatencyCommand(ERS_HERE, command);
52 }
53}
54//-----------------------------------------------------------------------------
55
56//-----------------------------------------------------------------------------
57void
58FLCmdGeneratorNode::validate_channel(uint32_t channel) const // NOLINT(build/unsigned)
59{
60 if (channel > 0x4)
61 {
62 throw InvalidFixedLatencyCommandChannel(ERS_HERE, channel);
63 }
64}
65//-----------------------------------------------------------------------------
66
67//-----------------------------------------------------------------------------
68void
69FLCmdGeneratorNode::send_fl_cmd(uint32_t command, // NOLINT(build/unsigned)
70 uint32_t channel) const // NOLINT(build/unsigned)
71{
72 validate_command(command);
73 validate_channel(channel);
74
75 getNode("sel").write(channel);
76
77 reset_sub_nodes(getNode("chan_ctrl"));
78
79 getNode("chan_ctrl.type").write(command);
80 getNode("ctrl.force").write(0x1);
81 getClient().dispatch();
82
83 getNode("ctrl.force").write(0x0);
84 getClient().dispatch();
85}
86//-----------------------------------------------------------------------------
87
88//-----------------------------------------------------------------------------
89void
90FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t channel, // NOLINT(build/unsigned)
91 double rate,
92 bool poisson,
93 uint32_t clock_frequency_hz) const
94{
95 enable_periodic_fl_cmd(0x8+channel, channel, rate, poisson, clock_frequency_hz);
96}
97//-----------------------------------------------------------------------------
98
99//-----------------------------------------------------------------------------
100void
101FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t command, // NOLINT(build/unsigned)
102 uint32_t channel, // NOLINT(build/unsigned)
103 double rate,
104 bool poisson,
105 uint32_t clock_frequency_hz) const
106{
107 uint32_t divisor;
108 uint32_t prescale;
109 double actual_rate;
110
111 parse_periodic_fl_cmd_rate(rate, clock_frequency_hz, actual_rate, divisor, prescale);
112
113 TLOG() << "Requested rate, actual rate: " << rate << ", " << actual_rate;
114 TLOG() << "prescale, divisor: " << prescale << ", " << divisor;
115
116 std::stringstream trig_stream;
117 trig_stream << "> Periodic rate for command 0x" << std::hex << command << ", on channel 0x" << channel
118 << " set to " << std::setprecision(3) << std::scientific << actual_rate << " Hz";
119 TLOG() << trig_stream.str();
120
121 std::stringstream trigger_mode_stream;
122 trigger_mode_stream << "> Trigger mode: ";
123
124 if (poisson) {
125 trigger_mode_stream << "poisson";
126 } else {
127 trigger_mode_stream << "periodic";
128 }
129 TLOG() << trigger_mode_stream.str();
130 enable_periodic_fl_cmd(command, channel, divisor, prescale, poisson);
131
132}
133//-----------------------------------------------------------------------------
134
135//-----------------------------------------------------------------------------
136void
137FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t channel, // NOLINT(build/unsigned)
138 uint32_t divisor, // NOLINT(build/unsigned)
139 uint32_t prescale, // NOLINT(build/unsigned)
140 bool poisson) const
141{
142 enable_periodic_fl_cmd(0x8+channel, channel, divisor, prescale, poisson);
143}
144//-----------------------------------------------------------------------------
145
146//-----------------------------------------------------------------------------
147void
148FLCmdGeneratorNode::enable_periodic_fl_cmd(uint32_t command, // NOLINT(build/unsigned)
149 uint32_t channel, // NOLINT(build/unsigned)
150 uint32_t divisor, // NOLINT(build/unsigned)
151 uint32_t prescale, // NOLINT(build/unsigned)
152 bool poisson) const
153{
154 validate_command(command);
155 validate_channel(channel);
156
157 getNode("sel").write(channel);
158
159 getNode("chan_ctrl.type").write(command);
160 getNode("chan_ctrl.rate_div_d").write(divisor);
161 getNode("chan_ctrl.rate_div_p").write(prescale);
162 getNode("chan_ctrl.patt").write(poisson);
163 getNode("chan_ctrl.en").write(1); // Start the command stream
164 getClient().dispatch();
165}
166//-----------------------------------------------------------------------------
167
168//-----------------------------------------------------------------------------
169void
170FLCmdGeneratorNode::disable_fake_trigger(uint32_t channel) const // NOLINT(build/unsigned)
171{
172 validate_channel(channel);
173
174 // Clear the internal trigger generator.
175 getNode("sel").write(channel);
176 reset_sub_nodes(getNode("chan_ctrl"));
177 TLOG() << "Fake trigger generator " << format_reg_value(channel) << " configuration cleared";
178}
179//------------------------------------------------------------------------------
180
181//------------------------------------------------------------------------------
182std::string
184{
185 std::stringstream counters_table;
186 auto accepted_counters = getNode("actrs").readBlock(getNode("actrs").getSize());
187 auto rejected_counters = getNode("rctrs").readBlock(getNode("actrs").getSize());
188 getClient().dispatch();
189
190 std::vector<uhal::ValVector<uint32_t>> counters_container = { accepted_counters, rejected_counters }; // NOLINT(build/unsigned)
191
192 counters_table << format_counters_table(counters_container,
193 { "Accept counters", "Reject counters" },
194 "Cmd gen counters",
195 { "0x0", "0x1", "0x2", "0x3", "0x4" },
196 "Chan");
197
198 if (print_out)
199 TLOG() << counters_table.str();
200 return counters_table.str();
201}
202//-----------------------------------------------------------------------------
203
204//-----------------------------------------------------------------------------
205// void
206// FLCmdGeneratorNode::get_info(opmonlib::InfoCollector& ic, int /*level*/) const
207// {
208// auto accepted_counters = getNode("actrs").readBlock(getNode("actrs").getSize());
209// auto rejected_counters = getNode("rctrs").readBlock(getNode("actrs").getSize());
210// getClient().dispatch();
211
212// uint number_of_channels = 5;
213
214// for (uint i = 0; i < number_of_channels; ++i) { // NOLINT(build/unsigned)
215
216// timingfirmwareinfo::TimingFLCmdCounter cmd_counter;
217// opmonlib::InfoCollector cmd_counter_ic;
218
219// cmd_counter.accepted = accepted_counters.at(i);
220// cmd_counter.rejected = rejected_counters.at(i);
221
222// std::string channel = "fl_cmd_channel_" + std::to_string(i);
223
224// cmd_counter_ic.add(cmd_counter);
225// ic.add(channel, cmd_counter_ic);
226// }
227// }
228//-----------------------------------------------------------------------------
229
230//-----------------------------------------------------------------------------
232 uint32_t clock_frequency_hz,
233 double& actual_rate,
234 uint32_t& divisor,
235 uint32_t& prescale)
236{
237 // Rate = (clock_frequency_hz / 2^(d+8)) / p where n in [0,15] and p in [1,256]
238
239 // DIVIDER (int): Frequency divider.
240
241 // The division from clock_frequency_hz to the desired rate is done in three steps:
242 // a) A pre-division by 256
243 // b) Division by a power of two set by n = 2 ^ rate_div_d (ranging from 2^0 -> 2^15)
244 // c) 1-in-n prescaling set by n = rate_div_p
245
246 double div = ceil(log(clock_frequency_hz / (requested_rate * 256 * 256)) / log(2));
247 if (div < 0) {
248 divisor = 0;
249 } else if (div > 15) {
250 divisor = 15;
251 } else {
252 divisor = div;
253 }
254
255 uint32_t ps = (uint32_t)((clock_frequency_hz / (requested_rate * 256 * (1 << divisor))) + 0.5); // NOLINT(build/unsigned)
256 if (ps == 0 || ps > 256)
257 {
258 throw BadRequestedFakeTriggerRate(ERS_HERE, requested_rate, ps);
259 } else {
260 prescale = ps;
261 }
262 actual_rate = static_cast<double>(clock_frequency_hz) / (256 * prescale * (1 << divisor));
263}
264//-----------------------------------------------------------------------------
265
266} // namespace timing
267} // namespace dunedaq
#define ERS_HERE
Class for master global node.
void disable_fake_trigger(uint32_t channel) const
Clear fake trigger configuration.
virtual void send_fl_cmd(uint32_t command, uint32_t channel) const
Send a fixed length command.
std::string get_cmd_counters_table(bool print_out=false) const
Get command counters status string.
void validate_channel(uint32_t channel) const
static void parse_periodic_fl_cmd_rate(double requested_rate, uint32_t clock_frequency_hz, double &actual_rate, uint32_t &divisor, uint32_t &prescale)
void enable_periodic_fl_cmd(uint32_t channel, double rate, bool poisson, uint32_t clock_frequency_hz) const
Configure fake trigger.
void validate_command(uint32_t command) const
std::string get_status(bool print_out=false) const override
Get status string, optionally print.
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(...)
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 format_counters_table(std::vector< T > counter_nodes, std::vector< std::string > counter_node_titles, std::string table_title, std::vector< std::string > counter_labels, std::string counter_labels_header)
Format reg-value table.
Definition toolbox.hxx:216
std::string format_reg_value(T reg_value, uint32_t base)
Definition toolbox.hxx:117
Including Qt Headers.