Son aktivite 1 month ago

Very bad converter from ValueChangeDump (VCD) to Tikz Timing on Latex.

vcd2latex.py Ham
1#!/usr/bin/env python3
2
3import vcdvcd, math
4from vcdvcd import VCDVCD
5
6vcdfile = "digital_port_tb.vcd"
7
8vcd = VCDVCD(vcdfile, only_sigs=True)
9
10all_signals = vcd.signals
11# print(all_signals)
12dataW = [0 for i in range(len(all_signals))]
13data = [[] for i in range(len(all_signals))]
14
15###########
16
17def nibble_to_hex(s):
18 for c in s:
19 if not c in '01':
20 return c
21 return hex(int(s, 2))[2:].upper()
22
23def binary_string_to_hex(s, w):
24 if len(s) == 1:
25 if s != '0' and s != '1':
26 return s
27
28 s = s.zfill(w)
29 n = 4
30 groups = [s[i:i+n] for i in range(0, len(s), n)]
31 hexgroups = [nibble_to_hex(x) for x in groups]
32 return "".join(hexgroups)
33
34
35class ParserCallbacks(vcdvcd.StreamParserCallbacks):
36 def __init__(self, deltas=True):
37 self._deltas = deltas
38 self._references_to_widths = {}
39
40 def enddefinitions(
41 self,
42 vcd,
43 signals,
44 cur_sig_vals
45 ):
46 if signals:
47 self._print_dumps_refs = signals
48 else:
49 self._print_dumps_refs = sorted(vcd.data[i].references[0] for i in cur_sig_vals.keys())
50 for i, ref in enumerate(self._print_dumps_refs, 1):
51 if i == 0:
52 i = 1
53 identifier_code = vcd.references_to_ids[ref]
54 size = int(vcd.data[identifier_code].size)
55 width = max(((size // 4)), int(math.floor(math.log10(i))) + 1)
56 self._references_to_widths[ref] = width
57 dataW[i-1] = size
58
59 def time(
60 self,
61 vcd,
62 time,
63 cur_sig_vals
64 ):
65 if (not self._deltas or vcd.signal_changed):
66 ss = []
67 ss.append('{}'.format(time))
68 for i, ref in enumerate(self._print_dumps_refs):
69 identifier_code = vcd.references_to_ids[ref]
70 value = cur_sig_vals[identifier_code]
71 data[i].append(binary_string_to_hex(value, dataW[i]))
72
73
74###########
75
76
77callbacks = ParserCallbacks()
78VCDVCD(
79 vcdfile,
80 signals=all_signals,
81 store_tvs=False,
82 callbacks=callbacks,
83)
84
85ltx = '''
86\\documentclass{standalone}
87\\usepackage{tikz-timing}
88
89\\begin{document}
90\\begin{tikztimingtable}[timing/xunit=35,timing/yunit=10]
91'''
92
93def latexEscape(val):
94 return val.\
95 replace("_", "\\_").\
96 replace("{", "\\{").\
97 replace("}", "\\}").\
98 replace("&", "\\&").\
99 replace("%", "\\%").\
100 replace("$", "\\$").\
101 replace("#", "\\#").\
102 replace("$", "\\$")
103
104
105for sig in range(len(data)):
106 sigName = latexEscape(all_signals[sig])
107 sigSeries = data[sig]
108 sigWidth = dataW[sig]
109 # print(f"SigName: {sigName} - SigWidth: {sigWidth}")
110 ltx += format(f" {sigName} &")
111 for value in sigSeries:
112 prefix = ""
113 token = format(f" D{{{value}}} ")
114 if value == "x":
115 token = "X"
116 elif value == "z":
117 token = "Z"
118 elif sigWidth == 1:
119 token = "H" if value == "1" else "L"
120 if "x" in token:
121 prefix = " [red] "
122 elif "z" in token:
123 prefix = " [blue] "
124
125 ltx += format(f" {prefix}{token} ;")
126 ltx += " \\\\\n"
127
128# ltx += "\\vertlines[help lines,opacity=0.3]{}\n"
129ltx += '''\\extracode
130\\vertlines[help lines,opacity=0.3]{}
131\\end{tikztimingtable}
132\\end{document}
133
134'''
135
136# print(ltx)
137with open("tmp.tex", "w") as f:
138 f.write(ltx)
139
140
141'''
142\\begin{tikztimingtable}[timing/wscale=0.8]
143 M-cycle & X 8D{M1} 8D{M2/M1} X \\\\
144 Instruction & ; [opacity=0.4] 9D{Previous} ; [opacity=1.0] 8D{LD r, r'} ; [opacity=0.4] X \\\\
145 Mem R/W & X 8D{R: opcode}; [opacity=0.4] 8D{R: next op} X \\\\
146 Mem addr & X 8D{PC} ; [opacity=0.4] 8D{PC+1} X \\\\
147\\end{tikztimingtable}
148'''
149