Browse Source

vcd improvements

devel
stefan 5 hours ago
parent
commit
7a9ed1e536
  1. 31
      src/kyupy/vcd.py

31
src/kyupy/vcd.py

@ -6,7 +6,7 @@ All variable values are flattened. Offsets are stored in each variable metadata.
""" """
from collections import namedtuple from collections import namedtuple
from dataclasses import dataclass from dataclasses import dataclass, field
from lark import Lark, Transformer from lark import Lark, Transformer
import numpy as np import numpy as np
@ -21,7 +21,7 @@ class Var:
idcode: str idcode: str
reference: str reference: str
scope: 'Scope' scope: 'Scope'
offset: int = 0 locs: list[int] = field(default_factory=list)
class Scope: class Scope:
@ -83,18 +83,18 @@ class VcdHeader:
class VcdVarMap: class VcdVarMap:
def __init__(self, header: VcdHeader, filter = lambda var: True) -> None: def __init__(self, header: VcdHeader, var_locs = lambda _: []) -> None:
self.var_list: list[Var] = [] self.var_list: list[Var] = []
def collect(scope): def collect(scope):
self.var_list.extend(v for v in scope.vars if filter(v)) for v in scope.vars:
v.locs = var_locs(v)
if v.locs is not None and len(v.locs) > 0:
assert len(v.locs) == v.width, f'{v.reference}: len(locs)={len(v.locs)} != width={v.width}'
self.var_list.append(v)
for sub in scope.sub_scopes: for sub in scope.sub_scopes:
collect(sub) collect(sub)
collect(header.root_scope) collect(header.root_scope)
offset = 0 self.total_width = max((max(v.locs) for v in self.var_list), default=-1) + 1
for var in self.var_list:
var.offset = offset
offset += var.width
self.total_width = offset
self.idcode2var = {var.idcode: var for var in self.var_list} self.idcode2var = {var.idcode: var for var in self.var_list}
@ -149,12 +149,12 @@ GRAMMAR = r"""
""" """
def load(file, var_filter = lambda var: True, step_filter = lambda time, values, var_map: True): def load(file, var_locs = lambda _: [], step_filter = lambda *_: True):
"""Parses the contents of ``file`` as Verilog Change Dump (VCD). """Parses the contents of ``file`` as Verilog Change Dump (VCD).
:param file: A file name or a file handle. Files with `.gz`-suffix are decompressed on-the-fly. :param file: A file name or a file handle. Files with `.gz`-suffix are decompressed on-the-fly.
:param var_filter: A callback function to include only certain variables in the output. :param var_locs: A callback ``(var) -> list[int]`` mapping each variable to ndarray column indices. Empty list drops the variable.
:param step_filter: A callback function to include only certain steps in the output. :param step_filter: A callback ``(time, values, var_map) -> bool`` to select which timesteps to include.
:return: A VcdData object with metadata and an ndarray with all values. :return: A VcdData object with metadata and an ndarray with all values.
""" """
vcd = readtext(file) vcd = readtext(file)
@ -163,7 +163,7 @@ def load(file, var_filter = lambda var: True, step_filter = lambda time, values,
vcd_header_str = vcd[:header_size] vcd_header_str = vcd[:header_size]
vcd_header : VcdHeader = Lark(GRAMMAR, parser="lalr", lexer='contextual', transformer=VcdHeaderTransformer()).parse(vcd_header_str) # type: ignore vcd_header : VcdHeader = Lark(GRAMMAR, parser="lalr", lexer='contextual', transformer=VcdHeaderTransformer()).parse(vcd_header_str) # type: ignore
vcd_data = vcd[header_size:].splitlines() vcd_data = vcd[header_size:].splitlines()
var_map = VcdVarMap(vcd_header, var_filter) var_map = VcdVarMap(vcd_header, var_locs)
chunk_size = 10240 chunk_size = 10240
chunks = [] chunks = []
@ -203,8 +203,9 @@ def load(file, var_filter = lambda var: True, step_filter = lambda time, values,
if len(value_str) < var.width: if len(value_str) < var.width:
value_str = _pad_char.get(value_str[0], '0') * (var.width - len(value_str)) + value_str value_str = _pad_char.get(value_str[0], '0') * (var.width - len(value_str)) + value_str
for i, c in enumerate(value_str): for i, c in enumerate(value_str):
chunk[step_idx, var.offset + var.width - 1 - i] = _val_map.get(c, logic.UNKNOWN) if var.locs[i] >= 0:
chunk[step_idx, var.locs[i]] = _val_map.get(c, logic.UNKNOWN)
chunks.append(chunk[:step_idx]) chunks.append(chunk[:step_idx])
data = np.concatenate(chunks, axis=0) data = np.concatenate(chunks, axis=0).T
return VcdData(var_map, steps, data) return VcdData(var_map, steps, data)
Loading…
Cancel
Save