DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
io.py
Go to the documentation of this file.
1from __future__ import print_function
2
3# Python imports
4import uhal
5import click
6import click_didyoumean
7import time
8import collections
9import math
10import sys
11import timing
12
13import timing.cli.toolbox as toolbox
14import timing.common.definitions as defs
15
16from click import echo, style, secho
17from os.path import join, expandvars, basename
18from timing.core import SI534xSlave, I2CExpanderSlave, DACSlave
19
20from timing.common.definitions import kBoardSim, kBoardFMC, kBoardPC059, kBoardMicrozed, kBoardTLU, kBoardFIB, kBoardMIB, kBoardPC069, kBoardGIB, kFIBRev2
21from timing.common.definitions import kFMCRev1, kFMCRev2, kFMCRev3, kFMCRev4, kPC059Rev1, kTLURev1, kSIMRev1, kFIBRev1, kMIBRev1, kGIBRev1
22from timing.common.definitions import kCarrierEnclustraA35, kCarrierKC705, kCarrierMicrozed, kCarrierNexusVideo, kCarrierTrenzTE0712
23from timing.common.definitions import kDesignMaster, kDesignOuroboros, kDesignOuroborosSim, kDesignEndpoint, kDesignFanout, kDesignChronos, kDesignBoreas, kDesignTest, kDesignKerberos, kDesignGaia, kDesignCharon, kDesignHades
24from timing.common.definitions import ClockSource, kFreeRun, kInput0, kInput1, kInput2, kInput3
25from timing.common.definitions import kBoardNameMap, kCarrierNameMap, kDesignNameMap, kUIDRevisionMap, kClockConfigMap
26from timing.common.definitions import kLibrarySupportedBoards, kLibrarySupportedDesigns
27
28# ------------------------------------------------------------------------------
29# __ ___ __
30# / |/ /__ ____ / /____ ____
31# / /|_/ / _ `(_-</ __/ -_) __/
32# /_/ /_/\_,_/___/\__/\__/_/
33
34
35@click.group('io', invoke_without_command=True)
36@click.pass_obj
37@click.argument('device', callback=toolbox.validate_device, shell_complete=toolbox.completeDevices)
38def io(obj, device):
39 '''
40 Timing master commands.
41
42 DEVICE: uhal device identifier
43 '''
44 lDevice = obj.mConnectionManager.getDevice(str(device))
45 if obj.mTimeout:
46 lDevice.setTimeoutPeriod(obj.mTimeout)
47
48 echo('Created device ' + click.style(lDevice.id(), fg='blue'))
49 lTopDesign = lDevice.getNode('')
50 lBoardInfo = toolbox.readSubNodes(lDevice.getNode('io.config'), False)
51 lDevice.dispatch()
52
53 if lBoardInfo['board_type'].value() in kLibrarySupportedBoards and lBoardInfo['design_type'].value() in kLibrarySupportedDesigns:
54 lTopDesign.validate_firmware_version()
55
56 echo("Design '{}' on board '{}' on carrier '{}' with frequency {} MHz".format(
57 style(kDesignNameMap[lBoardInfo['design_type'].value()], fg='blue'),
58 style(kBoardNameMap[lBoardInfo['board_type'].value()], fg='blue'),
59 style(kCarrierNameMap[lBoardInfo['carrier_type'].value()], fg='blue'),
60 style(str(lBoardInfo['clock_frequency'].value()/1e6), fg='blue')
61 ))
62
63 obj.mDevice = lDevice
64
65 obj.mBoardType = lBoardInfo['board_type'].value()
66 obj.mCarrierType = lBoardInfo['carrier_type'].value()
67 obj.mDesignType = lBoardInfo['design_type'].value()
68
69# ------------------------------------------------------------------------------
70
71# ------------------------------------------------------------------------------
72@io.command('reset', short_help="Perform a hard reset on the timing master.")
73@click.option('--soft', '-s', is_flag=True, default=False, help='Soft reset i.e. skip the clock chip configuration.')
74@click.option('--clock-source', 'clocksource', type=click.Choice(ClockSource.__members__.keys()), help='Manually specify clock source, free-running, upstream, etc..')
75@click.option('--force-pll-cfg', 'forcepllcfg', type=click.Path(exists=True), help='Manually specify clock config file' )
76@click.pass_obj
77@click.pass_context
78def reset(ctx, obj, soft, clocksource, forcepllcfg):
79 '''
80 Perform a hard reset on a timing board, including
81
82 \b
83 - ipbus registers
84 - i2c buses
85 - pll and pll configuration
86 '''
87
88 echo('Resetting ' + click.style(obj.mDevice.id(), fg='blue'))
89
90 lDevice = obj.mDevice
91 lBoardType = obj.mBoardType
92 lDesignType = obj.mDesignType
93
94 lIO = lDevice.getNode('io')
95
96 if lBoardType in kLibrarySupportedBoards:
97
98 if soft:
99 lIO.soft_reset()
100 return
101
102 if forcepllcfg is not None:
103 if clocksource is not None:
104 secho("You specified both a clock source for automatic clock config file look-up, and an explicit clock config file. Explicit clock config file will take precedence.", fg='yellow')
105
106 lIO.reset(forcepllcfg)
107 else:
108 lClockSource = None
109 if clocksource is None:
110 if lDesignType in [kDesignMaster, kDesignBoreas, kDesignOuroboros, kDesignOuroborosSim]:
111 lClockSource=kFreeRun
112 elif lDesignType in [kDesignEndpoint, kDesignChronos, kDesignHades, kDesignCharon]:
113 lClockSource=kInput1
114 elif lDesignType == kDesignFanout:
115 if lBoardType == kBoardFIB: #technically only fib v2
116 lClockSource=kInput0
117 elif lBoardType == kBoardPC059:
118 lClockSource=kInput1
119 elif lDesignType in [kDesignGaia, kDesignKerberos]:
120 lClockSource=kInput0
121
122 if lClockSource is None:
123 secho(f"Unable to match a default clock source for {kDesignNameMap[lDesignType]} on {kBoardNameMap[lBoardType]}\nReset failed!".format(), fg='red')
124 return
125 else:
126 secho(f"Default clock config selected for {kDesignNameMap[lDesignType]} on {kBoardNameMap[lBoardType]} is: {lClockSource}", fg='yellow')
127 else:
128 lClockSource=ClockSource.__members__[clocksource]
129
130 # lIO.reset_pll()
131 # lIO.getNode("csr.ctrl.i2c_sw_rst").write(0x0)
132 # lIO.getNode("csr.ctrl.i2c_exten_rst").write(0x0)
133 # lIO.getNode("csr.ctrl.clk_gen_rst").write(0x0)
134
135 # lIO.getNode("csr.ctrl.i2c_sw_rst").write(0x1)
136 # lIO.getNode("csr.ctrl.i2c_exten_rst").write(0x1)
137 # lIO.getNode("csr.ctrl.clk_gen_rst").write(0x1)
138 lIO.reset(lClockSource)
139 ctx.invoke(clkstatus)
140 else:
141 secho("Board identifier {} not supported by timing library".format(lBoardType), fg='yellow')
142 # board not supported by library, do reset here
143# ------------------------------------------------------------------------------
144
145# ------------------------------------------------------------------------------
146@io.command('freq', short_help="Measure some frequencies.")
147@click.pass_obj
148def freq(obj):
149 lDevice = obj.mDevice
150 lBoardType = obj.mBoardType
151 lIO = lDevice.getNode('io')
152
153 secho("PLL Clock frequency measurement:", fg='cyan')
154
155 if lBoardType in kLibrarySupportedBoards:
156 echo(lIO.get_clock_frequencies_table())
157 else:
158 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
159 # do freq measurement here
160 if lBoardType == kBoardMIB:
161
162 # MIB clock freq meas reg ops here
163
164 secho('MIB clock freqs', fg='green')
165# ------------------------------------------------------------------------------
166
167# ------------------------------------------------------------------------------
168@io.command('status')
169@click.pass_obj
170@click.pass_context
171@click.option('-v', 'verbose', is_flag=True)
172def status(ctx, obj, verbose):
173
174 lDevice = obj.mDevice
175 lBoardType = obj.mBoardType
176 lIO = lDevice.getNode('io')
177
178 if lBoardType in kLibrarySupportedBoards:
179 ctx.invoke(print_hardware_info)
180 echo(lIO.get_status())
181 else:
182 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
183 # do status printing here
184# ------------------------------------------------------------------------------
185
186# ------------------------------------------------------------------------------
187@io.command('clk-status')
188@click.pass_obj
189@click.pass_context
190@click.option('-v', 'verbose', is_flag=True)
191def clkstatus(ctx, obj, verbose):
192
193 lDevice = obj.mDevice
194 lDesignType = obj.mDesignType
195 lIO = lDevice.getNode('io')
196 lBoardType = obj.mBoardType
197
198 ctx.invoke(status)
199
200 echo()
201 ctx.invoke(freq)
202 echo()
203
204 if lBoardType in kLibrarySupportedBoards:
205 echo(lIO.get_pll_status())
206 else:
207 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
208 # do freq measurement here
209# ------------------------------------------------------------------------------
210
211# ------------------------------------------------------------------------------
212@io.command('dac-setup')
213@click.argument('value', type=click.IntRange(0,0xffff))
214@click.pass_obj
215@click.pass_context
216def dacsetup(ctx, obj, value):
217
218 lDevice = obj.mDevice
219 lBoardType = obj.mBoardType
220 lIO = lDevice.getNode('io')
221
222 if lBoardType == kBoardTLU:
223 lIO.configure_dac(0,value)
224 lIO.configure_dac(1,value)
225 secho("DAC1 and DAC2 set to " + hex(value), fg='cyan')
226 else:
227 secho("DAC setup only supported for TLU")
228# ------------------------------------------------------------------------------
229
230# ------------------------------------------------------------------------------
231@io.command('sfp-status', short_help="Read SFP parameters.")
232@click.pass_obj
233@click.pass_context
234@click.option('--sfp-id', 'sfp_id', required=False, type=click.IntRange(0, 8), help='SFP id to query.')
235def sfpstatus(ctx, obj, sfp_id):
236 '''
237 Read SFP status
238 '''
239
240 lDevice = obj.mDevice
241 lBoardType = obj.mBoardType
242 lCarrierType = obj.mCarrierType
243 lDesignType = obj.mDesignType
244
245 lIO = lDevice.getNode('io')
246
247
248 if lBoardType in kLibrarySupportedBoards:
249 ctx.invoke(print_hardware_info)
250 if sfp_id is not None:
251 echo(lIO.get_sfp_status(sfp_id))
252 else:
253 if lBoardType in [kBoardFMC, kBoardTLU, kBoardPC069]:
254 echo(lIO.get_sfp_status(0))
255 elif lBoardType in [ kBoardPC059, kBoardFIB, kBoardMIB, kBoardGIB ]:
256 # PC059 sfp id 0 is upstream sfp
257 if lBoardType == kBoardPC059:
258 lSFPIDRange = 9
259 elif lBoardType == kBoardFIB:
260 lSFPIDRange = 8
261 elif lBoardType == kBoardMIB:
262 lSFPIDRange = 3
263 elif lBoardType == kBoardGIB:
264 lSFPIDRange = 6
265 for i in range(lSFPIDRange):
266 try:
267 echo(lIO.get_sfp_status(i))
268 #echo()
269 except:
270 secho(f"SFP {i} status gather failed\n", fg='red')
271 pass
272 else:
273 secho(f"I don't know how many SFPs there are for board: {timing.common.definitions.BoardType(lBoardType)}\n", fg='red')
274
275 else:
276 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
277 # do sfp status here
278# ------------------------------------------------------------------------------
279
280# ------------------------------------------------------------------------------
281@io.command('switch-sfp-tx', short_help="Control sfp tx")
282@click.pass_obj
283@click.pass_context
284@click.option('--sfp-id', 'sfp_id', required=False, type=click.IntRange(0, 8), help='SFP id to query.')
285@click.option('--on/--off', default=False, help='enable/disable tx; default: FALSE')
286def switchsfptx(ctx, obj, sfp_id, on):
287 '''
288 Toggle SFP tx disable reg (if supported)
289 '''
290
291 lDevice = obj.mDevice
292 lBoardType = obj.mBoardType
293 lCarrierType = obj.mCarrierType
294 lDesignType = obj.mDesignType
295
296 lIO = lDevice.getNode('io')
297
298 if lBoardType in kLibrarySupportedBoards:
299 ctx.invoke(print_hardware_info)
300 lSFP=sfp_id
301 if sfp_id is None:
302 lSFP=0
303 lIO.switch_sfp_tx(lSFP, on)
304 else:
305 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
306 # do sfp switch here
307# ------------------------------------------------------------------------------
308
309# ------------------------------------------------------------------------------
310@io.command('switch-sfp-mux', short_help="Switch sfp mux")
311@click.argument('mux', type=int)
312@click.pass_obj
313def switchsfpmux(obj, mux):
314
315 lDevice = obj.mDevice
316 lBoardType = obj.mBoardType
317 lIO = lDevice.getNode('io')
318
319 if lBoardType in [kBoardPC059]:
320
321 echo("Setting sfp mux channel: {}".format(mux))
322 lIO.switch_sfp_mux_channel(mux)
323
324 else:
325 raise RuntimeError('Board {} does not have a sfp mux!'.format(kBoardNameMap[lBoardType]))
326# ------------------------------------------------------------------------------
327
328# ------------------------------------------------------------------------------
329@io.command('print-hardware-info')
330@click.pass_obj
331@click.pass_context
333
334 lDevice = obj.mDevice
335 lBoardType = obj.mBoardType
336 lIO = lDevice.getNode('io')
337
338 if lBoardType in kLibrarySupportedBoards:
339 try:
340 echo(lIO.get_hardware_info())
341 except:
342 secho("Failed to retrieve hardware information! I2C issue? Initial board reset needed?", fg='yellow')
343 e = sys.exc_info()[0]
344 secho("Error: {}".format(e), fg='red')
345 else:
346 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
347 # do status printing here
348# ------------------------------------------------------------------------------
349
350# ------------------------------------------------------------------------------
351@io.command('temp', short_help="Read board temperature")
352@click.pass_obj
353def temp(obj):
354
355 lDevice = obj.mDevice
356 lBoardType = obj.mBoardType
357 lIO = lDevice.getNode('io')
358
359 if lBoardType in [kBoardFIB]: # strictly only FIB v2
360 temp = lIO.read_board_temperature()
361 echo(f"Board temp: {temp} [C]")
362 else:
363 raise RuntimeError('Board {} does not have a temp reading!'.format(kBoardNameMap[lBoardType]))
364# ------------------------------------------------------------------------------
status(ctx, obj, verbose)
Definition io.py:172
sfpstatus(ctx, obj, sfp_id)
Definition io.py:235
freq(obj)
Definition io.py:148
print_hardware_info(ctx, obj)
Definition io.py:332
temp(obj)
Definition io.py:353
dacsetup(ctx, obj, value)
Definition io.py:216
reset(ctx, obj, soft, clocksource, forcepllcfg)
Definition io.py:78
switchsfptx(ctx, obj, sfp_id, on)
Definition io.py:286
switchsfpmux(obj, mux)
Definition io.py:313
clkstatus(ctx, obj, verbose)
Definition io.py:191