13 from __future__
import print_function
16 from writer
import VCDWriter
17 from bitstring
import BitArray
23 if sys.version_info[0] < 3:
24 from itertools
import izip
as zip
31 def printBin(evt, wordwidth=8, linewidth=8, paraheight=4):
32 words = [evt[word:word + wordwidth].bin
for word
in range(0, len(evt), wordwidth)]
33 lines = ([
' '.join(words[n:n + linewidth])
for n
in range(0, len(words), linewidth)])
34 paras = ([
'\n'.join(lines[n:n + paraheight])
for n
in range(0, len(lines), paraheight)])
35 print(
'\n\n'.join(paras))
38 def printHex(evt, wordwidth=32, linewidth=8, paraheight=4):
39 words = [evt[word:word + wordwidth].hex
for word
in range(0, len(evt), wordwidth)]
40 lines = ([
' '.join(words[n:n + linewidth])
for n
in range(0, len(words), linewidth)])
41 paras = ([
'\n'.join(lines[n:n + paraheight])
for n
in range(0, len(lines), paraheight)])
42 print(
'\n\n'.join(paras))
46 operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
47 ast.Div: op.truediv, ast.Pow: op.pow, ast.USub: op.neg}
51 return eval_(ast.parse(expr, mode=
'eval').body)
55 if isinstance(node, ast.Num):
57 elif isinstance(node, ast.BinOp):
58 return operators[type(node.op)](eval_(node.left), eval_(node.right))
59 elif isinstance(node, ast.UnaryOp):
60 return operators[type(node.op)](eval_(node.operand))
65 def makeAtlas(signals, evtsize):
67 Make bitmap from VHDL signal assignments.
68 input: string containing b2l signal designations.
70 [ [ name, start, stop, pos, size, module ], ... ]
74 finesses = re.findall(
r'(.+?)<=(.+?);', signals, re.DOTALL)
75 if len(finesses) != sum(1
if width > 0
else 0
for width
in evtsize):
76 raise Exception(
'Number of valid signal assignments does not match HSLB data dimension: ' + str(evtsize))
77 for finesse
in finesses:
78 for item
in re.split(
r'[\s\n]?&[\s\n]*', finesse[1].strip()):
79 item = re.sub(
r'--.+',
'', item)
80 dummy = re.match(
r'"([01]+)"', item)
82 sig = re.match(
r'(.+)\s*\((.+) downto (.+)\)', item.strip())
86 print(
'signal: ' + item.strip())
87 start = eval_expr(sig.group(2))
88 stop = eval_expr(sig.group(3))
89 size = start - stop + 1
91 raise ValueError(
'Vector size cannot be 0 or negative.')
94 size = len(dummy.group(1))
96 start, stop = size - 1, 0
97 atlas.append([name, start, stop, pos, size, finesse[0]])
99 if pos != sum(evtsize):
101 'Size of atlas:{} does not match event size:{}'.format(pos, evtsize))
105 def isUnamed(signal):
106 return signal[0] ==
"unamed"
109 def unpack(meta, headers, triggers, atlas, writer, evtsize):
111 transform into VCD signals from clock-seperated data and hitmap
113 unpackwith =
', '.join([
'bin:{}'.format(sig[4])
for sig
in atlas])
114 vcdVars = [writer.register_var(
115 sig[5], sig[0] +
'[{}:{}]'.format(sig[1], sig[2]),
'wire', size=sig[4])
if
116 not isUnamed(sig)
else None for sig
in atlas]
117 event = writer.register_var(
'm',
'event',
'event')
118 eventNo = writer.register_var(
'm',
'eventNo',
'integer')
119 subrun = writer.register_var(
'm',
'subrun',
'integer')
120 run = writer.register_var(
'm',
'run',
'integer')
121 delays = [writer.register_var(
'm',
'delay{}'.format(i),
'wire', size=9)
122 for i
in range(len(evtsize))]
123 lastvalues = [
None] * len(atlas)
126 power = period.bit_length() - 1
127 print(
'converting to waveform ...')
129 null = BitArray([0] * sum(evtsize))
131 change = writer.change
132 for trgInd, trg
in enumerate(triggers):
140 timestamp = iteration << power
141 writer.change(event, timestamp,
'1')
143 writer.change(eventNo, timestamp, meta[trgInd][0])
144 writer.change(run, timestamp, meta[trgInd][1])
145 writer.change(subrun, timestamp, meta[trgInd][2])
146 for i, d
in enumerate(delays):
147 if len(headers[trgInd][i]) <= 0:
149 writer.change(d, timestamp, headers[trgInd][i][64 + 11: 64 + 20].uint)
150 clocks = list(trg.cut(sum(evtsize)))
153 clocks = clocks[1:48] + [clocks[0]]
157 if timestamp & 1023 == 0:
158 print(
'\r{} us converted'.format(str(timestamp)[:-3]), end=
"")
160 timestamp = iteration << power
162 values = clock.unpack(unpackwith)
163 for i, sig
in enumerate(atlas):
165 if dummycheck
and '1' in values[i]
and '0' in values[i]:
166 print(
'[Warning] non-uniform dummy value detected at {}ns: {}'.format(
167 timestamp, sig[3] % sum(evtsize)))
170 if values[i] != lastvalues[i]:
171 change(vcdVars[i], timestamp, values[i])
185 def writeVCD(meta, data, atlas, fname, evtsize, combine=False):
187 evt: 2D list of HSLB buffers
188 atlas: list of iterates
191 samples = len(list(
filter(
None, data[0]))[0]) // list(
filter(
None, evtsize))[0]
192 NullArray = BitArray([])
197 clocks.append(BitArray([]).join(
198 itertools.chain.from_iterable(zip(
200 *[evt[buf][32 * 3:].cut(evtsize[buf])
201 if evtsize[buf] > 0
else [NullArray] * samples
203 for buf
in range(len(evtsize))]))))
204 headers.append([evt[buf][:32 * 3]
for buf
in range(len(evtsize))])
205 with open(fname,
'w')
as fout:
206 with VCDWriter(fout, timescale=
'1 ns', date=
'today')
as writer:
209 raise Exception(
'Combine has not been updated. Use literal instead.')
212 unpack(meta, headers, clocks, atlas, writer, evtsize)
215 if __name__ ==
"__main__":
217 parser = argparse.ArgumentParser()
218 parser.add_argument(
"-i",
"--pickle", help=
"input pickle file")
219 parser.add_argument(
"-s",
"--signal", help=
"input signal file")
220 parser.add_argument(
"-o",
"--output", help=
"output VCD file")
221 parser.add_argument(
"-nc",
"--nocheck", help=
"disable dummy variable check",
223 args = parser.parse_args()
225 with open(args.signal)
as fin:
226 evtsize = [int(width)
for width
in fin.readline().split()]
227 print(
'interpreting B2L data with dimension ' + str(evtsize))
228 atlas = makeAtlas(fin.read(), evtsize)
230 atlas = makeAtlas(signalsall, evtsize)
233 rfp = open(pica,
'rb')
234 data = pickle.load(rfp)
235 meta = pickle.load(rfp)
240 fname = args.output
if args.output
else pica[:pica.rfind(
'.')] +
'.vcd'
241 writeVCD(meta, data, atlas, fname, evtsize)
std::map< ExpRun, std::pair< double, double > > filter(const std::map< ExpRun, std::pair< double, double >> &runs, double cut, std::map< ExpRun, std::pair< double, double >> &runsRemoved)
filter events to remove runs shorter than cut, it stores removed runs in runsRemoved