DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
HermesCoreController.cpp
Go to the documentation of this file.
2
3#include <chrono> // std::chrono::seconds
4#include <fmt/core.h>
5#include <thread> // std::this_thread::sleep_for
6
7namespace dunedaq {
8namespace hermesmodules {
9
10//-----------------------------------------------------------------------------
11HermesCoreController::HermesCoreController(uhal::HwInterface hw, std::string readout_id)
12 : m_hw(hw)
13 , m_readout(m_hw.getNode(readout_id))
14{
15
16 this->load_hw_info();
17}
18
19//-----------------------------------------------------------------------------
21
22//-----------------------------------------------------------------------------
23void
25{
26
27 // Check magic number
28 auto magic = m_readout.getNode("info.magic").read();
29 m_readout.getClient().dispatch();
30 if (magic.value() != 0xdeadbeef) {
31 // TODO: add ERS exception
32 throw MagicNumberError(ERS_HERE, magic.value(), 0xdeadbeef);
33 }
34
35 auto design = m_readout.getNode("info.versions.design").read();
36 auto major = m_readout.getNode("info.versions.major").read();
37 auto minor = m_readout.getNode("info.versions.minor").read();
38 auto patch = m_readout.getNode("info.versions.patch").read();
39
40 auto n_mgt = m_readout.getNode("info.generics.n_mgts").read();
41 auto n_src = m_readout.getNode("info.generics.n_srcs").read();
42 auto ref_freq = m_readout.getNode("info.generics.ref_freq").read();
43 m_readout.getClient().dispatch();
44
45 // Version
46 m_core_info.design = design.value();
47 m_core_info.major = major.value();
48 m_core_info.minor = minor.value();
49 m_core_info.patch = patch.value();
50
51 // Generics
52 m_core_info.n_mgt = n_mgt.value();
53 m_core_info.n_src = n_src.value();
54 m_core_info.ref_freq = ref_freq.value();
55
56 // Extra info
58
59 fmt::print("Number of links: {}\n", m_core_info.n_mgt);
60 fmt::print("Number of sources: {}\n", m_core_info.n_src);
61 fmt::print("Reference freq: {}\n", m_core_info.ref_freq);
62 fmt::print("Sources per mux:{}\n", m_core_info.srcs_per_mux);
63}
64
65//-----------------------------------------------------------------------------
66void
68{
69 if (i >= m_core_info.n_mgt) {
70 throw LinkDoesNotExist(ERS_HERE, i);
71 }
72
73 m_readout.getNode("tx_path.csr_tx_mux.ctrl.tx_mux_sel").write(i);
74 m_readout.getClient().dispatch();
75}
76
77//-----------------------------------------------------------------------------
78void
80{
81 if (i >= m_core_info.n_src) {
82 throw InputBufferDoesNotExist(ERS_HERE, i);
83 }
84
85 m_readout.getNode("tx_path.tx_mux.csr.ctrl.sel_buf").write(i);
86 m_readout.getClient().dispatch();
87}
88
89//-----------------------------------------------------------------------------
90void
92{
93 if (i >= m_core_info.n_mgt) {
94 throw MgtDoesNotExist(ERS_HERE, i);
95 }
96
97 m_readout.getNode("tx_path.csr_udp_core.ctrl.udp_core_sel").write(i);
98 m_readout.getClient().dispatch();
99}
100
101//-----------------------------------------------------------------------------
102void
104{
105
106 if (nuke) {
107 m_readout.getNode("csr.ctrl.nuke").write(0x1);
108 m_readout.getClient().dispatch();
109
110 // time.sleep(0.1);
111 std::this_thread::sleep_for(std::chrono::milliseconds(1));
112
113 m_readout.getNode("csr.ctrl.nuke").write(0x0);
114 m_readout.getClient().dispatch();
115 }
116
117 m_readout.getNode("csr.ctrl.soft_rst").write(0x1);
118 m_readout.getClient().dispatch();
119
120 // time.sleep(0.1)
121 std::this_thread::sleep_for(std::chrono::milliseconds(1));
122
123 m_readout.getNode("csr.ctrl.soft_rst").write(0x0);
124 m_readout.getClient().dispatch();
125
126 // Check the ethernet core status
127 auto eth_rdy = m_readout.getNode("tx_path.tx_mux.csr.stat.eth_rdy").read();
128 m_readout.getClient().dispatch();
129
130 // If the ethernet core is not ready, issue a phy reset
131 if (!eth_rdy) {
132 m_readout.getNode("pcs_pma.debug.csr.ctrl.phy_reset").write(0x1);
133 m_readout.getNode("pcs_pma.debug.csr.ctrl.phy_reset").write(0x0);
134 m_readout.getClient().dispatch();
135 }
136}
137
138//-----------------------------------------------------------------------------
139bool
140HermesCoreController::is_link_in_error(uint16_t link, bool do_throw)
141{
142
143 this->sel_tx_mux(link);
144
145 auto& tx_mux_stat = m_readout.getNode("tx_path.tx_mux.csr.stat");
146 auto err = tx_mux_stat.getNode("err").read();
147 auto eth_rdy = tx_mux_stat.getNode("eth_rdy").read();
148 auto src_rdy = tx_mux_stat.getNode("src_rdy").read();
149 auto udp_rdy = tx_mux_stat.getNode("udp_rdy").read();
150 tx_mux_stat.getClient().dispatch();
151
152 bool is_error = (err || !eth_rdy || !src_rdy || !udp_rdy);
153
154 if (do_throw && is_error) {
155 throw LinkInError(ERS_HERE, link, err, eth_rdy, src_rdy, udp_rdy);
156 }
157
158 return is_error;
159}
160
161//-----------------------------------------------------------------------------
162void
164{
165
166 this->sel_tx_mux(link);
167
168 auto& tx_mux_ctrl = m_readout.getNode("tx_path.tx_mux.csr.ctrl");
169
170 // Not sure what to do with this
171 auto tx_en = tx_mux_ctrl.getNode("tx_en").read();
172 auto buf_en = tx_mux_ctrl.getNode("en_buf").read();
173 auto ctrl_en = tx_mux_ctrl.getNode("en").read();
174
175 if (enable) {
176
177 // Assume that all is off
178
179 // Enable the main logic
180 tx_mux_ctrl.getNode("en").write(0x1);
181 tx_mux_ctrl.getClient().dispatch();
182
183 // Enable transmitter first
184 tx_mux_ctrl.getNode("tx_en").write(0x1);
185 tx_mux_ctrl.getClient().dispatch();
186
187 // Enable buffers last
188 tx_mux_ctrl.getNode("en_buf").write(0x1);
189 tx_mux_ctrl.getClient().dispatch();
190
191 } else {
192
193 // Disable buffers last
194 tx_mux_ctrl.getNode("en_buf").write(0x0);
195 tx_mux_ctrl.getClient().dispatch();
196
197 // Disable transmitter first
198 tx_mux_ctrl.getNode("tx_en").write(0x0);
199 tx_mux_ctrl.getClient().dispatch();
200
201 // Disable the main logic
202 tx_mux_ctrl.getNode("en").write(0x0);
203 tx_mux_ctrl.getClient().dispatch();
204 }
205}
206
207//-----------------------------------------------------------------------------
208void
209HermesCoreController::config_mux(uint16_t link, uint16_t det, uint16_t crate, uint16_t slot)
210{
211 this->sel_tx_mux(link);
212
213 auto& mux_ctrl = m_readout.getNode("tx_path.tx_mux.mux.ctrl");
214
215 mux_ctrl.getNode("detid").write(det);
216 mux_ctrl.getNode("crate").write(crate);
217 mux_ctrl.getNode("slot").write(slot);
218 mux_ctrl.getClient().dispatch();
219}
220
221//-----------------------------------------------------------------------------
222void
224 uint64_t src_mac,
225 uint32_t src_ip,
226 uint16_t src_port,
227 uint64_t dst_mac,
228 uint32_t dst_ip,
229 uint16_t dst_port,
230 uint32_t filters)
231{
232
233 if (link >= m_core_info.n_mgt) {
234 throw LinkDoesNotExist(ERS_HERE, link);
235 }
236
237 this->sel_udp_core(link);
238
239 // const std::string udp_ctrl_name = fmt::format("udp.udp_core_{}.udp_core_control.nz_rst_ctrl");
240 const auto& udp_ctrl = m_readout.getNode("tx_path.udp_core.udp_core_control");
241
242 udp_ctrl.getNode("src_addr_ctrl.use_external").write(0);
243
244 // Load the source mac address
245 udp_ctrl.getNode("src_addr_ctrl.src_mac_addr_lower").write(src_mac & 0xffffffff);
246 udp_ctrl.getNode("src_addr_ctrl.src_mac_addr_upper").write((src_mac >> 32) & 0xffff);
247
248 // Load the source ip address
249 udp_ctrl.getNode("src_addr_ctrl.src_ip_addr").write(src_ip);
250
251 // Load the dst mac address
252 udp_ctrl.getNode("ctrl.dst_mac_addr_lower").write(dst_mac & 0xffffffff);
253 udp_ctrl.getNode("ctrl.dst_mac_addr_upper").write((dst_mac >> 32) & 0xffff);
254
255 // Load the dst ip address
256 udp_ctrl.getNode("ctrl.dst_ip_addr").write(dst_ip);
257
258 // Ports
259 udp_ctrl.getNode("src_addr_ctrl.src_port").write(src_port);
260 udp_ctrl.getNode("ctrl.dst_port").write(dst_port);
261
262 udp_ctrl.getNode("ctrl.filter_control").write(filters);
263 udp_ctrl.getClient().dispatch();
264}
265
266//-----------------------------------------------------------------------------
267void
268HermesCoreController::config_fake_src(uint16_t link, uint16_t n_src, uint16_t data_len, uint16_t rate)
269{
270
271 this->sel_tx_mux(link);
272
273 auto was_en_buf = m_readout.getNode("tx_path.tx_mux.csr.ctrl.en_buf").read();
274 m_readout.getNode("tx_path.tx_mux.csr.ctrl.en_buf").write(0x0);
275 m_readout.getClient().dispatch();
276
277 for (size_t src_id(0); src_id < m_core_info.srcs_per_mux; ++src_id) {
278 this->sel_tx_mux_buf(src_id);
279
280 bool src_en = (src_id < n_src);
281 m_readout.getNode("tx_path.tx_mux.buf.ctrl.fake_en").write(src_en);
282 m_readout.getClient().dispatch();
283 if (!src_en) {
284 continue;
285 }
286 m_readout.getNode("tx_path.tx_mux.buf.ctrl.dlen").write(data_len);
287
288 m_readout.getNode("tx_path.tx_mux.buf.ctrl.rate_rdx").write(rate);
289 m_readout.getClient().dispatch();
290 }
291
292 m_readout.getNode("tx_path.tx_mux.csr.ctrl.en_buf").write(was_en_buf.value());
293 m_readout.getClient().dispatch();
294}
295
296//-----------------------------------------------------------------------------
299{
300
301 this->sel_tx_mux(link);
302
303 auto detid = m_readout.getNode("tx_path.tx_mux.mux.ctrl.detid").read();
304 auto crate = m_readout.getNode("tx_path.tx_mux.mux.ctrl.crate").read();
305 auto slot = m_readout.getNode("tx_path.tx_mux.mux.ctrl.slot").read();
306
307 m_readout.getClient().dispatch();
308
309 return { detid.value(), crate.value(), slot.value() };
310}
311
312//-----------------------------------------------------------------------------
315{
316 this->sel_tx_mux(link);
317 this->sel_udp_core(link);
318
319 opmon::LinkInfo info;
320
321 const auto& mux_stats = m_readout.getNode("tx_path.tx_mux.csr.stat");
322 auto err = mux_stats.getNode("err").read();
323 auto eth_rdy = mux_stats.getNode("eth_rdy").read();
324 auto src_rdy = mux_stats.getNode("src_rdy").read();
325 auto udp_rdy = mux_stats.getNode("udp_rdy").read();
326 mux_stats.getClient().dispatch();
327
328 const auto& udp_ctrl = m_readout.getNode(fmt::format("tx_path.udp_core.udp_core_control"));
329 const auto& rx_stats = udp_ctrl.getNode("rx_packet_counters");
330
331 auto rx_arp_count = rx_stats.getNode("arp_count").read();
332 auto rx_ping_count = rx_stats.getNode("ping_count").read();
333 auto rx_udp_count = rx_stats.getNode("udp_count").read();
334 rx_stats.getClient().dispatch();
335
336 const auto& tx_stats = udp_ctrl.getNode("tx_packet_counters");
337
338 auto tx_arp_count = tx_stats.getNode("arp_count").read();
339 auto tx_ping_count = tx_stats.getNode("ping_count").read();
340 auto tx_udp_count = tx_stats.getNode("udp_count").read();
341 tx_stats.getClient().dispatch();
342
343 info.set_err(err.value());
344 info.set_eth_rdy(eth_rdy.value());
345 info.set_src_rdy(src_rdy.value());
346 info.set_udp_rdy(udp_rdy.value());
347
348 info.set_rcvd_arp_count(rx_arp_count.value());
349 info.set_rcvd_ping_count(rx_ping_count.value());
350 info.set_rcvd_udp_count(rx_udp_count.value());
351
352 info.set_sent_arp_count(tx_arp_count.value());
353 info.set_sent_ping_count(tx_ping_count.value());
354 info.set_sent_udp_count(tx_udp_count.value());
355
356 return info;
357}
358
359}
360}
#define ERS_HERE
HermesCoreController(uhal::HwInterface, std::string readout_id="")
void config_udp(uint16_t link, uint64_t src_mac, uint32_t src_ip, uint16_t src_port, uint64_t dst_mac, uint32_t dst_ip, uint16_t dst_port, uint32_t filters)
void config_mux(uint16_t link, uint16_t det, uint16_t crate, uint16_t slot)
bool is_link_in_error(uint16_t link, bool do_throw=false)
void config_fake_src(uint16_t link, uint16_t n_src, uint16_t data_len, uint16_t rate)
The DUNE-DAQ namespace.