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, kBoardGIBV3, 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 if clocksource is None:
109 lClockSource = toolbox.get_default_clock_source(
110 lDesignType, lBoardType)
111 if lClockSource is None:
112 secho(f"Unable to match a default clock source for {kDesignNameMap[lDesignType]} on {kBoardNameMap[lBoardType]}\nReset failed!".format(), fg='red')
113 return
114 else:
115 secho(f"Default clock config selected for {kDesignNameMap[lDesignType]} on {kBoardNameMap[lBoardType]} is: {lClockSource}", fg='yellow')
116 else:
117 lClockSource=ClockSource.__members__[clocksource]
118
119 # lIO.reset_pll()
120 # lIO.getNode("csr.ctrl.i2c_sw_rst").write(0x0)
121 # lIO.getNode("csr.ctrl.i2c_exten_rst").write(0x0)
122 # lIO.getNode("csr.ctrl.clk_gen_rst").write(0x0)
123
124 # lIO.getNode("csr.ctrl.i2c_sw_rst").write(0x1)
125 # lIO.getNode("csr.ctrl.i2c_exten_rst").write(0x1)
126 # lIO.getNode("csr.ctrl.clk_gen_rst").write(0x1)
127 lIO.reset(lClockSource)
128 time.sleep(0.5)
129 ctx.invoke(clkstatus)
130 else:
131 secho("Board identifier {} not supported by timing library".format(lBoardType), fg='yellow')
132 # board not supported by library, do reset here
133# ------------------------------------------------------------------------------
134
135# ------------------------------------------------------------------------------
136@io.command('freq', short_help="Measure some frequencies.")
137@click.pass_obj
138def freq(obj):
139 lDevice = obj.mDevice
140 lBoardType = obj.mBoardType
141 lIO = lDevice.getNode('io')
142
143 secho("PLL Clock frequency measurement:", fg='cyan')
144
145 if lBoardType in kLibrarySupportedBoards:
146 echo(lIO.get_clock_frequencies_table())
147 else:
148 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
149 # do freq measurement here
150 if lBoardType == kBoardMIB:
151
152 # MIB clock freq meas reg ops here
153
154 secho('MIB clock freqs', fg='green')
155# ------------------------------------------------------------------------------
156
157# ------------------------------------------------------------------------------
158@io.command('status')
159@click.pass_obj
160@click.pass_context
161@click.option('-v', 'verbose', is_flag=True)
162def status(ctx, obj, verbose):
163
164 lDevice = obj.mDevice
165 lBoardType = obj.mBoardType
166 lIO = lDevice.getNode('io')
167
168 if lBoardType in kLibrarySupportedBoards:
169 ctx.invoke(print_hardware_info)
170 echo(lIO.get_status())
171 else:
172 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
173 # do status printing here
174# ------------------------------------------------------------------------------
175
176# ------------------------------------------------------------------------------
177@io.command('configure-pll', short_help="Configure board PLL.")
178@click.option('--clock-source', 'clocksource', type=click.Choice(ClockSource.__members__.keys()), help='Manually specify clock source, free-running, upstream, etc..')
179@click.option('--force-pll-cfg', 'forcepllcfg', type=click.Path(exists=True), help='Manually specify clock config file' )
180@click.pass_obj
181@click.pass_context
182def configure_pll(ctx, obj, clocksource, forcepllcfg):
183 '''
184 Perform a pll configuration
185
186 \b
187 - pll and pll configuration
188 '''
189
190 echo('PLL configuration ' + click.style(obj.mDevice.id(), fg='blue'))
191
192 lDevice = obj.mDevice
193 lBoardType = obj.mBoardType
194 lDesignType = obj.mDesignType
195
196 lIO = lDevice.getNode('io')
197
198 if lBoardType in kLibrarySupportedBoards:
199 if forcepllcfg is not None:
200 if clocksource is not None:
201 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')
202
203 lIO.configure_pll(forcepllcfg)
204 else:
205 if clocksource is None:
206 lClockSource = toolbox.get_default_clock_source(
207 lDesignType, lBoardType)
208 if lClockSource is None:
209 secho(f"Unable to match a default clock source for {kDesignNameMap[lDesignType]} on {kBoardNameMap[lBoardType]}\nReset failed!".format(), fg='red')
210 return
211 else:
212 secho(f"Default clock config selected for {kDesignNameMap[lDesignType]} on {kBoardNameMap[lBoardType]} is: {lClockSource}", fg='yellow')
213 else:
214 lClockSource=ClockSource.__members__[clocksource]
215 lIO.configure_pll(lClockSource)
216 ctx.invoke(clkstatus)
217 else:
218 secho("Board identifier {} not supported by timing library".format(lBoardType), fg='yellow')
219 # board not supported by library, do reset here
220# ------------------------------------------------------------------------------
221
222# ------------------------------------------------------------------------------
223@io.command('clk-status')
224@click.pass_obj
225@click.pass_context
226@click.option('-v', 'verbose', is_flag=True)
227def clkstatus(ctx, obj, verbose):
228
229 lDevice = obj.mDevice
230 lDesignType = obj.mDesignType
231 lIO = lDevice.getNode('io')
232 lBoardType = obj.mBoardType
233
234 ctx.invoke(status)
235
236 echo()
237
238 if lBoardType in kLibrarySupportedBoards:
239 echo(lIO.get_pll_status())
240 else:
241 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
242 # do freq measurement here
243 echo()
244
245 ctx.invoke(freq)
246# ------------------------------------------------------------------------------
247
248# ------------------------------------------------------------------------------
249@io.command('dac-setup')
250@click.argument('value', type=click.IntRange(0,0xffff))
251@click.pass_obj
252@click.pass_context
253def dacsetup(ctx, obj, value):
254
255 lDevice = obj.mDevice
256 lBoardType = obj.mBoardType
257 lIO = lDevice.getNode('io')
258
259 if lBoardType == kBoardTLU:
260 lIO.configure_dac(0,value)
261 lIO.configure_dac(1,value)
262 secho("DAC1 and DAC2 set to " + hex(value), fg='cyan')
263 else:
264 secho("DAC setup only supported for TLU")
265# ------------------------------------------------------------------------------
266
267# ------------------------------------------------------------------------------
268@io.command('sfp-status', short_help="Read SFP parameters.")
269@click.pass_obj
270@click.pass_context
271@click.option('--sfp-id', 'sfp_id', required=False, type=click.IntRange(0, 8), help='SFP id to query.')
272def sfpstatus(ctx, obj, sfp_id):
273 '''
274 Read SFP status
275 '''
276
277 lDevice = obj.mDevice
278 lBoardType = obj.mBoardType
279 lCarrierType = obj.mCarrierType
280 lDesignType = obj.mDesignType
281
282 lIO = lDevice.getNode('io')
283
284
285 if lBoardType in kLibrarySupportedBoards:
286 ctx.invoke(print_hardware_info)
287 if sfp_id is not None:
288 echo(lIO.get_sfp_status(sfp_id))
289 else:
290 if lBoardType in [kBoardFMC, kBoardTLU, kBoardPC069]:
291 echo(lIO.get_sfp_status(0))
292 elif lBoardType in [ kBoardPC059, kBoardFIB, kBoardMIB,
293 kBoardGIB, kBoardGIBV3 ]:
294 # PC059 sfp id 0 is upstream sfp
295 if lBoardType == kBoardPC059:
296 lSFPIDRange = 9
297 elif lBoardType == kBoardFIB:
298 lSFPIDRange = 8
299 elif lBoardType == kBoardMIB:
300 lSFPIDRange = 3
301 elif lBoardType == kBoardGIB:
302 lSFPIDRange = 6
303 elif lBoardType == kBoardGIBV3:
304 lSFPIDRange = 7
305 for i in range(lSFPIDRange):
306 try:
307 echo(lIO.get_sfp_status(i))
308 #echo()
309 except Exception as e:
310 if isinstance(e, RuntimeError) and str(e) == " I2C bus: i2c error. Transfer finished but bus still busy I2CException on bus: i2c":
311 secho(f"Bad SFP {i} found with exception:")
312 secho(str(e))
313 if lBoardType in [kBoardGIB, kBoardGIBV3]:
314 secho("resetting i2c after failure\n", fg='yellow')
315 lDevice.getNode("io.csr.ctrl.i2c_sw_rst").write(0x0)
316 lDevice.dispatch()
317 lDevice.getNode("io.csr.ctrl.i2c_sw_rst").write(0x1)
318 lDevice.dispatch()
319 else:
320 secho(f"SFP {i} status gather failed with exception:", fg='red')
321 secho(str(e))
322 pass
323 else:
324 secho(f"I don't know how many SFPs there are for board: {timing.common.definitions.BoardType(lBoardType)}\n", fg='red')
325
326 else:
327 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
328 # do sfp status here
329# ------------------------------------------------------------------------------
330
331# ------------------------------------------------------------------------------
332@io.command('switch-sfp-tx', short_help="Control sfp tx")
333@click.pass_obj
334@click.pass_context
335@click.option('--sfp-id', 'sfp_id', required=False, type=click.IntRange(0, 8), help='SFP id to query.')
336@click.option('--on/--off', default=False, help='enable/disable tx; default: FALSE')
337def switchsfptx(ctx, obj, sfp_id, on):
338 '''
339 Toggle SFP tx disable reg (if supported)
340 '''
341
342 lDevice = obj.mDevice
343 lBoardType = obj.mBoardType
344 lCarrierType = obj.mCarrierType
345 lDesignType = obj.mDesignType
346
347 lIO = lDevice.getNode('io')
348
349 if lBoardType in kLibrarySupportedBoards:
350 ctx.invoke(print_hardware_info)
351 lSFP=sfp_id
352 if sfp_id is None:
353 lSFP=0
354 lIO.switch_sfp_tx(lSFP, on)
355 else:
356 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
357 # do sfp switch here
358# ------------------------------------------------------------------------------
359
360# ------------------------------------------------------------------------------
361@io.command('switch-sfp-mux', short_help="Switch sfp mux")
362@click.argument('mux', type=int)
363@click.pass_obj
364def switchsfpmux(obj, mux):
365
366 lDevice = obj.mDevice
367 lBoardType = obj.mBoardType
368 lIO = lDevice.getNode('io')
369
370 if lBoardType in [kBoardPC059]:
371
372 echo("Setting sfp mux channel: {}".format(mux))
373 lIO.switch_sfp_mux_channel(mux)
374
375 else:
376 raise RuntimeError('Board {} does not have a sfp mux!'.format(kBoardNameMap[lBoardType]))
377# ------------------------------------------------------------------------------
378
379# ------------------------------------------------------------------------------
380@io.command('print-hardware-info')
381@click.pass_obj
382@click.pass_context
384
385 lDevice = obj.mDevice
386 lBoardType = obj.mBoardType
387 lIO = lDevice.getNode('io')
388
389 if lBoardType in kLibrarySupportedBoards:
390 try:
391 echo(lIO.get_hardware_info())
392 except:
393 secho("Failed to retrieve hardware information! I2C issue? Initial board reset needed?", fg='yellow')
394 e = sys.exc_info()[0]
395 secho("Error: {}".format(e), fg='red')
396 else:
397 secho("Board {} not supported by timing library".format(lBoardType), fg='yellow')
398 # do status printing here
399# ------------------------------------------------------------------------------
400
401# ------------------------------------------------------------------------------
402@io.command('temp', short_help="Read board temperature")
403@click.pass_obj
404def temp(obj):
405
406 lDevice = obj.mDevice
407 lBoardType = obj.mBoardType
408 lIO = lDevice.getNode('io')
409
410 if lBoardType in [kBoardFIB]: # strictly only FIB v2
411 temp = lIO.read_board_temperature()
412 echo(f"Board temp: {temp} [C]")
413 else:
414 raise RuntimeError('Board {} does not have a temp reading!'.format(kBoardNameMap[lBoardType]))
415# ------------------------------------------------------------------------------
status(ctx, obj, verbose)
Definition io.py:162
sfpstatus(ctx, obj, sfp_id)
Definition io.py:272
freq(obj)
Definition io.py:138
print_hardware_info(ctx, obj)
Definition io.py:383
temp(obj)
Definition io.py:404
dacsetup(ctx, obj, value)
Definition io.py:253
reset(ctx, obj, soft, clocksource, forcepllcfg)
Definition io.py:78
switchsfptx(ctx, obj, sfp_id, on)
Definition io.py:337
switchsfpmux(obj, mux)
Definition io.py:364
clkstatus(ctx, obj, verbose)
Definition io.py:227
configure_pll(ctx, obj, clocksource, forcepllcfg)
Definition io.py:182