From 799c07a1262d50ae65bdb5a000aa92539ee75181 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 12:47:15 +0100 Subject: [PATCH] Did share, opt_share and fsm --- tests/Makefile | 6 +- tests/fsm/.gitignore | 2 +- tests/fsm/{generate.py => generate_mk.py} | 36 ++++++----- tests/fsm/run-test.sh | 45 ------------- tests/gen_tests_makefile.py | 63 +++++++++---------- tests/opt_share/.gitignore | 2 +- .../opt_share/{generate.py => generate_mk.py} | 62 +++++++++--------- tests/opt_share/run-test.sh | 51 --------------- tests/rpc/generate_mk.py | 8 +++ tests/share/.gitignore | 2 +- tests/share/{generate.py => generate_mk.py} | 47 +++++++------- tests/share/run-test.sh | 40 ------------ tests/xprop/generate_mk.py | 11 ++-- 13 files changed, 122 insertions(+), 253 deletions(-) rename tests/fsm/{generate.py => generate_mk.py} (89%) delete mode 100755 tests/fsm/run-test.sh rename tests/opt_share/{generate.py => generate_mk.py} (61%) delete mode 100755 tests/opt_share/run-test.sh create mode 100644 tests/rpc/generate_mk.py rename tests/share/{generate.py => generate_mk.py} (80%) delete mode 100755 tests/share/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index f5642c940..aa82ccc61 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -57,9 +57,9 @@ MK_TEST_DIRS += ./simple_abc9 MK_TEST_DIRS += ./hana MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./realmath -#SH_TEST_DIRS += ./share -#SH_TEST_DIRS += ./opt_share -#SH_TEST_DIRS += ./fsm +MK_TEST_DIRS += ./share +MK_TEST_DIRS += ./opt_share +MK_TEST_DIRS += ./fsm #SH_TEST_DIRS += ./memlib #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces diff --git a/tests/fsm/.gitignore b/tests/fsm/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/fsm/.gitignore +++ b/tests/fsm/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/fsm/generate.py b/tests/fsm/generate_mk.py similarity index 89% rename from tests/fsm/generate.py rename to tests/fsm/generate_mk.py index 784e5a054..dc3518009 100644 --- a/tests/fsm/generate.py +++ b/tests/fsm/generate_mk.py @@ -1,21 +1,18 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager +from pathlib import Path # set to 'True' to compare verific with yosys test_verific = False -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target - def random_expr(variables): c = random.choice(['bin', 'uni', 'var', 'const']) if c == 'bin': @@ -39,12 +36,16 @@ args = parser.parse_args() seed = args.seed if seed is None: seed = random.randrange(sys.maxsize) -print("PRNG seed: %d" % seed) +print("fsm PRNG seed: %d" % seed) random.seed(seed) +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() + for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): rst2 = random.choice([False, True]) if rst2: print('module uut_%05d(clk, rst1, rst2, rst, a, b, c, x, y, z);' % (idx)) @@ -99,16 +100,16 @@ for idx in range(args.count): print(' end') print(' end') print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): if test_verific: - print('read_verilog temp/uut_%05d.v' % idx) + print('read_verilog uut_%05d.v' % idx) print('proc;; rename uut_%05d gold' % idx) - print('verific -vlog2k temp/uut_%05d.v' % idx) + print('verific -vlog2k uut_%05d.v' % idx) print('verific -import uut_%05d' % idx) print('rename uut_%05d gate' % idx) else: - print('read_verilog temp/uut_%05d.v' % idx) + print('read_verilog uut_%05d.v' % idx) print('proc;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) @@ -118,3 +119,4 @@ for idx in range(args.count): print('miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter') print('sat -verify-no-timeout -timeout 20 -seq 5 -set-at 1 %s_rst 1 -prove trigger 0 -prove-skip 1 -show-inputs -show-outputs miter' % ('gold' if rst2 else 'in')) +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/fsm/run-test.sh b/tests/fsm/run-test.sh deleted file mode 100755 index 304242126..000000000 --- a/tests/fsm/run-test.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=50 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -{ - all_targets="all_targets:" - echo "all: all_targets" - echo " @echo" - for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - idx=$( printf "%05d" $i ) - echo "temp/uut_${idx}.log: temp/uut_${idx}.ys temp/uut_${idx}.v" - echo " @echo -n '[$i]'" - echo " @../../yosys -ql temp/uut_${idx}.out temp/uut_${idx}.ys >/dev/null 2>&1" - echo " @mv temp/uut_${idx}.out temp/uut_${idx}.log" - echo " @grep -q 'SAT proof finished' temp/uut_${idx}.log && echo -n K || echo -n T" - all_targets="$all_targets temp/uut_${idx}.log" - done - echo "$all_targets" -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile - -exit 0 diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 2f842f570..969a0f41a 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -4,6 +4,7 @@ import glob import os import sys import argparse +from contextlib import contextmanager yosys_basedir = os.path.relpath(os.path.join(os.path.dirname(__file__), "..")) common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk")) @@ -11,17 +12,17 @@ common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk") def _cwd_base(): return os.path.basename(os.getcwd()) -def generate_target(name, command, out=sys.stdout): +def generate_target(name, command): #target = f"{_cwd_base()}-{name}" target = f"{name}" - print(f"all: {target}", file=out) - print(f".PHONY: {target}", file=out) - print(f"{target}:", file=out) + print(f"all: {target}") + print(f".PHONY: {target}") + print(f"{target}:") if command: - print(f"\t@$(call run_test,{target}, \\", file=out) - print(f"\t{command})", file=out) + print(f"\t@$(call run_test,{target}, \\") + print(f"\t{command})") else: - print(f"\t@$(call run_test,{target})", file=out) + print(f"\t@$(call run_test,{target})") def generate_ys_test(ys_file, yosys_args="", commands=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' @@ -90,37 +91,37 @@ def generate_tests(argv, cmds): if f != "run-test.sh": generate_bash_test(f, cmds) -def print_header(extra=None, out=sys.stdout): - print(f"include {common_mk}", file=out) - print(f"YOSYS ?= {yosys_basedir}/yosys", file=out) - print("", file=out) - print("export YOSYS_MAX_THREADS := 4", file=out) +def print_header(extra=None): + print(f"include {common_mk}") + print(f"YOSYS ?= {yosys_basedir}/yosys") + print("") + print("export YOSYS_MAX_THREADS := 4") if extra: for line in extra: - print(line, file=out) - print("", file=out) - print(".PHONY: all", file=out) - print("all:", file=out) + print(line) + print("") + print(".PHONY: all") + print("all:") + +@contextmanager +def redirect_stdout(new_target): + old_target, sys.stdout = sys.stdout, new_target + try: + yield new_target + finally: + sys.stdout = old_target def generate(argv, extra=None, cmds=""): with open("Makefile", "w") as f: - old = sys.stdout - sys.stdout = f - try: + with redirect_stdout(f): print_header(extra) generate_tests(argv, cmds) - finally: - sys.stdout = old def generate_custom(callback, extra=None): with open("Makefile", "w") as f: - old = sys.stdout - sys.stdout = f - try: + with redirect_stdout(f): print_header(extra) callback() - finally: - sys.stdout = old def generate_autotest_file(test_file, commands): cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1; \\\n{commands}" @@ -128,16 +129,12 @@ def generate_autotest_file(test_file, commands): def generate_autotest(pattern, extra_flags, cmds=""): with open("Makefile", "w") as f: - old = sys.stdout - sys.stdout = f - try: + with redirect_stdout(f): print_header([ f"EXTRA_FLAGS = {extra_flags}", "SEED ?=", "ifneq ($(strip $(SEED)),)", " SEEDOPT=-S$(SEED)", "endif", ]) - for f in sorted(glob.glob(pattern)): - generate_autotest_file(f, cmds) - finally: - sys.stdout = old + for fn in sorted(glob.glob(pattern)): + generate_autotest_file(fn, cmds) diff --git a/tests/opt_share/.gitignore b/tests/opt_share/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/opt_share/.gitignore +++ b/tests/opt_share/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/opt_share/generate.py b/tests/opt_share/generate_mk.py similarity index 61% rename from tests/opt_share/generate.py rename to tests/opt_share/generate_mk.py index 2ec92f7de..0d7e494e9 100644 --- a/tests/opt_share/generate.py +++ b/tests/opt_share/generate_mk.py @@ -1,48 +1,42 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager - - -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target - +from pathlib import Path def random_plus_x(): return "%s x" % random.choice(['+', '+', '+', '-', '-', '|', '&', '^']) - def maybe_plus_x(expr): if random.randint(0, 4) == 0: return "(%s %s)" % (expr, random_plus_x()) else: return expr - -parser = argparse.ArgumentParser( - formatter_class=argparse.ArgumentDefaultsHelpFormatter) -parser.add_argument('-S', '--seed', type=int, help='seed for PRNG') -parser.add_argument('-c', - '--count', - type=int, - default=100, - help='number of test cases to generate') +parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') +parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("opt_share PRNG seed: %d" % seed) +random.seed(seed) + +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('module uut_%05d(a, b, c, s, y);' % (idx)) op = random.choice([ random.choice(['+', '-', '*', '/', '%']), @@ -67,20 +61,20 @@ for idx in range(args.count): cast2, ops2[0], op, ops2[1])) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): - print('read_verilog temp/uut_%05d.v' % idx) + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): + print('read_verilog uut_%05d.v' % idx) print('proc;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) - print('tee -a temp/all_share_log.txt log') - print('tee -a temp/all_share_log.txt log #job# uut_%05d' % idx) - print('tee -a temp/all_share_log.txt opt gate') - print('tee -a temp/all_share_log.txt opt_share gate') - print('tee -a temp/all_share_log.txt opt_clean gate') + print('tee -o uut_%05d.txt opt gate' % idx) + print('tee -o uut_%05d.txt opt_share gate' % idx) + print('tee -o uut_%05d.txt opt_clean gate' % idx) print( 'miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter' ) print( 'sat -set-def-inputs -verify -prove trigger 0 -show-inputs -show-outputs miter' ) + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/opt_share/run-test.sh b/tests/opt_share/run-test.sh deleted file mode 100755 index e33399567..000000000 --- a/tests/opt_share/run-test.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -{ - echo ".PHONY: all" - echo "all:" - - for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - idx=$( printf "%05d" $i ) - echo ".PHONY: test-$idx" - echo "all: test-$idx" - echo "test-$idx:" - printf "\t@%s\n" \ - "echo -n [$i]" \ - "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1" - done -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile -echo - -failed_share=$( echo $( gawk '/^#job#/ { j=$2; db[j]=0; } /^Removing [246] cells/ { delete db[j]; } END { for (j in db) print(j); }' temp/all_share_log.txt ) ) -if [ -n "$failed_share" ]; then - echo "Resource sharing failed for the following test cases: $failed_share" - false -fi - -exit 0 diff --git a/tests/rpc/generate_mk.py b/tests/rpc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/rpc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/share/.gitignore b/tests/share/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/share/.gitignore +++ b/tests/share/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/share/generate.py b/tests/share/generate_mk.py similarity index 80% rename from tests/share/generate.py rename to tests/share/generate_mk.py index 7e87bd648..6a40758e1 100644 --- a/tests/share/generate.py +++ b/tests/share/generate_mk.py @@ -1,17 +1,14 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager - -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target +from pathlib import Path def random_plus_x(): return "%s x" % random.choice(['+', '+', '+', '-', '-', '|', '&', '^']) @@ -27,13 +24,19 @@ parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("share PRNG seed: %d" % seed) +random.seed(seed) + +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): if random.choice(['bin', 'uni']) == 'bin': print('module uut_%05d(a, b, c, d, x, s, y);' % (idx)) op = random.choice([ @@ -67,16 +70,16 @@ for idx in range(args.count): random.choice(['', '$signed', '$unsigned']), op, maybe_plus_x('b'), random_plus_x() if random.randint(0, 4) == 0 else '')) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): - print('read_verilog temp/uut_%05d.v' % idx) - print('proc;;') + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): + print('read_verilog uut_%05d.v' % idx) + print('proc -noopt;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) - print('tee -a temp/all_share_log.txt log') - print('tee -a temp/all_share_log.txt log #job# uut_%05d' % idx) - print('tee -a temp/all_share_log.txt wreduce') - print('tee -a temp/all_share_log.txt share -aggressive gate') + print('tee -o uut_%05d.txt wreduce' % idx) + print('tee -a uut_%05d.txt share -aggressive gate' % idx) print('miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter') print('sat -set-def-inputs -verify -prove trigger 0 -show-inputs -show-outputs miter') + print('! grep -q \'^Removing [246] cells\' uut_%05d.txt' % idx) +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/share/run-test.sh b/tests/share/run-test.sh deleted file mode 100755 index 36349baad..000000000 --- a/tests/share/run-test.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -echo "running tests.." -for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - echo -n "[$i]" - idx=$( printf "%05d" $i ) - ../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1 -done -echo - -failed_share=$( echo $( gawk '/^#job#/ { j=$2; db[j]=0; } /^Removing [246] cells/ { delete db[j]; } END { for (j in db) print(j); }' temp/all_share_log.txt ) ) -if [ -n "$failed_share" ]; then - echo "Resource sharing failed for the following test cases: $failed_share" - false -fi - -exit 0 diff --git a/tests/xprop/generate_mk.py b/tests/xprop/generate_mk.py index 67ab26bda..c4a351247 100644 --- a/tests/xprop/generate_mk.py +++ b/tests/xprop/generate_mk.py @@ -22,9 +22,10 @@ if args.seed is None: print(f"xprop PRNG seed: {args.seed}") -makefile = open("Makefile", "w") -gen_tests_makefile.print_header(out = makefile) +makefile = open("Makefile", "w") +with gen_tests_makefile.redirect_stdout(makefile): + gen_tests_makefile.print_header() def add_test(name, src, seq=False): if not re.search(args.filter, name): @@ -35,9 +36,9 @@ def add_test(name, src, seq=False): with open(f"{workdir}/uut.v", "w") as uut: print(src, file=uut) seq_arg = " -s" if seq else "" - gen_tests_makefile.generate_target(workdir, - f"cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1", - out=makefile) + with gen_tests_makefile.redirect_stdout(makefile): + gen_tests_makefile.generate_target(workdir, + f"cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1") def cell_test(name, cell, inputs, outputs, params, initial={}, defclock=False, seq=False): ports = []