Последняя активность 1 month ago

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

Версия 121f6ca8ae2c24015655e09fd47ae7e5db8d7a15

vcd2latex.py Исходник
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 """
25 Convert a binary string to hexadecimal.
26 If any non 0/1 values are present such as 'x', return that single character
27 as a representation.
28 :param s: the string to be converted
29 :type s: str
30 """
31 if len(s) == 1:
32 if s != '0' and s != '1':
33 return s
34
35 s = s.zfill(w)
36 n = 4
37 groups = [s[i:i+n] for i in range(0, len(s), n)]
38 hexgroups = [nibble_to_hex(x) for x in groups]
39 return "".join(hexgroups)
40 return s
41 # for c in s:
42 # if not c in '01':
43 # return c
44 # return hex(int(s, 2))[2:]
45
46
47class ParserCallbacks(vcdvcd.StreamParserCallbacks):
48 def __init__(self, deltas=True):
49 self._deltas = deltas
50 self._references_to_widths = {}
51
52 def enddefinitions(
53 self,
54 vcd,
55 signals,
56 cur_sig_vals
57 ):
58 if signals:
59 self._print_dumps_refs = signals
60 else:
61 self._print_dumps_refs = sorted(vcd.data[i].references[0] for i in cur_sig_vals.keys())
62 for i, ref in enumerate(self._print_dumps_refs, 1):
63 if i == 0:
64 i = 1
65 identifier_code = vcd.references_to_ids[ref]
66 size = int(vcd.data[identifier_code].size)
67 width = max(((size // 4)), int(math.floor(math.log10(i))) + 1)
68 self._references_to_widths[ref] = width
69 # print(ref, i, size)
70 dataW[i-1] = size
71
72 def time(
73 self,
74 vcd,
75 time,
76 cur_sig_vals
77 ):
78 if (not self._deltas or vcd.signal_changed):
79 ss = []
80 ss.append('{}'.format(time))
81 for i, ref in enumerate(self._print_dumps_refs):
82 identifier_code = vcd.references_to_ids[ref]
83 value = cur_sig_vals[identifier_code]
84 data[i].append(binary_string_to_hex(value, dataW[i]))
85
86
87###########
88
89
90callbacks = ParserCallbacks()
91VCDVCD(
92 vcdfile,
93 signals=all_signals,
94 store_tvs=False,
95 callbacks=callbacks,
96)
97
98ltx = '''
99\\documentclass{standalone}
100\\usepackage{tikz-timing}
101
102\\begin{document}
103\\begin{tikztimingtable}[timing/xunit=35,timing/yunit=10]
104'''
105
106def latexEscape(val):
107 return val.\
108 replace("_", "\\_").\
109 replace("{", "\\{").\
110 replace("}", "\\}").\
111 replace("&", "\\&").\
112 replace("%", "\\%").\
113 replace("$", "\\$").\
114 replace("#", "\\#").\
115 replace("$", "\\$")
116
117
118for sig in range(len(data)):
119 sigName = latexEscape(all_signals[sig])
120 sigSeries = data[sig]
121 sigWidth = dataW[sig]
122 # print(f"SigName: {sigName} - SigWidth: {sigWidth}")
123 ltx += format(f" {sigName} &")
124 for value in sigSeries:
125 prefix = ""
126 token = format(f" D{{{value}}} ")
127 if value == "x":
128 token = "X"
129 elif value == "z":
130 token = "Z"
131 elif sigWidth == 1:
132 token = "H" if value == "1" else "L"
133 if "x" in token:
134 prefix = " [red] "
135 elif "z" in token:
136 prefix = " [blue] "
137
138 ltx += format(f" {prefix}{token} ;")
139 ltx += " \\\\\n"
140
141# ltx += "\\vertlines[help lines,opacity=0.3]{}\n"
142ltx += '''\\extracode
143\\vertlines[help lines,opacity=0.3]{}
144\\end{tikztimingtable}
145\\end{document}
146
147'''
148
149# print(ltx)
150with open("tmp.tex", "w") as f:
151 f.write(ltx)
152
153
154'''
155\\begin{tikztimingtable}[timing/wscale=0.8]
156 M-cycle & X 8D{M1} 8D{M2/M1} X \\\\
157 Instruction & ; [opacity=0.4] 9D{Previous} ; [opacity=1.0] 8D{LD r, r'} ; [opacity=0.4] X \\\\
158 Mem R/W & X 8D{R: opcode}; [opacity=0.4] 8D{R: next op} X \\\\
159 Mem addr & X 8D{PC} ; [opacity=0.4] 8D{PC+1} X \\\\
160\\end{tikztimingtable}
161'''
162