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