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