Last active
March 4, 2024 20:59
-
-
Save racerxdl/0aeeb5430f999abace58a135a5039827 to your computer and use it in GitHub Desktop.
Very bad converter from ValueChangeDump (VCD) to Tikz Timing on Latex.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import vcdvcd, math | |
from vcdvcd import VCDVCD | |
vcdfile = "digital_port_tb.vcd" | |
vcd = VCDVCD(vcdfile, only_sigs=True) | |
all_signals = vcd.signals | |
# print(all_signals) | |
dataW = [0 for i in range(len(all_signals))] | |
data = [[] for i in range(len(all_signals))] | |
########### | |
def nibble_to_hex(s): | |
for c in s: | |
if not c in '01': | |
return c | |
return hex(int(s, 2))[2:].upper() | |
def binary_string_to_hex(s, w): | |
if len(s) == 1: | |
if s != '0' and s != '1': | |
return s | |
s = s.zfill(w) | |
n = 4 | |
groups = [s[i:i+n] for i in range(0, len(s), n)] | |
hexgroups = [nibble_to_hex(x) for x in groups] | |
return "".join(hexgroups) | |
class ParserCallbacks(vcdvcd.StreamParserCallbacks): | |
def __init__(self, deltas=True): | |
self._deltas = deltas | |
self._references_to_widths = {} | |
def enddefinitions( | |
self, | |
vcd, | |
signals, | |
cur_sig_vals | |
): | |
if signals: | |
self._print_dumps_refs = signals | |
else: | |
self._print_dumps_refs = sorted(vcd.data[i].references[0] for i in cur_sig_vals.keys()) | |
for i, ref in enumerate(self._print_dumps_refs, 1): | |
if i == 0: | |
i = 1 | |
identifier_code = vcd.references_to_ids[ref] | |
size = int(vcd.data[identifier_code].size) | |
width = max(((size // 4)), int(math.floor(math.log10(i))) + 1) | |
self._references_to_widths[ref] = width | |
dataW[i-1] = size | |
def time( | |
self, | |
vcd, | |
time, | |
cur_sig_vals | |
): | |
if (not self._deltas or vcd.signal_changed): | |
ss = [] | |
ss.append('{}'.format(time)) | |
for i, ref in enumerate(self._print_dumps_refs): | |
identifier_code = vcd.references_to_ids[ref] | |
value = cur_sig_vals[identifier_code] | |
data[i].append(binary_string_to_hex(value, dataW[i])) | |
########### | |
callbacks = ParserCallbacks() | |
VCDVCD( | |
vcdfile, | |
signals=all_signals, | |
store_tvs=False, | |
callbacks=callbacks, | |
) | |
ltx = ''' | |
\\documentclass{standalone} | |
\\usepackage{tikz-timing} | |
\\begin{document} | |
\\begin{tikztimingtable}[timing/xunit=35,timing/yunit=10] | |
''' | |
def latexEscape(val): | |
return val.\ | |
replace("_", "\\_").\ | |
replace("{", "\\{").\ | |
replace("}", "\\}").\ | |
replace("&", "\\&").\ | |
replace("%", "\\%").\ | |
replace("$", "\\$").\ | |
replace("#", "\\#").\ | |
replace("$", "\\$") | |
for sig in range(len(data)): | |
sigName = latexEscape(all_signals[sig]) | |
sigSeries = data[sig] | |
sigWidth = dataW[sig] | |
# print(f"SigName: {sigName} - SigWidth: {sigWidth}") | |
ltx += format(f" {sigName} &") | |
for value in sigSeries: | |
prefix = "" | |
token = format(f" D{{{value}}} ") | |
if value == "x": | |
token = "X" | |
elif value == "z": | |
token = "Z" | |
elif sigWidth == 1: | |
token = "H" if value == "1" else "L" | |
if "x" in token: | |
prefix = " [red] " | |
elif "z" in token: | |
prefix = " [blue] " | |
ltx += format(f" {prefix}{token} ;") | |
ltx += " \\\\\n" | |
# ltx += "\\vertlines[help lines,opacity=0.3]{}\n" | |
ltx += '''\\extracode | |
\\vertlines[help lines,opacity=0.3]{} | |
\\end{tikztimingtable} | |
\\end{document} | |
''' | |
# print(ltx) | |
with open("tmp.tex", "w") as f: | |
f.write(ltx) | |
''' | |
\\begin{tikztimingtable}[timing/wscale=0.8] | |
M-cycle & X 8D{M1} 8D{M2/M1} X \\\\ | |
Instruction & ; [opacity=0.4] 9D{Previous} ; [opacity=1.0] 8D{LD r, r'} ; [opacity=0.4] X \\\\ | |
Mem R/W & X 8D{R: opcode}; [opacity=0.4] 8D{R: next op} X \\\\ | |
Mem addr & X 8D{PC} ; [opacity=0.4] 8D{PC+1} X \\\\ | |
\\end{tikztimingtable} | |
''' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment