13 from __future__
import print_function
16 from writer
import VCDWriter
17 from bitstring
import BitArray
19 from operator
import itemgetter
24 if sys.version_info[0] < 3:
25 from itertools
import izip
as zip
26 evtsize = [2048, 2048, 0, 0]
33 def printBin(evt, wordwidth=8, linewidth=8, paraheight=4):
34 words = [evt[word:word + wordwidth].bin
for word
in range(0, len(evt), wordwidth)]
35 lines = ([
' '.join(words[n:n + linewidth])
for n
in range(0, len(words), linewidth)])
36 paras = ([
'\n'.join(lines[n:n + paraheight])
for n
in range(0, len(lines), paraheight)])
37 print(
'\n\n'.join(paras))
40 def printHex(evt, wordwidth=32, linewidth=8, paraheight=4):
41 words = [evt[word:word + wordwidth].hex
for word
in range(0, len(evt), wordwidth)]
42 lines = ([
' '.join(words[n:n + linewidth])
for n
in range(0, len(words), linewidth)])
43 paras = ([
'\n'.join(lines[n:n + paraheight])
for n
in range(0, len(lines), paraheight)])
44 print(
'\n\n'.join(paras))
49 dddd(15 downto 0) & cntr125M(15 downto 0) &
50 hitMapTsf(191 downto 0) & valid_tracker(0 downto 0) &
52 tracker_out[0](428 downto 210) & ccSelf(8 downto 0) &
53 unamed (77 downto 36) &
54 mergers[5](255 downto 236) & mergers[5](235 downto 0) &
55 mergers[4](255 downto 236) & mergers[4](235 downto 0) &
56 mergers[3](255 downto 236) & mergers[3](235 downto 0) &
57 mergers[2](255 downto 236) & mergers[2](235 downto 0) &
58 mergers[1](255 downto 236) & mergers[1](235 downto 0) &
59 mergers[0](255 downto 236) & mergers[0](235 downto 0)
63 ddd(15 downto 0) & cntr125M2D(15 downto 0) &
64 "000" & TSF0_input(218 downto 210) &
65 "000" & TSF2_input(218 downto 210) &
66 "000" & TSF4_input(218 downto 210) &
67 "000" & TSF6_input(218 downto 210) &
68 "000" & TSF8_input(218 downto 210) &
71 ''.join([
"""TSF{sl:d}_input({high:d} downto {low:d}) &
72 TSF{sl:d}_input({high2:d} downto {low2:d}) &
73 """.format(sl=sl, high=h, low=h - 7, high2=h - 8, low2=h - 20)
for sl
in range(0, 9, 2)
for h
in range(209, 0, -21)]) + \
74 """unamed(901 downto 0)
77 signalsall = signalsnk + signalstsf2
81 operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
82 ast.Div: op.truediv, ast.Pow: op.pow, ast.USub: op.neg}
86 return eval_(ast.parse(expr, mode=
'eval').body)
90 if isinstance(node, ast.Num):
92 elif isinstance(node, ast.BinOp):
93 return operators[type(node.op)](eval_(node.left), eval_(node.right))
94 elif isinstance(node, ast.UnaryOp):
95 return operators[type(node.op)](eval_(node.operand))
100 def makeAtlas(signals, evtsize):
102 Make bitmap from VHDL signal assignments.
103 input: string containing b2l signal designations.
104 output: list of lists
105 [ [ name, start, stop, pos, size, module ], ... ]
109 finesses = re.findall(
r'(.+?)<=(.+?);', signals, re.DOTALL)
110 if len(finesses) != sum(1
if width > 0
else 0
for width
in evtsize):
111 raise Exception(
'Number of valid signal assignments does not match HSLB data dimension: ' + str(evtsize))
112 for finesse
in finesses:
113 for item
in re.split(
r'[\s\n]?&[\s\n]*', finesse[1].strip()):
114 item = re.sub(
r'--.+',
'', item)
115 dummy = re.match(
r'"([01]+)"', item)
117 sig = re.match(
r'(.+)\s*\((.+) downto (.+)\)', item.strip())
118 print(
'signal: ' + item.strip())
119 start = eval_expr(sig.group(2))
120 stop = eval_expr(sig.group(3))
121 size = start - stop + 1
123 raise ValueError(
'Vector size cannot be 0 or negative.')
126 size = len(dummy.group(1))
128 start, stop = size - 1, 0
129 atlas.append([name, start, stop, pos, size, finesse[0]])
131 if pos != sum(evtsize):
133 'Size of atlas:{} does not match event size:{}'.format(pos, evtsize))
137 def isUnamed(signal):
138 return signal[0] ==
"unamed"
141 def unpack(triggers, atlas, writer):
143 transform into VCD signals from clock-seperated data and hitmap
145 unpackwith =
', '.join([
'bin:{}'.format(sig[4])
for sig
in atlas])
146 vcdVars = [writer.register_var(
147 sig[5], sig[0] +
'[{}:{}]'.format(sig[1], sig[2]),
'wire', size=sig[4])
if
148 not isUnamed(sig)
else None for sig
in atlas]
149 event = writer.register_var(
'm',
'event',
'event')
150 lastvalues = [
None] * len(atlas)
153 power = period.bit_length() - 1
154 print(
'converting to waveform ...')
156 timestamp = iteration << power
157 writer.change(event, timestamp,
'1')
158 for clock
in trg.cut(sum(evtsize)):
159 if timestamp & 1023 == 0:
160 print(
'\r{} us converted'.format(str(timestamp)[:-3]), end=
"")
162 timestamp = iteration << power
164 values = clock.unpack(unpackwith)
165 for i, sig
in enumerate(atlas):
167 if dummycheck
and '1' in values[i]
and '0' in values[i]:
168 print(
'[Warning] non-uniform dummy value detected at {}ns: {}'.format(
169 timestamp, sig[3] % sum(evtsize)))
172 if values[i] != lastvalues[i]:
173 writer.change(vcdVars[i], timestamp, values[i])
178 def literalVCD(triggers, atlas, writer):
180 This is slower than unpack(). Use that instead.
181 write a VCD file from clock-seperated data and hitmap
183 vcdVars = [writer.register_var(
184 'm', sig[0] +
'[{}:{}]'.format(sig[1], sig[2]),
'wire', size=sig[4])
if
185 sig[0] !=
'unamed' else 0
for sig
in atlas]
186 event = writer.register_var(
'm',
'event',
'event')
190 power = period.bit_length() - 1
192 timestamp = iteration << power
193 writer.change(event, timestamp,
'1')
194 for value
in trg.cut(sum(evtsize)):
195 if timestamp & 1023 == 0:
196 print(
'\r{} us completed'.format(str(timestamp)[:-3]),)
198 timestamp = iteration << power
200 for i, sig
in enumerate(atlas):
201 sigvalue = value[sig[3]:sig[3] + sig[4]]
202 lastsigvalue = lastvalue[sig[3]:sig[3] + sig[4]]
if lastvalue
else None
203 if sig[0] ==
'unamed':
204 if dummycheck
and sigvalue.any(1)
and sigvalue.any(0):
205 with sys.stderr
as fout:
207 '[Warning] non-uniform dummy value detected at {}ns: {}'.format(
208 timestamp, sig[3] % sum(evtsize)))
211 if not lastvalue
or sigvalue != lastsigvalue:
212 writer.change(vcdVars[i], timestamp, sigvalue.bin)
216 def combVCD(clocks, atlas, writer):
221 for i
in range(len(atlas)):
222 if atlas[i][0] ==
'unamed' or atlas[i][0]
in [x[0]
for x
in comAtlas]:
225 for j
in range(i + 1, len(atlas)):
226 if atlas[j][0] == atlas[i][0]:
227 signal.append(atlas[j])
228 signal = sorted(signal, key=itemgetter(1), reverse=
True)
231 comAtlas.append(signal[0])
232 vars = [writer.register_var(
233 'm', sig[0] +
'[{}:{}]'.format(sig[1], sig[-3]),
'wire',
234 size=sum(sig[4::5]))
for sig
in comAtlas]
235 for timestamp, value
in enumerate(clocks):
236 for i, sig
in enumerate(comAtlas):
237 writer.change(vars[i], 32 * timestamp,
238 BitArray([]).join([value[sig[n]:sig[n] + sig[n + 1]]
for n
in range(3, len(sig), 5)]).bin)
241 def writeVCD(data, atlas, fname, size, combine=False):
243 evt: 2D list of HSLB buffers
244 atlas: list of iterates
247 samples = len(list(
filter(
None, data[0][0]))[0]) // list(
filter(
None, evtsize))[0]
248 NullArray = BitArray([])
253 clocks.append(BitArray([]).join(
254 itertools.chain.from_iterable(zip(
255 *[entry[buf].cut(size[buf])
256 if size[buf] > 0
else [NullArray] * samples
257 for buf
in range(4)]))))
258 with open(fname,
'w')
as fout:
259 with VCDWriter(fout, timescale=
'1 ns', date=
'today')
as writer:
262 raise Exception(
'Combine has not been updated. Use literal instead.')
265 unpack(clocks, atlas, writer)
268 if __name__ ==
"__main__":
270 parser = argparse.ArgumentParser()
271 parser.add_argument(
"-i",
"--pickle", help=
"input pickle file")
272 parser.add_argument(
"-s",
"--signal", help=
"input signal file")
273 parser.add_argument(
"-o",
"--output", help=
"output VCD file")
274 parser.add_argument(
"-nc",
"--nocheck", help=
"disable dummy variable check",
276 args = parser.parse_args()
278 with open(args.signal)
as fin:
279 evtsize = [int(width)
for width
in fin.readline().split()]
280 print(
'interpreting B2L data with dimension ' + str(evtsize))
281 atlas = makeAtlas(fin.read(), evtsize)
283 atlas = makeAtlas(signalsall, evtsize)
286 rfp = open(pica,
'rb')
287 data = pickle.load(rfp)
292 fname = args.output
if args.output
else pica[:pica.rfind(
'.')] +
'.vcd'
293 writeVCD(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