#!/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} '''