DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
toolbox.py
Go to the documentation of this file.
1from __future__ import print_function
2
3import re
4import signal
5
6import timing.common.definitions as defs
7import click
8import time
9
10from click import echo, style, secho
11
12# ------------------------------------------------------------------------------
13def get_default_clock_source(lDesign, lBoard):
14 lClockSource = None
15 if lDesign in [defs.kDesignMaster, defs.kDesignBoreas,
16 defs.kDesignOuroboros, defs.kDesignOuroborosSim]:
17 lClockSource = defs.kFreeRun
18 elif lDesign in [defs.kDesignEndpoint, defs.kDesignChronos,
19 defs.kDesignHades, defs.kDesignCharon]:
20 lClockSource = defs.kInput1
21 elif lDesign == defs.kDesignFanout:
22 if lBoard == defs.kBoardFIB: #technically only fib v2
23 lClockSource = defs.kInput0
24 elif lBoard == defs.kBoardPC059:
25 lClockSource = defs.kInput1
26 elif lDesign in [defs.kDesignGaia, defs.kDesignKerberos]:
27 lClockSource = defs.kInput0
28 return lClockSource
29# ------------------------------------------------------------------------------
30
31# ------------------------------------------------------------------------------
32def hookDebugger(debugger='gdb'):
33 '''debugging helper, hooks debugger to running interpreter process'''
34
35 import os
36 pid = os.spawnvp(os.P_NOWAIT,
37 debugger, [debugger, '-q', 'python', str(os.getpid())])
38
39 # give debugger some time to attach to the python process
40 import time
41 time.sleep( 1 )
42
43 # verify the process' existence (will raise OSError if failed)
44 os.waitpid( pid, os.WNOHANG )
45 os.kill( pid, 0 )
46 return
47# ------------------------------------------------------------------------------
48
49# ------------------------------------------------------------------------------
50class IntRange(click.types.IntParamType):
51 """A parameter that works similar to :data:`click.INT` but restricts
52 the value to fit into a range. The default behavior is to fail if the
53 value falls outside the range, but it can also be silently clamped
54 between the two edges.
55
56 See :ref:`ranges` for an example.
57 """
58 name = 'integer range'
59
60 def __init__(self, min=None, max=None, clamp=False):
61 self.min = min
62 self.max = max
63 self.clamp = clamp
64
65 def convert(self, value, param, ctx):
66
67 if type(value) == str:
68 if value.startswith('0x'):
69 base = 16
70 elif value.startswith('0o'):
71 bae = 8
72 elif value.startswith('0b'):
73 base = 2
74 else:
75 base = 10
76 rv = int(value, base)
77 else:
78 rv = int(value)
79 if self.clamp:
80 if self.min is not None and rv < self.min:
81 return self.min
82 if self.max is not None and rv > self.max:
83 return self.max
84 if self.min is not None and rv < self.min or \
85 self.max is not None and rv > self.max:
86 if self.min is None:
87 self.fail('%s is bigger than the maximum valid value '
88 '%s.' % (rv, self.max), param, ctx)
89 elif self.max is None:
90 self.fail('%s is smaller than the minimum valid value '
91 '%s.' % (rv, self.min), param, ctx)
92 else:
93 self.fail('%s is not in the valid range of %s to %s.'
94 % (rv, self.min, self.max), param, ctx)
95 return rv
96
97 def __repr__(self):
98 return 'IntRange(%r, %r)' % (self.min, self.max)
99# ------------------------------------------------------------------------------
100
101
102# ------------------------------------------------------------------------------
103def sanitizeConnectionPaths(aConnectionPaths):
104
105 lConnectionList = aConnectionPaths.split(';')
106 for i,c in enumerate(lConnectionList):
107 if re.match('^\w+://.*', c) is None:
108 lConnectionList[i] = 'file://'+c
109 return ';'.join(lConnectionList)
110# ------------------------------------------------------------------------------
111
112# ------------------------------------------------------------------------------
113def completeDevices(ctx, args, incomplete):
114 import uhal
115 root_ctx = ctx.find_root()
116 devs = uhal.ConnectionManager(sanitizeConnectionPaths(str(root_ctx.params['connections']))).getDevices()
117 return [k for k in devs if incomplete in k]
118 # return []
119# ------------------------------------------------------------------------------
120
121
122# ------------------------------------------------------------------------------
123def readSubNodes(aNode, dispatch=True):
124 lValues = { n:aNode.getNode(n).read() for n in aNode.getNodes() }
125
126 if dispatch:
127 aNode.getClient().dispatch()
128 return lValues
129# ------------------------------------------------------------------------------
130
131
132# ------------------------------------------------------------------------------
133def resetSubNodes(aNode, aValue=0x0, dispatch=True):
134 """
135 Reset subnodes of aNode to aValue
136 """
137 lValues = { n:aNode.getNode(n).write(aValue) for n in aNode.getNodes() }
138 if dispatch:
139 aNode.getClient().dispatch()
140# ------------------------------------------------------------------------------
141
142# ------------------------------------------------------------------------------
143def hookDebugger(debugger='gdb'):
144 '''
145 debugging helper, hooks debugger to running interpreter process
146 '''
147
148 import os
149 pid = os.spawnvp(os.P_NOWAIT,
150 debugger, [debugger, '-q', 'python', str(os.getpid())])
151
152 # give debugger some time to attach to the python process
153 import time
154 time.sleep( 1 )
155
156 # verify the process' existence (will raise OSError if failed)
157 os.waitpid( pid, os.WNOHANG )
158 os.kill( pid, 0 )
159 return
160# ------------------------------------------------------------------------------
161
162# -----------------
163def validate_device(ctx, param, value):
164
165 lDevices = ctx.obj.mConnectionManager.getDevices()
166 if value not in lDevices:
167 raise click.BadParameter(
168 'Device must be one of '+
169 ', '.join(["'"+lId+"'" for lId in lDevices])
170 )
171 return value
172# -----------------
173
174
175# -----------------
176def complete_device(ctx, args, incomplete):
177 lDevices = ctx.obj.mConnectionManager.getDevices()
178
179 return [k for k in lDevices if incomplete in k]
180# -----------------
181
182# ------------------------------------------------------------------------------
183def split(ctx, param, value):
184 if value is None:
185 return []
186
187 return value.split(',')
188# ------------------------------------------------------------------------------
189
190# ------------------------------------------------------------------------------
191def __str2int__( value ):
192 if value.startswith('0x'):
193 base = 16
194 elif value.startswith('0o'):
195 bae = 8
196 elif value.startswith('0b'):
197 base = 2
198 else:
199 base = 10
200 return int(value, base)
201
202def split_ints(ctx, param, value):
203
204 sep = ','
205 dash = '-'
206
207 if value is None:
208 return []
209
210 numbers = []
211 for item in value.split(sep):
212 nums = item.split(dash)
213 if len(nums) == 1:
214 # single entry
215 numbers.append(__str2int__(item))
216 elif len(nums) == 2:
217 # range
218 i, j = __str2int__(nums[0]), __str2int__(nums[1])
219 if i > j:
220 click.ClickException('Invalid interval '+item)
221 numbers.extend(list(range(i,j+1)))
222 else:
223 click.ClickException('Malformed option (comma separated list expected): {}'.format(value))
224
225 return numbers
226# ------------------------------------------------------------------------------
227
228
229# ------------------------------------------------------------------------------
230def printRegTable(aRegs, aHeader=True, sort=True):
231 echo ( format_reg_table(aRegs, aHeader, sort) )
232# ------------------------------------------------------------------------------
233
234# ------------------------------------------------------------------------------
235def printDictTable(aDict, aHdr=True, aSort=True, aFmtr=None):
236 echo ( formatDictTable(aDict, aHdr, aSort, aFmtr) )
237# ------------------------------------------------------------------------------
238
239
240# ------------------------------------------------------------------------------
241def collateTables(t1, t2):
242 l1 = t1.split('\n')
243 l2 = t2.split('\n')
244
245 col1 = max([len(escape_ansi(l)) for l in l1])
246 col2 = max([len(escape_ansi(l)) for l in l2])
247
248 nrows = max(len(l1), len(l2));
249
250 l1 += [''] * (nrows - len(l1))
251 l2 += [''] * (nrows - len(l2))
252 fmt = '\'{:<%d}\' \'{:<%d}\'' % (col1, col2)
253 for c1,c2 in zip(l1, l2):
254 print (c1 + ' '*(col1-len(escape_ansi(c1))), ' ' ,c2 + ' '*(col2-len(escape_ansi(c2))))
255# ------------------------------------------------------------------------------
256
257# ------------------------------------------------------------------------------
258kReEscapeAnsi = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
259
260def escape_ansi(line):
261 return kReEscapeAnsi.sub('', line)
262# ------------------------------------------------------------------------------
263
264# ------------------------------------------------------------------------------
265def formatTStamp( aRawTStamp, clock_frequency_hz ):
266 ts = int(aRawTStamp[0]) + int((aRawTStamp[1]) << 32)
267
268 lSubSec = ts % clock_frequency_hz
269 lSecFromEpoch = ts / clock_frequency_hz
270
271 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime(lSecFromEpoch))
272# ------------------------------------------------------------------------------
273
274
275# ------------------------------------------------------------------------------
276def tstamp2int( aRawTStamp ):
277 return int(aRawTStamp[0]) + int((aRawTStamp[1]) << 32)
278# ------------------------------------------------------------------------------
279
280
281# ------------------------------------------------------------------------------
282def fmtEpState(aState):
283 aState = aState.value()
284 return '{} ({})'.format(defs.kEpStates[aState], hex(aState)) if aState in defs.kEpStates else hex(aState)
285# ------------------------------------------------------------------------------
286
287
288# ------------------------------------------------------------------------------
289class InterruptHandler(object):
290
291 def __init__(self, sig=signal.SIGINT):
292 self.sig = sig
293
294 def __enter__(self):
295
296 self.interrupted = False
297 self.released = False
298
299 self.original_handler = signal.getsignal(self.sig)
300
301 def handler(signum, frame):
302 self.release()
303 self.interrupted = True
304
305 signal.signal(self.sig, handler)
306
307 return self
308
309 def __exit__(self, type, value, tb):
310 self.release()
311
312 def release(self):
313
314 if self.released:
315 return False
316
317 signal.signal(self.sig, self.original_handler)
318
319 self.released = True
320
321 return True
322# ------------------------------------------------------------------------------
323
324# ------------------------------------------------------------------------------
325def twos_complement(value, n_bits):
326 if (value & (1 << (n_bits - 1))) != 0:
327 value = value - (1 << n_bits)
328 return value
329# ------------------------------------------------------------------------------
__init__(self, min=None, max=None, clamp=False)
Definition toolbox.py:60
convert(self, value, param, ctx)
Definition toolbox.py:65
__init__(self, sig=signal.SIGINT)
Definition toolbox.py:291
__exit__(self, type, value, tb)
Definition toolbox.py:309
resetSubNodes(aNode, aValue=0x0, dispatch=True)
Definition toolbox.py:133
formatTStamp(aRawTStamp, clock_frequency_hz)
Definition toolbox.py:265
readSubNodes(aNode, dispatch=True)
Definition toolbox.py:123
sanitizeConnectionPaths(aConnectionPaths)
Definition toolbox.py:103
fmtEpState(aState)
Definition toolbox.py:282
split(ctx, param, value)
Definition toolbox.py:183
hookDebugger(debugger='gdb')
Definition toolbox.py:32
completeDevices(ctx, args, incomplete)
Definition toolbox.py:113
printRegTable(aRegs, aHeader=True, sort=True)
Definition toolbox.py:230
printDictTable(aDict, aHdr=True, aSort=True, aFmtr=None)
Definition toolbox.py:235
tstamp2int(aRawTStamp)
Definition toolbox.py:276
complete_device(ctx, args, incomplete)
Definition toolbox.py:176
twos_complement(value, n_bits)
Definition toolbox.py:325
get_default_clock_source(lDesign, lBoard)
Definition toolbox.py:13
validate_device(ctx, param, value)
Definition toolbox.py:163
collateTables(t1, t2)
Definition toolbox.py:241
split_ints(ctx, param, value)
Definition toolbox.py:202