diff --git a/test_regress/driver.py b/test_regress/driver.py index d26d3fd6c..566a0db3e 100755 --- a/test_regress/driver.py +++ b/test_regress/driver.py @@ -2548,85 +2548,6 @@ class VlTest: case _: self.error("Unknown trace file format " + traceFn) - @staticmethod - def _vcd_parse_header(filename: str, root_scope: 'str | None' = None) -> 'tuple[dict, dict]': - """Parse VCD header into hierarchy data and signal-code mapping. - - Returns (hier_data, var_codes) where: - hier_data: dict used by _vcd_read for hierarchy comparison - (scope paths -> scope description, var paths -> $var prefix, - attr paths -> $attrbegin text) - var_codes: dict mapping 'scope.signal' -> VCD code identifier - """ - hier_data: dict = {} - var_codes: dict = {} - hier_stack = [root_scope] if root_scope else [] - attr: list = [] - with open(filename, 'r', encoding='latin-1') as fh: - for line in fh: - m_scope = re.search(r'\$scope\s+(\S*)\s+(\S+)', line) - m_var = re.search(r'(\$var\s+\S+\s+\d+\s+)(\S+)\s+(.+)\s+\$end', line) - m_attr = re.search(r'(\$attrbegin .* \$end)', line) - if m_scope: - scope_type = m_scope.group(1) - name = m_scope.group(2) - hier_stack.append(name) - scope = '.'.join(hier_stack) - hier_data[scope] = scope_type + " " + name - if attr: - hier_data[scope + "#"] = " ".join(attr) - attr = [] - elif m_var: - scope = '.'.join(hier_stack) - decl_prefix = m_var.group(1) - code = m_var.group(2) - var_name = m_var.group(3) - hier_data[scope + "." + var_name] = decl_prefix - if attr: - hier_data[scope + "." + var_name + "#"] = " ".join(attr) - attr = [] - bare_name = var_name.split()[0] - var_codes[scope + "." + bare_name] = code - elif m_attr: - attr.append(m_attr.group(1)) - elif re.search(r'\$enddefinitions', line): - break - n = len(re.findall(r'\$upscope', line)) - if n: - for _i in range(0, n): - hier_stack.pop() - return hier_data, var_codes - - def _vcd_read(self, filename: str) -> dict: - data, _ = self._vcd_parse_header(filename, root_scope="TOP") - return data - - def vcd_extract_codes(self, filename: str) -> dict: - _, codes = self._vcd_parse_header(filename) - return codes - - def vcd_check_aliased(self, codes: dict, sig_a: str, sig_b: str) -> None: - code_a = codes.get(sig_a) - code_b = codes.get(sig_b) - if code_a is None: - self.error(f"Signal '{sig_a}' not found in VCD") - if code_b is None: - self.error(f"Signal '{sig_b}' not found in VCD") - if code_a != code_b: - self.error(f"Expected '{sig_a}' (code {code_a}) to alias " - f"'{sig_b}' (code {code_b})") - - def vcd_check_not_aliased(self, codes: dict, sig_a: str, sig_b: str) -> None: - code_a = codes.get(sig_a) - code_b = codes.get(sig_b) - if code_a is None: - self.error(f"Signal '{sig_a}' not found in VCD") - if code_b is None: - self.error(f"Signal '{sig_b}' not found in VCD") - if code_a == code_b: - self.error(f"Expected '{sig_a}' and '{sig_b}' to have different codes, " - f"both have code {code_a}") - def inline_checks(self) -> None: covfn = self.coverage_filename contents = self.file_contents(covfn) diff --git a/test_regress/t/trace_struct_alias_common.py b/test_regress/t/trace_struct_alias_common.py index e5e418f68..df38a1266 100644 --- a/test_regress/t/trace_struct_alias_common.py +++ b/test_regress/t/trace_struct_alias_common.py @@ -7,6 +7,55 @@ # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +def _vcd_extract_codes(filename): + """Parse VCD header and return dict mapping 'scope.signal' -> code.""" + codes = {} + scope_stack = [] + with open(filename, 'r', encoding='latin-1') as fh: + for line in fh: + line = line.strip() + if line.startswith("$scope"): + parts = line.split() + # $scope $end + scope_stack.append(parts[2]) + elif line.startswith("$var"): + parts = line.split() + # $var ... $end + code = parts[3] + name = parts[4] + full = '.'.join(scope_stack) + '.' + name + codes[full] = code + elif line.startswith("$upscope"): + scope_stack.pop() + elif line.startswith("$enddefinitions"): + break + return codes + + +def _check_aliased(test, codes, sig_a, sig_b): + code_a = codes.get(sig_a) + code_b = codes.get(sig_b) + if code_a is None: + test.error(f"Signal '{sig_a}' not found in VCD") + if code_b is None: + test.error(f"Signal '{sig_b}' not found in VCD") + if code_a != code_b: + test.error(f"Expected '{sig_a}' (code {code_a}) to alias " + f"'{sig_b}' (code {code_b})") + + +def _check_not_aliased(test, codes, sig_a, sig_b): + code_a = codes.get(sig_a) + code_b = codes.get(sig_b) + if code_a is None: + test.error(f"Signal '{sig_a}' not found in VCD") + if code_b is None: + test.error(f"Signal '{sig_b}' not found in VCD") + if code_a == code_b: + test.error(f"Expected '{sig_a}' and '{sig_b}' to have different codes, " + f"both have code {code_a}") + + def run(test): (fmt, ) = test.parse_name(r"t_trace_struct_alias_([a-z]+)") @@ -20,16 +69,16 @@ def run(test): test.execute() if fmt == "vcd": - codes = test.vcd_extract_codes(test.trace_filename) + codes = _vcd_extract_codes(test.trace_filename) - test.vcd_check_not_aliased(codes, "top.t.s1.a", "top.t.s2.a") + _check_not_aliased(test, codes, "top.t.s1.a", "top.t.s2.a") - test.vcd_check_aliased(codes, "top.t.s3.a", "top.t.alias_of_s3a") + _check_aliased(test, codes, "top.t.s3.a", "top.t.alias_of_s3a") - test.vcd_check_aliased(codes, "top.t.s4.a", "top.t.s5.a") - test.vcd_check_aliased(codes, "top.t.s4.b", "top.t.s5.b") + _check_aliased(test, codes, "top.t.s4.a", "top.t.s5.a") + _check_aliased(test, codes, "top.t.s4.b", "top.t.s5.b") - test.vcd_check_aliased(codes, "top.t.s6.a", "top.t.source_val") + _check_aliased(test, codes, "top.t.s6.a", "top.t.source_val") test.trace_identical(test.trace_filename, test.golden_filename) diff --git a/test_regress/t/trace_struct_array_multi_inst_common.py b/test_regress/t/trace_struct_array_multi_inst_common.py index e22d1f83c..937d399ff 100644 --- a/test_regress/t/trace_struct_array_multi_inst_common.py +++ b/test_regress/t/trace_struct_array_multi_inst_common.py @@ -74,10 +74,8 @@ def run(test): test.trace_identical(test.trace_filename, test.golden_filename) - if fmt == "fst": - _check_empty_scopes_vcd(test, test.trace_filename + ".vcd") - elif fmt == "vcd": - _check_empty_scopes_vcd(test, test.trace_filename) + if fmt in ("fst", "vcd"): + _check_empty_scopes_vcd(test, test.golden_filename) elif fmt == "saif": _check_empty_scopes_saif(test, test.trace_filename)