From 4a4c3a3be616098a34ae4079b24e501dcfbb7130 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 18 May 2026 08:50:38 +0200 Subject: [PATCH] Make better validation --- tests/memories/generate_mk.py | 48 +------------- tests/memories/validate.py | 116 ++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 47 deletions(-) create mode 100644 tests/memories/validate.py diff --git a/tests/memories/generate_mk.py b/tests/memories/generate_mk.py index cfb29acb9..93a5bec04 100644 --- a/tests/memories/generate_mk.py +++ b/tests/memories/generate_mk.py @@ -8,51 +8,5 @@ import gen_tests_makefile gen_tests_makefile.generate_autotest("*.v", "", """if grep -Eq 'expect-(wr-ports|rd-ports|rd-clk)' $@; then \\ $(YOSYS) -f verilog -qp "proc; opt; memory -nomap; dump -outfile $(@:.v=).dmp t:\\$$mem_v2" $@; \\ - if grep -q expect-wr-ports $@; then \\ - val=$$(gawk '/expect-wr-ports/ { print $$3; }' $@); \\ - grep -Fq "parameter \\\\WR_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of write ports."; exit 1; }; \\ - fi; \\ - if grep -q expect-wr-wide-continuation $@; then \\ - val=$$(gawk '/expect-wr-wide-continuation/ { print $$3; }' $@); \\ - grep -Fq "parameter \\\\WR_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected write wide continuation."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-ports $@; then \\ - val=$$(gawk '/expect-rd-ports/ { print $$3; }' $@); \\ - grep -Fq "parameter \\\\RD_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of read ports."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-clk $@; then \\ - val=$$(gawk '/expect-rd-clk/ { print $$3; }' $@); \\ - grep -Fq "connect \\\\RD_CLK $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read clock."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-en $@; then \\ - val=$$(gawk '/expect-rd-en/ { print $$3; }' $@); \\ - grep -Fq "connect \\\\RD_EN $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read enable."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-srst-sig $@; then \\ - val=$$(gawk '/expect-rd-srst-sig/ { print $$3; }' $@); \\ - grep -Fq "connect \\\\RD_SRST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-srst-val $@; then \\ - val=$$(gawk '/expect-rd-srst-val/ { print $$3; }' $@); \\ - grep -Fq "parameter \\\\RD_SRST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset value."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-arst-sig $@; then \\ - val=$$(gawk '/expect-rd-arst-sig/ { print $$3; }' $@); \\ - grep -Fq "connect \\\\RD_ARST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-arst-val $@; then \\ - val=$$(gawk '/expect-rd-arst-val/ { print $$3; }' $@); \\ - grep -Fq "parameter \\\\RD_ARST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset value."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-init-val $@; then \\ - val=$$(gawk '/expect-rd-init-val/ { print $$3; }' $@); \\ - grep -Fq "parameter \\\\RD_INIT_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read init value."; exit 1; }; \\ - fi; \\ - if grep -q expect-rd-wide-continuation $@; then \\ - val=$$(gawk '/expect-rd-wide-continuation/ { print $$3; }' $@); \\ - grep -Fq "parameter \\\\RD_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read wide continuation."; exit 1; }; \\ - fi; \\ - if grep -q expect-no-rd-clk $@; then \\ - grep -Fq "connect \\\\RD_CLK 1'x" $(@:.v=).dmp || { echo " ERROR: Expected no read clock."; exit 1; }; \\ - fi; \\ + python3 validate.py $@ $(@:.v=).dmp; \\ fi""") diff --git a/tests/memories/validate.py b/tests/memories/validate.py new file mode 100644 index 000000000..88aabdd49 --- /dev/null +++ b/tests/memories/validate.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +import re +import sys +from pathlib import Path + +CHECKS = [ + ( + "expect-wr-ports", + r"parameter \\WR_PORTS {val}$", + "ERROR: Unexpected number of write ports.", + ), + ( + "expect-wr-wide-continuation", + r"parameter \\WR_WIDE_CONTINUATION {val}$", + "ERROR: Unexpected write wide continuation.", + ), + ( + "expect-rd-ports", + r"parameter \\RD_PORTS {val}$", + "ERROR: Unexpected number of read ports.", + ), + ( + "expect-rd-clk", + r"connect \\RD_CLK {val}$", + "ERROR: Unexpected read clock.", + ), + ( + "expect-rd-en", + r"connect \\RD_EN {val}$", + "ERROR: Unexpected read enable.", + ), + ( + "expect-rd-srst-sig", + r"connect \\RD_SRST {val}$", + "ERROR: Unexpected read sync reset.", + ), + ( + "expect-rd-srst-val", + r"parameter \\RD_SRST_VALUE {val}$", + "ERROR: Unexpected read sync reset value.", + ), + ( + "expect-rd-arst-sig", + r"connect \\RD_ARST {val}$", + "ERROR: Unexpected read async reset.", + ), + ( + "expect-rd-arst-val", + r"parameter \\RD_ARST_VALUE {val}$", + "ERROR: Unexpected read async reset value.", + ), + ( + "expect-rd-init-val", + r"parameter \\RD_INIT_VALUE {val}$", + "ERROR: Unexpected read init value.", + ), + ( + "expect-rd-wide-continuation", + r"parameter \\RD_WIDE_CONTINUATION {val}$", + "ERROR: Unexpected read wide continuation.", + ), + ( + "expect-no-rd-clk", + r"connect \\RD_CLK 1'x$", + "ERROR: Expected no read clock.", + ), +] + + +def extract_expect_value(src_text: str, key: str): + pattern = rf"{re.escape(key)}\s+(\S+)" + m = re.search(pattern, src_text) + return m.group(1) if m else None + + +def main(): + if len(sys.argv) != 3: + print(f"Usage: {sys.argv[0]} ", file=sys.stderr) + return 2 + + srcfile = Path(sys.argv[1]) + dmpfile = Path(sys.argv[2]) + + try: + src_text = srcfile.read_text() + except Exception as e: + print(f"ERROR: Failed to read {srcfile}: {e}", file=sys.stderr) + return 2 + + try: + dmp_text = dmpfile.read_text() + except Exception as e: + print(f"ERROR: Failed to read {dmpfile}: {e}", file=sys.stderr) + return 2 + + for key, pattern_template, errmsg in CHECKS: + if "{val}" in pattern_template: + val = extract_expect_value(src_text, key) + if val is None: + continue + pattern = pattern_template.format(val=re.escape(val)) + else: + if key not in src_text: + continue + pattern = pattern_template + + if not re.search(pattern, dmp_text, re.MULTILINE): + print(errmsg, file=sys.stderr) + return 1 + + print("ok.") + return 0 + + +if __name__ == "__main__": + sys.exit(main())