dest="time", default=0, type=int, metavar='<max-time>', help="Define a time at which to stop converting") args = ap.parse_args() # Get output stream out = sys.stdout if args.output != '-': out = open(args.output, "w") # Construct VCD parser print('Parsing input vcd.', file=sys.stderr) vcd = VCDVCD(args.input) data = vcd.get_data() print('Done.', file=sys.stderr) def format_value_dump(val, size, n_elems): """ Formats the value string to a hexadecimal representation, 0-padded to the next byte. Args: val (str): the string representing the value to format size (int): the bitwidth of val n_elems (int): the number of elements, required to pretty_print arrays. An array has the number of n_elems < size Returns: The formatted value. If the value is not numeric (e.g. an 'x'), val is returned as is. """ digit = val.isdigit() words = int(math.ceil(size / 8) * 2)
def get_stream_if_stats(vcd_file, if_base_name): """Return statistics for given streaming interface in vcd trace in the following dict format: <stream_state>: (<num_samples>, <fraction_of_time>), where <stream_state> is the combination of (V)alid/(R)eady values, <num_samples> is the approximate number of rising clock edges spent in <state> , and <fraction_of_time> is the fraction of <num_samples> to total amount of time recorded by the trace. Example: {"{'V': 0, 'R': 0}": (5, 0.0006060606060606061), "{'V': 1, 'R': 0}": (0, 0.0), "{'V': 0, 'R': 1}": (7605, 0.9218181818181819), "{'V': 1, 'R': 1}": (640, 0.07757575757575758)} Here we can see the stream was transmitting values 7.7% of the time, and 9.2% of the time there was no incoming data (valid 0, ready 1) """ if_valid = if_base_name + vname if_ready = if_base_name + rname v = VCDVCD(vcd_file, signals=[if_valid], store_tvs=True) endtime = v.get_endtime() v = v.get_data() assert len(v) != 0, "Streaming interface not found" v = list(v.values())[0]["tv"] v = list(map(lambda x: ("V", x[0], x[1]), v)) v.append(("V", endtime, "0")) r = VCDVCD(vcd_file, signals=[if_ready], store_tvs=True).get_data() assert len(r) != 0, "Streaming interface not found" r = list(r.values())[0]["tv"] r = list(map(lambda x: ("R", x[0], x[1]), r)) r.append(("R", endtime, "0")) events = sorted(v + r, key=lambda x: x[1]) ret = { "{'V': 0, 'R': 0}": 0, "{'V': 1, 'R': 0}": 0, "{'V': 0, 'R': 1}": 0, "{'V': 1, 'R': 1}": 0, } status = {"V": 0, "R": 0} last_time = 0 total_rising_clock_edges = 0 for (sig, time, val) in events: # pyverilator generates 5 time units per sample time = time / 5 # pyverilator generates 4 samples per clock period n_rising_clock_edges = int((time - last_time) / 4) # note that the calculation of n_rising_clock_edges is approximate # doing this exactly would require a cycle-by-cycle walkthrough of the # trace, which can take very long ret[str(status)] += n_rising_clock_edges total_rising_clock_edges += n_rising_clock_edges status[sig] = int(val) last_time = time for state in ret: v = ret[state] ret[state] = (v, v / total_rising_clock_edges) return ret
def get_data(vcd_path): """Load a vcd file and return the list of signal names including path """ vcd = VCDVCD(vcd_path) return vcd.get_data()
def vcd_to_signals(vcd_path, signals='', module_path=''): """Load a vcd file times and values into Signals Args: vcd_path: Path to the .vcd file. signals: Name(s) of the signals to load. None or [] loads them all. module_path: Path of the signal(s) in the RTL hierarchy. A string to apply to all the signals, or a dictionary {name: path,} if a list of signals is provided. In order to select signals by module (and differentiate signals with equal names located in different modules), provide the path to the signals that you want to extract. Example: Signals in the vcd file: 'dut.Top/uAdder/data[15:0]', 'dut.Top/uAdder/en', 'dut.Top/uAdder/dv', 'dut.Top/uMux/data[31:0]', 'dut.Top/uMux/en', 'dut.Top/uMux/dv', Setting signals_base_path='uMux/' will return: {'data': Signal(this will be 'dut.Top/uMux/data[31:0]'), 'en': Signal(this will be 'dut.Top/uMux/en'), 'dv': Signal(this will be 'dut.Top/uMux/dv')} """ from hdlcomposer.signals import Signal vcd = VCDVCD(vcd_path) signals_in_vcd = vcd.get_signals() data = vcd.get_data() result_signals = {} if not signals: signals = signals_in_vcd elif not isinstance(signals, list): signals = [signals] if not isinstance(module_path, dict): module_path = {name: module_path for name in signals} for identifier in data: signal_names_in_id = data[identifier]['references'] for vcd_signal_name in signal_names_in_id: for signal_name in module_path: size = int(data[identifier]['size']) matches, found_signal_name = find_signal_name( vcd_signal_name, signal_name, module_path[signal_name], (size > 1)) if matches: module_path.pop(signal_name) result_signals[found_signal_name] = Signal( signal_type=data[identifier]['var_type'], signal_width=int(data[identifier]['size']), signal_path=vcd_signal_name) result_signals[found_signal_name].waveform = [ list(tv) for tv in data[identifier]['tv'] ] break return result_signals
from __future__ import print_function import sys from pprint import PrettyPrinter from vcdvcd import VCDVCD if (len(sys.argv) > 1): vcd_path = sys.argv[1] else: vcd_path = 'counter_tb.vcd' pp = PrettyPrinter() print('# get_data()') vcd = VCDVCD(vcd_path) pp.pprint(vcd.get_data()) print() print('# get_data(only_sigs=True)') vcd = VCDVCD(vcd_path, only_sigs=True) PrettyPrinter().pprint(vcd.get_data()) print() print('# get_signals()') vcd = VCDVCD(vcd_path, only_sigs=True) pp.pprint(vcd.get_signals()) print() print('# __init__(signals=)') vcd_only_sigs = VCDVCD(vcd_path, only_sigs=True) signals = vcd_only_sigs.get_signals()