def get_fifo_count_max(vcd_file, fifo_count_signal): "Return the maximum value of the given FIFO count signal in vcd trace." d = VCDVCD(vcd_file, signals=[fifo_count_signal], store_tvs=True).get_data() assert len(d) != 0, "FIFO count signal not found" events = list(d.values())[0]["tv"] max = 0 for (time, val) in events: current = int(val, base=2) if current > max: max = current return max
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