10from rich.table
import Table
11from rich.logging
import RichHandler
16from pprint
import pprint
27 t.add_column(
'value', style=
'green')
28 for k,v
in vals.items():
36 t.add_column(
'value', style=
'green')
37 for k,v
in vals.items():
59 for i
in sorted(node.getNodes()):
60 regs[i] = node.getNode(i).read()
61 node.getClient().dispatch()
63 return {k: v.value()
for k, v
in regs.items()}
69 node.getClient().dispatch()
70 return {node.getId(): v.value()}
81 magic = self.
node.getNode(
'info.magic').read()
84 if self.
magic != 0xdeadbeef:
85 raise ValueError(f
"Magic number check failed. Expected '0xdeadbeef', found '{hex(self.magic)}'")
89 n_mgt = self.
node.getNode(
'info.generics.n_mgts').read()
90 n_src = self.
node.getNode(
'info.generics.n_srcs').read()
91 ref_freq = self.
node.getNode(
'info.generics.ref_freq').read()
102 return self.
node.getNode(id)
105 return self.
node.getNodes(regex)
113 self.
node.getNode(
'samp.ctrl.samp').write(
True)
114 self.
node.getNode(
'samp.ctrl.samp').write(
False)
117 self.
node.getNode(
'samp.ctrl.samp').write(
True)
120 self.
node.getNode(
'samp.ctrl.samp').write(
False)
128 raise ValueError(f
"Link {i} does not exist ({self.n_mgt})")
130 self.
get_node(
'tx_path.csr_tx_mux.ctrl.tx_mux_sel').write(i)
132 j = self.
get_node(
'tx_path.csr_tx_mux.ctrl.tx_mux_sel').read()
134 print(f
"Link {j} selected")
140 raise ValueError(f
"Input buffer {i} does not exist ({self.n_src})")
142 self.
node.getNode(
'tx_path.tx_mux.csr.ctrl.sel_buf').write(i)
148 raise ValueError(f
"Link {i} does not exist ({self.n_mgt})")
150 self.
node.getNode(
'tx_path.csr_udp_core.ctrl.udp_core_sel').write(i)
159mgts_all = tuple(str(i)
for i
in range(MAX_MGT))
161CONTEXT_SETTINGS = dict(help_option_names=[
'-h',
'--help'])
171 lDevices = ctx.obj.cm.getDevices()
172 if value
and (value
not in lDevices):
173 raise click.BadParameter(
174 'Device must be one of '+
175 ', '.join([
"'"+lId+
"'" for lId
in lDevices])
183 uhal.setLogLevelTo(uhal.LogLevel.WARNING)
196 is_zcu = hw.getNodes(
'tx.info')
197 is_detector = hw.getNodes(
'info')
201 tx_mux = hw.getNode(
'tx')
203 print(
"detector mode")
204 tx_mux = hw.getNode()
206 raise ValueError(f
"{self.device_id} is neither a zcu nor a detector board")
222@click.group(chain=True, context_settings=CONTEXT_SETTINGS)
223@click.option('-c', '--connection-file', default=None, help="IPBus connection file ")
224@click.option('-d', '--device', callback=validate_device, help="IPBus device")
227def cli(obj, connection_file, device):
229 obj.connection_file_path = connection_file
230 obj.device_id = device
236 t = Table(title=
"Control hosts")
239 for h
in obj.cm.getDevices():
243 t = Table(title=
"Receivers")
245 t.add_column(
'mac', style=
'green')
246 t.add_column(
'ip', style=
'blue')
247 t.add_column(
'port', style=
'blue')
248 for h,d
in rx_endpoints.items():
249 t.add_row(h, f
"0x{d['mac']:012x}", f
"{d['ip']}", str(d[
'port']))
252 t = Table(title=
"Transmitters")
254 t.add_column(
'mac', style=
'green')
255 t.add_column(
'ip', style=
'blue')
256 t.add_column(
'port', style=
'blue')
257 for h,d
in tx_endpoints.items():
258 t.add_row(h, f
"0x{d['mac']:012x}", f
"{d['ip']}", str(d[
'port']))
263@click.option('--nuke', is_flag=True, default=None)
270 hrms.get_node(
'csr.ctrl.nuke').write(0x1)
275 hrms.get_node(
'csr.ctrl.nuke').write(0x0)
278 hrms.get_node(
'csr.ctrl.soft_rst').write(0x1)
283 hrms.get_node(
'csr.ctrl.soft_rst').write(0x0)
288@click.option('--en/--dis', 'enable', default=None)
289@click.option('--buf-en/--buf-dis', 'buf_en', default=None)
290@click.option('--tx-en/--tx-dis', 'tx_en', default=None)
291@click.option('-l', '--link', type=int, default=0)
293def enable(obj, enable, buf_en, tx_en, link):
300 raise ValueError(f
"MGT {link} not instantiated")
302 hrms.sel_tx_mux(link)
306 tx_en = tx_en
if tx_en
is not None else enable
307 buf_en = buf_en
if buf_en
is not None else enable
309 if tx_en
is not None:
310 print(f
"- {'Enabling' if tx_en else 'Disabling'} 'tx block'")
311 hrms.get_node(
'tx_path.tx_mux.csr.ctrl.tx_en').write(tx_en)
314 if buf_en
is not None:
315 print(f
"- {'Enabling' if buf_en else 'Disabling'} 'input buffers'")
316 hrms.get_node(
'tx_path.tx_mux.csr.ctrl.en_buf').write(buf_en)
320 if enable
is not None:
321 print(f
"- {'Enabling' if enable else 'Disabling'} 'mux'")
322 hrms.get_node(
'tx_path.tx_mux.csr.ctrl.en').write(enable)
329 top_ctrl =
dump_sub_regs(hrms.get_node(
'tx_path.tx_mux.csr.ctrl'))
336@cli.command("mux-config")
337@click.argument('detid', type=int)
338@click.argument('crate', type=int)
339@click.argument('slot', type=int)
340@click.option('-l', '--link', type=int, default=0)
343 """Configure the UDP blocks """
347 hrms.sel_tx_mux(link)
349 hrms.get_node(
'tx_path.tx_mux.mux.ctrl.detid').write(detid)
350 hrms.get_node(
'tx_path.tx_mux.mux.ctrl.crate').write(crate)
351 hrms.get_node(
'tx_path.tx_mux.mux.ctrl.slot').write(slot)
353 mux_ctrl =
dump_sub_regs(hrms.get_node(
'tx_path.tx_mux.mux.ctrl'))
356 dict_to_hextable(mux_ctrl, title=f
'Link {link} mux cfg', show_header=
False),
360@cli.command("udp-config")
361@click.argument('src_id', type=click.Choice(tx_endpoints.keys()))
362@click.argument('dst_id', type=click.Choice(rx_endpoints.keys()))
363@click.option('-l', '--link', type=int, default=0)
366 """Configure the UDP blocks """
368 filter_control = 0x07400307
371 if link >= hrms.n_mgt:
372 raise ValueError(f
"Link {link} not instantiated")
374 hrms.sel_udp_core(link)
376 dst = rx_endpoints[dst_id]
377 src = tx_endpoints[src_id]
379 udp_core_ctrl = f
'tx_path.udp_core.udp_core_control'
381 hrms.get_node(f
'{udp_core_ctrl}.ctrl.filter_control').write(filter_control)
383 hrms.get_node(f
'{udp_core_ctrl}.src_addr_ctrl.use_external').write(0);
387 src_u32 = int.from_bytes(socket.inet_aton(src[
'ip']),
"big")
388 print(f
"Our ip address: {src['ip']} (0x{src_u32:08x})")
390 hrms.get_node(f
'{udp_core_ctrl}.src_addr_ctrl.src_ip_addr').write(src_u32)
394 dst_u32 = int.from_bytes(socket.inet_aton(dst[
'ip']),
"big")
395 print(f
"Their ip address: {dst['ip']} (0x{dst_u32:08x})")
396 hrms.get_node(f
'{udp_core_ctrl}.ctrl.dst_ip_addr').write(dst_u32)
400 print(f
"Our mac address: 0x{src['mac']:012x}")
401 hrms.get_node(f
'{udp_core_ctrl}.src_addr_ctrl.src_mac_addr_lower').write(src[
'mac'] & 0xffffffff)
402 hrms.get_node(f
'{udp_core_ctrl}.src_addr_ctrl.src_mac_addr_upper').write((src[
'mac'] >> 32) & 0xffff)
405 print(f
"Their mac address: 0x{dst['mac']:012x}")
406 hrms.get_node(f
'{udp_core_ctrl}.ctrl.dst_mac_addr_lower').write(dst[
'mac'] & 0xffffffff)
407 hrms.get_node(f
'{udp_core_ctrl}.ctrl.dst_mac_addr_upper').write((dst[
'mac'] >> 32) & 0xffff)
410 hrms.get_node(f
'{udp_core_ctrl}.src_addr_ctrl.src_port').write(src[
'port'])
411 hrms.get_node(f
'{udp_core_ctrl}.ctrl.dst_port').write(dst[
'port'])
416@cli.command("zcu-src-config")
417@click.option('-l', '--link', type=int, default=0)
418@click.option('-n', '--en-n-src', type=click.IntRange(0, MAX_SRCS_P_MGT), default=1)
419@click.option('-d', '--dlen', type=click.IntRange(0, 0xfff), default=0x383)
420@click.option('-r', '--rate-rdx', type=click.IntRange(0, 0x3f), default=0xa)
423 """Configure trivial data sources"""
425 hw = obj.cm.getDevice(obj.device_id)
438 if link >= hrms.n_mgt:
439 raise ValueError(f
"MGT {link} not instantiated")
441 if en_n_src > hrms.n_srcs_p_mgt:
442 raise ValueError(f
"{en_n_src} must be lower than the number of generators per link ({hrms.n_srcs_p_mgt})")
444 for i
in range(hrms.n_srcs_p_mgt):
445 src_id = hrms.n_srcs_p_mgt*link+i
446 hw.getNode(
'src.csr.ctrl.sel').write(src_id)
447 src_en = (i<en_n_src)
448 print(f
'Configuring generator {src_id} : {src_en}')
462 for i
in range(hrms.n_srcs_p_mgt):
463 hw.getNode(
'src.csr.ctrl.sel').write(i)
468 grid.add_column(
"ctrl")
469 grid.add_column(
"stat")
474 for j
in range(hrms.n_srcs_p_mgt):
500@cli.command("fakesrc-config")
501@click.option('-l', '--link', type=int, default=0)
502@click.option('-n', '--n-src', type=click.IntRange(0, MAX_SRCS_P_MGT), default=1)
503@click.option('-s', '--src', type=click.IntRange(0, MAX_SRCS_P_MGT), default=
None, multiple=
True)
504@click.option('-k', '--data-len', type=click.IntRange(0, 0xfff), default=0x383)
505@click.option('-r', '--rate-rdx', type=click.IntRange(0, 0x3f), default=0xa)
508 """Configure trivial data sources"""
512 all_srcs = set(range(hrms.n_srcs_p_mgt))
518 if en_srcs != set.intersection(all_srcs, en_srcs):
519 raise ValueError(
"AAARGH")
524 hrms.sel_tx_mux(link)
526 if n_src > hrms.n_srcs_p_mgt:
527 raise ValueError(f
"{n_src} must be lower than the number of generators per link ({n_srcs_p_mgt})")
529 was_en = hrms.get_node(
'tx_path.tx_mux.csr.ctrl.en_buf').read()
531 hrms.get_node(
'tx_path.tx_mux.csr.ctrl.en_buf').write(0x0)
534 for src_id
in range(hrms.n_srcs_p_mgt):
535 hrms.sel_tx_mux_buf(src_id)
537 src_en = (src_id
in en_srcs)
538 print(f
'Configuring generator {src_id} : {src_en}')
540 hrms.get_node(
'tx_path.tx_mux.buf.ctrl.fake_en').write(src_en)
544 hrms.get_node(
'tx_path.tx_mux.buf.ctrl.dlen').write(data_len)
546 hrms.get_node(
'tx_path.tx_mux.buf.ctrl.rate_rdx').write(rate_rdx)
549 hrms.get_node(
'tx_path.tx_mux.csr.ctrl.en_buf').write(was_en.value())
555@click.option('-l', '--links', 'sel_links', type=click.Choice(mgts_all), multiple=
True, default=
None)
556@click.option('-s', '--seconds', type=int, default=0)
557@click.option('-u/-U', '--show-udp/--hide-udp', 'show_udp', default=True)
558@click.option('-b/-B', '--show-buf/--hide-buf', 'show_buf', default=True)
560def stats(obj, sel_links, seconds, show_udp, show_buf):
561 """Simple program that greets NAME for a total of COUNT times."""
565 mgts = list(range(hrms.n_mgt))
571 sel_links = [int(s)
for s
in sel_links]
575 if not set(sel_links).issubset(mgts):
576 print(sel_links, mgts)
577 raise ValueError(f
"MGTs {set(sel_links)-set(mgts)} are not instantiated")
581 print(f
"Sampling hermes counters for {seconds}s")
582 hrms.sample_ctrs(seconds)
584 ts_l = hrms.get_node(
'samp.samp_ts_l').read()
585 ts_h = hrms.get_node(
'samp.samp_ts_h').read()
588 print(f
"Current timestamp : {(ts_h.value() << 32) + ts_l.value()}")
596 print(f
'---Tx Mux {i} Status---')
602 top_ctrl =
dump_sub_regs(hrms.get_node(
'tx_path.tx_mux.csr.ctrl'))
603 top_stat =
dump_sub_regs(hrms.get_node(
'tx_path.tx_mux.csr.stat'))
604 ctrl_mux =
dump_sub_regs(hrms.get_node(
'tx_path.tx_mux.mux.ctrl'))
605 stat_mux =
dump_sub_regs(hrms.get_node(
'tx_path.tx_mux.mux.stat'))
608 grid.add_column(
"ctrl")
609 grid.add_column(
"stat")
621 ctrl_udp_src =
dump_sub_regs(hrms.get_node(f
'tx_path.udp_core.udp_core_control.src_addr_ctrl'))
622 ctrl_udp =
dump_sub_regs(hrms.get_node(f
'tx_path.udp_core.udp_core_control.ctrl'))
623 ctrl_flt_udp =
dump_sub_regs(hrms.get_node(f
'tx_path.udp_core.udp_core_control.ctrl.filter_control'))
624 if hrms.get_nodes(f
'tx_path.udp_core.udp_core_control.rx_packet_counters'):
625 print(
"New tx counters found")
626 stat_rx_udp =
dump_sub_regs(hrms.get_node(f
'tx_path.udp_core.udp_core_control.rx_packet_counters'))
627 stat_tx_udp =
dump_sub_regs(hrms.get_node(f
'tx_path.udp_core.udp_core_control.tx_packet_counters'))
629 print(
"No new tx counters found")
630 stat_rx_udp =
dump_sub_regs(hrms.get_node(f
'tx_path.udp_core.udp_core_control.tx_packet_counters'))
631 stat_tx_udp = {
'-':0}
635 ctrl_srcdst[
'src_ip'] = ctrl_udp_src[
'src_ip_addr']
636 ctrl_srcdst[
'dst_ip'] = ctrl_udp[
'dst_ip_addr']
637 ctrl_srcdst[
'src_mac'] = (ctrl_udp_src[
'src_mac_addr_upper'] << 32) + ctrl_udp_src[
'src_mac_addr_lower']
638 ctrl_srcdst[
'dst_mac'] = (ctrl_udp[
'dst_mac_addr_upper'] << 32) + ctrl_udp[
'dst_mac_addr_lower']
639 ctrl_srcdst[
'src_port'] = ctrl_udp_src[
'src_port']
640 ctrl_srcdst[
'dst_port'] = ctrl_udp[
'dst_port']
643 grid.add_column(
"ctrl")
644 grid.add_column(
"stat")
657 src_ids = tuple(range(hrms.n_srcs_p_mgt))
660 hrms.sel_tx_mux_buf(j)
662 s[
'blk_acc'] = (s[
'blk_acc_h']<<32)+s[
'blk_acc_l']
663 s[
'blk_oflow'] = (s[
'blk_oflow_h']<<32)+s[
'blk_oflow_l']
664 s[
'blk_rej'] = (s[
'blk_rej_h']<<32)+s[
'blk_rej_l']
665 s[
'ts'] = (s[
'ts_h']<<32)+s[
'ts_l']
666 s[
'vol'] = (s[
'vol_h']<<32)+s[
'vol_l']
667 s[
'blk_longlast'] = (s[
'blk_longlast_h']<<32)+s[
'blk_longlast_l']
668 s[
'blk_lastnotval'] = (s[
'blk_lastnotval_h']<<32)+s[
'blk_lastnotval_l']
670 for k
in tuple(s.keys()):
671 for n
in (
'blk_acc_',
'blk_oflow_',
'blk_rej_',
'ts_',
'vol_',
'blk_longlast_',
'blk_lastnotval_'):
675 for k
in (
'ctrl',
'stat',
'buf_mon'):
687 t.add_column(f
'Buf {j}', style=
'green')
691 for k,v
in ibuf_stats.items():
692 reg_names = reg_names.union(v.keys())
694 for n
in sorted(reg_names):
695 t.add_row(n,*(hex(ibuf_stats[j][n])
for j
in src_ids))
701@click.option('-r', '--phy-reset', is_flag=True, default=None, help="Reset the phy block")
704 TX path low-level controls
708 pcs_pma_node = hrms.get_node(
'pcs_pma')
711 print(
"[cyan]Resetting phy[/cyan]")
712 pcs_pma_node.getNode(
'debug.csr.ctrl.phy_reset').write(0x1)
713 pcs_pma_node.getNode(
'debug.csr.ctrl.phy_reset').write(0x0)
714 pcs_pma_node.getClient().dispatch()
715 print(
"[cyan]Phy reset completed[/cyan]")
722 TX path clock monitoring
731 pcs_pma_node = hrms.get_node(
'pcs_pma')
734 stats = { n: pcs_pma_node.getNode(
'debug.csr.stat.'+n).read()
for n
in pcs_pma_node.getNode(
'debug.csr.stat').getNodes() }
735 pcs_pma_node.getClient().dispatch()
737 print(
dict_to_hextable(stats, title=
'TX clock registers', show_header=
False))
741 for idx, clk_id
in enumerate(clk_ids):
743 fn = pcs_pma_node.getNode(
'freq')
744 fn.getNode(
'ctrl.chan_sel').write(idx)
745 fn.getNode(
'ctrl.en_crap_mode').write(0x0)
746 fn.getClient().dispatch()
749 c = fn.getNode(
'freq.count').read()
750 v = fn.getNode(
'freq.valid').read()
751 fn.getClient().dispatch()
754 print(f
'[red]Failed to measure frequency of clock {clk_id}[/red]')
759 true_count = int(c)*64
761 clk_freq = true_count/denominator*ipb_freq
763 print(f
"Measured clock '{clk_id}'")
764 clk_freqs[clk_id] = clk_freq
767 print(
dict_to_table({k:f
"{v/1000000:7.3f} MHz" for k,v
in clk_freqs.items()}, title=
'TX clocks', show_header=
False))
773if __name__ ==
'__main__':
774 FORMAT =
"%(message)s"
776 level=
"INFO", format=FORMAT, datefmt=
"[%X]", handlers=[RichHandler()]
sample_ctrs(self, int seconds)
sel_udp_core(self, int i)
sel_tx_mux_buf(self, int i)
dict_to_hextable(dict vals, **kwargs)
dict_to_table(dict vals, **kwargs)
stats(obj, sel_links, seconds, show_udp, show_buf)
cli(obj, connection_file, device)
fakesrc_config(obj, link, n_src, src, data_len, rate_rdx)
udp_config(obj, src_id, dst_id, link)
mux_config(obj, detid, crate, slot, link)
read_and_print(hw, reg_list)
validate_device(ctx, param, value)
zcu_src_config(obj, link, en_n_src, dlen, rate_rdx)