From 92ef719434e970561f7415e35e6cb66b93a39239 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 09:41:39 +0100 Subject: [PATCH 01/36] Split vanilla-test to separate Makefile --- Makefile | 108 +++---------------------------------------------- tests/Makefile | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 102 deletions(-) create mode 100644 tests/Makefile diff --git a/Makefile b/Makefile index 33ff74fa4..01b9fbdc4 100644 --- a/Makefile +++ b/Makefile @@ -918,110 +918,14 @@ else ABCOPT="" endif -# Tests that generate .mk with tests/gen-tests-makefile.sh -MK_TEST_DIRS = -MK_TEST_DIRS += tests/arch/analogdevices -MK_TEST_DIRS += tests/arch/anlogic -MK_TEST_DIRS += tests/arch/ecp5 -MK_TEST_DIRS += tests/arch/efinix -MK_TEST_DIRS += tests/arch/gatemate -MK_TEST_DIRS += tests/arch/gowin -MK_TEST_DIRS += tests/arch/ice40 -MK_TEST_DIRS += tests/arch/intel_alm -MK_TEST_DIRS += tests/arch/machxo2 -MK_TEST_DIRS += tests/arch/microchip -MK_TEST_DIRS += tests/arch/nanoxplore -MK_TEST_DIRS += tests/arch/nexus -MK_TEST_DIRS += tests/arch/quicklogic/pp3 -MK_TEST_DIRS += tests/arch/quicklogic/qlf_k6n10f -MK_TEST_DIRS += tests/arch/xilinx -MK_TEST_DIRS += tests/bugpoint -MK_TEST_DIRS += tests/opt -MK_TEST_DIRS += tests/sat -MK_TEST_DIRS += tests/sdc -MK_TEST_DIRS += tests/sim -MK_TEST_DIRS += tests/svtypes -MK_TEST_DIRS += tests/techmap -MK_TEST_DIRS += tests/various -MK_TEST_DIRS += tests/rtlil -ifeq ($(ENABLE_VERIFIC),1) -ifneq ($(YOSYS_NOVERIFIC),1) -MK_TEST_DIRS += tests/verific -endif -endif -MK_TEST_DIRS += tests/verilog - -# Tests that don't generate .mk -SH_TEST_DIRS = -SH_TEST_DIRS += tests/simple -SH_TEST_DIRS += tests/simple_abc9 -SH_TEST_DIRS += tests/hana -SH_TEST_DIRS += tests/asicworld -# SH_TEST_DIRS += tests/realmath -SH_TEST_DIRS += tests/share -SH_TEST_DIRS += tests/opt_share -SH_TEST_DIRS += tests/fsm -SH_TEST_DIRS += tests/memlib -SH_TEST_DIRS += tests/bram -SH_TEST_DIRS += tests/svinterfaces -SH_TEST_DIRS += tests/xprop -SH_TEST_DIRS += tests/select -SH_TEST_DIRS += tests/peepopt -SH_TEST_DIRS += tests/proc -SH_TEST_DIRS += tests/blif -SH_TEST_DIRS += tests/arch -SH_TEST_DIRS += tests/rpc -SH_TEST_DIRS += tests/memfile -SH_TEST_DIRS += tests/fmt -SH_TEST_DIRS += tests/cxxrtl -SH_TEST_DIRS += tests/liberty -ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) -SH_TEST_DIRS += tests/functional -endif - -# Tests that don't generate .mk and need special args -SH_ABC_TEST_DIRS = -SH_ABC_TEST_DIRS += tests/memories -SH_ABC_TEST_DIRS += tests/aiger -SH_ABC_TEST_DIRS += tests/alumacc - -# seed-tests/ is a dummy string, not a directory -.PHONY: seed-tests -seed-tests: $(SH_TEST_DIRS:%=seed-tests/%) -.PHONY: seed-tests/% -seed-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) - +cd $* && bash run-test.sh $(SEEDOPT) - +@echo "...passed tests in $*" - -# abcopt-tests/ is a dummy string, not a directory -.PHONY: abcopt-tests -abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-tests/%) -abcopt-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) - +@echo "...passed tests in $*" - -# makefile-tests/ is a dummy string, not a directory -.PHONY: makefile-tests -makefile-tests: $(MK_TEST_DIRS:%=makefile-tests/%) -# this target actually emits .mk files -%.mk: - +cd $(dir $*) && bash run-test.sh -# this one spawns submake on each -makefile-tests/%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) - $(MAKE) -C $* -f run-test.mk - +@echo "...passed tests in $*" - test: vanilla-test unit-test -vanilla-test: makefile-tests abcopt-tests seed-tests - @echo "" - @echo " Passed \"make vanilla-test\"." -ifeq ($(ENABLE_VERIFIC),1) -ifeq ($(YOSYS_NOVERIFIC),1) - @echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1." -endif -endif - @echo "" +.PHONY: vanilla-test + +vanilla-test: + @$(MAKE) -C tests vanilla-test \ + $(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \ + $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 000000000..3ec125e48 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,105 @@ +# Tests that generate .mk with ./gen-tests-makefile.sh +MK_TEST_DIRS = +MK_TEST_DIRS += ./arch/analogdevices +MK_TEST_DIRS += ./arch/anlogic +MK_TEST_DIRS += ./arch/ecp5 +MK_TEST_DIRS += ./arch/efinix +MK_TEST_DIRS += ./arch/gatemate +MK_TEST_DIRS += ./arch/gowin +MK_TEST_DIRS += ./arch/ice40 +MK_TEST_DIRS += ./arch/intel_alm +MK_TEST_DIRS += ./arch/machxo2 +MK_TEST_DIRS += ./arch/microchip +MK_TEST_DIRS += ./arch/nanoxplore +MK_TEST_DIRS += ./arch/nexus +MK_TEST_DIRS += ./arch/quicklogic/pp3 +MK_TEST_DIRS += ./arch/quicklogic/qlf_k6n10f +MK_TEST_DIRS += ./arch/xilinx +MK_TEST_DIRS += ./bugpoint +MK_TEST_DIRS += ./opt +MK_TEST_DIRS += ./sat +MK_TEST_DIRS += ./sdc +MK_TEST_DIRS += ./sim +MK_TEST_DIRS += ./svtypes +MK_TEST_DIRS += ./techmap +MK_TEST_DIRS += ./various +MK_TEST_DIRS += ./rtlil +ifeq ($(ENABLE_VERIFIC),1) +ifneq ($(YOSYS_NOVERIFIC),1) +MK_TEST_DIRS += ./verific +endif +endif +MK_TEST_DIRS += ./verilog + +# Tests that don't generate .mk +SH_TEST_DIRS = +SH_TEST_DIRS += ./simple +SH_TEST_DIRS += ./simple_abc9 +SH_TEST_DIRS += ./hana +SH_TEST_DIRS += ./asicworld +# SH_TEST_DIRS += ./realmath +SH_TEST_DIRS += ./share +SH_TEST_DIRS += ./opt_share +SH_TEST_DIRS += ./fsm +SH_TEST_DIRS += ./memlib +SH_TEST_DIRS += ./bram +SH_TEST_DIRS += ./svinterfaces +SH_TEST_DIRS += ./xprop +SH_TEST_DIRS += ./select +SH_TEST_DIRS += ./peepopt +SH_TEST_DIRS += ./proc +SH_TEST_DIRS += ./blif +SH_TEST_DIRS += ./arch +SH_TEST_DIRS += ./rpc +SH_TEST_DIRS += ./memfile +SH_TEST_DIRS += ./fmt +SH_TEST_DIRS += ./cxxrtl +SH_TEST_DIRS += ./liberty +ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +SH_TEST_DIRS += ./functional +endif + +# Tests that don't generate .mk and need special args +SH_ABC_TEST_DIRS = +SH_ABC_TEST_DIRS += ./memories +SH_ABC_TEST_DIRS += ./aiger +SH_ABC_TEST_DIRS += ./alumacc + +all: vanilla-test + +# seed-./ is a dummy string, not a directory +.PHONY: seed-tests +seed-tests: $(SH_TEST_DIRS:%=seed-./%) +.PHONY: seed-./% +seed-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) + +cd $* && bash run-test.sh $(SEEDOPT) + +@echo "...passed tests in $*" + +# abcopt-./ is a dummy string, not a directory +.PHONY: abcopt-tests +abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) +abcopt-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) + +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) + +@echo "...passed tests in $*" + +# makefile-./ is a dummy string, not a directory +.PHONY: makefile-tests +makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) +# this target actually emits .mk files +%.mk: + +cd $(dir $*) && bash run-test.sh +# this one spawns submake on each +makefile-./%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) + $(MAKE) -C $* -f run-test.mk + +@echo "...passed tests in $*" + +vanilla-test: makefile-tests abcopt-tests seed-tests + @echo "" + @echo " Passed \"make vanilla-test\"." +ifeq ($(ENABLE_VERIFIC),1) +ifeq ($(YOSYS_NOVERIFIC),1) + @echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1." +endif +endif + @echo "" + From 108a9133d0750eb963c99e02095358875f6105b5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 10:01:23 +0100 Subject: [PATCH 02/36] Move clean for tests in proper Makefile --- Makefile | 10 +--------- tests/Makefile | 10 ++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 01b9fbdc4..104a535a6 100644 --- a/Makefile +++ b/Makefile @@ -1091,16 +1091,8 @@ clean: clean-py clean-unit-test rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) rm -f kernel/version_*.o kernel/version_*.cc rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d - rm -rf tests/asicworld/*.out tests/asicworld/*.log - rm -rf tests/hana/*.out tests/hana/*.log - rm -rf tests/simple/*.out tests/simple/*.log - rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp - rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log - rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp tests/various/temp rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_* - rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff - rm -f tests/tools/cmp_tbdata - rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + -$(MAKE) -C $(YOSYS_SRC)/tests clean -$(MAKE) -C $(YOSYS_SRC)/docs clean rm -rf docs/util/__pycache__ rm -f libyosys.so diff --git a/tests/Makefile b/tests/Makefile index 3ec125e48..7f4e0f739 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -103,3 +103,13 @@ endif endif @echo "" +clean: + rm -rf ./asicworld/*.out ./asicworld/*.log + rm -rf ./hana/*.out ./hana/*.log + rm -rf ./simple/*.out ./simple/*.log + rm -rf ./memories/*.out ./memories/*.log ./memories/*.dmp + rm -rf ./sat/*.log ./techmap/*.log ./various/*.log + rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp + rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff + rm -f ./tools/cmp_tbdata + rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) From 1a864c72aedcdb111f3ba797445061975aaf3595 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 10:08:52 +0100 Subject: [PATCH 03/36] Make sure targets are built for tests --- Makefile | 2 +- tests/Makefile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 104a535a6..8a38910d6 100644 --- a/Makefile +++ b/Makefile @@ -922,7 +922,7 @@ test: vanilla-test unit-test .PHONY: vanilla-test -vanilla-test: +vanilla-test: $(TARGETS) $(EXTRA_TARGETS) @$(MAKE) -C tests vanilla-test \ $(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \ $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) diff --git a/tests/Makefile b/tests/Makefile index 7f4e0f739..e82c2f718 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -71,14 +71,14 @@ all: vanilla-test .PHONY: seed-tests seed-tests: $(SH_TEST_DIRS:%=seed-./%) .PHONY: seed-./% -seed-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) +seed-./%: %/run-test.sh +cd $* && bash run-test.sh $(SEEDOPT) +@echo "...passed tests in $*" # abcopt-./ is a dummy string, not a directory .PHONY: abcopt-tests abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) -abcopt-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) +abcopt-./%: %/run-test.sh +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) +@echo "...passed tests in $*" @@ -89,7 +89,7 @@ makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) %.mk: +cd $(dir $*) && bash run-test.sh # this one spawns submake on each -makefile-./%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) +makefile-./%: %/run-test.mk $(MAKE) -C $* -f run-test.mk +@echo "...passed tests in $*" From 6526e88d14482d4a29fbd3c316eb7a2f51ab1d8a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 10:15:27 +0100 Subject: [PATCH 04/36] Propagate ABCOPT and SEEDOPT --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8a38910d6..b28ee21ac 100644 --- a/Makefile +++ b/Makefile @@ -925,7 +925,8 @@ test: vanilla-test unit-test vanilla-test: $(TARGETS) $(EXTRA_TARGETS) @$(MAKE) -C tests vanilla-test \ $(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \ - $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) + $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) \ + SEEDOPT=$(SEEDOPT) ABCOPT=$(ABCOPT) VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all From c08a2aa3ff5293c2bf63cf7f97a24f0aacd75ea1 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:02:20 +0100 Subject: [PATCH 05/36] Do not write to console for makefile-tests --- tests/Makefile | 27 ++++++++++++++------------- tests/gen-tests-makefile.sh | 4 ++-- tests/sim/run-test.sh | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index e82c2f718..aaa921ab3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -79,19 +79,20 @@ seed-./%: %/run-test.sh .PHONY: abcopt-tests abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) abcopt-./%: %/run-test.sh - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) + +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) >/dev/null 2>&1 +@echo "...passed tests in $*" # makefile-./ is a dummy string, not a directory .PHONY: makefile-tests +#.SILENT: $(MK_TEST_DIRS:%=%/run-test.mk) makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) # this target actually emits .mk files %.mk: - +cd $(dir $*) && bash run-test.sh + +@cd $(dir $*) && bash run-test.sh # this one spawns submake on each makefile-./%: %/run-test.mk - $(MAKE) -C $* -f run-test.mk - +@echo "...passed tests in $*" + @$(MAKE) -C $* -f run-test.mk + @echo "...passed tests in $*" vanilla-test: makefile-tests abcopt-tests seed-tests @echo "" @@ -104,12 +105,12 @@ endif @echo "" clean: - rm -rf ./asicworld/*.out ./asicworld/*.log - rm -rf ./hana/*.out ./hana/*.log - rm -rf ./simple/*.out ./simple/*.log - rm -rf ./memories/*.out ./memories/*.log ./memories/*.dmp - rm -rf ./sat/*.log ./techmap/*.log ./various/*.log - rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp - rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff - rm -f ./tools/cmp_tbdata - rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + @rm -rf ./asicworld/*.out ./asicworld/*.log + @rm -rf ./hana/*.out ./hana/*.log + @rm -rf ./simple/*.out ./simple/*.log + @rm -rf ./memories/*.out ./memories/*.log ./memories/*.dmp + @rm -rf ./sat/*.log ./techmap/*.log ./various/*.log + @rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp + @rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff + @rm -f ./tools/cmp_tbdata + @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) diff --git a/tests/gen-tests-makefile.sh b/tests/gen-tests-makefile.sh index a0fb23ac3..07d70c2a8 100755 --- a/tests/gen-tests-makefile.sh +++ b/tests/gen-tests-makefile.sh @@ -17,14 +17,14 @@ generate_target() { generate_ys_test() { ys_file=$1 yosys_args_=${2:-} - generate_target "$ys_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${ys_file}.err $yosys_args_ $ys_file && mv ${ys_file}.err ${ys_file}.log" + generate_target "$ys_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${ys_file}.err $yosys_args_ $ys_file >/dev/null 2>&1 && mv ${ys_file}.err ${ys_file}.log" } # $ generate_tcl_test tcl_file [yosys_args] generate_tcl_test() { tcl_file=$1 yosys_args_=${2:-} - generate_target "$tcl_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${tcl_file}.err $yosys_args_ $tcl_file && mv ${tcl_file}.err ${tcl_file}.log" + generate_target "$tcl_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${tcl_file}.err $yosys_args_ $tcl_file >/dev/null 2>&1 && mv ${tcl_file}.err ${tcl_file}.log" } # $ generate_bash_test bash_file diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh index 43571e057..cff85eb65 100755 --- a/tests/sim/run-test.sh +++ b/tests/sim/run-test.sh @@ -6,7 +6,7 @@ find tb/* -name tb*.v | while read name; do test_name=$(basename $name .v) echo "Test $test_name" verilog_name=${test_name:3}.v - iverilog -o tb/$test_name.out $name $verilog_name - ./tb/$test_name.out -fst + iverilog -o tb/$test_name.out $name $verilog_name >/dev/null 2>&1 + ./tb/$test_name.out -fst >/dev/null 2>&1 done generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" From 169b9994dcdd23dd19fb6fad361ab5fb057af299 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:05:47 +0100 Subject: [PATCH 06/36] Ignore some generated files --- tests/various/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/various/.gitignore b/tests/various/.gitignore index 9296a04c0..1431c4096 100644 --- a/tests/various/.gitignore +++ b/tests/various/.gitignore @@ -9,3 +9,4 @@ /temp /smtlib2_module.smt2 /smtlib2_module-filtered.smt2 +/*.aig From a1559948682972b7078049441a9df2c55853e23e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:18:05 +0100 Subject: [PATCH 07/36] Cleanup for abcopt-tests --- tests/Makefile | 2 +- tests/aiger/run-test.sh | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index aaa921ab3..d34db2100 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -79,7 +79,7 @@ seed-./%: %/run-test.sh .PHONY: abcopt-tests abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) abcopt-./%: %/run-test.sh - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) >/dev/null 2>&1 + +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) +@echo "...passed tests in $*" # makefile-./ is a dummy string, not a directory diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index 94d83ede4..5208fa030 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -22,7 +22,7 @@ for aag in *.aag; do # (which would have been created by the reference aig2aig utility, # available from http://fmv.jku.at/aiger/) echo "Checking $aag." - $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" + $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" >/dev/null 2>&1 ../../yosys -qp " read_verilog ${aag%.*}_ref.v prep @@ -34,12 +34,12 @@ design -import gold -as gold design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aag}.log +" -l ${aag}.log >/dev/null 2>&1 done for aig in *.aig; do echo "Checking $aig." - $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" + $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" >/dev/null 2>&1 ../../yosys -qp " read_verilog ${aig%.*}_ref.v prep @@ -51,18 +51,18 @@ design -import gold -as gold design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aig}.log +" -l ${aig}.log >/dev/null 2>&1 done for y in *.ys; do echo "Running $y." - ../../yosys -ql ${y%.*}.log $y + ../../yosys -ql ${y%.*}.log $y >/dev/null 2>&1 done # compare aigmap with reference # make gold with: rm gold/*; yosys --no-version -p "test_cell -aigmap -w gold/ -n 1 -s 1 all" rm -rf gate; mkdir gate -../../yosys --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" +../../yosys --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1 ( set -o pipefail diff --brief gold gate | tee aigmap.err From ede782d7e3571449f232cc5cef1796784474d9f6 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:50:30 +0100 Subject: [PATCH 08/36] Clean some seed-tests outputs --- tests/arch/run-test.sh | 6 +++--- tests/blif/run-test.sh | 2 +- tests/cxxrtl/run-test.sh | 2 +- tests/memfile/run-test.sh | 20 ++++++++++---------- tests/proc/run-test.sh | 2 +- tests/select/run-test.sh | 2 +- tests/svinterfaces/runone.sh | 14 +++++++------- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh index 7602717d2..087abf536 100755 --- a/tests/arch/run-test.sh +++ b/tests/arch/run-test.sh @@ -12,12 +12,12 @@ for arch in ../../techlibs/*; do if [ "${defines[$arch_name]}" ]; then for def in ${defines[$arch_name]}; do echo -n "Test $path -D$def ->" - iverilog -t null -I$arch -D$def -DNO_ICE40_DEFAULT_ASSIGNMENTS $path + iverilog -t null -I$arch -D$def -DNO_ICE40_DEFAULT_ASSIGNMENTS $path >/dev/null 2>&1 echo " ok" done else echo -n "Test $path ->" - iverilog -t null -I$arch -g2005-sv $path + iverilog -t null -I$arch -g2005-sv $path >/dev/null 2>&1 echo " ok" fi done @@ -25,6 +25,6 @@ done for path in "../../techlibs/common/simcells.v" "../../techlibs/common/simlib.v"; do echo -n "Test $path ->" - iverilog -t null $path + iverilog -t null $path >/dev/null 2>&1 echo " ok" done diff --git a/tests/blif/run-test.sh b/tests/blif/run-test.sh index 14b9ead8e..97f12d288 100755 --- a/tests/blif/run-test.sh +++ b/tests/blif/run-test.sh @@ -3,7 +3,7 @@ source ../common-env.sh set -e for x in *.ys; do echo "Running $x.." - ../../yosys --no-version -ql ${x%.ys}.log $x + ../../yosys --no-version -ql ${x%.ys}.log $x >/dev/null 2>&1 done for x in *.blif; do diff --git a/tests/cxxrtl/run-test.sh b/tests/cxxrtl/run-test.sh index aa7a0c26c..b21c79899 100755 --- a/tests/cxxrtl/run-test.sh +++ b/tests/cxxrtl/run-test.sh @@ -14,5 +14,5 @@ run_subtest value run_subtest value_fuzz # Compile-only test. -../../yosys -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" +../../yosys -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" >/dev/null 2>&1 ${CXX:-g++} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc diff --git a/tests/memfile/run-test.sh b/tests/memfile/run-test.sh index 44c1e4821..e2583ef3b 100755 --- a/tests/memfile/run-test.sh +++ b/tests/memfile/run-test.sh @@ -9,32 +9,32 @@ cp content1.dat temp/content2.dat cd .. echo "Running from the parent directory with content1.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 echo "Running from the parent directory with temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 echo "Running from the parent directory with memfile/temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" >/dev/null 2>&1 cd memfile echo "Running from the same directory with content1.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" +../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 echo "Running from the same directory with temp/content2.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 cd temp echo "Running from a child directory with content1.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 echo "Running from a child directory with temp/content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 echo "Running from a child directory with content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 cd .. echo "Checking a failure when zero length filename is provided" -if ../../yosys -qp "read_verilog memory.v"; then +if ../../yosys -qp "read_verilog memory.v" >/dev/null 2>&1; then echo "The execution should fail but it didn't happen, which is WRONG." exit 1 else @@ -42,7 +42,7 @@ else fi echo "Checking a failure when not existing filename is provided" -if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory"; then +if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory" >/dev/null 2>&1; then echo "The execution should fail but it didn't happen, which is WRONG." exit 1 else diff --git a/tests/proc/run-test.sh b/tests/proc/run-test.sh index 2e3f5235c..241b32295 100755 --- a/tests/proc/run-test.sh +++ b/tests/proc/run-test.sh @@ -3,5 +3,5 @@ source ../common-env.sh set -e for x in *.ys; do echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x + ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 done diff --git a/tests/select/run-test.sh b/tests/select/run-test.sh index 2e3f5235c..241b32295 100755 --- a/tests/select/run-test.sh +++ b/tests/select/run-test.sh @@ -3,5 +3,5 @@ source ../common-env.sh set -e for x in *.ys; do echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x + ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 done diff --git a/tests/svinterfaces/runone.sh b/tests/svinterfaces/runone.sh index 2d6e0463d..598517db9 100755 --- a/tests/svinterfaces/runone.sh +++ b/tests/svinterfaces/runone.sh @@ -18,19 +18,19 @@ $PWD/../../yosys -p "read_verilog -sv ${TESTNAME}_ref.v ; hierarchy -check -top rm -f a.out reference_result.txt dut_result.txt -iverilog -g2012 ${TESTNAME}_syn.v -iverilog -g2012 ${TESTNAME}_ref_syn.v +iverilog -g2012 ${TESTNAME}_syn.v >/dev/null 2>&1 +iverilog -g2012 ${TESTNAME}_ref_syn.v >/dev/null 2>&1 set +e -iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v -./a.out +iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v >/dev/null 2>&1 +./a.out >/dev/null 2>&1 mv output.txt reference_result.txt if [ -f ${TESTNAME}_wrapper.v ] ; then - iverilog -g2012 ${TESTNAME}_tb_wrapper.v ${TESTNAME}_syn.v + iverilog -g2012 ${TESTNAME}_tb_wrapper.v ${TESTNAME}_syn.v >/dev/null 2>&1 else - iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v + iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v >/dev/null 2>&1 fi -./a.out +./a.out >/dev/null 2>&1 mv output.txt dut_result.txt diff reference_result.txt dut_result.txt > ${TESTNAME}.diff From 8a6954413ff52bc084c8d7e6d413fefe3612823b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 15:57:24 +0100 Subject: [PATCH 09/36] Clean some seed-tests outputs --- tests/cxxrtl/run-test.sh | 2 +- tests/fmt/run-test.sh | 34 +++++++++++++++++----------------- tests/fsm/run-test.sh | 2 +- tests/liberty/run-test.sh | 4 ++-- tests/opt_share/run-test.sh | 2 +- tests/share/run-test.sh | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/cxxrtl/run-test.sh b/tests/cxxrtl/run-test.sh index b21c79899..6a0bd2355 100755 --- a/tests/cxxrtl/run-test.sh +++ b/tests/cxxrtl/run-test.sh @@ -1,7 +1,7 @@ #!/bin/bash source ../common-env.sh -set -ex +set -e run_subtest () { local subtest=$1; shift diff --git a/tests/fmt/run-test.sh b/tests/fmt/run-test.sh index a3402f953..094f52a2f 100644 --- a/tests/fmt/run-test.sh +++ b/tests/fmt/run-test.sh @@ -1,17 +1,17 @@ #!/usr/bin/env bash source ../common-env.sh -set -ex +set -e -../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $0}' >yosys-initial_display.log +../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $0}' >yosys-initial_display.log 2>&1 iverilog -o iverilog-initial_display initial_display.v ./iverilog-initial_display >iverilog-initial_display.log diff yosys-initial_display.log iverilog-initial_display.log test_always_display () { local subtest=$1; shift - ../../yosys -p "read_verilog $* always_display.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-1.v - ../../yosys -p "read_verilog yosys-always_display-${subtest}-1.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-2.v + ../../yosys -p "read_verilog $* always_display.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-1.v >/dev/null 2>&1 + ../../yosys -p "read_verilog yosys-always_display-${subtest}-1.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-2.v >/dev/null 2>&1 diff yosys-always_display-${subtest}-1.v yosys-always_display-${subtest}-2.v } @@ -25,15 +25,15 @@ test_always_display star_en -DEVENT_STAR -DCOND_EN test_roundtrip () { local subtest=$1; shift - ../../yosys -p "read_verilog $* roundtrip.v; proc; clean" -o yosys-roundtrip-${subtest}-1.v - ../../yosys -p "read_verilog yosys-roundtrip-${subtest}-1.v; proc; clean" -o yosys-roundtrip-${subtest}-2.v + ../../yosys -p "read_verilog $* roundtrip.v; proc; clean" -o yosys-roundtrip-${subtest}-1.v >/dev/null 2>&1 + ../../yosys -p "read_verilog yosys-roundtrip-${subtest}-1.v; proc; clean" -o yosys-roundtrip-${subtest}-2.v >/dev/null 2>&1 diff yosys-roundtrip-${subtest}-1.v yosys-roundtrip-${subtest}-2.v - iverilog $* -o iverilog-roundtrip-${subtest} roundtrip.v roundtrip_tb.v + iverilog $* -o iverilog-roundtrip-${subtest} roundtrip.v roundtrip_tb.v >/dev/null 2>&1 ./iverilog-roundtrip-${subtest} >iverilog-roundtrip-${subtest}.log - iverilog $* -o iverilog-roundtrip-${subtest}-1 yosys-roundtrip-${subtest}-1.v roundtrip_tb.v + iverilog $* -o iverilog-roundtrip-${subtest}-1 yosys-roundtrip-${subtest}-1.v roundtrip_tb.v >/dev/null 2>&1 ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-1.log - iverilog $* -o iverilog-roundtrip-${subtest}-2 yosys-roundtrip-${subtest}-2.v roundtrip_tb.v + iverilog $* -o iverilog-roundtrip-${subtest}-2 yosys-roundtrip-${subtest}-2.v roundtrip_tb.v >/dev/null 2>&1 ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-2.log diff iverilog-roundtrip-${subtest}.log iverilog-roundtrip-${subtest}-1.log diff iverilog-roundtrip-${subtest}-1.log iverilog-roundtrip-${subtest}-2.log @@ -51,10 +51,10 @@ test_roundtrip bin_signed -DBASE_HEX -DSIGN="signed" test_cxxrtl () { local subtest=$1; shift - ../../yosys -p "read_verilog ${subtest}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" + ../../yosys -p "read_verilog ${subtest}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" >/dev/null 2>&1 ${CXX:-g++} -std=c++11 -o yosys-${subtest} -I../../backends/cxxrtl/runtime ${subtest}_tb.cc -lstdc++ ./yosys-${subtest} 2>yosys-${subtest}.log - iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v + iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v >/dev/null 2>&1 ./iverilog-${subtest} |grep -v '\$finish called' >iverilog-${subtest}.log diff iverilog-${subtest}.log yosys-${subtest}.log } @@ -63,16 +63,16 @@ test_cxxrtl always_full test_cxxrtl always_comb # Ensure Verilog backend preserves behaviour of always block with multiple $displays. -../../yosys -p "read_verilog always_full.v; prep; clean" -o yosys-always_full-1.v -iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v +../../yosys -p "read_verilog always_full.v; prep; clean" -o yosys-always_full-1.v >/dev/null 2>&1 +iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v >/dev/null 2>&1 ./iverilog-always_full-1 |grep -v '\$finish called' >iverilog-always_full-1.log diff iverilog-always_full.log iverilog-always_full-1.log -../../yosys -p "read_verilog display_lm.v" >yosys-display_lm.log -../../yosys -p "read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc" +../../yosys -p "read_verilog display_lm.v" >yosys-display_lm.log 2>&1 +../../yosys -p "read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc" >/dev/null 2>&1 ${CXX:-g++} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++ ./yosys-display_lm_cc >yosys-display_lm_cc.log for log in yosys-display_lm.log yosys-display_lm_cc.log; do - grep "^%l: \\\\bot\$" "$log" - grep "^%m: \\\\bot\$" "$log" + grep "^%l: \\\\bot\$" "$log" >/dev/null 2>&1 + grep "^%m: \\\\bot\$" "$log" >/dev/null 2>&1 done diff --git a/tests/fsm/run-test.sh b/tests/fsm/run-test.sh index 139ea8261..304242126 100755 --- a/tests/fsm/run-test.sh +++ b/tests/fsm/run-test.sh @@ -31,7 +31,7 @@ python3 generate.py -c $count $seed 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" + 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" diff --git a/tests/liberty/run-test.sh b/tests/liberty/run-test.sh index d5fb65e16..1b6873f26 100755 --- a/tests/liberty/run-test.sh +++ b/tests/liberty/run-test.sh @@ -10,13 +10,13 @@ for x in *.lib; do diff $x.filtered $x.filtered.ok diff $x.verilogsim $x.verilogsim.ok if [[ -e ${x%.lib}.log.ok ]]; then - ../../yosys -p "dfflibmap -info -liberty ${x}" -TqqQl ${x%.lib}.log + ../../yosys -p "dfflibmap -info -liberty ${x}" -TqqQl ${x%.lib}.log >/dev/null 2>&1 diff ${x%.lib}.log ${x%.lib}.log.ok fi done for x in *.ys; do echo "Running $x.." - ../../yosys -q -s $x -l ${x%.ys}.log + ../../yosys -q -s $x -l ${x%.ys}.log >/dev/null 2>&1 done diff --git a/tests/opt_share/run-test.sh b/tests/opt_share/run-test.sh index e3a6e8b7b..e33399567 100755 --- a/tests/opt_share/run-test.sh +++ b/tests/opt_share/run-test.sh @@ -34,7 +34,7 @@ python3 generate.py -c $count $seed echo "test-$idx:" printf "\t@%s\n" \ "echo -n [$i]" \ - "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys" + "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1" done } > temp/makefile diff --git a/tests/share/run-test.sh b/tests/share/run-test.sh index 0cef580a7..36349baad 100755 --- a/tests/share/run-test.sh +++ b/tests/share/run-test.sh @@ -27,7 +27,7 @@ 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 + ../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1 done echo From 2123121d23e9f832d47a0523b72c7af0ac8bf0d8 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 16:15:07 +0100 Subject: [PATCH 10/36] Fix deprecation warning --- tests/tools/autotest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index c9a12b66b..e19a8d5af 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -148,7 +148,7 @@ do rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then - egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} + grep -Ev '^\s*`timescale' ../$fn > ${bn}_ref.${ext} elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then $abcprog -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" else From 486c3715fb5b39b18c1cac0a06939273317f4072 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 11 Mar 2026 08:02:11 +0100 Subject: [PATCH 11/36] Enabled realmath that was disabled for some reason --- tests/Makefile | 2 +- tests/realmath/run-test.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index d34db2100..6742b6076 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -37,7 +37,7 @@ SH_TEST_DIRS += ./simple SH_TEST_DIRS += ./simple_abc9 SH_TEST_DIRS += ./hana SH_TEST_DIRS += ./asicworld -# SH_TEST_DIRS += ./realmath +SH_TEST_DIRS += ./realmath SH_TEST_DIRS += ./share SH_TEST_DIRS += ./opt_share SH_TEST_DIRS += ./fsm diff --git a/tests/realmath/run-test.sh b/tests/realmath/run-test.sh index 833e8c3f4..918c93a9f 100755 --- a/tests/realmath/run-test.sh +++ b/tests/realmath/run-test.sh @@ -23,8 +23,8 @@ echo "running tests.." for ((i = 0; i < $count; i++)); do echo -n "[$i]" idx=$( printf "%05d" $i ) - ../../../yosys -qq uut_${idx}.ys - iverilog -o uut_${idx}_tb uut_${idx}_tb.v uut_${idx}.v uut_${idx}_syn.v + ../../../yosys -qq uut_${idx}.ys >/dev/null 2>&1 + iverilog -o uut_${idx}_tb uut_${idx}_tb.v uut_${idx}.v uut_${idx}_syn.v >/dev/null 2>&1 ./uut_${idx}_tb | tee uut_${idx}.err if test -s uut_${idx}.err; then echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." From 2fb0ca49ff8576d0458d3e764f89ce7e9234e4ce Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 08:38:05 +0100 Subject: [PATCH 12/36] Convert gen-tests shell script to python --- tests/.gitignore | 1 + tests/Makefile | 17 +-- tests/aiger/generate_mk.py | 68 +++++++++++ tests/alumacc/generate_mk.py | 8 ++ tests/arch/analogdevices/generate_mk.py | 9 ++ tests/arch/analogdevices/run-test.sh | 5 - tests/arch/anlogic/generate_mk.py | 8 ++ tests/arch/anlogic/run-test.sh | 4 - tests/arch/ecp5/generate_mk.py | 8 ++ tests/arch/ecp5/run-test.sh | 4 - tests/arch/efinix/generate_mk.py | 8 ++ tests/arch/efinix/run-test.sh | 4 - tests/arch/fabulous/fsm.ys | 8 +- tests/arch/fabulous/generate_mk.py | 8 ++ tests/arch/gatemate/generate_mk.py | 8 ++ tests/arch/gatemate/run-test.sh | 4 - tests/arch/gowin/generate_mk.py | 8 ++ tests/arch/gowin/run-test.sh | 4 - tests/arch/ice40/generate_mk.py | 8 ++ tests/arch/ice40/run-test.sh | 4 - tests/arch/intel_alm/generate_mk.py | 8 ++ tests/arch/intel_alm/run-test.sh | 4 - tests/arch/machxo2/generate_mk.py | 8 ++ tests/arch/machxo2/run-test.sh | 4 - tests/arch/microchip/generate_mk.py | 8 ++ tests/arch/microchip/run-test.sh | 4 - tests/arch/nanoxplore/generate_mk.py | 8 ++ tests/arch/nanoxplore/run-test.sh | 4 - tests/arch/nexus/generate_mk.py | 8 ++ tests/arch/nexus/run-test.sh | 4 - tests/arch/quicklogic/pp3/generate_mk.py | 8 ++ tests/arch/quicklogic/pp3/run-test.sh | 4 - .../arch/quicklogic/qlf_k6n10f/generate_mk.py | 9 ++ tests/arch/quicklogic/qlf_k6n10f/run-test.sh | 5 - tests/arch/xilinx/generate_mk.py | 8 ++ tests/arch/xilinx/run-test.sh | 4 - tests/bugpoint/generate_mk.py | 8 ++ tests/bugpoint/run-test.sh | 4 - tests/gen-tests-makefile.sh | 110 ------------------ tests/gen_tests_makefile.py | 86 ++++++++++++++ tests/opt/generate_mk.py | 8 ++ tests/opt/run-test.sh | 4 - tests/rtlil/generate_mk.py | 8 ++ tests/rtlil/run-test.sh | 4 - tests/sat/generate_mk.py | 8 ++ tests/sat/run-test.sh | 4 - tests/sdc/generate_mk.py | 8 ++ tests/sdc/run-test.sh | 4 - tests/sim/generate_mk.py | 35 ++++++ tests/sim/run-test.sh | 12 -- tests/svtypes/generate_mk.py | 8 ++ tests/svtypes/run-test.sh | 4 - tests/techmap/generate_mk.py | 8 ++ tests/techmap/run-test.sh | 4 - tests/various/generate_mk.py | 8 ++ tests/various/run-test.sh | 4 - tests/verific/generate_mk.py | 8 ++ tests/verific/run-test.sh | 5 - tests/verilog/generate_mk.py | 8 ++ tests/verilog/run-test.sh | 4 - 60 files changed, 421 insertions(+), 237 deletions(-) create mode 100644 tests/aiger/generate_mk.py create mode 100644 tests/alumacc/generate_mk.py create mode 100644 tests/arch/analogdevices/generate_mk.py delete mode 100755 tests/arch/analogdevices/run-test.sh create mode 100644 tests/arch/anlogic/generate_mk.py delete mode 100755 tests/arch/anlogic/run-test.sh create mode 100644 tests/arch/ecp5/generate_mk.py delete mode 100755 tests/arch/ecp5/run-test.sh create mode 100644 tests/arch/efinix/generate_mk.py delete mode 100755 tests/arch/efinix/run-test.sh create mode 100644 tests/arch/fabulous/generate_mk.py create mode 100644 tests/arch/gatemate/generate_mk.py delete mode 100755 tests/arch/gatemate/run-test.sh create mode 100644 tests/arch/gowin/generate_mk.py delete mode 100755 tests/arch/gowin/run-test.sh create mode 100644 tests/arch/ice40/generate_mk.py delete mode 100755 tests/arch/ice40/run-test.sh create mode 100644 tests/arch/intel_alm/generate_mk.py delete mode 100755 tests/arch/intel_alm/run-test.sh create mode 100644 tests/arch/machxo2/generate_mk.py delete mode 100644 tests/arch/machxo2/run-test.sh create mode 100644 tests/arch/microchip/generate_mk.py delete mode 100755 tests/arch/microchip/run-test.sh create mode 100644 tests/arch/nanoxplore/generate_mk.py delete mode 100755 tests/arch/nanoxplore/run-test.sh create mode 100644 tests/arch/nexus/generate_mk.py delete mode 100644 tests/arch/nexus/run-test.sh create mode 100644 tests/arch/quicklogic/pp3/generate_mk.py delete mode 100755 tests/arch/quicklogic/pp3/run-test.sh create mode 100644 tests/arch/quicklogic/qlf_k6n10f/generate_mk.py delete mode 100755 tests/arch/quicklogic/qlf_k6n10f/run-test.sh create mode 100644 tests/arch/xilinx/generate_mk.py delete mode 100755 tests/arch/xilinx/run-test.sh create mode 100644 tests/bugpoint/generate_mk.py delete mode 100755 tests/bugpoint/run-test.sh delete mode 100755 tests/gen-tests-makefile.sh create mode 100644 tests/gen_tests_makefile.py create mode 100644 tests/opt/generate_mk.py delete mode 100755 tests/opt/run-test.sh create mode 100644 tests/rtlil/generate_mk.py delete mode 100755 tests/rtlil/run-test.sh create mode 100644 tests/sat/generate_mk.py delete mode 100755 tests/sat/run-test.sh create mode 100644 tests/sdc/generate_mk.py delete mode 100755 tests/sdc/run-test.sh create mode 100644 tests/sim/generate_mk.py delete mode 100755 tests/sim/run-test.sh create mode 100644 tests/svtypes/generate_mk.py delete mode 100755 tests/svtypes/run-test.sh create mode 100644 tests/techmap/generate_mk.py delete mode 100755 tests/techmap/run-test.sh create mode 100644 tests/various/generate_mk.py delete mode 100755 tests/various/run-test.sh create mode 100644 tests/verific/generate_mk.py delete mode 100755 tests/verific/run-test.sh create mode 100644 tests/verilog/generate_mk.py delete mode 100755 tests/verilog/run-test.sh diff --git a/tests/.gitignore b/tests/.gitignore index d8e01e026..da4350076 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,3 +2,4 @@ *.out *.err run-test.mk +**/Makefile diff --git a/tests/Makefile b/tests/Makefile index 6742b6076..5ec699417 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,9 +1,10 @@ -# Tests that generate .mk with ./gen-tests-makefile.sh +# Tests that generate Makefile with gen_tests_makefile.py MK_TEST_DIRS = MK_TEST_DIRS += ./arch/analogdevices MK_TEST_DIRS += ./arch/anlogic MK_TEST_DIRS += ./arch/ecp5 MK_TEST_DIRS += ./arch/efinix +MK_TEST_DIRS += ./arch/fabulous MK_TEST_DIRS += ./arch/gatemate MK_TEST_DIRS += ./arch/gowin MK_TEST_DIRS += ./arch/ice40 @@ -84,14 +85,14 @@ abcopt-./%: %/run-test.sh # makefile-./ is a dummy string, not a directory .PHONY: makefile-tests -#.SILENT: $(MK_TEST_DIRS:%=%/run-test.mk) +.SILENT: $(MK_TEST_DIRS:%=%/Makefile) makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) -# this target actually emits .mk files -%.mk: - +@cd $(dir $*) && bash run-test.sh -# this one spawns submake on each -makefile-./%: %/run-test.mk - @$(MAKE) -C $* -f run-test.mk +# this target actually emits Makefile files +%/Makefile: + +@cd $* && python3 generate_mk.py + +makefile-./%: %/Makefile + @$(MAKE) -C $* @echo "...passed tests in $*" vanilla-test: makefile-tests abcopt-tests seed-tests diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py new file mode 100644 index 000000000..e0a15332e --- /dev/null +++ b/tests/aiger/generate_mk.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +import glob +import os + +yosys = "../../yosys" +default_abc = "../../yosys-abc" + +aags = sorted(glob.glob("*.aag")) +yss = sorted(glob.glob("*.ys")) + +print("ABC ?= " + default_abc) +print("YOSYS ?= " + yosys) +print() + +def base(fn): + return os.path.splitext(fn)[0] + +# NB: *.aag and *.aig must contain a symbol table naming the primary +# inputs and outputs, otherwise ABC and Yosys will name them +# arbitrarily (and inconsistently with each other). + +# Since ABC cannot read *.aag, read the *.aig instead +# (which would have been created by the reference aig2aig utility, +# available from http://fmv.jku.at/aiger/) + +for aag in aags: + b = base(aag) + + print(f"all: {aag}") + print(f".PHONY: {aag}") + print(f"{aag}:") + print(f"\t@echo Checking {aag}.") + print(f"\t@$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\" >/dev/null 2>&1") + print("\t@$(YOSYS) -qp \"\\") + print(f"\tread_verilog {b}_ref.v; \\") + print("\tprep; \\") + print("\tdesign -stash gold; \\") + print(f"\tread_aiger -clk_name clock {aag}; \\") + print("\tprep; \\") + print("\tdesign -stash gate; \\") + print("\tdesign -import gold -as gold; \\") + print("\tdesign -import gate -as gate; \\") + print("\tmiter -equiv -flatten -make_assert -make_outputs gold gate miter; \\") + print("\tsat -verify -prove-asserts -show-ports -seq 16 miter; \\") + print(f"\t\" -l {aag}.log >/dev/null 2>&1") + print() + +# ---- Yosys script tests ---- +for ys in yss: + b = base(ys) + print(f"all: {ys}") + print(f".PHONY: {ys}") + print(f"{ys}: ") + print(f"\t@echo Running {ys}.") + print(f"\t@$(YOSYS) -ql {b}.log {ys} >/dev/null 2>&1") + print() + +# ---- aigmap test ---- +print(f"all: aigmap") +print(f".PHONY: aigmap") +print("aigmap:") +print("\t@echo Running aigmap.") +print("\t@rm -rf gate; mkdir gate") +print('\t@$(YOSYS) --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1') +print("\t@set -o pipefail; diff --brief gold gate | tee aigmap.err") +print("\t@rm -f aigmap.err") +print() diff --git a/tests/alumacc/generate_mk.py b/tests/alumacc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/alumacc/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/arch/analogdevices/generate_mk.py b/tests/arch/analogdevices/generate_mk.py new file mode 100644 index 000000000..b453168c0 --- /dev/null +++ b/tests/arch/analogdevices/generate_mk.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile +import mem_gen + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/analogdevices/run-test.sh b/tests/arch/analogdevices/run-test.sh deleted file mode 100755 index 9b5e2f7f4..000000000 --- a/tests/arch/analogdevices/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -python3 mem_gen.py -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/arch/anlogic/generate_mk.py b/tests/arch/anlogic/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/anlogic/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/anlogic/run-test.sh b/tests/arch/anlogic/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/anlogic/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/ecp5/generate_mk.py b/tests/arch/ecp5/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/ecp5/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/ecp5/run-test.sh b/tests/arch/ecp5/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/ecp5/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/efinix/generate_mk.py b/tests/arch/efinix/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/efinix/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/efinix/run-test.sh b/tests/arch/efinix/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/efinix/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/fabulous/fsm.ys b/tests/arch/fabulous/fsm.ys index 9c3831682..15fd19247 100644 --- a/tests/arch/fabulous/fsm.ys +++ b/tests/arch/fabulous/fsm.ys @@ -11,9 +11,9 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module - +stat select -assert-count 6 t:LUTFF -select -assert-max 4 t:LUT2 -select -assert-max 2 t:LUT3 -select -assert-max 9 t:LUT4 +select -assert-max 5 t:LUT2 +select -assert-max 4 t:LUT3 +select -assert-max 8 t:LUT4 select -assert-none t:LUT2 t:LUT3 t:LUT4 t:LUTFF %% t:* %D diff --git a/tests/arch/fabulous/generate_mk.py b/tests/arch/fabulous/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/fabulous/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gatemate/generate_mk.py b/tests/arch/gatemate/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/gatemate/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gatemate/run-test.sh b/tests/arch/gatemate/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/gatemate/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/gowin/generate_mk.py b/tests/arch/gowin/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/gowin/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gowin/run-test.sh b/tests/arch/gowin/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/gowin/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/ice40/generate_mk.py b/tests/arch/ice40/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/ice40/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/ice40/run-test.sh b/tests/arch/ice40/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/ice40/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/intel_alm/generate_mk.py b/tests/arch/intel_alm/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/intel_alm/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/intel_alm/run-test.sh b/tests/arch/intel_alm/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/intel_alm/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/machxo2/generate_mk.py b/tests/arch/machxo2/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/machxo2/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/machxo2/run-test.sh b/tests/arch/machxo2/run-test.sh deleted file mode 100644 index 691b70966..000000000 --- a/tests/arch/machxo2/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/microchip/generate_mk.py b/tests/arch/microchip/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/microchip/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/microchip/run-test.sh b/tests/arch/microchip/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/microchip/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/nanoxplore/generate_mk.py b/tests/arch/nanoxplore/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/nanoxplore/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/nanoxplore/run-test.sh b/tests/arch/nanoxplore/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/nanoxplore/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/nexus/generate_mk.py b/tests/arch/nexus/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/nexus/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/nexus/run-test.sh b/tests/arch/nexus/run-test.sh deleted file mode 100644 index 691b70966..000000000 --- a/tests/arch/nexus/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/quicklogic/pp3/generate_mk.py b/tests/arch/quicklogic/pp3/generate_mk.py new file mode 100644 index 000000000..e001d7e4a --- /dev/null +++ b/tests/arch/quicklogic/pp3/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/quicklogic/pp3/run-test.sh b/tests/arch/quicklogic/pp3/run-test.sh deleted file mode 100755 index 43a7874b2..000000000 --- a/tests/arch/quicklogic/pp3/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py b/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py new file mode 100644 index 000000000..e9abad21a --- /dev/null +++ b/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../../..") + +import gen_tests_makefile +import mem_gen + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/quicklogic/qlf_k6n10f/run-test.sh b/tests/arch/quicklogic/qlf_k6n10f/run-test.sh deleted file mode 100755 index c7daba12d..000000000 --- a/tests/arch/quicklogic/qlf_k6n10f/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -python3 mem_gen.py -source ../../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/arch/xilinx/generate_mk.py b/tests/arch/xilinx/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/xilinx/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", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/xilinx/run-test.sh b/tests/arch/xilinx/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/xilinx/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/bugpoint/generate_mk.py b/tests/bugpoint/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/bugpoint/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/bugpoint/run-test.sh b/tests/bugpoint/run-test.sh deleted file mode 100755 index 006c731e3..000000000 --- a/tests/bugpoint/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts diff --git a/tests/gen-tests-makefile.sh b/tests/gen-tests-makefile.sh deleted file mode 100755 index 07d70c2a8..000000000 --- a/tests/gen-tests-makefile.sh +++ /dev/null @@ -1,110 +0,0 @@ -set -eu - -YOSYS_BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../ >/dev/null 2>&1 && pwd)" - -# $ generate_target target_name test_command -generate_target() { - target_name=$(basename $PWD)-$1 - test_command=$2 - echo "all: $target_name" - echo ".PHONY: $target_name" - echo "$target_name:" - printf "\t@YOSYS_MAX_THREADS=4 %s\n" "$test_command" - printf "\t@echo 'Passed %s'\n" "$target_name" -} - -# $ generate_ys_test ys_file [yosys_args] -generate_ys_test() { - ys_file=$1 - yosys_args_=${2:-} - generate_target "$ys_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${ys_file}.err $yosys_args_ $ys_file >/dev/null 2>&1 && mv ${ys_file}.err ${ys_file}.log" -} - -# $ generate_tcl_test tcl_file [yosys_args] -generate_tcl_test() { - tcl_file=$1 - yosys_args_=${2:-} - generate_target "$tcl_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${tcl_file}.err $yosys_args_ $tcl_file >/dev/null 2>&1 && mv ${tcl_file}.err ${tcl_file}.log" -} - -# $ generate_bash_test bash_file -generate_bash_test() { - bash_file=$1 - generate_target "$bash_file" "bash -v $bash_file >${bash_file}.err 2>&1 && mv ${bash_file}.err ${bash_file}.log" -} - -# $ generate_tests [-y|--yosys-scripts] [-s|--prove-sv] [-b|--bash] [-a|--yosys-args yosys_args] -generate_tests() { - do_ys=false - do_tcl=false - do_sv=false - do_sh=false - yosys_args="" - - while [[ $# -gt 0 ]]; do - arg="$1" - case "$arg" in - -y|--yosys-scripts) - do_ys=true - shift - ;; - -t|--tcl-scripts) - do_tcl=true - shift - ;; - -s|--prove-sv) - do_sv=true - shift - ;; - -b|--bash) - do_sh=true - shift - ;; - -a|--yosys-args) - yosys_args+="$2" - shift - shift - ;; - *) - echo >&2 "Unknown argument: $1" - exit 1 - esac - done - - if [[ ! ( $do_ys = true || $do_tcl = true || $do_sv = true || $do_sh = true ) ]]; then - echo >&2 "Error: No file types selected" - exit 1 - fi - - echo ".PHONY: all" - echo "all:" - - if [[ $do_ys = true ]]; then - for x in *.ys; do - generate_ys_test "$x" "$yosys_args" - done - fi; - if [[ $do_tcl = true ]]; then - for x in *.tcl; do - generate_tcl_test "$x" "$yosys_args" - done - fi; - if [[ $do_sv = true ]]; then - for x in *.sv; do - if [ ! -f "${x%.sv}.ys" ]; then - generate_ys_test "$x" "-p \"prep -top top; async2sync; sat -enable_undef -verify -prove-asserts\" $yosys_args" - fi; - done - fi; - if [[ $do_sh == true ]]; then - for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - generate_bash_test "$s" - fi - done - fi -} - -generate_mk() { - generate_tests "$@" > run-test.mk -} diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py new file mode 100644 index 000000000..dbd7a2bc9 --- /dev/null +++ b/tests/gen_tests_makefile.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 + +import glob +import os +import sys +import argparse + +yosys_basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + +def _cwd_base(): + return os.path.basename(os.getcwd()) + +def generate_target(name, command): + target = f"{_cwd_base()}-{name}" + print(f"all: {target}") + print(f".PHONY: {target}") + print(f"{target}:") + print(f"\t@YOSYS_MAX_THREADS=4 {command}") + print(f"\t@echo 'Passed {target}'") + +def generate_ys_test(ys_file, yosys_args=""): + cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' + generate_target(ys_file, cmd) + +def generate_tcl_test(tcl_file, yosys_args=""): + cmd = f'$(YOSYS) -ql {tcl_file}.err {yosys_args} {tcl_file} >/dev/null 2>&1 && mv {tcl_file}.err {tcl_file}.log' + generate_target(tcl_file, cmd) + +def generate_sv_test(sv_file, yosys_args=""): + base = os.path.splitext(sv_file)[0] + if not os.path.exists(base + ".ys"): + yosys_cmd = '-p "prep -top top; async2sync; sat -enable_undef -verify -prove-asserts"' + cmd = f'$(YOSYS) -ql {sv_file}.err {yosys_cmd} {yosys_args} {sv_file} >/dev/null 2>&1 && mv {sv_file}.err {sv_file}.log' + generate_target(sv_file, cmd) + +def generate_bash_test(sh_file): + cmd = f"bash -v {sh_file} >{sh_file}.err 2>&1 && mv {sh_file}.err {sh_file}.log" + generate_target(sh_file, cmd) + +def generate_tests(argv): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("-y", "--yosys-scripts", action="store_true") + parser.add_argument("-t", "--tcl-scripts", action="store_true") + parser.add_argument("-s", "--prove-sv", action="store_true") + parser.add_argument("-b", "--bash", action="store_true") + parser.add_argument("-a", "--yosys-args", default="") + + args = parser.parse_args(argv) + + if not (args.yosys_scripts or args.tcl_scripts or args.prove_sv or args.bash): + raise RuntimeError("No file types selected") + + print(f"YOSYS ?= {yosys_basedir}/yosys") + print() + + print(".PHONY: all") + print("all:") + + if args.yosys_scripts: + for f in sorted(glob.glob("*.ys")): + generate_ys_test(f, args.yosys_args) + + if args.tcl_scripts: + for f in sorted(glob.glob("*.tcl")): + generate_tcl_test(f, args.yosys_args) + + if args.prove_sv: + for f in sorted(glob.glob("*.sv")): + generate_sv_test(f, args.yosys_args) + + if args.bash: + for f in sorted(glob.glob("*.sh")): + if f != "run-test.sh": + generate_bash_test(f) + +def generate(argv, extra=None): + with open("Makefile", "w") as f: + old = sys.stdout + sys.stdout = f + try: + if extra: + for line in extra: + print(line) + generate_tests(argv) + finally: + sys.stdout = old diff --git a/tests/opt/generate_mk.py b/tests/opt/generate_mk.py new file mode 100644 index 000000000..4c31c5a2b --- /dev/null +++ b/tests/opt/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", "--tcl-scripts"]) diff --git a/tests/opt/run-test.sh b/tests/opt/run-test.sh deleted file mode 100755 index 1d1d9b7a6..000000000 --- a/tests/opt/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --tcl-scripts diff --git a/tests/rtlil/generate_mk.py b/tests/rtlil/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/rtlil/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", "--bash"]) diff --git a/tests/rtlil/run-test.sh b/tests/rtlil/run-test.sh deleted file mode 100755 index 83cdf8aeb..000000000 --- a/tests/rtlil/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --bash --yosys-scripts diff --git a/tests/sat/generate_mk.py b/tests/sat/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/sat/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/sat/run-test.sh b/tests/sat/run-test.sh deleted file mode 100755 index 006c731e3..000000000 --- a/tests/sat/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts diff --git a/tests/sdc/generate_mk.py b/tests/sdc/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/sdc/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", "--bash"]) diff --git a/tests/sdc/run-test.sh b/tests/sdc/run-test.sh deleted file mode 100755 index 971664bdb..000000000 --- a/tests/sdc/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash \ No newline at end of file diff --git a/tests/sim/generate_mk.py b/tests/sim/generate_mk.py new file mode 100644 index 000000000..57138762d --- /dev/null +++ b/tests/sim/generate_mk.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +import subprocess +from pathlib import Path + +print("Generate FST for sim models") + +for name in Path("tb").rglob("tb*.v"): + test_name = name.stem + print(f"Test {test_name}") + + verilog_name = f"{test_name[3:]}.v" + + out_file = Path("tb") / f"{test_name}.out" + + subprocess.run( + ["iverilog", "-o", str(out_file), str(name), verilog_name], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True + ) + + subprocess.run( + [str(out_file), "-fst"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True + ) + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh deleted file mode 100755 index cff85eb65..000000000 --- a/tests/sim/run-test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -echo "Generate FST for sim models" -find tb/* -name tb*.v | while read name; do - test_name=$(basename $name .v) - echo "Test $test_name" - verilog_name=${test_name:3}.v - iverilog -o tb/$test_name.out $name $verilog_name >/dev/null 2>&1 - ./tb/$test_name.out -fst >/dev/null 2>&1 -done -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/svtypes/generate_mk.py b/tests/svtypes/generate_mk.py new file mode 100644 index 000000000..618163cca --- /dev/null +++ b/tests/svtypes/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", "--prove-sv"]) diff --git a/tests/svtypes/run-test.sh b/tests/svtypes/run-test.sh deleted file mode 100755 index 8b0333f27..000000000 --- a/tests/svtypes/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --prove-sv diff --git a/tests/techmap/generate_mk.py b/tests/techmap/generate_mk.py new file mode 100644 index 000000000..c8a4fe054 --- /dev/null +++ b/tests/techmap/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", "--tcl-scripts", "--bash", "--yosys-args", "-e 'select out of bounds'"]) diff --git a/tests/techmap/run-test.sh b/tests/techmap/run-test.sh deleted file mode 100755 index 0766db999..000000000 --- a/tests/techmap/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --tcl-scripts --bash --yosys-args "-e 'select out of bounds'" diff --git a/tests/various/generate_mk.py b/tests/various/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/various/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", "--bash"]) diff --git a/tests/various/run-test.sh b/tests/various/run-test.sh deleted file mode 100755 index dee032827..000000000 --- a/tests/various/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/verific/generate_mk.py b/tests/verific/generate_mk.py new file mode 100644 index 000000000..c8c8c53c3 --- /dev/null +++ b/tests/verific/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", "--bash"],["export ASAN_OPTIONS=halt_on_error=0"]) diff --git a/tests/verific/run-test.sh b/tests/verific/run-test.sh deleted file mode 100755 index 1666ee1f9..000000000 --- a/tests/verific/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash -{ echo 'export ASAN_OPTIONS=halt_on_error=0'; cat run-test.mk; } > run-test.mk.tmp && mv run-test.mk.tmp run-test.mk diff --git a/tests/verilog/generate_mk.py b/tests/verilog/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/verilog/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", "--bash"]) diff --git a/tests/verilog/run-test.sh b/tests/verilog/run-test.sh deleted file mode 100755 index dee032827..000000000 --- a/tests/verilog/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash From f9cd49f7b9e2900b3b64612536cd209c5101a20e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 09:51:15 +0100 Subject: [PATCH 13/36] Save results, and create summary and report --- tests/.gitignore | 1 + tests/Makefile | 76 +++++++++++++++++++++++-------------- tests/gen_tests_makefile.py | 17 +++++++-- 3 files changed, 63 insertions(+), 31 deletions(-) diff --git a/tests/.gitignore b/tests/.gitignore index da4350076..8fa73e3d6 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,3 +3,4 @@ *.err run-test.mk **/Makefile +*.result diff --git a/tests/Makefile b/tests/Makefile index 5ec699417..237cf6ec0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -34,37 +34,37 @@ MK_TEST_DIRS += ./verilog # Tests that don't generate .mk SH_TEST_DIRS = -SH_TEST_DIRS += ./simple -SH_TEST_DIRS += ./simple_abc9 -SH_TEST_DIRS += ./hana -SH_TEST_DIRS += ./asicworld -SH_TEST_DIRS += ./realmath -SH_TEST_DIRS += ./share -SH_TEST_DIRS += ./opt_share -SH_TEST_DIRS += ./fsm -SH_TEST_DIRS += ./memlib -SH_TEST_DIRS += ./bram -SH_TEST_DIRS += ./svinterfaces -SH_TEST_DIRS += ./xprop -SH_TEST_DIRS += ./select -SH_TEST_DIRS += ./peepopt -SH_TEST_DIRS += ./proc -SH_TEST_DIRS += ./blif -SH_TEST_DIRS += ./arch -SH_TEST_DIRS += ./rpc -SH_TEST_DIRS += ./memfile -SH_TEST_DIRS += ./fmt -SH_TEST_DIRS += ./cxxrtl -SH_TEST_DIRS += ./liberty -ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) -SH_TEST_DIRS += ./functional -endif +#SH_TEST_DIRS += ./simple +#SH_TEST_DIRS += ./simple_abc9 +#SH_TEST_DIRS += ./hana +#SH_TEST_DIRS += ./asicworld +#SH_TEST_DIRS += ./realmath +#SH_TEST_DIRS += ./share +#SH_TEST_DIRS += ./opt_share +#SH_TEST_DIRS += ./fsm +#SH_TEST_DIRS += ./memlib +#SH_TEST_DIRS += ./bram +#SH_TEST_DIRS += ./svinterfaces +#SH_TEST_DIRS += ./xprop +#SH_TEST_DIRS += ./select +#SH_TEST_DIRS += ./peepopt +#SH_TEST_DIRS += ./proc +#SH_TEST_DIRS += ./blif +#SH_TEST_DIRS += ./arch +#SH_TEST_DIRS += ./rpc +#SH_TEST_DIRS += ./memfile +#SH_TEST_DIRS += ./fmt +#SH_TEST_DIRS += ./cxxrtl +#SH_TEST_DIRS += ./liberty +#ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +#SH_TEST_DIRS += ./functional +#endif # Tests that don't generate .mk and need special args SH_ABC_TEST_DIRS = -SH_ABC_TEST_DIRS += ./memories -SH_ABC_TEST_DIRS += ./aiger -SH_ABC_TEST_DIRS += ./alumacc +#SH_ABC_TEST_DIRS += ./memories +#SH_ABC_TEST_DIRS += ./aiger +#SH_ABC_TEST_DIRS += ./alumacc all: vanilla-test @@ -104,6 +104,15 @@ ifeq ($(YOSYS_NOVERIFIC),1) endif endif @echo "" + @pass=$$(grep -h PASS **/*.result 2>/dev/null | wc -l); \ + fail=$$(grep -h FAIL **/*.result 2>/dev/null | wc -l); \ + total=$$((pass + fail)); \ + echo "=========================="; \ + echo "Tests: $$total"; \ + echo "Passed: $$pass"; \ + echo "Failed: $$fail"; \ + echo "=========================="; \ + test $$fail -eq 0 clean: @rm -rf ./asicworld/*.out ./asicworld/*.log @@ -115,3 +124,14 @@ clean: @rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff @rm -f ./tools/cmp_tbdata @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + @find . -name '*.result' -type f -exec rm -f {} + + @find . -mindepth 2 \( -path './sva*' -o -path './unit*' \) -prune -o -name 'Makefile' -type f -exec rm -f {} + + +.PHONY: report +report: + @echo "==========================" + @echo "Failing tests:" + @find . -name '*.result' -type f -exec grep -H '^FAIL$$' {} + \ + | cut -d: -f1 \ + | sed 's|^\./||; s|\.result$$||' + @echo "==========================" diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index dbd7a2bc9..dea815174 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -15,8 +15,8 @@ def generate_target(name, command): print(f"all: {target}") print(f".PHONY: {target}") print(f"{target}:") - print(f"\t@YOSYS_MAX_THREADS=4 {command}") - print(f"\t@echo 'Passed {target}'") + print(f"\t@@$(call run_test,{target}, \\") + print(f"\tYOSYS_MAX_THREADS=4 {command})") def generate_ys_test(ys_file, yosys_args=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' @@ -52,7 +52,18 @@ def generate_tests(argv): print(f"YOSYS ?= {yosys_basedir}/yosys") print() - + print("define run_test") + print(" rc=0; \\") + print(" $(2) || rc=$$?; \\") + print(" if [ $$rc -eq 0 ]; then \\") + print(" echo \"PASS $1\"; \\") + print(" echo PASS > $1.result; \\") + print(" else \\") + print(" echo \"FAIL $1\"; \\") + print(" echo FAIL > $1.result; \\") + print(" fi") + print("endef") + print() print(".PHONY: all") print("all:") From 903c74e42b237b973c0971b064a7ff3a0e91433e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 10:10:34 +0100 Subject: [PATCH 14/36] Look for all result files --- tests/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 237cf6ec0..55276e730 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -104,8 +104,12 @@ ifeq ($(YOSYS_NOVERIFIC),1) endif endif @echo "" - @pass=$$(grep -h PASS **/*.result 2>/dev/null | wc -l); \ - fail=$$(grep -h FAIL **/*.result 2>/dev/null | wc -l); \ + -@$(MAKE) summary + +.PHONY: summary +summary: + @pass=$$(find . -type f -name '*.result' -exec grep '^PASS$$' {} + | wc -l); \ + fail=$$(find . -type f -name '*.result' -exec grep '^FAIL$$' {} + | wc -l); \ total=$$((pass + fail)); \ echo "=========================="; \ echo "Tests: $$total"; \ From 144da16583ccab366a960859c6862562bc1391e2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 10:15:17 +0100 Subject: [PATCH 15/36] report on summary --- tests/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index 55276e730..5b32bc51d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -104,7 +104,7 @@ ifeq ($(YOSYS_NOVERIFIC),1) endif endif @echo "" - -@$(MAKE) summary + -@$(MAKE) --no-print-directory summary .PHONY: summary summary: @@ -116,6 +116,10 @@ summary: echo "Passed: $$pass"; \ echo "Failed: $$fail"; \ echo "=========================="; \ + if [ $$fail -ne 0 ]; then \ + echo; \ + $(MAKE) --no-print-directory report; \ + fi; \ test $$fail -eq 0 clean: From 413b9a4639be842f3b7fa871d172cd66ed6039d5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 11:00:08 +0100 Subject: [PATCH 16/36] Add common.mk --- tests/Makefile | 32 ++++++--------------------- tests/common.mk | 43 +++++++++++++++++++++++++++++++++++++ tests/gen_tests_makefile.py | 16 +++----------- 3 files changed, 53 insertions(+), 38 deletions(-) create mode 100644 tests/common.mk diff --git a/tests/Makefile b/tests/Makefile index 5b32bc51d..d22e0bf50 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,3 +1,10 @@ +ifneq ($(wildcard ../Makefile.conf),) +include ../Makefile.conf +endif + +OVERRIDE_MAIN=1 +include ./common.mk + # Tests that generate Makefile with gen_tests_makefile.py MK_TEST_DIRS = MK_TEST_DIRS += ./arch/analogdevices @@ -106,22 +113,6 @@ endif @echo "" -@$(MAKE) --no-print-directory summary -.PHONY: summary -summary: - @pass=$$(find . -type f -name '*.result' -exec grep '^PASS$$' {} + | wc -l); \ - fail=$$(find . -type f -name '*.result' -exec grep '^FAIL$$' {} + | wc -l); \ - total=$$((pass + fail)); \ - echo "=========================="; \ - echo "Tests: $$total"; \ - echo "Passed: $$pass"; \ - echo "Failed: $$fail"; \ - echo "=========================="; \ - if [ $$fail -ne 0 ]; then \ - echo; \ - $(MAKE) --no-print-directory report; \ - fi; \ - test $$fail -eq 0 - clean: @rm -rf ./asicworld/*.out ./asicworld/*.log @rm -rf ./hana/*.out ./hana/*.log @@ -134,12 +125,3 @@ clean: @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) @find . -name '*.result' -type f -exec rm -f {} + @find . -mindepth 2 \( -path './sva*' -o -path './unit*' \) -prune -o -name 'Makefile' -type f -exec rm -f {} + - -.PHONY: report -report: - @echo "==========================" - @echo "Failing tests:" - @find . -name '*.result' -type f -exec grep -H '^FAIL$$' {} + \ - | cut -d: -f1 \ - | sed 's|^\./||; s|\.result$$||' - @echo "==========================" diff --git a/tests/common.mk b/tests/common.mk new file mode 100644 index 000000000..ee4c5dee7 --- /dev/null +++ b/tests/common.mk @@ -0,0 +1,43 @@ +all: + +ifndef OVERRIDE_MAIN +clean: + @rm -f *.log *.result +endif + +define run_test + rc=0; \ + $(2) || rc=$$?; \ + if [ $$rc -eq 0 ]; then \ + echo "PASS $1"; \ + echo PASS > $1.result; \ + else \ + echo "FAIL $1"; \ + echo FAIL > $1.result; \ + fi +endef + +.PHONY: summary +summary: + @pass=$$(find . -type f -name '*.result' -exec grep '^PASS$$' {} + | wc -l); \ + fail=$$(find . -type f -name '*.result' -exec grep '^FAIL$$' {} + | wc -l); \ + total=$$((pass + fail)); \ + echo "=========================="; \ + echo "Tests: $$total"; \ + echo "Passed: $$pass"; \ + echo "Failed: $$fail"; \ + echo "=========================="; \ + if [ $$fail -ne 0 ]; then \ + echo; \ + $(MAKE) --no-print-directory report; \ + fi; \ + test $$fail -eq 0 + +.PHONY: report +report: + @echo "==========================" + @echo "Failing tests:" + @find . -name '*.result' -type f -exec grep -H '^FAIL$$' {} + \ + | cut -d: -f1 \ + | sed 's|^\./||; s|\.result$$||' + @echo "==========================" diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index dea815174..b61e4917d 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -5,7 +5,8 @@ import os import sys import argparse -yosys_basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +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")) def _cwd_base(): return os.path.basename(os.getcwd()) @@ -50,20 +51,9 @@ def generate_tests(argv): if not (args.yosys_scripts or args.tcl_scripts or args.prove_sv or args.bash): raise RuntimeError("No file types selected") + print(f"include {common_mk}") print(f"YOSYS ?= {yosys_basedir}/yosys") print() - print("define run_test") - print(" rc=0; \\") - print(" $(2) || rc=$$?; \\") - print(" if [ $$rc -eq 0 ]; then \\") - print(" echo \"PASS $1\"; \\") - print(" echo PASS > $1.result; \\") - print(" else \\") - print(" echo \"FAIL $1\"; \\") - print(" echo FAIL > $1.result; \\") - print(" fi") - print("endef") - print() print(".PHONY: all") print("all:") From f2e1ac23a27cbf17aa17969ae463064c489bcb89 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 11:15:21 +0100 Subject: [PATCH 17/36] add prep --- tests/Makefile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index d22e0bf50..152b9b1dd 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -94,8 +94,13 @@ abcopt-./%: %/run-test.sh .PHONY: makefile-tests .SILENT: $(MK_TEST_DIRS:%=%/Makefile) makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) +prep: $(MK_TEST_DIRS:%=%/Makefile) + @echo "All Makefiles generated." # this target actually emits Makefile files -%/Makefile: +.PHONY: force-create +force-create: + +%/Makefile: force-create +@cd $* && python3 generate_mk.py makefile-./%: %/Makefile @@ -122,6 +127,5 @@ clean: @rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp @rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff @rm -f ./tools/cmp_tbdata - @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + @rm -f $(addsuffix /Makefile,$(MK_TEST_DIRS)) @find . -name '*.result' -type f -exec rm -f {} + - @find . -mindepth 2 \( -path './sva*' -o -path './unit*' \) -prune -o -name 'Makefile' -type f -exec rm -f {} + From 80fff7ce0984086cad0a888e7d6069ecc2caab59 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 11:18:03 +0100 Subject: [PATCH 18/36] cleanup --- tests/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 152b9b1dd..1974462c2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -96,10 +96,9 @@ abcopt-./%: %/run-test.sh makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) prep: $(MK_TEST_DIRS:%=%/Makefile) @echo "All Makefiles generated." -# this target actually emits Makefile files -.PHONY: force-create -force-create: +.PHONY: force-create +# this target actually emits Makefile files %/Makefile: force-create +@cd $* && python3 generate_mk.py From af3a53720c63d04436f662c47ba30b9e669319aa Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 10:13:10 +0100 Subject: [PATCH 19/36] Use generic testing on few more places --- tests/Makefile | 5 ++- tests/aiger/generate_mk.py | 88 ++++++++++++++++--------------------- tests/aiger/run-test.sh | 70 ----------------------------- tests/alumacc/run-test.sh | 7 --- tests/bind/generate_mk.py | 8 ++++ tests/bind/run-test.sh | 20 --------- tests/gen_tests_makefile.py | 34 +++++++++++++- 7 files changed, 82 insertions(+), 150 deletions(-) delete mode 100755 tests/aiger/run-test.sh delete mode 100644 tests/alumacc/run-test.sh create mode 100644 tests/bind/generate_mk.py delete mode 100755 tests/bind/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 1974462c2..117399cd2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -23,6 +23,7 @@ MK_TEST_DIRS += ./arch/nexus MK_TEST_DIRS += ./arch/quicklogic/pp3 MK_TEST_DIRS += ./arch/quicklogic/qlf_k6n10f MK_TEST_DIRS += ./arch/xilinx +MK_TEST_DIRS += ./bind MK_TEST_DIRS += ./bugpoint MK_TEST_DIRS += ./opt MK_TEST_DIRS += ./sat @@ -70,8 +71,8 @@ SH_TEST_DIRS = # Tests that don't generate .mk and need special args SH_ABC_TEST_DIRS = #SH_ABC_TEST_DIRS += ./memories -#SH_ABC_TEST_DIRS += ./aiger -#SH_ABC_TEST_DIRS += ./alumacc +MK_TEST_DIRS += ./aiger +MK_TEST_DIRS += ./alumacc all: vanilla-test diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py index e0a15332e..00be5b5f9 100644 --- a/tests/aiger/generate_mk.py +++ b/tests/aiger/generate_mk.py @@ -1,18 +1,13 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import glob import os -yosys = "../../yosys" -default_abc = "../../yosys-abc" - -aags = sorted(glob.glob("*.aag")) -yss = sorted(glob.glob("*.ys")) - -print("ABC ?= " + default_abc) -print("YOSYS ?= " + yosys) -print() - def base(fn): return os.path.splitext(fn)[0] @@ -23,46 +18,41 @@ def base(fn): # Since ABC cannot read *.aag, read the *.aig instead # (which would have been created by the reference aig2aig utility, # available from http://fmv.jku.at/aiger/) +def create_tests(): + aags = sorted(glob.glob("*.aag")) + yss = sorted(glob.glob("*.ys")) + for aag in aags: + b = base(aag) -for aag in aags: - b = base(aag) + cmd = [ + f"$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\" >/dev/null 2>&1;", + "$(YOSYS) -qp \"", + f"read_verilog {b}_ref.v;", + "prep;", + "design -stash gold;", + f"read_aiger -clk_name clock {aag};", + "prep;", + "design -stash gate;", + "design -import gold -as gold;", + "design -import gate -as gate;", + "miter -equiv -flatten -make_assert -make_outputs gold gate miter;", + "sat -verify -prove-asserts -show-ports -seq 16 miter;", + f"\" -l {aag}.log >/dev/null 2>&1" + ] - print(f"all: {aag}") - print(f".PHONY: {aag}") - print(f"{aag}:") - print(f"\t@echo Checking {aag}.") - print(f"\t@$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\" >/dev/null 2>&1") - print("\t@$(YOSYS) -qp \"\\") - print(f"\tread_verilog {b}_ref.v; \\") - print("\tprep; \\") - print("\tdesign -stash gold; \\") - print(f"\tread_aiger -clk_name clock {aag}; \\") - print("\tprep; \\") - print("\tdesign -stash gate; \\") - print("\tdesign -import gold -as gold; \\") - print("\tdesign -import gate -as gate; \\") - print("\tmiter -equiv -flatten -make_assert -make_outputs gold gate miter; \\") - print("\tsat -verify -prove-asserts -show-ports -seq 16 miter; \\") - print(f"\t\" -l {aag}.log >/dev/null 2>&1") - print() + gen_tests_makefile.generate_cmd_test(aag, cmd) -# ---- Yosys script tests ---- -for ys in yss: - b = base(ys) - print(f"all: {ys}") - print(f".PHONY: {ys}") - print(f"{ys}: ") - print(f"\t@echo Running {ys}.") - print(f"\t@$(YOSYS) -ql {b}.log {ys} >/dev/null 2>&1") - print() + # ---- Yosys script tests ---- + for ys in yss: + gen_tests_makefile.generate_ys_test(ys) -# ---- aigmap test ---- -print(f"all: aigmap") -print(f".PHONY: aigmap") -print("aigmap:") -print("\t@echo Running aigmap.") -print("\t@rm -rf gate; mkdir gate") -print('\t@$(YOSYS) --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1') -print("\t@set -o pipefail; diff --brief gold gate | tee aigmap.err") -print("\t@rm -f aigmap.err") -print() + cmd = [ "rm -rf gate; mkdir gate;", + "$(YOSYS) --no-version -p \"test_cell -aigmap -w gate/ -n 1 -s 1 all\" >/dev/null 2>&1;", + "set -o pipefail; diff --brief gold gate | tee aigmap.err;", + "rm -f aigmap.err" ] + + gen_tests_makefile.generate_cmd_test("aigmap", cmd) + +extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc" ] + +gen_tests_makefile.generate_custom(create_tests, extra) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh deleted file mode 100755 index 5208fa030..000000000 --- a/tests/aiger/run-test.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -OPTIND=1 -abcprog="../../yosys-abc" # default to built-in version of abc -while getopts "A:" opt -do - case "$opt" in - A) abcprog="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -# NB: *.aag and *.aig must contain a symbol table naming the primary -# inputs and outputs, otherwise ABC and Yosys will name them -# arbitrarily (and inconsistently with each other). - -for aag in *.aag; do - # Since ABC cannot read *.aag, read the *.aig instead - # (which would have been created by the reference aig2aig utility, - # available from http://fmv.jku.at/aiger/) - echo "Checking $aag." - $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" >/dev/null 2>&1 - ../../yosys -qp " -read_verilog ${aag%.*}_ref.v -prep -design -stash gold -read_aiger -clk_name clock $aag -prep -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aag}.log >/dev/null 2>&1 -done - -for aig in *.aig; do - echo "Checking $aig." - $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" >/dev/null 2>&1 - ../../yosys -qp " -read_verilog ${aig%.*}_ref.v -prep -design -stash gold -read_aiger -clk_name clock $aig -prep -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aig}.log >/dev/null 2>&1 -done - -for y in *.ys; do - echo "Running $y." - ../../yosys -ql ${y%.*}.log $y >/dev/null 2>&1 -done - -# compare aigmap with reference -# make gold with: rm gold/*; yosys --no-version -p "test_cell -aigmap -w gold/ -n 1 -s 1 all" -rm -rf gate; mkdir gate -../../yosys --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1 -( - set -o pipefail - diff --brief gold gate | tee aigmap.err -) -rm aigmap.err diff --git a/tests/alumacc/run-test.sh b/tests/alumacc/run-test.sh deleted file mode 100644 index 2e3f5235c..000000000 --- a/tests/alumacc/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/bind/generate_mk.py b/tests/bind/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/bind/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/bind/run-test.sh b/tests/bind/run-test.sh deleted file mode 100755 index ea56b70f0..000000000 --- a/tests/bind/run-test.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -set -e -{ -echo "all::" -for x in *.ys; do - echo "all:: run-$x" - echo "run-$x:" - echo " @echo 'Running $x..'" - echo " @../../yosys -ql ${x%.ys}.log $x" -done -for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - echo "all:: run-$s" - echo "run-$s:" - echo " @echo 'Running $s..'" - echo " @bash $s" - fi -done -} > run-test.mk -exec ${MAKE:-make} -f run-test.mk diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index b61e4917d..747603737 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -12,11 +12,12 @@ def _cwd_base(): return os.path.basename(os.getcwd()) def generate_target(name, command): - target = f"{_cwd_base()}-{name}" + #target = f"{_cwd_base()}-{name}" + target = f"{name}" print(f"all: {target}") print(f".PHONY: {target}") print(f"{target}:") - print(f"\t@@$(call run_test,{target}, \\") + print(f"\t@$(call run_test,{target}, \\") print(f"\tYOSYS_MAX_THREADS=4 {command})") def generate_ys_test(ys_file, yosys_args=""): @@ -38,6 +39,16 @@ def generate_bash_test(sh_file): cmd = f"bash -v {sh_file} >{sh_file}.err 2>&1 && mv {sh_file}.err {sh_file}.log" generate_target(sh_file, cmd) +def unpack_cmd(cmd): + if isinstance(cmd, str): + return cmd + if isinstance(cmd, (list, tuple)): + return " \\\n".join(cmd) + raise TypeError("cmd must be a string or a list/tuple of strings") + +def generate_cmd_test(test_name, cmd, yosys_args=""): + generate_target(test_name, unpack_cmd(cmd)) + def generate_tests(argv): parser = argparse.ArgumentParser(add_help=False) parser.add_argument("-y", "--yosys-scripts", action="store_true") @@ -85,3 +96,22 @@ def generate(argv, extra=None): generate_tests(argv) finally: sys.stdout = old + +def generate_custom(callback, extra=None): + with open("Makefile", "w") as f: + old = sys.stdout + sys.stdout = f + try: + print(f"include {common_mk}") + print(f"YOSYS ?= {yosys_basedir}/yosys") + if extra: + for line in extra: + print(line) + print() + print(".PHONY: all") + print("all:") + print() + + callback() + finally: + sys.stdout = old From 896fac04ed8e2d0a825374eddfab2a578c460ba9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 10:48:10 +0100 Subject: [PATCH 20/36] cleanup --- tests/gen_tests_makefile.py | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 747603737..0f106a7db 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -18,7 +18,7 @@ def generate_target(name, command): print(f".PHONY: {target}") print(f"{target}:") print(f"\t@$(call run_test,{target}, \\") - print(f"\tYOSYS_MAX_THREADS=4 {command})") + print(f"\t{command})") def generate_ys_test(ys_file, yosys_args=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' @@ -62,12 +62,6 @@ def generate_tests(argv): if not (args.yosys_scripts or args.tcl_scripts or args.prove_sv or args.bash): raise RuntimeError("No file types selected") - print(f"include {common_mk}") - print(f"YOSYS ?= {yosys_basedir}/yosys") - print() - print(".PHONY: all") - print("all:") - if args.yosys_scripts: for f in sorted(glob.glob("*.ys")): generate_ys_test(f, args.yosys_args) @@ -85,14 +79,24 @@ def generate_tests(argv): if f != "run-test.sh": generate_bash_test(f) +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) + print() + print(".PHONY: all") + print("all:") + def generate(argv, extra=None): with open("Makefile", "w") as f: old = sys.stdout sys.stdout = f try: - if extra: - for line in extra: - print(line) + print_header(extra) generate_tests(argv) finally: sys.stdout = old @@ -102,16 +106,7 @@ def generate_custom(callback, extra=None): old = sys.stdout sys.stdout = f try: - print(f"include {common_mk}") - print(f"YOSYS ?= {yosys_basedir}/yosys") - if extra: - for line in extra: - print(line) - print() - print(".PHONY: all") - print("all:") - print() - + print_header(extra) callback() finally: sys.stdout = old From 488f14424525ca877223299db9627aaaeea6a3e9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 13:07:11 +0100 Subject: [PATCH 21/36] Convert autotest script wrapper --- tests/Makefile | 8 ++--- tests/asicworld/generate_mk.py | 8 +++++ tests/asicworld/run-test.sh | 15 --------- tests/gen_tests_makefile.py | 20 ++++++++++++ tests/hana/generate_mk.py | 8 +++++ tests/hana/run-test.sh | 15 --------- tests/simple/generate_mk.py | 17 ++++++++++ tests/simple/run-test.sh | 21 ------------ tests/simple_abc9/generate_mk.py | 44 +++++++++++++++++++++++++ tests/simple_abc9/run-test.sh | 55 -------------------------------- 10 files changed, 101 insertions(+), 110 deletions(-) create mode 100644 tests/asicworld/generate_mk.py delete mode 100755 tests/asicworld/run-test.sh create mode 100644 tests/hana/generate_mk.py delete mode 100755 tests/hana/run-test.sh create mode 100644 tests/simple/generate_mk.py delete mode 100755 tests/simple/run-test.sh create mode 100644 tests/simple_abc9/generate_mk.py delete mode 100755 tests/simple_abc9/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 117399cd2..29f44e554 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -42,10 +42,10 @@ MK_TEST_DIRS += ./verilog # Tests that don't generate .mk SH_TEST_DIRS = -#SH_TEST_DIRS += ./simple -#SH_TEST_DIRS += ./simple_abc9 -#SH_TEST_DIRS += ./hana -#SH_TEST_DIRS += ./asicworld +MK_TEST_DIRS += ./simple +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 diff --git a/tests/asicworld/generate_mk.py b/tests/asicworld/generate_mk.py new file mode 100644 index 000000000..2f1df0646 --- /dev/null +++ b/tests/asicworld/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.v", "-e") diff --git a/tests/asicworld/run-test.sh b/tests/asicworld/run-test.sh deleted file mode 100755 index c9b4118a7..000000000 --- a/tests/asicworld/run-test.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed EXTRA_FLAGS+="-e" *.v diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 0f106a7db..a01653c19 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -110,3 +110,23 @@ def generate_custom(callback, extra=None): callback() finally: sys.stdout = old + +def generate_autotest_file(test_file): + cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1" + generate_target(test_file, cmd) + +def generate_autotest(pattern, extra_flags): + with open("Makefile", "w") as f: + old = sys.stdout + sys.stdout = f + try: + 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) + finally: + sys.stdout = old diff --git a/tests/hana/generate_mk.py b/tests/hana/generate_mk.py new file mode 100644 index 000000000..0068c590a --- /dev/null +++ b/tests/hana/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("test_*.v", "-l hana_vlib.v -n 300 -e") diff --git a/tests/hana/run-test.sh b/tests/hana/run-test.sh deleted file mode 100755 index 8533e5544..000000000 --- a/tests/hana/run-test.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed EXTRA_FLAGS="-l hana_vlib.v -n 300 -e" test_*.v diff --git a/tests/simple/generate_mk.py b/tests/simple/generate_mk.py new file mode 100644 index 000000000..f8e79bcaf --- /dev/null +++ b/tests/simple/generate_mk.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import shutil + +# ---------------------- +# Check if iverilog is installed +# ---------------------- +if shutil.which("iverilog") is None: + print("Error: Icarus Verilog 'iverilog' not found.", file=sys.stderr) + sys.exit(1) + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.*v", "") diff --git a/tests/simple/run-test.sh b/tests/simple/run-test.sh deleted file mode 100755 index c3711fe3e..000000000 --- a/tests/simple/run-test.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! command -v iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.{sv,v} diff --git a/tests/simple_abc9/generate_mk.py b/tests/simple_abc9/generate_mk.py new file mode 100644 index 000000000..44dd7e2b4 --- /dev/null +++ b/tests/simple_abc9/generate_mk.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import shutil +import os +from pathlib import Path + +# ---------------------- +# Check if iverilog is installed +# ---------------------- +if shutil.which("iverilog") is None: + print("Error: Icarus Verilog 'iverilog' not found.", file=sys.stderr) + sys.exit(1) + +src_dir = Path("../simple") +# ---------------------- +# Copy all files from ../simple to current directory +# ---------------------- +for file in src_dir.glob("*.v"): + shutil.copy(file, os.path.join(".", file.name)) + +for file in src_dir.glob("*.sv"): + shutil.copy(file, os.path.join(".", file.name)) + +# bug 2675 +bug_file = os.path.join(".", "specify.v") +if os.path.exists(bug_file): + os.remove(bug_file) + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.*v", "-f \"verilog -noblackbox -specify\" -n 300 -p '\ + read_verilog -icells -lib +/abc9_model.v; \ + hierarchy; \ + synth -run coarse; \ + opt -full; \ + techmap; \ + abc9 -lut 4; \ + clean; \ + check -assert * abc9_test037 %d; \ + select -assert-none t:?_NOT_ t:?_AND_ %%; \ + setattr -mod -unset blackbox -unset whitebox =*'") diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh deleted file mode 100755 index 0b3e5061f..000000000 --- a/tests/simple_abc9/run-test.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! command -v iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -for file in `ls *.v *.sv`; do - if [ ! -f "../simple/$file" -a "$file" != "abc9.v" ]; then - echo "Warning: $file is in simple_abc9/, but not in simple/" - backup="$file.bak" - if [ -f "$backup" ]; then - if cmp "$file" "$backup" > /dev/null; then - echo " => $backup already exists and matches; removing $file" - rm "$file" - else - echo " => $backup already exists but differs; leaving $file in place" - fi - else - echo " => moving $file to $backup" - mv -i "$file" "$backup" - fi - fi -done - -cp ../simple/*.v . -cp ../simple/*.sv . -rm specify.v # bug 2675 -DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-f \"verilog -noblackbox -specify\" -n 300 -p '\ - read_verilog -icells -lib +/abc9_model.v; \ - hierarchy; \ - synth -run coarse; \ - opt -full; \ - techmap; \ - abc9 -lut 4; \ - clean; \ - check -assert * abc9_test037 %d; \ - select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ - setattr -mod -unset blackbox -unset whitebox =*'" - -# NOTE: Skip 'check -assert' on abc9_test037 because it intentionally has a combinatorial loop From fa92d226601692c42243d68ebb03a04a1a63dfb8 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 15:45:59 +0100 Subject: [PATCH 22/36] Document not covered --- tests/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/Makefile b/tests/Makefile index 29f44e554..c5bae2a92 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -5,6 +5,16 @@ endif OVERRIDE_MAIN=1 include ./common.mk +# Directories with tests not run: +# errors +# lut +# pyosys +# smv +# sva +# tools +# unit +# vloghtb + # Tests that generate Makefile with gen_tests_makefile.py MK_TEST_DIRS = MK_TEST_DIRS += ./arch/analogdevices From 77147fb0dbed4b3f8332d731ef68db9f36acb5bb Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 08:46:34 +0100 Subject: [PATCH 23/36] Correctly handle errors --- tests/common.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/common.mk b/tests/common.mk index ee4c5dee7..9d45e3762 100644 --- a/tests/common.mk +++ b/tests/common.mk @@ -6,8 +6,9 @@ clean: endif define run_test + @set -e; \ rc=0; \ - $(2) || rc=$$?; \ + ( set -e; $(2) ) || rc=$$?; \ if [ $$rc -eq 0 ]; then \ echo "PASS $1"; \ echo PASS > $1.result; \ From 92bdccf2be2bb85d03a446660470b2355ff1343d Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 08:46:58 +0100 Subject: [PATCH 24/36] Convert memories tests --- tests/Makefile | 12 +----- tests/gen_tests_makefile.py | 10 ++--- tests/memories/generate_mk.py | 58 ++++++++++++++++++++++++++++ tests/memories/run-test.sh | 73 ----------------------------------- tests/tools/autotest.mk | 13 ------- 5 files changed, 65 insertions(+), 101 deletions(-) create mode 100644 tests/memories/generate_mk.py delete mode 100755 tests/memories/run-test.sh delete mode 100644 tests/tools/autotest.mk diff --git a/tests/Makefile b/tests/Makefile index c5bae2a92..864fa973d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -79,8 +79,7 @@ MK_TEST_DIRS += ./asicworld #endif # Tests that don't generate .mk and need special args -SH_ABC_TEST_DIRS = -#SH_ABC_TEST_DIRS += ./memories +MK_TEST_DIRS += ./memories MK_TEST_DIRS += ./aiger MK_TEST_DIRS += ./alumacc @@ -94,13 +93,6 @@ seed-./%: %/run-test.sh +cd $* && bash run-test.sh $(SEEDOPT) +@echo "...passed tests in $*" -# abcopt-./ is a dummy string, not a directory -.PHONY: abcopt-tests -abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) -abcopt-./%: %/run-test.sh - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) - +@echo "...passed tests in $*" - # makefile-./ is a dummy string, not a directory .PHONY: makefile-tests .SILENT: $(MK_TEST_DIRS:%=%/Makefile) @@ -117,7 +109,7 @@ makefile-./%: %/Makefile @$(MAKE) -C $* @echo "...passed tests in $*" -vanilla-test: makefile-tests abcopt-tests seed-tests +vanilla-test: makefile-tests seed-tests @echo "" @echo " Passed \"make vanilla-test\"." ifeq ($(ENABLE_VERIFIC),1) diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index a01653c19..d714820e5 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -111,11 +111,11 @@ def generate_custom(callback, extra=None): finally: sys.stdout = old -def generate_autotest_file(test_file): - cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1" +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}" generate_target(test_file, cmd) -def generate_autotest(pattern, extra_flags): +def generate_autotest(pattern, extra_flags, cmds=""): with open("Makefile", "w") as f: old = sys.stdout sys.stdout = f @@ -124,9 +124,9 @@ def generate_autotest(pattern, extra_flags): "SEED ?=", "ifneq ($(strip $(SEED)),)", " SEEDOPT=-S$(SEED)", - "endif" + "endif", ]) for f in sorted(glob.glob(pattern)): - generate_autotest_file(f) + generate_autotest_file(f, cmds) finally: sys.stdout = old diff --git a/tests/memories/generate_mk.py b/tests/memories/generate_mk.py new file mode 100644 index 000000000..0df27bc5e --- /dev/null +++ b/tests/memories/generate_mk.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +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; \\ +fi""") \ No newline at end of file diff --git a/tests/memories/run-test.sh b/tests/memories/run-test.sh deleted file mode 100755 index 8f83e11a1..000000000 --- a/tests/memories/run-test.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -OPTIND=1 -seed="" # default to no seed specified -abcopt="" -while getopts "A:S:" opt -do - case "$opt" in - A) abcopt="-A $OPTARG" ;; - S) seed="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -${MAKE:-make} -f ../tools/autotest.mk SEED="$seed" EXTRA_FLAGS="$abcopt" *.v - -for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do - echo -n "Testing expectations for $f .." - ../../yosys -f verilog -qp "proc; opt; memory -nomap;; dump -outfile ${f%.v}.dmp t:\$mem_v2" $f - if grep -q expect-wr-ports $f; then - grep -q "parameter \\\\WR_PORTS $(gawk '/expect-wr-ports/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected number of write ports."; false; } - fi - if grep -q expect-wr-wide-continuation $f; then - grep -q "parameter \\\\WR_WIDE_CONTINUATION $(gawk '/expect-wr-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected write wide continuation."; false; } - fi - if grep -q expect-rd-ports $f; then - grep -q "parameter \\\\RD_PORTS $(gawk '/expect-rd-ports/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected number of read ports."; false; } - fi - if grep -q expect-rd-clk $f; then - grep -q "connect \\\\RD_CLK \\$(gawk '/expect-rd-clk/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read clock."; false; } - fi - if grep -q expect-rd-en $f; then - grep -q "connect \\\\RD_EN \\$(gawk '/expect-rd-en/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read enable."; false; } - fi - if grep -q expect-rd-srst-sig $f; then - grep -q "connect \\\\RD_SRST \\$(gawk '/expect-rd-srst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read sync reset."; false; } - fi - if grep -q expect-rd-srst-val $f; then - grep -q "parameter \\\\RD_SRST_VALUE $(gawk '/expect-rd-srst-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read sync reset value."; false; } - fi - if grep -q expect-rd-arst-sig $f; then - grep -q "connect \\\\RD_ARST \\$(gawk '/expect-rd-arst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read async reset."; false; } - fi - if grep -q expect-rd-arst-val $f; then - grep -q "parameter \\\\RD_ARST_VALUE $(gawk '/expect-rd-arst-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read async reset value."; false; } - fi - if grep -q expect-rd-init-val $f; then - grep -q "parameter \\\\RD_INIT_VALUE $(gawk '/expect-rd-init-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read init value."; false; } - fi - if grep -q expect-rd-wide-continuation $f; then - grep -q "parameter \\\\RD_WIDE_CONTINUATION $(gawk '/expect-rd-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read wide continuation."; false; } - fi - if grep -q expect-no-rd-clk $f; then - grep -q "connect \\\\RD_CLK 1'x\$" ${f%.v}.dmp || - { echo " ERROR: Expected no read clock."; false; } - fi - echo " ok." -done - diff --git a/tests/tools/autotest.mk b/tests/tools/autotest.mk deleted file mode 100644 index e0f2bcdc1..000000000 --- a/tests/tools/autotest.mk +++ /dev/null @@ -1,13 +0,0 @@ - -# Don't bother defining default values for SEED and EXTRA_FLAGS. -# Their "natural" default values should be sufficient, -# and they may be overridden in the environment. -ifneq ($(strip $(SEED)),) -SEEDOPT=-S$(SEED) -endif - -$(MAKECMDGOALS): - @$(basename $(MAKEFILE_LIST)).sh -G -j $(SEEDOPT) $(EXTRA_FLAGS) $@ - -.PHONY: $(MAKECMDGOALS) - From d0ac6d979198fc073c8811b03ae60d548058e5cd Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 09:45:33 +0100 Subject: [PATCH 25/36] Converted blif tests --- tests/Makefile | 2 +- tests/blif/generate_mk.py | 11 +++++++++++ tests/blif/run-test.sh | 11 ----------- tests/gen_tests_makefile.py | 30 +++++++++++++++++++----------- 4 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 tests/blif/generate_mk.py delete mode 100755 tests/blif/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 864fa973d..6b8535822 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -67,7 +67,7 @@ MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./select #SH_TEST_DIRS += ./peepopt #SH_TEST_DIRS += ./proc -#SH_TEST_DIRS += ./blif +MK_TEST_DIRS += ./blif #SH_TEST_DIRS += ./arch #SH_TEST_DIRS += ./rpc #SH_TEST_DIRS += ./memfile diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py new file mode 100644 index 000000000..41f2d769d --- /dev/null +++ b/tests/blif/generate_mk.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"], [], +"""if [ -f $(@:.ys=.blif) ]; then \\ + diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1; \\ +fi""") \ No newline at end of file diff --git a/tests/blif/run-test.sh b/tests/blif/run-test.sh deleted file mode 100755 index 97f12d288..000000000 --- a/tests/blif/run-test.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys --no-version -ql ${x%.ys}.log $x >/dev/null 2>&1 -done - -for x in *.blif; do - diff $x.out $x.ok -done \ No newline at end of file diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index d714820e5..84640780b 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -20,23 +20,31 @@ def generate_target(name, command): print(f"\t@$(call run_test,{target}, \\") print(f"\t{command})") -def generate_ys_test(ys_file, yosys_args=""): +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' + if commands: + cmd += f"; \\\n{commands}" generate_target(ys_file, cmd) -def generate_tcl_test(tcl_file, yosys_args=""): +def generate_tcl_test(tcl_file, yosys_args="", commands=""): cmd = f'$(YOSYS) -ql {tcl_file}.err {yosys_args} {tcl_file} >/dev/null 2>&1 && mv {tcl_file}.err {tcl_file}.log' + if commands: + cmd += f"; \\\n{commands}" generate_target(tcl_file, cmd) -def generate_sv_test(sv_file, yosys_args=""): +def generate_sv_test(sv_file, yosys_args="", commands=""): base = os.path.splitext(sv_file)[0] if not os.path.exists(base + ".ys"): yosys_cmd = '-p "prep -top top; async2sync; sat -enable_undef -verify -prove-asserts"' cmd = f'$(YOSYS) -ql {sv_file}.err {yosys_cmd} {yosys_args} {sv_file} >/dev/null 2>&1 && mv {sv_file}.err {sv_file}.log' + if commands: + cmd += f"; \\\n{commands}" generate_target(sv_file, cmd) -def generate_bash_test(sh_file): +def generate_bash_test(sh_file, commands=""): cmd = f"bash -v {sh_file} >{sh_file}.err 2>&1 && mv {sh_file}.err {sh_file}.log" + if commands: + cmd += f"; \\\n{commands}" generate_target(sh_file, cmd) def unpack_cmd(cmd): @@ -49,7 +57,7 @@ def unpack_cmd(cmd): def generate_cmd_test(test_name, cmd, yosys_args=""): generate_target(test_name, unpack_cmd(cmd)) -def generate_tests(argv): +def generate_tests(argv, cmds): parser = argparse.ArgumentParser(add_help=False) parser.add_argument("-y", "--yosys-scripts", action="store_true") parser.add_argument("-t", "--tcl-scripts", action="store_true") @@ -64,20 +72,20 @@ def generate_tests(argv): if args.yosys_scripts: for f in sorted(glob.glob("*.ys")): - generate_ys_test(f, args.yosys_args) + generate_ys_test(f, args.yosys_args, cmds) if args.tcl_scripts: for f in sorted(glob.glob("*.tcl")): - generate_tcl_test(f, args.yosys_args) + generate_tcl_test(f, args.yosys_args, cmds) if args.prove_sv: for f in sorted(glob.glob("*.sv")): - generate_sv_test(f, args.yosys_args) + generate_sv_test(f, args.yosys_args, cmds) if args.bash: for f in sorted(glob.glob("*.sh")): if f != "run-test.sh": - generate_bash_test(f) + generate_bash_test(f, cmds) def print_header(extra=None): print(f"include {common_mk}") @@ -91,13 +99,13 @@ def print_header(extra=None): print(".PHONY: all") print("all:") -def generate(argv, extra=None): +def generate(argv, extra=None, cmds=""): with open("Makefile", "w") as f: old = sys.stdout sys.stdout = f try: print_header(extra) - generate_tests(argv) + generate_tests(argv, cmds) finally: sys.stdout = old From de8b6286b84cf09d4fe42e3b27fae50dafb3bd23 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 09:54:33 +0100 Subject: [PATCH 26/36] Converted some more --- tests/Makefile | 6 +++--- tests/peepopt/generate_mk.py | 8 ++++++++ tests/peepopt/run-test.sh | 7 ------- tests/proc/generate_mk.py | 8 ++++++++ tests/proc/run-test.sh | 7 ------- tests/select/generate_mk.py | 8 ++++++++ tests/select/run-test.sh | 7 ------- 7 files changed, 27 insertions(+), 24 deletions(-) create mode 100644 tests/peepopt/generate_mk.py delete mode 100644 tests/peepopt/run-test.sh create mode 100644 tests/proc/generate_mk.py delete mode 100755 tests/proc/run-test.sh create mode 100644 tests/select/generate_mk.py delete mode 100755 tests/select/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 6b8535822..23d152bd7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -64,9 +64,9 @@ MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces #SH_TEST_DIRS += ./xprop -#SH_TEST_DIRS += ./select -#SH_TEST_DIRS += ./peepopt -#SH_TEST_DIRS += ./proc +MK_TEST_DIRS += ./select +MK_TEST_DIRS += ./peepopt +MK_TEST_DIRS += ./proc MK_TEST_DIRS += ./blif #SH_TEST_DIRS += ./arch #SH_TEST_DIRS += ./rpc diff --git a/tests/peepopt/generate_mk.py b/tests/peepopt/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/peepopt/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/peepopt/run-test.sh b/tests/peepopt/run-test.sh deleted file mode 100644 index 2e3f5235c..000000000 --- a/tests/peepopt/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/proc/generate_mk.py b/tests/proc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/proc/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/proc/run-test.sh b/tests/proc/run-test.sh deleted file mode 100755 index 241b32295..000000000 --- a/tests/proc/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 -done diff --git a/tests/select/generate_mk.py b/tests/select/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/select/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/select/run-test.sh b/tests/select/run-test.sh deleted file mode 100755 index 241b32295..000000000 --- a/tests/select/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 -done From 2b10385eddccd91beefd1c7a01db65ab4e7ac763 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 15:25:28 +0100 Subject: [PATCH 27/36] Convert xprop tests --- tests/Makefile | 2 +- tests/gen_tests_makefile.py | 33 +++++++++++---------- tests/xprop/{generate.py => generate_mk.py} | 29 ++++++++---------- tests/xprop/run-test.sh | 6 ---- 4 files changed, 32 insertions(+), 38 deletions(-) rename tests/xprop/{generate.py => generate_mk.py} (94%) delete mode 100755 tests/xprop/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 23d152bd7..f5642c940 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -63,7 +63,7 @@ MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./memlib #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces -#SH_TEST_DIRS += ./xprop +MK_TEST_DIRS += ./xprop MK_TEST_DIRS += ./select MK_TEST_DIRS += ./peepopt MK_TEST_DIRS += ./proc diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 84640780b..2f842f570 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -11,14 +11,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): +def generate_target(name, command, out=sys.stdout): #target = f"{_cwd_base()}-{name}" target = f"{name}" - print(f"all: {target}") - print(f".PHONY: {target}") - print(f"{target}:") - print(f"\t@$(call run_test,{target}, \\") - print(f"\t{command})") + print(f"all: {target}", file=out) + print(f".PHONY: {target}", file=out) + print(f"{target}:", file=out) + if command: + print(f"\t@$(call run_test,{target}, \\", file=out) + print(f"\t{command})", file=out) + else: + print(f"\t@$(call run_test,{target})", file=out) 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' @@ -87,17 +90,17 @@ def generate_tests(argv, cmds): if f != "run-test.sh": generate_bash_test(f, cmds) -def print_header(extra=None): - print(f"include {common_mk}") - print(f"YOSYS ?= {yosys_basedir}/yosys") - print() - print("export YOSYS_MAX_THREADS := 4") +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) if extra: for line in extra: - print(line) - print() - print(".PHONY: all") - print("all:") + print(line, file=out) + print("", file=out) + print(".PHONY: all", file=out) + print("all:", file=out) def generate(argv, extra=None, cmds=""): with open("Makefile", "w") as f: diff --git a/tests/xprop/generate.py b/tests/xprop/generate_mk.py similarity index 94% rename from tests/xprop/generate.py rename to tests/xprop/generate_mk.py index 484f1661c..67ab26bda 100644 --- a/tests/xprop/generate.py +++ b/tests/xprop/generate_mk.py @@ -1,6 +1,12 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + import os import re -import sys import random import argparse @@ -16,7 +22,9 @@ if args.seed is None: print(f"xprop PRNG seed: {args.seed}") -makefile = open("run-test.mk", "w") +makefile = open("Makefile", "w") + +gen_tests_makefile.print_header(out = makefile) def add_test(name, src, seq=False): if not re.search(args.filter, name): @@ -26,17 +34,10 @@ def add_test(name, src, seq=False): os.makedirs(workdir, exist_ok=True) with open(f"{workdir}/uut.v", "w") as uut: print(src, file=uut) - print(f"all: {workdir}", file=makefile) - print(f".PHONY: {workdir}", file=makefile) - print(f"{workdir}:", file=makefile) seq_arg = " -s" if seq else "" - print( - f"\t@cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1 || echo {workdir}: failed > status\n" - f"\t@cat {workdir}/status\n" - f"\t@grep '^.*: ok' {workdir}/status\n" - , - file=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", + out=makefile) def cell_test(name, cell, inputs, outputs, params, initial={}, defclock=False, seq=False): ports = [] @@ -119,10 +120,6 @@ def dff_test(width, pol, defclock): def dffe_test(width, pol, enpol, defclock): cell_test(f"dffe_{width}{'np'[pol]}{'np'[enpol]}{'xd'[defclock]}", 'dffe', {"CLK": 1, "EN": 1, "D": width}, {"Q": width}, {"WIDTH": width, "CLK_POLARITY": int(pol), "EN_POLARITY": int(enpol)}, defclock=defclock, seq=True) - -print(".PHONY: all", file=makefile) -print("all:\n\t@echo done\n", file=makefile) - for cell in ["not", "pos", "neg"]: if args.more: unary_test(cell, 1, False, 1) diff --git a/tests/xprop/run-test.sh b/tests/xprop/run-test.sh deleted file mode 100755 index 303c0bb3b..000000000 --- a/tests/xprop/run-test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e - -python3 generate.py $@ -${MAKE:-make} -f run-test.mk From 799c07a1262d50ae65bdb5a000aa92539ee75181 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 12:47:15 +0100 Subject: [PATCH 28/36] 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 = [] From 4ff4af73893b5e26a4688bbb8fd4e0292bb75009 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 15:12:51 +0100 Subject: [PATCH 29/36] Try fixing tests --- tests/blif/generate_mk.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py index 41f2d769d..47cb9accd 100644 --- a/tests/blif/generate_mk.py +++ b/tests/blif/generate_mk.py @@ -6,6 +6,6 @@ sys.path.append("..") import gen_tests_makefile gen_tests_makefile.generate(["--yosys-scripts"], [], -"""if [ -f $(@:.ys=.blif) ]; then \\ - diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1; \\ -fi""") \ No newline at end of file +"""[ ! -f $(@:.ys=.blif) ] || \\ + diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ +""") \ No newline at end of file From 323747e3de3c27b9096e8d5df2822b6647573fe6 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 15:38:24 +0100 Subject: [PATCH 30/36] Better fix --- tests/blif/generate_mk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py index 47cb9accd..bd6d74fd9 100644 --- a/tests/blif/generate_mk.py +++ b/tests/blif/generate_mk.py @@ -7,5 +7,5 @@ import gen_tests_makefile gen_tests_makefile.generate(["--yosys-scripts"], [], """[ ! -f $(@:.ys=.blif) ] || \\ - diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ + sed '1d' $(@:.ys=.blif).out | diff - <(sed '1d' $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ """) \ No newline at end of file From 0297eabeb3a5179802bffe6df74656132b88699b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 16:16:58 +0100 Subject: [PATCH 31/36] Make test simple --- tests/blif/gatesi.blif.ok | 1 - tests/blif/gatesi.ys | 4 +++- tests/blif/generate_mk.py | 5 +---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/blif/gatesi.blif.ok b/tests/blif/gatesi.blif.ok index e99d7906f..8213a8a89 100644 --- a/tests/blif/gatesi.blif.ok +++ b/tests/blif/gatesi.blif.ok @@ -1,4 +1,3 @@ -# Generated by Yosys .model test .inputs clk in_a_var[0] in_a_var[1] in_a_var[2] in_a_var[3] in_a_var[4] in_a_var[5] in_a_var[6] in_a_var[7] in_b_var[0] in_b_var[1] in_b_var[2] in_b_var[3] in_b_var[4] in_b_var[5] in_b_var[6] in_b_var[7] diff --git a/tests/blif/gatesi.ys b/tests/blif/gatesi.ys index 44c022bb9..0f1ebd911 100644 --- a/tests/blif/gatesi.ys +++ b/tests/blif/gatesi.ys @@ -1,2 +1,4 @@ read_blif gatesi.blif -write_blif -gatesi gatesi.blif.out \ No newline at end of file +write_blif -gatesi gatesi.blif.out +! tail -n +2 gatesi.blif.out > gatesi.blif.out.tmp && mv gatesi.blif.out.tmp gatesi.blif.out +! diff gatesi.blif.out gatesi.blif.ok diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py index bd6d74fd9..96aa6be79 100644 --- a/tests/blif/generate_mk.py +++ b/tests/blif/generate_mk.py @@ -5,7 +5,4 @@ sys.path.append("..") import gen_tests_makefile -gen_tests_makefile.generate(["--yosys-scripts"], [], -"""[ ! -f $(@:.ys=.blif) ] || \\ - sed '1d' $(@:.ys=.blif).out | diff - <(sed '1d' $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ -""") \ No newline at end of file +gen_tests_makefile.generate(["--yosys-scripts"]) \ No newline at end of file From ca77e0a5db46e9f9556ff477d85bba319ccad694 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:00:40 +0100 Subject: [PATCH 32/36] Convert memlib tests --- tests/Makefile | 2 +- tests/memlib/generate.py | 82 +++++++++++++++---------------------- tests/memlib/generate_mk.py | 28 +++++++++++++ tests/memlib/run-test.sh | 16 -------- 4 files changed, 62 insertions(+), 66 deletions(-) create mode 100644 tests/memlib/generate_mk.py delete mode 100755 tests/memlib/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index aa82ccc61..37d4bdbf2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -60,7 +60,7 @@ MK_TEST_DIRS += ./asicworld MK_TEST_DIRS += ./share MK_TEST_DIRS += ./opt_share MK_TEST_DIRS += ./fsm -#SH_TEST_DIRS += ./memlib +MK_TEST_DIRS += ./memlib #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces MK_TEST_DIRS += ./xprop diff --git a/tests/memlib/generate.py b/tests/memlib/generate.py index 46eff6b43..0b6c27b1a 100644 --- a/tests/memlib/generate.py +++ b/tests/memlib/generate.py @@ -319,8 +319,8 @@ if (OFFSET > 0) begin always @(mem_read, subaddr_r) rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; -end -else +end +else begin always @(posedge clk) case (OFFSET) @@ -970,7 +970,7 @@ for (abits, wbits, words, defs, cells) in [ name, ENABLES.format(abits=abits, wbits=wbits, words=words), ["wren"], defs, cells )) - + # abits/dbits determination (aka general geometry picking) GEOMETRIC = """ module top(clk, rwa, rd, wd, we); @@ -991,7 +991,7 @@ always @(posedge clk) if (we) mem[rwa] <= wd; else - rd <= mem[rwa]; + rd <= mem[rwa]; endmodule """ @@ -1372,7 +1372,7 @@ for (abits, wbits, rwords, cntquad, cntoct) in [ (4, 2, 4, 1, 1), (4, 2, 5, 2, 1), (4, 2, 6, 2, 1), - (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read + (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read (4, 2, 8, 3, 1), # ports per quad port LUT (i.e. 7 ports in 2, 8 ports in 3) (4, 2, 9, 3, 2), (4, 4, 1, 2, 2), @@ -1440,7 +1440,7 @@ for (testname, reset_gate, rdwr, clk_en, add_logic) in [ write = "if (wren) \n\t\tmem[addr] <= wdata;" if rdwr == "new": - read = """if (rden) + read = """if (rden) if (wren) rdata <= wdata; else @@ -1466,7 +1466,7 @@ end""" TESTS.append(Test( testname, PRIORITY.format(code=code, abits=4, wbits=8, words=2), - ["block_sp_full"], ["USE_SRST"], + ["block_sp_full"], ["USE_SRST"], {"RAM_BLOCK_SP": 1, "$*": add_logic} )) @@ -1510,10 +1510,10 @@ end""" TESTS.append(Test( testname, PRIORITY.format(code=code, abits=4, wbits=1, words=2), - ["block_sp_full"], defs, + ["block_sp_full"], defs, {"RAM_BLOCK_SP": 1, "$*": add_logic} )) - + ROM_CASE = """ module rom(input clk, input [2:0] addr, {attr}output reg [7:0] data); @@ -1536,44 +1536,28 @@ endmodule TESTS.append(Test("rom_case", ROM_CASE.format(attr=""), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 0})) TESTS.append(Test("rom_case_block", ROM_CASE.format(attr="(* rom_style = \"block\" *) "), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 1})) -with open("run-test.mk", "w") as mf: - mf.write("ifneq ($(strip $(SEED)),)\n") - mf.write("SEEDOPT=-S$(SEED)\n") - mf.write("endif\n") - mf.write("all:") - for t in TESTS: - mf.write(" " + t.name) - mf.write("\n") - mf.write(".PHONY: all\n") - - - for t in TESTS: - with open("t_{}.v".format(t.name), "w") as tf: - tf.write(t.src) - with open("t_{}.ys".format(t.name), "w") as sf: - sf.write("proc\n") - sf.write("opt\n") - sf.write("opt -full\n") - sf.write("memory -nomap\n") - sf.write("dump\n") - sf.write("memory_libmap") - for lib in t.libs: - sf.write(" -lib ../memlib_{}.txt".format(lib)) - for d in t.defs: - sf.write(" -D {}".format(d)) - sf.write("\n") - sf.write("memory_map\n") - for k, v in t.cells.items(): - if isinstance(v, tuple): - (cc, ca) = v - sf.write("select -assert-count {} t:{}\n".format(cc, k)) - for kk, vv in ca.items(): - sf.write("select -assert-count {} t:{} r:{}={} %i\n".format(cc, k, kk, vv)) - else: - sf.write("select -assert-count {} t:{}\n".format(v, k)) - mf.write("{}:\n".format(t.name)) - mf.write("\t@../tools/autotest.sh -G -j $(SEEDOPT) $(EXTRA_FLAGS) -p 'script ../t_{}.ys'".format(t.name)) +for t in TESTS: + with open("t_{}.v".format(t.name), "w") as tf: + tf.write(t.src) + with open("t_{}.ys".format(t.name), "w") as sf: + sf.write("proc\n") + sf.write("opt\n") + sf.write("opt -full\n") + sf.write("memory -nomap\n") + sf.write("dump\n") + sf.write("memory_libmap") for lib in t.libs: - mf.write(" -l memlib_{}.v".format(lib)) - mf.write(" t_{}.v || (cat t_{}.err; exit 1)\n".format(t.name, t.name)) - mf.write(".PHONY: {}\n".format(t.name)) + sf.write(" -lib ../memlib_{}.txt".format(lib)) + for d in t.defs: + sf.write(" -D {}".format(d)) + sf.write("\n") + sf.write("memory_map\n") + for k, v in t.cells.items(): + if isinstance(v, tuple): + (cc, ca) = v + sf.write("select -assert-count {} t:{}\n".format(cc, k)) + for kk, vv in ca.items(): + sf.write("select -assert-count {} t:{} r:{}={} %i\n".format(cc, k, kk, vv)) + else: + sf.write("select -assert-count {} t:{}\n".format(v, k)) + diff --git a/tests/memlib/generate_mk.py b/tests/memlib/generate_mk.py new file mode 100644 index 000000000..3cc20b614 --- /dev/null +++ b/tests/memlib/generate_mk.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile +from generate import TESTS + +def create_tests(): + for t in TESTS: + libs_args = "" + for lib in t.libs: + libs_args += f" -l memlib_{lib}.v" + cmd = ( + f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} " + f"-p 'script ../t_{t.name}.ys'" + f"{libs_args} " + f"t_{t.name}.v >/dev/null 2>&1 || (cat t_{t.name}.err; exit 1)" + ) + gen_tests_makefile.generate_target(t.name, cmd) + +extra = [ + "SEED ?=", + "ifneq ($(strip $(SEED)),)", + " SEEDOPT=-S$(SEED)", + "endif", +] +gen_tests_makefile.generate_custom(create_tests, extra) diff --git a/tests/memlib/run-test.sh b/tests/memlib/run-test.sh deleted file mode 100755 index 9e95fb255..000000000 --- a/tests/memlib/run-test.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -eu - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) seed="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -python3 generate.py -exec ${MAKE:-make} -f run-test.mk SEED="$seed" From e7cc04954d243f8bea0c6827f73625e8569d4b67 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:08:27 +0100 Subject: [PATCH 33/36] Convert memfile tests --- tests/Makefile | 2 +- tests/memfile/generate_mk.py | 69 ++++++++++++++++++++++++++++++++++++ tests/memfile/run-test.sh | 50 -------------------------- 3 files changed, 70 insertions(+), 51 deletions(-) create mode 100644 tests/memfile/generate_mk.py delete mode 100755 tests/memfile/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 37d4bdbf2..19e79718e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -70,7 +70,7 @@ MK_TEST_DIRS += ./proc MK_TEST_DIRS += ./blif #SH_TEST_DIRS += ./arch #SH_TEST_DIRS += ./rpc -#SH_TEST_DIRS += ./memfile +MK_TEST_DIRS += ./memfile #SH_TEST_DIRS += ./fmt #SH_TEST_DIRS += ./cxxrtl #SH_TEST_DIRS += ./liberty diff --git a/tests/memfile/generate_mk.py b/tests/memfile/generate_mk.py new file mode 100644 index 000000000..a40f99ad0 --- /dev/null +++ b/tests/memfile/generate_mk.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def create_tests(): + setup = "mkdir -p temp && cp content1.dat temp/content2.dat" + + gen_tests_makefile.generate_cmd_test("parent_content1", [ + f"{setup};", + '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("parent_content2_temp", [ + f"{setup};", + '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("parent_content2_full", [ + f"{setup};", + '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"memfile/temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("same_content1", [ + f"{setup};", + '$(YOSYS) -qp "read_verilog -defer memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory" >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("same_content2", [ + f"{setup};", + '$(YOSYS) -qp "read_verilog -defer memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory" >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("child_content1", [ + f"{setup};", + '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("child_content2_temp", [ + f"{setup};", + '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("child_content2_direct", [ + f"{setup};", + '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("fail_empty_filename", + '! $(YOSYS) -qp "read_verilog memory.v" >/dev/null 2>&1') + + gen_tests_makefile.generate_cmd_test("fail_missing_file", [ + '! $(YOSYS) -qp "read_verilog -defer memory.v;', + 'chparam -set MEMFILE \\"content3.dat\\" memory" >/dev/null 2>&1', + ]) + +extra = ["YOSYS_ABS := $(abspath $(YOSYS))"] +gen_tests_makefile.generate_custom(create_tests, extra) + diff --git a/tests/memfile/run-test.sh b/tests/memfile/run-test.sh deleted file mode 100755 index e2583ef3b..000000000 --- a/tests/memfile/run-test.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -mkdir -p temp -cp content1.dat temp/content2.dat - -cd .. - -echo "Running from the parent directory with content1.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 -echo "Running from the parent directory with temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 -echo "Running from the parent directory with memfile/temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" >/dev/null 2>&1 - -cd memfile - -echo "Running from the same directory with content1.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 -echo "Running from the same directory with temp/content2.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 - -cd temp - -echo "Running from a child directory with content1.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 -echo "Running from a child directory with temp/content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 -echo "Running from a child directory with content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 - -cd .. - -echo "Checking a failure when zero length filename is provided" -if ../../yosys -qp "read_verilog memory.v" >/dev/null 2>&1; then - echo "The execution should fail but it didn't happen, which is WRONG." - exit 1 -else - echo "Execution failed, which is OK." -fi - -echo "Checking a failure when not existing filename is provided" -if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory" >/dev/null 2>&1; then - echo "The execution should fail but it didn't happen, which is WRONG." - exit 1 -else - echo "Execution failed, which is OK." -fi From a54c0149bfb6902fec4ebc4573ebd542c3fa009e Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:24:54 +0100 Subject: [PATCH 34/36] Convert bram tests --- tests/Makefile | 2 +- tests/bram/{generate.py => generate_mk.py} | 24 ++++++++++- tests/bram/run-test.sh | 48 ---------------------- 3 files changed, 24 insertions(+), 50 deletions(-) rename tests/bram/{generate.py => generate_mk.py} (95%) delete mode 100755 tests/bram/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 19e79718e..48ea1774f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -61,7 +61,7 @@ MK_TEST_DIRS += ./share MK_TEST_DIRS += ./opt_share MK_TEST_DIRS += ./fsm MK_TEST_DIRS += ./memlib -#SH_TEST_DIRS += ./bram +MK_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces MK_TEST_DIRS += ./xprop MK_TEST_DIRS += ./select diff --git a/tests/bram/generate.py b/tests/bram/generate_mk.py similarity index 95% rename from tests/bram/generate.py rename to tests/bram/generate_mk.py index 79dd500a3..a18972703 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate_mk.py @@ -4,6 +4,10 @@ import argparse import os import sys import random +import glob + +sys.path.append("..") +import gen_tests_makefile debug_mode = False @@ -287,9 +291,11 @@ if args.seed is not None: else: seed = (int(os.times()[4]*100) + os.getpid()) % 900000 + 100000 -print("PRNG seed: %d" % seed) +print("bram PRNG seed: %d" % seed) random.seed(seed) +os.makedirs("temp", exist_ok=True) + for k1 in range(args.count): dsc_f = open("temp/brams_%02d.txt" % k1, "w") sim_f = open("temp/brams_%02d.v" % k1, "w") @@ -303,3 +309,19 @@ for k1 in range(args.count): for k2 in range(lenk2): create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, random.randrange(2 if k2+1 < lenk2 else 1)) +configs = sorted(set( + os.path.basename(f).replace("brams_", "").replace(".txt", "") + for f in glob.glob("temp/brams_*.txt") +)) + +def create_tests(): + for i in configs: + for j in configs: + if i != j: + gen_tests_makefile.generate_cmd_test( + f"bram_{i}_{j}", + f"bash run-single.sh {i} {j} >/dev/null 2>&1" + ) + +gen_tests_makefile.generate_custom(create_tests) + diff --git a/tests/bram/run-test.sh b/tests/bram/run-test.sh deleted file mode 100755 index 47f24f5dd..000000000 --- a/tests/bram/run-test.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# MAKE="make -j8" time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=5 -seed="" # default to no seed specified -debug="" -while getopts "c:dS:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - d) debug="-d" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp - -echo "generating tests.." -python3 generate.py $debug -c $count $seed - -{ - echo -n "all:" - for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do - for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo -n " temp/job_${i}_${j}.ok" - done; done - echo - for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do - for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo "temp/job_${i}_${j}.ok:" - echo " @bash run-single.sh ${i} ${j}" - echo " @echo 'Passed memory_bram test ${i}_${j}.'" - echo " @touch \$@" - done; done -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile - -exit 0 From 57bf4378d335668fd86e57ddbd72be32fa875511 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:31:47 +0100 Subject: [PATCH 35/36] Consolidated memlib generate script --- tests/memlib/generate.py | 1563 ---------------------------------- tests/memlib/generate_mk.py | 1567 ++++++++++++++++++++++++++++++++++- 2 files changed, 1565 insertions(+), 1565 deletions(-) delete mode 100644 tests/memlib/generate.py diff --git a/tests/memlib/generate.py b/tests/memlib/generate.py deleted file mode 100644 index 0b6c27b1a..000000000 --- a/tests/memlib/generate.py +++ /dev/null @@ -1,1563 +0,0 @@ -# TODO: - -# - priority logic -# - swizzles for weird width progressions - - -class Test: - def __init__(self, name, src, libs, defs, cells): - self.name = name - self.src = src - self.libs = libs - self.defs = defs - self.cells = cells - -TESTS = [] - -### basic sanity tests -# Asynchronous-read RAM - -ASYNC = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output wire [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -assign rd = mem[ra]; - -endmodule -""" - -ASYNC_SMALL = ASYNC.format(abits=6, dbits=6) -ASYNC_BIG = ASYNC.format(abits=11, dbits=10) - -TESTS += [ - Test("async_big", ASYNC_BIG, ["lut", "block_tdp"], [], {"RAM_LUT": 384}), - Test("async_big_block", ASYNC_BIG, ["block_tdp"], [], {"RAM_BLOCK_TDP": 0}), - Test("async_small", ASYNC_SMALL, ["lut", "block_tdp"], [], {"RAM_LUT": 8}), - Test("async_small_block", ASYNC_SMALL, ["block_tdp"], [], {"RAM_BLOCK_TDP": 0}), -] - -# Synchronous SDP read first -SYNC = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -{attr} -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" - -SYNC_SMALL = SYNC.format(abits=6, dbits=6, attr="") -SYNC_SMALL_BLOCK = SYNC.format(abits=6, dbits=6, attr='(* ram_style="block" *)') -SYNC_BIG = SYNC.format(abits=11, dbits=10, attr="") -SYNC_MID = SYNC.format(abits=6, dbits=16, attr="") - -TESTS += [ - Test("sync_big", SYNC_BIG, ["lut", "block_tdp"], [], {"RAM_BLOCK_TDP": 20}), - Test("sync_big_sdp", SYNC_BIG, ["lut", "block_sdp"], [], {"RAM_BLOCK_SDP": 20}), - Test("sync_big_lut", SYNC_BIG, ["lut"], [], {"RAM_LUT": 384}), - Test("sync_small", SYNC_SMALL, ["lut", "block_tdp"], [], {"RAM_LUT": 8}), - Test("sync_small_block", SYNC_SMALL, ["block_tdp"], [], {"RAM_BLOCK_TDP": 1}), - Test("sync_small_block_attr", SYNC_SMALL_BLOCK, ["lut", "block_tdp"], [], {"RAM_BLOCK_TDP": 1}), -] - -### initialization values testing -LUT_INIT = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output wire [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -integer i; -initial - for (i = 0; i < 2**ABITS-1; i = i + 1) - mem[i] = {ival}; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -assign rd = mem[ra]; - -endmodule -""" - -INIT_LUT_ZEROS = LUT_INIT.format(abits=4, dbits=4, ival=0); -INIT_LUT_VAL = LUT_INIT.format(abits=4, dbits=4, ival=5); -INIT_LUT_VAL2 = LUT_INIT.format(abits=6, dbits=6, ival="6'h12"); -INIT_LUT_X = LUT_INIT.format(abits=4, dbits=4, ival="4'hx") - -TESTS += [ - Test("init_lut_zeros_zero", INIT_LUT_ZEROS, ["lut"], ["INIT_ZERO"], {"RAM_LUT":1}), - Test("init_lut_zeros_any", INIT_LUT_ZEROS, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), - Test("init_lut_val_zero", INIT_LUT_VAL, ["lut"], ["INIT_ZERO"], {"RAM_LUT":0}), #CHECK: no emulation? - Test("init_lut_val_any", INIT_LUT_VAL, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), - Test("init_lut_val_no_undef", INIT_LUT_VAL, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":1}), - Test("init_lut_val2_any", INIT_LUT_VAL2, ["lut"], ["INIT_ANY"], {"RAM_LUT":8}), - Test("init_lut_val2_no_undef", INIT_LUT_VAL2, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":8}), - Test("init_lut_x_none", INIT_LUT_X, ["lut"], ["INIT_NONE"], {"RAM_LUT":1}), - Test("init_lut_x_zero", INIT_LUT_X, ["lut"], ["INIT_ZERO"], {"RAM_LUT":1}), - Test("init_lut_x_any", INIT_LUT_X, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), - Test("init_lut_x_no_undef", INIT_LUT_X, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":1}), -] - -### width testing 9-bit-per-byte -RAM_9b1B = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" - -RAM_18b2B = RAM_9b1B.format(abits=3, dbits=18); -RAM_9b1B = RAM_9b1B.format(abits=4, dbits=9); -RAM_4b1B = RAM_9b1B.format(abits=5, dbits=4); -RAM_2b1B = RAM_9b1B.format(abits=6, dbits=2); -RAM_1b1B = RAM_9b1B.format(abits=7, dbits=1); - -TESTS += [ - Test("ram_18b2B", RAM_18b2B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_9b1B", RAM_9b1B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_4b1B", RAM_4b1B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_2b1B", RAM_2b1B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_1b1B", RAM_1b1B, ["9b1B"], [], {"RAM_9b1B":1}), -] - -### initializing 9-bits-per-byte -RAM_9b1B_init = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -integer i; -initial - for (i = 0; i < 2**ABITS-1; i = i + 1) - mem[i] = {ival}; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" - -INIT_9b1B_ZEROS = RAM_9b1B_init.format(abits=4, dbits=9, ival=0); -INIT_9b1B_VAL = RAM_9b1B_init.format(abits=4, dbits=9, ival=275); -INIT_13b2B_VAL = RAM_9b1B_init.format(abits=3, dbits=13, ival="13'h01f3") -INIT_18b2B_VAL = RAM_9b1B_init.format(abits=4, dbits=18, ival="18'h1f39a"); -INIT_4b1B_X = RAM_9b1B_init.format(abits=5, dbits=4, ival="4'hx") - -TESTS += [ - Test("init_9b1B_zeros_zero", INIT_9b1B_ZEROS, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":1}), - Test("init_9b1B_zeros_any", INIT_9b1B_ZEROS, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_9b1B_val_zero", INIT_9b1B_VAL, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":0}), #CHECK: no emulation? - Test("init_9b1B_val_any", INIT_9b1B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_9b1B_val_no_undef", INIT_9b1B_VAL, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":1}), - Test("init_13b2B_val_any", INIT_13b2B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_18b2B_val_any", INIT_18b2B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":2}), - Test("init_18b2B_val_no_undef", INIT_18b2B_VAL, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":2}), - Test("init_4b1B_x_none", INIT_4b1B_X, ["9b1B"], ["INIT_NONE"], {"RAM_9b1B":1}), - Test("init_4b1B_x_zero", INIT_4b1B_X, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":1}), - Test("init_4b1B_x_any", INIT_4b1B_X, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_4b1B_x_no_undef", INIT_4b1B_X, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":1}), -] - -### Clock polarity combinations -# I'm not entirely convinced auto-test is correctly testing clock edging -# but they do at least all gen/synth -SYNCCLOCK = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = 8; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" -for (abits, cnt, wclk, rclk, shared) in [ - (4, 1, "ANY","ANY", False), - (4, 1, "ANY","NEG", False), - (4, 1, "ANY","POS", False), - (4, 1, "NEG","ANY", False), - (4, 1, "NEG","POS", False), - (4, 1, "NEG","NEG", False), - (4, 1, "POS","ANY", False), - (4, 1, "POS","NEG", False), - (4, 1, "POS","POS", False), - (4, 1, "ANY","ANY", True), - (4, 0, "NEG","POS", True), # FF mapping - (4, 1, "NEG","NEG", True), - (4, 0, "POS","NEG", True), # FF mapping - (4, 1, "POS","POS", True), - # cannot combine "ANY" with "POS|NEG" when using shared clock -]: - name = f"clock_a{abits}_w{wclk}r{rclk}s{shared}" - defs = ["WCLK_" + wclk, "RCLK_" + rclk] - if (shared): - defs.append("SHARED_CLK") - TESTS.append(Test( - name, SYNCCLOCK.format(abits=abits), - ["clock_sdp"], defs, {"RAM_CLOCK_SDP": cnt} - )) - -### mixed width testing -# Wide write port -MIXED_WRITE = """ -module top(clk, ra, wa, rd, wd, we); - -localparam WABITS = {wabits}; -localparam WDBITS = {wdbits}; - -localparam RABITS = {rabits}; -localparam RDBITS = {rdbits}; - -input wire clk; -input wire we; -input wire [WABITS-1:0] wa; -input wire [WDBITS-1:0] wd; -input wire [RABITS-1:0] ra; -output reg [RDBITS-1:0] rd; - -localparam DEPTH = (2**WABITS); - -localparam OFFSET = RABITS-WABITS; - -(* syn_ramstyle = "block_ram" *) -reg [WDBITS-1:0] mem [0:DEPTH-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -if (OFFSET > 0) begin - reg [WDBITS-1:0] mem_read; - reg [OFFSET-1:0] subaddr_r; - always @(posedge clk) begin - mem_read <= mem[ra[RABITS-1:OFFSET]]; - subaddr_r <= ra[OFFSET-1:0]; - end - - always @(mem_read, subaddr_r) - rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; -end -else -begin - always @(posedge clk) - case (OFFSET) - 0: rd <= mem[ra]; - -1: rd <= {{ mem[ra], mem[ra+1] }}; - endcase -end -endmodule -""" - -UNMIXED = MIXED_WRITE.format(wabits=4, wdbits=9, rabits=4, rdbits=9) -MIXED_9_18 = MIXED_WRITE.format(wabits=5, wdbits=9, rabits=4, rdbits=18) -MIXED_18_9 = MIXED_WRITE.format(wabits=3, wdbits=18, rabits=4, rdbits=9) -MIXED_36_9 = MIXED_WRITE.format(wabits=3, wdbits=36, rabits=5, rdbits=9) -MIXED_4_2 = MIXED_WRITE.format(wabits=5, wdbits=4, rabits=6, rdbits=2); - -TESTS += [ - Test("unmixed", UNMIXED, ["9b1B"], [], {"RAM_9b1B":1}), - Test("mixed_9_18", MIXED_9_18, ["9b1B"], [], {"RAM_9b1B":4}), #CHECK: only using half the memory - Test("mixed_18_9", MIXED_18_9, ["9b1B"], [], {"RAM_9b1B":1}), - Test("mixed_36_9", MIXED_36_9, ["9b1B"], [], {"RAM_9b1B":2}), - Test("mixed_4_2", MIXED_4_2, ["9b1B"], [], {"RAM_9b1B":1}), -] - -### basic TDP test - -TDP = """ -module top(clka, clkb, addra, addrb, rda, rdb, wda, wdb, wea, web); - -localparam ABITS = 6; -localparam DBITS = 6; - -input wire clka, clkb; -input wire wea, web; -input wire [ABITS-1:0] addra, addrb; -input wire [DBITS-1:0] wda, wdb; -output reg [DBITS-1:0] rda, rdb; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clka) - if (wea) - mem[addra] <= wda; - else - rda <= mem[addra]; - -always @(posedge clkb) - if (web) - mem[addrb] <= wdb; - else - rdb <= mem[addrb]; - -endmodule -""" - -TESTS += [ - Test("tdp", TDP, ["block_tdp", "block_sdp"], [], {"RAM_BLOCK_TDP": 1}), -] - -# shared clock -# Synchronous SDP with clock domain crossing -SYNC_2CLK = """ -module top(rclk, wclk, ra, wa, rd, wd, we); - -localparam ABITS = 6; -localparam DBITS = 16; - -input wire rclk, wclk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge wclk) - if (we) - mem[wa] <= wd; - -always @(posedge rclk) - rd <= mem[ra]; - -endmodule -""" - -TESTS += [ - Test("sync_2clk", SYNC_2CLK, ["block_sdp"], [], {"RAM_BLOCK_SDP": 1}), - Test("sync_shared", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_2clk_shared", SYNC_2CLK, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 0}), -] - -# inter-port transparency -# Synchronous SDP with write-first behaviour -SYNC_TRANS = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = 6; -localparam DBITS = 16; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(negedge clk) - if (we) - mem[wa] <= wd; - -always @(negedge clk) begin - rd <= mem[ra]; - if (we && ra == wa) - rd <= wd; -end - -endmodule -""" - -TESTS += [ - Test("sync_trans_old_old", SYNC_MID, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 0})}), - Test("sync_trans_old_new", SYNC_MID, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_trans_old_none", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_trans_new_old", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_trans_new_new", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 1})}), - Test("sync_trans_new_none", SYNC_TRANS, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), -] - -# rdwr checks -# Synchronous single-port RAM with mutually exclusive read/write -SP_NO_CHANGE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) - mem[addr] <= wd; - else - rd <= mem[addr]; -end - -endmodule -""" - -SP_NO_CHANGE_BE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire [1:0] we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) begin - if (we[0]) - mem[addr][7:0] <= wd[7:0]; - if (we[1]) - mem[addr][15:8] <= wd[15:8]; - end else - rd <= mem[addr]; -end - -endmodule -""" - -# Synchronous single-port RAM with write-first behaviour -SP_NEW = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) begin - mem[addr] <= wd; - rd <= wd; - end else - rd <= mem[addr]; -end - -endmodule -""" - -SP_NEW_BE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire [1:0] we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - rd <= mem[addr]; - if (we[0]) begin - mem[addr][7:0] <= wd[7:0]; - rd[7:0] <= wd[7:0]; - end - if (we[1]) begin - mem[addr][15:8] <= wd[15:8]; - rd[15:8] <= wd[15:8]; - end -end - -endmodule -""" - -# Synchronous single-port RAM with read-first behaviour -SP_OLD = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) - mem[addr] <= wd; - rd <= mem[addr]; -end - -endmodule -""" - -SP_OLD_BE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire [1:0] we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we[0]) - mem[addr][7:0] <= wd[7:0]; - if (we[1]) - mem[addr][15:8] <= wd[15:8]; - rd <= mem[addr]; -end - -endmodule -""" - -TESTS += [ - Test("sp_nc_none", SP_NO_CHANGE, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), - Test("sp_new_none", SP_NEW, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), - Test("sp_old_none", SP_OLD, ["block_sp"], [], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_nc", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_nc", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_nc", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_new", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new", SP_NEW, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_new", SP_OLD, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_old", SP_NO_CHANGE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_old", SP_NEW, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_old", SP_OLD, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_nc_new_only", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new_only", SP_NEW, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_new_only", SP_OLD, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_new_only_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new_only_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 2}), - Test("sp_old_new_only_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_new_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_new_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_old_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_old_be", SP_NEW_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_old_be", SP_OLD_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_nc_nc_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_nc_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 2}), - Test("sp_old_nc_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_auto", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_auto", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), - Test("sp_old_auto", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), - Test("sp_nc_auto_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_auto_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), - Test("sp_old_auto_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), -] - -# Synchronous read port with initial value -SP_INIT = """ -module top(clk, addr, rd, wd, we, re); - -input wire clk; -input wire we, re; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; - if (re) - rd <= mem[addr]; -end - -endmodule -""" - -SP_INIT_X = SP_INIT.format(ival="16'hxxxx") -SP_INIT_0 = SP_INIT.format(ival="16'h0000") -SP_INIT_V = SP_INIT.format(ival="16'h55aa") - -TESTS += [ - Test("sp_init_x_x", SP_INIT_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_x_x_re", SP_INIT_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_x_x_ce", SP_INIT_X, ["block_sp"], ["CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_x", SP_INIT_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_x_re", SP_INIT_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_0", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_0_re", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_any", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_any_re", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_x", SP_INIT_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_x_re", SP_INIT_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_0", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_0_re", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_any", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_any_re", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), -] - -# Synchronous read port with asynchronous reset -SP_ARST = """ -module top(clk, addr, rd, wd, we, re, ar); - -input wire clk; -input wire we, re, ar; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; -end -always @(posedge clk, posedge ar) begin - if (ar) - rd <= {aval}; - else if (re) - rd <= mem[addr]; -end - -endmodule -""" - -SP_ARST_X = SP_ARST.format(ival="16'hxxxx", aval="16'hxxxx") -SP_ARST_0 = SP_ARST.format(ival="16'hxxxx", aval="16'h0000") -SP_ARST_V = SP_ARST.format(ival="16'hxxxx", aval="16'h55aa") -SP_ARST_E = SP_ARST.format(ival="16'h55aa", aval="16'h55aa") -SP_ARST_N = SP_ARST.format(ival="16'h1234", aval="16'h55aa") - -TESTS += [ - Test("sp_arst_x_x", SP_ARST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_x_x_re", SP_ARST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_x", SP_ARST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_x_re", SP_ARST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_0", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_0_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_any", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_any_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_init", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_init_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_x", SP_ARST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_x_re", SP_ARST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_0", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_0_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_any", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_any_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_init", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_init_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_x", SP_ARST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_x_re", SP_ARST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_0", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_0_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_any", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_any_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_init", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_init_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_x", SP_ARST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_x_re", SP_ARST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_0", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_0_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_any", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_any_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_init", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_init_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), -] - -# Synchronous read port with synchronous reset (reset priority over enable) -SP_SRST = """ -module top(clk, addr, rd, wd, we, re, sr); - -input wire clk; -input wire we, re, sr; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; -end -always @(posedge clk) begin - if (sr) - rd <= {sval}; - else if (re) - rd <= mem[addr]; -end - -endmodule -""" - -# Synchronous read port with synchronous reet (enable priority over reset) -SP_SRST_G = """ -module top(clk, addr, rd, wd, we, re, sr); - -input wire clk; -input wire we, re, sr; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; -end -always @(posedge clk) begin - if (re) begin - if (sr) - rd <= {sval}; - else - rd <= mem[addr]; - end -end - -endmodule -""" - -SP_SRST_X = SP_SRST.format(ival="16'hxxxx", sval="16'hxxxx") -SP_SRST_0 = SP_SRST.format(ival="16'hxxxx", sval="16'h0000") -SP_SRST_V = SP_SRST.format(ival="16'hxxxx", sval="16'h55aa") -SP_SRST_E = SP_SRST.format(ival="16'h55aa", sval="16'h55aa") -SP_SRST_N = SP_SRST.format(ival="16'h1234", sval="16'h55aa") -SP_SRST_GV = SP_SRST_G.format(ival="16'hxxxx", sval="16'h55aa") - -TESTS += [ - Test("sp_srst_x_x", SP_SRST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_x_x_re", SP_SRST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_x", SP_SRST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_x_re", SP_SRST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_0", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_0_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_any", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_any_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_init", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_init_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_x", SP_SRST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_x_re", SP_SRST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_0", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_0_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_re_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_ce", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_ce_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_init", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_init_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_x", SP_SRST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_x_re", SP_SRST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_0", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_0_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_any", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_any_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_init", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_init_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_x", SP_SRST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_x_re", SP_SRST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_0", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_0_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_any", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_any_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_init", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_init_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_x", SP_SRST_GV, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_x_re", SP_SRST_GV, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_0", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_0_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_re_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_ce", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_ce_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_init", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_init_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), -] - -# Byte enables, wrbe_separate -SYNC_ENABLE = """ -module top(clk, rwa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] rwa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) begin - if (we) - mem[rwa] <= wd; - else - rd <= mem[rwa]; -end - -endmodule -""" - -for (abits, dbits, sep, defs, cells) in [ - (4, 4, False, ["NO_BYTE"], {"RAM_WREN": 1}), - (5, 4, False, ["NO_BYTE"], {"RAM_WREN": 2}), - (6, 4, False, ["NO_BYTE"], {"RAM_WREN": 4}), - # (4, 4, True, ["NO_BYTE"], {"RAM_WREN": 1}), # should throw an error - (3, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), # needs two write ports - (4, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), - (4, 4, False, ["W4_B4"], {"RAM_WREN": 1}), - (4, 8, True, ["W4_B4"], {"RAM_WREN": 2}), - (4, 8, False, ["W8_B4"], {"RAM_WREN": 1}), - (4, 8, True, ["W8_B4"], {"RAM_WREN": 1}), - (4, 8, False, ["W8_B8"], {"RAM_WREN": 1}), - (4, 8, True, ["W8_B8"], {"RAM_WREN": 1}), - -]: - name = f"wren_a{abits}d{dbits}_{defs[0]}" - if (sep): - defs.append("WRBE_SEPARATE") - name += "_separate" - - TESTS.append(Test( - name, SYNC_ENABLE.format(abits=abits, dbits=dbits), - ["wren"], defs, cells - )) - -# Write port with byte enables -ENABLES = """ -module top(clk, we, be, rwa, wd, rd); - -localparam ABITS = {abits}; -localparam WBITS = {wbits}; -localparam WORDS = {words}; - -input wire clk; -input wire we; -input wire [WORDS-1:0] be; -input wire [ABITS-1:0] rwa; -input wire [(WBITS*WORDS)-1:0] wd; -output reg [(WBITS*WORDS)-1:0] rd; - -reg [(WBITS*WORDS)-1:0] mem [0:2**ABITS-1]; - -integer i; -always @(posedge clk) - for (i=0; i> {bw}]) - for (j = 0; j < 2**{bw}; j = j + 1) - mem[wa << {ww} | i | j] <= wd[i | j]; - -always @(posedge rclk) - if (rr) - rd <= {sval}; - else if (re) - for (i = 0; i < 2**{rw}; i = i + 1) - rd[i] <= mem[ra << {rw} | i]; - -endmodule -""" - -for (aw, rw, ww, bw, xw, sval, cnt) in [ - (6, 1, 1, 1, 1, "2'h1", 1), - (7, 1, 1, 1, 1, "2'h2", 2), - (8, 1, 1, 1, 1, "2'h3", 4), - (6, 0, 0, 0, 0, "2'h0", 1), - (6, 1, 0, 0, 0, "2'h0", 1), - (6, 2, 0, 0, 0, "2'h0", 1), - (6, 3, 0, 0, 0, "2'h0", 1), - (6, 4, 0, 0, 0, "2'h0", 1), - (6, 5, 0, 0, 0, "2'h0", 2), - (6, 0, 1, 0, 0, "2'h0", 2), - (6, 0, 1, 1, 0, "2'h0", 1), - (6, 0, 2, 0, 0, "2'h0", 4), - (6, 0, 2, 2, 0, "2'h0", 1), - (6, 0, 3, 2, 0, "2'h0", 1), - (6, 0, 4, 2, 0, "2'h0", 1), - (6, 0, 5, 2, 0, "2'h0", 2), - (7, 0, 0, 0, 0, "2'h0", 2), - (7, 1, 0, 0, 0, "2'h0", 2), - (7, 2, 0, 0, 0, "2'h0", 2), - (7, 3, 0, 0, 0, "2'h0", 2), - (7, 4, 0, 0, 0, "2'h0", 2), - (7, 5, 0, 0, 0, "2'h0", 2), - (7, 0, 1, 0, 0, "2'h0", 2), - (7, 0, 1, 1, 0, "2'h0", 2), - (7, 0, 2, 0, 0, "2'h0", 4), - (7, 0, 2, 2, 0, "2'h0", 2), - (7, 0, 3, 2, 0, "2'h0", 2), - (7, 0, 4, 2, 0, "2'h0", 2), - (7, 0, 5, 2, 0, "2'h0", 2), -]: - TESTS.append(Test( - f"wide_sdp_a{aw}r{rw}w{ww}b{bw}x{xw}", - WIDE_SDP.format(aw=aw, rw=rw, ww=ww, bw=bw, xw=xw, sval=sval), - ["wide_sdp"], [], - {"RAM_WIDE_SDP": cnt} - )) - -WIDE_SP = """ -module top(clk, a, rd, re, rr, wd, we); - -input wire clk, re, rr; -input wire [2**({ww}-{bw})-1:0] we; -input wire [{aw}-1:0] a; -input wire [2**{ww}-1:0] wd; -output reg [2**{rw}-1:0] rd; - -reg mem [0:2**{aw}-1]; - -initial mem[3] = 0; -initial mem[17] = 1; -initial mem[23] = 0; -initial mem[24] = 1; - -integer i, j; -always @(posedge clk) begin - for (i = 0; i < 2**{ww}; i = i + 2**{bw}) - if (we[i >> {bw}]) - for (j = 0; j < 2**{bw}; j = j + 1) - mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; - if (rr) - rd <= {sval}; - else if (re) - for (i = 0; i < 2**{rw}; i = i + 1) - rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; -end - -endmodule -""" - -for (aw, rw, ww, bw, sval, cnt) in [ - (6, 1, 1, 1, "2'h1", 1), - (7, 1, 1, 1, "2'h2", 2), - (8, 1, 1, 1, "2'h3", 4), - (6, 0, 0, 0, "2'h0", 1), - (6, 1, 0, 0, "2'h0", 1), - (6, 2, 0, 0, "2'h0", 1), - (6, 3, 0, 0, "2'h0", 1), - (6, 4, 0, 0, "2'h0", 1), - (6, 5, 0, 0, "2'h0", 2), - (6, 0, 1, 0, "2'h0", 2), - (6, 0, 1, 1, "2'h0", 1), - (6, 0, 2, 0, "2'h0", 4), - (6, 0, 2, 2, "2'h0", 1), - (6, 0, 3, 2, "2'h0", 1), - (6, 0, 4, 2, "2'h0", 1), - (6, 0, 5, 2, "2'h0", 2), - (7, 0, 0, 0, "2'h0", 2), - (7, 1, 0, 0, "2'h0", 2), - (7, 2, 0, 0, "2'h0", 2), - (7, 3, 0, 0, "2'h0", 2), - (7, 4, 0, 0, "2'h0", 2), - (7, 5, 0, 0, "2'h0", 2), - (7, 0, 1, 0, "2'h0", 2), - (7, 0, 1, 1, "2'h0", 2), - (7, 0, 2, 0, "2'h0", 4), - (7, 0, 2, 2, "2'h0", 2), - (7, 0, 3, 2, "2'h0", 2), - (7, 0, 4, 2, "2'h0", 2), - (7, 0, 5, 2, "2'h0", 2), -]: - TESTS.append(Test( - f"wide_sp_mix_a{aw}r{rw}w{ww}b{bw}", - WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), - ["wide_sp"], ["WIDTH_MIX"], - {"RAM_WIDE_SP": cnt} - )) - -for (aw, rw, ww, bw, sval, cnt) in [ - (6, 1, 1, 1, "2'h1", 1), - (7, 1, 1, 1, "2'h2", 2), - (8, 1, 1, 1, "2'h3", 4), - (6, 0, 0, 0, "2'h0", 1), - (6, 1, 0, 0, "2'h0", 2), - (6, 2, 0, 0, "2'h0", 4), - (6, 3, 0, 0, "2'h0", 4), - (6, 4, 0, 0, "2'h0", 4), - (6, 5, 0, 0, "2'h0", 8), - (6, 0, 1, 0, "2'h0", 2), - (6, 0, 1, 1, "2'h0", 1), - (6, 0, 2, 0, "2'h0", 4), - (6, 0, 2, 2, "2'h0", 1), - (6, 0, 3, 2, "2'h0", 1), - (6, 0, 4, 2, "2'h0", 1), - (6, 0, 5, 2, "2'h0", 2), - (7, 0, 0, 0, "2'h0", 2), - (7, 1, 0, 0, "2'h0", 2), - (7, 2, 0, 0, "2'h0", 4), - (7, 3, 0, 0, "2'h0", 8), - (7, 4, 0, 0, "2'h0", 8), - (7, 5, 0, 0, "2'h0", 8), - (7, 0, 1, 0, "2'h0", 2), - (7, 0, 1, 1, "2'h0", 2), - (7, 0, 2, 0, "2'h0", 4), - (7, 0, 2, 2, "2'h0", 2), - (7, 0, 3, 2, "2'h0", 2), - (7, 0, 4, 2, "2'h0", 2), - (7, 0, 5, 2, "2'h0", 2), -]: - TESTS.append(Test( - f"wide_sp_tied_a{aw}r{rw}w{ww}b{bw}", - WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), - ["wide_sp"], [], - {"RAM_WIDE_SP": cnt} - )) - -WIDE_RW = """ -module top(clk, a, rd, re, wd, we); - -input wire clk, re; -input wire [2**({ww}-{bw})-1:0] we; -input wire [{aw}-1:0] a; -input wire [2**{ww}-1:0] wd; -output reg [2**{rw}-1:0] rd; - -(* ram_block *) -reg mem [0:2**{aw}-1]; - -initial mem[3] = 0; -initial mem[17] = 1; -initial mem[23] = 0; -initial mem[24] = 1; - -integer i, j; -always @(posedge clk) begin - for (i = 0; i < 2**{ww}; i = i + 2**{bw}) - if (we[i >> {bw}]) - for (j = 0; j < 2**{bw}; j = j + 1) - mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; - if (re) - for (i = 0; i < 2**{rw}; i = i + 1) - rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; -end - -endmodule -""" - -for (aw, rw, ww, bw, cntww, cntwr) in [ - (6, 1, 1, 1, 2, 1), - (7, 1, 1, 1, 4, 2), - (8, 1, 1, 1, 8, 4), - (6, 0, 0, 0, 4, 2), - (6, 1, 0, 0, 4, 2), - (6, 2, 0, 0, 4, 2), - (6, 3, 0, 0, 8, 2), - (6, 4, 0, 0, 16, 4), - (6, 5, 0, 0, 32, 8), - (6, 0, 1, 0, 4, 2), - (6, 0, 1, 1, 2, 1), - (6, 0, 2, 0, 4, 4), - (6, 0, 2, 2, 1, 2), - (6, 0, 3, 2, 1, 4), - (6, 0, 4, 2, 2, 8), - (6, 0, 5, 2, 4, 16), - (7, 0, 0, 0, 8, 4), - (7, 1, 0, 0, 8, 4), - (7, 2, 0, 0, 8, 4), - (7, 3, 0, 0, 8, 4), - (7, 4, 0, 0, 16, 4), - (7, 5, 0, 0, 32, 8), - (7, 0, 1, 0, 8, 4), - (7, 0, 1, 1, 4, 2), - (7, 0, 2, 0, 8, 4), - (7, 0, 2, 2, 2, 2), - (7, 0, 3, 2, 2, 4), - (7, 0, 4, 2, 2, 8), - (7, 0, 5, 2, 4, 16), -]: - TESTS.append(Test( - f"wide_read_a{aw}r{rw}w{ww}b{bw}", - WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), - ["wide_read"], [], - {"RAM_WIDE_READ": cntwr} - )) - TESTS.append(Test( - f"wide_write_a{aw}r{rw}w{ww}b{bw}", - WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), - ["wide_write"], [], - {"RAM_WIDE_WRITE": cntww} - )) - -# Multiple read ports -# 1rw port plus 3 (or 7) r ports -QUAD_PORT = """ -module top(clk, rwa, r0a, r1a, r2a, rd, r0d, r1d, r2d, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] rwa; -input wire [ABITS-1:0] r0a; -input wire [ABITS-1:0] r1a; -input wire [ABITS-1:0] r2a; -input wire [DBITS-1:0] wd; -output wire [DBITS-1:0] rd; -output wire [DBITS-1:0] r0d; -output wire [DBITS-1:0] r1d; -output wire [DBITS-1:0] r2d; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[rwa] <= wd; - -assign rd = mem[rwa]; -assign r0d = mem[r0a]; -assign r1d = mem[r1a]; -assign r2d = mem[r2a]; - -endmodule -""" - -for (abits, dbits, cnt) in [ - (2, 2, 1), - (4, 2, 1), - (5, 2, 2), - (4, 4, 2), - (6, 2, 4), - (4, 8, 4), -]: - TESTS.append(Test( - f"quad_port_a{abits}d{dbits}", - QUAD_PORT.format(abits=abits, dbits=dbits), - ["multilut"], ["PORTS_QUAD"], - {"LUT_MULTI": cnt} - )) - -# Wide asynchronous read port -WIDE_READ = """ -module top(clk, we, rwa, wd, rd); - -localparam ABITS = {abits}; -localparam WBITS = {wbits}; -localparam RWORDS = {rwords}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] rwa; -input wire [WBITS-1:0] wd; -output wire [(WBITS*RWORDS)-1:0] rd; - -reg [WBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[rwa] <= wd; - -genvar i; -generate - for (i = 0; i < RWORDS; i = i + 1) - assign rd[i*WBITS+:WBITS] = mem[rwa + i]; -endgenerate - -endmodule -""" - -for (abits, wbits, rwords, cntquad, cntoct) in [ - (4, 2, 1, 1, 1), - (4, 2, 2, 1, 1), - (4, 2, 3, 1, 1), - (4, 2, 4, 1, 1), - (4, 2, 5, 2, 1), - (4, 2, 6, 2, 1), - (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read - (4, 2, 8, 3, 1), # ports per quad port LUT (i.e. 7 ports in 2, 8 ports in 3) - (4, 2, 9, 3, 2), - (4, 4, 1, 2, 2), - (4, 4, 4, 2, 2), - (4, 4, 6, 4, 2), - (4, 4, 9, 6, 4), - (5, 2, 1, 2, 2), - (5, 2, 4, 2, 2), - (5, 2, 9, 6, 4), -]: - TESTS.append(Test( - f"wide_quad_a{abits}w{wbits}r{rwords}", - WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), - ["multilut"], ["PORTS_QUAD"], - {"LUT_MULTI": cntquad} - )) - TESTS.append(Test( - f"wide_oct_a{abits}w{wbits}r{rwords}", - WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), - ["multilut"], ["PORTS_OCT"], - {"LUT_MULTI": cntoct} - )) - -# signal priorities & pattern testing -PRIORITY = """ -module top(clk, clken, wren, wben, rden, rst, addr, wdata, rdata); - -localparam ABITS = {abits}; -localparam WBITS = {wbits}; -localparam WORDS = {words}; - -localparam BITS = WBITS * WORDS; - -input wire clk, clken; -input wire wren, rden, rst; -input wire [WORDS-1:0] wben; -input wire [ABITS-1:0] addr; -input wire [BITS-1:0] wdata; -output reg [BITS-1:0] rdata; - -reg [BITS-1:0] mem [0:2**ABITS-1]; - -integer i; -always @(posedge clk) begin -{code} -end -endmodule -""" -#reset_gate in ["ungated", "rst", "rden && rst"] -#clk_en in [True, False] -#rdwr in ["nc", "old", "new", "undef", "newdef"] - -for (testname, reset_gate, rdwr, clk_en, add_logic) in [ - ("no_reset", "", "old", False, 0), - ("gclken", "rst", "old", False, 0), - ("ungated", "ungated", "old", False, 1), # muxes wren with rst - ("gclken_ce", "rst", "old", True, 3), # AND to simulate CLK_EN - ("grden", "rden && rst", "old", False, 1), # selects _clken, simulates _rden - ("grden_ce", "rden && rst", "old", True, 4), # both of the above - ("exclwr", "", "nc", False, 2), # selects new_only and simulates - ("excl_rst", "rst", "nc", False, 3), # as above, extra gate for rst - ("transwr", "", "new", False, 0), - ("trans_rst", "rst", "new", False, 0), -]: - write = "if (wren) \n\t\tmem[addr] <= wdata;" - - if rdwr == "new": - read = """if (rden) - if (wren) - rdata <= wdata; - else - rdata <= mem[addr];""" - else: - read = "if (rden) \n\t\trdata <= mem[addr];" - - if "rst" in reset_gate: - read = f"if ({reset_gate})\n\t\trdata <= 0; \n\telse {read}" - - if reset_gate == "ungated": - outer = "if (rst)\n\trdata <= 0;\nelse " - else: - outer = "" - - if clk_en: - outer = f"{outer}if (clken) " - - code = f"""{outer}begin - {write} - {"else " if rdwr == "nc" else ""}{read} -end""" - - TESTS.append(Test( - testname, PRIORITY.format(code=code, abits=4, wbits=8, words=2), - ["block_sp_full"], ["USE_SRST"], - {"RAM_BLOCK_SP": 1, "$*": add_logic} - )) - -for (testname, reset_gate, defs, rdwr, add_logic) in [ - ("wr_byte", "", ["USE_SRST_BLOCKING"], "old", 0), - ("trans_byte", "", ["USE_SRST_BLOCKING"], "new", 0), - ("wr_rst_byte", "rst", ["USE_SRST"], "old", 2), # expected mux to emulate blocking - ("rst_wr_byte", "rst", ["USE_SRST_BLOCKING"], "old", 2), # should use hardware blocking, doesn't - ("rdenrst_wr_byte", "rden && rst", ["USE_SRST"], "old", 3), -]: - wordsloop = "for (i=0; i 0) begin + reg [WDBITS-1:0] mem_read; + reg [OFFSET-1:0] subaddr_r; + always @(posedge clk) begin + mem_read <= mem[ra[RABITS-1:OFFSET]]; + subaddr_r <= ra[OFFSET-1:0]; + end + + always @(mem_read, subaddr_r) + rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; +end +else +begin + always @(posedge clk) + case (OFFSET) + 0: rd <= mem[ra]; + -1: rd <= {{ mem[ra], mem[ra+1] }}; + endcase +end +endmodule +""" + +UNMIXED = MIXED_WRITE.format(wabits=4, wdbits=9, rabits=4, rdbits=9) +MIXED_9_18 = MIXED_WRITE.format(wabits=5, wdbits=9, rabits=4, rdbits=18) +MIXED_18_9 = MIXED_WRITE.format(wabits=3, wdbits=18, rabits=4, rdbits=9) +MIXED_36_9 = MIXED_WRITE.format(wabits=3, wdbits=36, rabits=5, rdbits=9) +MIXED_4_2 = MIXED_WRITE.format(wabits=5, wdbits=4, rabits=6, rdbits=2); + +TESTS += [ + Test("unmixed", UNMIXED, ["9b1B"], [], {"RAM_9b1B":1}), + Test("mixed_9_18", MIXED_9_18, ["9b1B"], [], {"RAM_9b1B":4}), #CHECK: only using half the memory + Test("mixed_18_9", MIXED_18_9, ["9b1B"], [], {"RAM_9b1B":1}), + Test("mixed_36_9", MIXED_36_9, ["9b1B"], [], {"RAM_9b1B":2}), + Test("mixed_4_2", MIXED_4_2, ["9b1B"], [], {"RAM_9b1B":1}), +] + +### basic TDP test + +TDP = """ +module top(clka, clkb, addra, addrb, rda, rdb, wda, wdb, wea, web); + +localparam ABITS = 6; +localparam DBITS = 6; + +input wire clka, clkb; +input wire wea, web; +input wire [ABITS-1:0] addra, addrb; +input wire [DBITS-1:0] wda, wdb; +output reg [DBITS-1:0] rda, rdb; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clka) + if (wea) + mem[addra] <= wda; + else + rda <= mem[addra]; + +always @(posedge clkb) + if (web) + mem[addrb] <= wdb; + else + rdb <= mem[addrb]; + +endmodule +""" + +TESTS += [ + Test("tdp", TDP, ["block_tdp", "block_sdp"], [], {"RAM_BLOCK_TDP": 1}), +] + +# shared clock +# Synchronous SDP with clock domain crossing +SYNC_2CLK = """ +module top(rclk, wclk, ra, wa, rd, wd, we); + +localparam ABITS = 6; +localparam DBITS = 16; + +input wire rclk, wclk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge wclk) + if (we) + mem[wa] <= wd; + +always @(posedge rclk) + rd <= mem[ra]; + +endmodule +""" + +TESTS += [ + Test("sync_2clk", SYNC_2CLK, ["block_sdp"], [], {"RAM_BLOCK_SDP": 1}), + Test("sync_shared", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_2clk_shared", SYNC_2CLK, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 0}), +] + +# inter-port transparency +# Synchronous SDP with write-first behaviour +SYNC_TRANS = """ +module top(clk, ra, wa, rd, wd, we); + +localparam ABITS = 6; +localparam DBITS = 16; + +input wire clk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(negedge clk) + if (we) + mem[wa] <= wd; + +always @(negedge clk) begin + rd <= mem[ra]; + if (we && ra == wa) + rd <= wd; +end + +endmodule +""" + +TESTS += [ + Test("sync_trans_old_old", SYNC_MID, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 0})}), + Test("sync_trans_old_new", SYNC_MID, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_trans_old_none", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_trans_new_old", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_trans_new_new", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 1})}), + Test("sync_trans_new_none", SYNC_TRANS, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), +] + +# rdwr checks +# Synchronous single-port RAM with mutually exclusive read/write +SP_NO_CHANGE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) + mem[addr] <= wd; + else + rd <= mem[addr]; +end + +endmodule +""" + +SP_NO_CHANGE_BE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire [1:0] we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) begin + if (we[0]) + mem[addr][7:0] <= wd[7:0]; + if (we[1]) + mem[addr][15:8] <= wd[15:8]; + end else + rd <= mem[addr]; +end + +endmodule +""" + +# Synchronous single-port RAM with write-first behaviour +SP_NEW = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) begin + mem[addr] <= wd; + rd <= wd; + end else + rd <= mem[addr]; +end + +endmodule +""" + +SP_NEW_BE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire [1:0] we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + rd <= mem[addr]; + if (we[0]) begin + mem[addr][7:0] <= wd[7:0]; + rd[7:0] <= wd[7:0]; + end + if (we[1]) begin + mem[addr][15:8] <= wd[15:8]; + rd[15:8] <= wd[15:8]; + end +end + +endmodule +""" + +# Synchronous single-port RAM with read-first behaviour +SP_OLD = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) + mem[addr] <= wd; + rd <= mem[addr]; +end + +endmodule +""" + +SP_OLD_BE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire [1:0] we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we[0]) + mem[addr][7:0] <= wd[7:0]; + if (we[1]) + mem[addr][15:8] <= wd[15:8]; + rd <= mem[addr]; +end + +endmodule +""" + +TESTS += [ + Test("sp_nc_none", SP_NO_CHANGE, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), + Test("sp_new_none", SP_NEW, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), + Test("sp_old_none", SP_OLD, ["block_sp"], [], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_nc", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_nc", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_nc", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_new", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new", SP_NEW, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_new", SP_OLD, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_old", SP_NO_CHANGE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_old", SP_NEW, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_old", SP_OLD, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_nc_new_only", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new_only", SP_NEW, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_new_only", SP_OLD, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_new_only_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new_only_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 2}), + Test("sp_old_new_only_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_new_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_new_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_old_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_old_be", SP_NEW_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_old_be", SP_OLD_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_nc_nc_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_nc_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 2}), + Test("sp_old_nc_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_auto", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_auto", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), + Test("sp_old_auto", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), + Test("sp_nc_auto_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_auto_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), + Test("sp_old_auto_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), +] + +# Synchronous read port with initial value +SP_INIT = """ +module top(clk, addr, rd, wd, we, re); + +input wire clk; +input wire we, re; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; + if (re) + rd <= mem[addr]; +end + +endmodule +""" + +SP_INIT_X = SP_INIT.format(ival="16'hxxxx") +SP_INIT_0 = SP_INIT.format(ival="16'h0000") +SP_INIT_V = SP_INIT.format(ival="16'h55aa") + +TESTS += [ + Test("sp_init_x_x", SP_INIT_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_x_x_re", SP_INIT_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_x_x_ce", SP_INIT_X, ["block_sp"], ["CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_x", SP_INIT_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_x_re", SP_INIT_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_0", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_0_re", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_any", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_any_re", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_x", SP_INIT_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_x_re", SP_INIT_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_0", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_0_re", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_any", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_any_re", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), +] + +# Synchronous read port with asynchronous reset +SP_ARST = """ +module top(clk, addr, rd, wd, we, re, ar); + +input wire clk; +input wire we, re, ar; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; +end +always @(posedge clk, posedge ar) begin + if (ar) + rd <= {aval}; + else if (re) + rd <= mem[addr]; +end + +endmodule +""" + +SP_ARST_X = SP_ARST.format(ival="16'hxxxx", aval="16'hxxxx") +SP_ARST_0 = SP_ARST.format(ival="16'hxxxx", aval="16'h0000") +SP_ARST_V = SP_ARST.format(ival="16'hxxxx", aval="16'h55aa") +SP_ARST_E = SP_ARST.format(ival="16'h55aa", aval="16'h55aa") +SP_ARST_N = SP_ARST.format(ival="16'h1234", aval="16'h55aa") + +TESTS += [ + Test("sp_arst_x_x", SP_ARST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_x_x_re", SP_ARST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_x", SP_ARST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_x_re", SP_ARST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_0", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_0_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_any", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_any_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_init", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_init_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_x", SP_ARST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_x_re", SP_ARST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_0", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_0_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_any", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_any_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_init", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_init_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_x", SP_ARST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_x_re", SP_ARST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_0", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_0_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_any", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_any_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_init", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_init_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_x", SP_ARST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_x_re", SP_ARST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_0", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_0_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_any", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_any_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_init", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_init_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), +] + +# Synchronous read port with synchronous reset (reset priority over enable) +SP_SRST = """ +module top(clk, addr, rd, wd, we, re, sr); + +input wire clk; +input wire we, re, sr; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; +end +always @(posedge clk) begin + if (sr) + rd <= {sval}; + else if (re) + rd <= mem[addr]; +end + +endmodule +""" + +# Synchronous read port with synchronous reet (enable priority over reset) +SP_SRST_G = """ +module top(clk, addr, rd, wd, we, re, sr); + +input wire clk; +input wire we, re, sr; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; +end +always @(posedge clk) begin + if (re) begin + if (sr) + rd <= {sval}; + else + rd <= mem[addr]; + end +end + +endmodule +""" + +SP_SRST_X = SP_SRST.format(ival="16'hxxxx", sval="16'hxxxx") +SP_SRST_0 = SP_SRST.format(ival="16'hxxxx", sval="16'h0000") +SP_SRST_V = SP_SRST.format(ival="16'hxxxx", sval="16'h55aa") +SP_SRST_E = SP_SRST.format(ival="16'h55aa", sval="16'h55aa") +SP_SRST_N = SP_SRST.format(ival="16'h1234", sval="16'h55aa") +SP_SRST_GV = SP_SRST_G.format(ival="16'hxxxx", sval="16'h55aa") + +TESTS += [ + Test("sp_srst_x_x", SP_SRST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_x_x_re", SP_SRST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_x", SP_SRST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_x_re", SP_SRST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_0", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_0_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_any", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_any_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_init", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_init_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_x", SP_SRST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_x_re", SP_SRST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_0", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_0_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_re_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_ce", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_ce_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_init", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_init_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_x", SP_SRST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_x_re", SP_SRST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_0", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_0_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_any", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_any_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_init", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_init_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_x", SP_SRST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_x_re", SP_SRST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_0", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_0_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_any", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_any_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_init", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_init_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_x", SP_SRST_GV, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_x_re", SP_SRST_GV, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_0", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_0_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_re_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_ce", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_ce_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_init", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_init_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), +] + +# Byte enables, wrbe_separate +SYNC_ENABLE = """ +module top(clk, rwa, rd, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] rwa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) begin + if (we) + mem[rwa] <= wd; + else + rd <= mem[rwa]; +end + +endmodule +""" + +for (abits, dbits, sep, defs, cells) in [ + (4, 4, False, ["NO_BYTE"], {"RAM_WREN": 1}), + (5, 4, False, ["NO_BYTE"], {"RAM_WREN": 2}), + (6, 4, False, ["NO_BYTE"], {"RAM_WREN": 4}), + # (4, 4, True, ["NO_BYTE"], {"RAM_WREN": 1}), # should throw an error + (3, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), # needs two write ports + (4, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), + (4, 4, False, ["W4_B4"], {"RAM_WREN": 1}), + (4, 8, True, ["W4_B4"], {"RAM_WREN": 2}), + (4, 8, False, ["W8_B4"], {"RAM_WREN": 1}), + (4, 8, True, ["W8_B4"], {"RAM_WREN": 1}), + (4, 8, False, ["W8_B8"], {"RAM_WREN": 1}), + (4, 8, True, ["W8_B8"], {"RAM_WREN": 1}), + +]: + name = f"wren_a{abits}d{dbits}_{defs[0]}" + if (sep): + defs.append("WRBE_SEPARATE") + name += "_separate" + + TESTS.append(Test( + name, SYNC_ENABLE.format(abits=abits, dbits=dbits), + ["wren"], defs, cells + )) + +# Write port with byte enables +ENABLES = """ +module top(clk, we, be, rwa, wd, rd); + +localparam ABITS = {abits}; +localparam WBITS = {wbits}; +localparam WORDS = {words}; + +input wire clk; +input wire we; +input wire [WORDS-1:0] be; +input wire [ABITS-1:0] rwa; +input wire [(WBITS*WORDS)-1:0] wd; +output reg [(WBITS*WORDS)-1:0] rd; + +reg [(WBITS*WORDS)-1:0] mem [0:2**ABITS-1]; + +integer i; +always @(posedge clk) + for (i=0; i> {bw}]) + for (j = 0; j < 2**{bw}; j = j + 1) + mem[wa << {ww} | i | j] <= wd[i | j]; + +always @(posedge rclk) + if (rr) + rd <= {sval}; + else if (re) + for (i = 0; i < 2**{rw}; i = i + 1) + rd[i] <= mem[ra << {rw} | i]; + +endmodule +""" + +for (aw, rw, ww, bw, xw, sval, cnt) in [ + (6, 1, 1, 1, 1, "2'h1", 1), + (7, 1, 1, 1, 1, "2'h2", 2), + (8, 1, 1, 1, 1, "2'h3", 4), + (6, 0, 0, 0, 0, "2'h0", 1), + (6, 1, 0, 0, 0, "2'h0", 1), + (6, 2, 0, 0, 0, "2'h0", 1), + (6, 3, 0, 0, 0, "2'h0", 1), + (6, 4, 0, 0, 0, "2'h0", 1), + (6, 5, 0, 0, 0, "2'h0", 2), + (6, 0, 1, 0, 0, "2'h0", 2), + (6, 0, 1, 1, 0, "2'h0", 1), + (6, 0, 2, 0, 0, "2'h0", 4), + (6, 0, 2, 2, 0, "2'h0", 1), + (6, 0, 3, 2, 0, "2'h0", 1), + (6, 0, 4, 2, 0, "2'h0", 1), + (6, 0, 5, 2, 0, "2'h0", 2), + (7, 0, 0, 0, 0, "2'h0", 2), + (7, 1, 0, 0, 0, "2'h0", 2), + (7, 2, 0, 0, 0, "2'h0", 2), + (7, 3, 0, 0, 0, "2'h0", 2), + (7, 4, 0, 0, 0, "2'h0", 2), + (7, 5, 0, 0, 0, "2'h0", 2), + (7, 0, 1, 0, 0, "2'h0", 2), + (7, 0, 1, 1, 0, "2'h0", 2), + (7, 0, 2, 0, 0, "2'h0", 4), + (7, 0, 2, 2, 0, "2'h0", 2), + (7, 0, 3, 2, 0, "2'h0", 2), + (7, 0, 4, 2, 0, "2'h0", 2), + (7, 0, 5, 2, 0, "2'h0", 2), +]: + TESTS.append(Test( + f"wide_sdp_a{aw}r{rw}w{ww}b{bw}x{xw}", + WIDE_SDP.format(aw=aw, rw=rw, ww=ww, bw=bw, xw=xw, sval=sval), + ["wide_sdp"], [], + {"RAM_WIDE_SDP": cnt} + )) + +WIDE_SP = """ +module top(clk, a, rd, re, rr, wd, we); + +input wire clk, re, rr; +input wire [2**({ww}-{bw})-1:0] we; +input wire [{aw}-1:0] a; +input wire [2**{ww}-1:0] wd; +output reg [2**{rw}-1:0] rd; + +reg mem [0:2**{aw}-1]; + +initial mem[3] = 0; +initial mem[17] = 1; +initial mem[23] = 0; +initial mem[24] = 1; + +integer i, j; +always @(posedge clk) begin + for (i = 0; i < 2**{ww}; i = i + 2**{bw}) + if (we[i >> {bw}]) + for (j = 0; j < 2**{bw}; j = j + 1) + mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; + if (rr) + rd <= {sval}; + else if (re) + for (i = 0; i < 2**{rw}; i = i + 1) + rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; +end + +endmodule +""" + +for (aw, rw, ww, bw, sval, cnt) in [ + (6, 1, 1, 1, "2'h1", 1), + (7, 1, 1, 1, "2'h2", 2), + (8, 1, 1, 1, "2'h3", 4), + (6, 0, 0, 0, "2'h0", 1), + (6, 1, 0, 0, "2'h0", 1), + (6, 2, 0, 0, "2'h0", 1), + (6, 3, 0, 0, "2'h0", 1), + (6, 4, 0, 0, "2'h0", 1), + (6, 5, 0, 0, "2'h0", 2), + (6, 0, 1, 0, "2'h0", 2), + (6, 0, 1, 1, "2'h0", 1), + (6, 0, 2, 0, "2'h0", 4), + (6, 0, 2, 2, "2'h0", 1), + (6, 0, 3, 2, "2'h0", 1), + (6, 0, 4, 2, "2'h0", 1), + (6, 0, 5, 2, "2'h0", 2), + (7, 0, 0, 0, "2'h0", 2), + (7, 1, 0, 0, "2'h0", 2), + (7, 2, 0, 0, "2'h0", 2), + (7, 3, 0, 0, "2'h0", 2), + (7, 4, 0, 0, "2'h0", 2), + (7, 5, 0, 0, "2'h0", 2), + (7, 0, 1, 0, "2'h0", 2), + (7, 0, 1, 1, "2'h0", 2), + (7, 0, 2, 0, "2'h0", 4), + (7, 0, 2, 2, "2'h0", 2), + (7, 0, 3, 2, "2'h0", 2), + (7, 0, 4, 2, "2'h0", 2), + (7, 0, 5, 2, "2'h0", 2), +]: + TESTS.append(Test( + f"wide_sp_mix_a{aw}r{rw}w{ww}b{bw}", + WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), + ["wide_sp"], ["WIDTH_MIX"], + {"RAM_WIDE_SP": cnt} + )) + +for (aw, rw, ww, bw, sval, cnt) in [ + (6, 1, 1, 1, "2'h1", 1), + (7, 1, 1, 1, "2'h2", 2), + (8, 1, 1, 1, "2'h3", 4), + (6, 0, 0, 0, "2'h0", 1), + (6, 1, 0, 0, "2'h0", 2), + (6, 2, 0, 0, "2'h0", 4), + (6, 3, 0, 0, "2'h0", 4), + (6, 4, 0, 0, "2'h0", 4), + (6, 5, 0, 0, "2'h0", 8), + (6, 0, 1, 0, "2'h0", 2), + (6, 0, 1, 1, "2'h0", 1), + (6, 0, 2, 0, "2'h0", 4), + (6, 0, 2, 2, "2'h0", 1), + (6, 0, 3, 2, "2'h0", 1), + (6, 0, 4, 2, "2'h0", 1), + (6, 0, 5, 2, "2'h0", 2), + (7, 0, 0, 0, "2'h0", 2), + (7, 1, 0, 0, "2'h0", 2), + (7, 2, 0, 0, "2'h0", 4), + (7, 3, 0, 0, "2'h0", 8), + (7, 4, 0, 0, "2'h0", 8), + (7, 5, 0, 0, "2'h0", 8), + (7, 0, 1, 0, "2'h0", 2), + (7, 0, 1, 1, "2'h0", 2), + (7, 0, 2, 0, "2'h0", 4), + (7, 0, 2, 2, "2'h0", 2), + (7, 0, 3, 2, "2'h0", 2), + (7, 0, 4, 2, "2'h0", 2), + (7, 0, 5, 2, "2'h0", 2), +]: + TESTS.append(Test( + f"wide_sp_tied_a{aw}r{rw}w{ww}b{bw}", + WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), + ["wide_sp"], [], + {"RAM_WIDE_SP": cnt} + )) + +WIDE_RW = """ +module top(clk, a, rd, re, wd, we); + +input wire clk, re; +input wire [2**({ww}-{bw})-1:0] we; +input wire [{aw}-1:0] a; +input wire [2**{ww}-1:0] wd; +output reg [2**{rw}-1:0] rd; + +(* ram_block *) +reg mem [0:2**{aw}-1]; + +initial mem[3] = 0; +initial mem[17] = 1; +initial mem[23] = 0; +initial mem[24] = 1; + +integer i, j; +always @(posedge clk) begin + for (i = 0; i < 2**{ww}; i = i + 2**{bw}) + if (we[i >> {bw}]) + for (j = 0; j < 2**{bw}; j = j + 1) + mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; + if (re) + for (i = 0; i < 2**{rw}; i = i + 1) + rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; +end + +endmodule +""" + +for (aw, rw, ww, bw, cntww, cntwr) in [ + (6, 1, 1, 1, 2, 1), + (7, 1, 1, 1, 4, 2), + (8, 1, 1, 1, 8, 4), + (6, 0, 0, 0, 4, 2), + (6, 1, 0, 0, 4, 2), + (6, 2, 0, 0, 4, 2), + (6, 3, 0, 0, 8, 2), + (6, 4, 0, 0, 16, 4), + (6, 5, 0, 0, 32, 8), + (6, 0, 1, 0, 4, 2), + (6, 0, 1, 1, 2, 1), + (6, 0, 2, 0, 4, 4), + (6, 0, 2, 2, 1, 2), + (6, 0, 3, 2, 1, 4), + (6, 0, 4, 2, 2, 8), + (6, 0, 5, 2, 4, 16), + (7, 0, 0, 0, 8, 4), + (7, 1, 0, 0, 8, 4), + (7, 2, 0, 0, 8, 4), + (7, 3, 0, 0, 8, 4), + (7, 4, 0, 0, 16, 4), + (7, 5, 0, 0, 32, 8), + (7, 0, 1, 0, 8, 4), + (7, 0, 1, 1, 4, 2), + (7, 0, 2, 0, 8, 4), + (7, 0, 2, 2, 2, 2), + (7, 0, 3, 2, 2, 4), + (7, 0, 4, 2, 2, 8), + (7, 0, 5, 2, 4, 16), +]: + TESTS.append(Test( + f"wide_read_a{aw}r{rw}w{ww}b{bw}", + WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), + ["wide_read"], [], + {"RAM_WIDE_READ": cntwr} + )) + TESTS.append(Test( + f"wide_write_a{aw}r{rw}w{ww}b{bw}", + WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), + ["wide_write"], [], + {"RAM_WIDE_WRITE": cntww} + )) + +# Multiple read ports +# 1rw port plus 3 (or 7) r ports +QUAD_PORT = """ +module top(clk, rwa, r0a, r1a, r2a, rd, r0d, r1d, r2d, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] rwa; +input wire [ABITS-1:0] r0a; +input wire [ABITS-1:0] r1a; +input wire [ABITS-1:0] r2a; +input wire [DBITS-1:0] wd; +output wire [DBITS-1:0] rd; +output wire [DBITS-1:0] r0d; +output wire [DBITS-1:0] r1d; +output wire [DBITS-1:0] r2d; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) + if (we) + mem[rwa] <= wd; + +assign rd = mem[rwa]; +assign r0d = mem[r0a]; +assign r1d = mem[r1a]; +assign r2d = mem[r2a]; + +endmodule +""" + +for (abits, dbits, cnt) in [ + (2, 2, 1), + (4, 2, 1), + (5, 2, 2), + (4, 4, 2), + (6, 2, 4), + (4, 8, 4), +]: + TESTS.append(Test( + f"quad_port_a{abits}d{dbits}", + QUAD_PORT.format(abits=abits, dbits=dbits), + ["multilut"], ["PORTS_QUAD"], + {"LUT_MULTI": cnt} + )) + +# Wide asynchronous read port +WIDE_READ = """ +module top(clk, we, rwa, wd, rd); + +localparam ABITS = {abits}; +localparam WBITS = {wbits}; +localparam RWORDS = {rwords}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] rwa; +input wire [WBITS-1:0] wd; +output wire [(WBITS*RWORDS)-1:0] rd; + +reg [WBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) + if (we) + mem[rwa] <= wd; + +genvar i; +generate + for (i = 0; i < RWORDS; i = i + 1) + assign rd[i*WBITS+:WBITS] = mem[rwa + i]; +endgenerate + +endmodule +""" + +for (abits, wbits, rwords, cntquad, cntoct) in [ + (4, 2, 1, 1, 1), + (4, 2, 2, 1, 1), + (4, 2, 3, 1, 1), + (4, 2, 4, 1, 1), + (4, 2, 5, 2, 1), + (4, 2, 6, 2, 1), + (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read + (4, 2, 8, 3, 1), # ports per quad port LUT (i.e. 7 ports in 2, 8 ports in 3) + (4, 2, 9, 3, 2), + (4, 4, 1, 2, 2), + (4, 4, 4, 2, 2), + (4, 4, 6, 4, 2), + (4, 4, 9, 6, 4), + (5, 2, 1, 2, 2), + (5, 2, 4, 2, 2), + (5, 2, 9, 6, 4), +]: + TESTS.append(Test( + f"wide_quad_a{abits}w{wbits}r{rwords}", + WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), + ["multilut"], ["PORTS_QUAD"], + {"LUT_MULTI": cntquad} + )) + TESTS.append(Test( + f"wide_oct_a{abits}w{wbits}r{rwords}", + WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), + ["multilut"], ["PORTS_OCT"], + {"LUT_MULTI": cntoct} + )) + +# signal priorities & pattern testing +PRIORITY = """ +module top(clk, clken, wren, wben, rden, rst, addr, wdata, rdata); + +localparam ABITS = {abits}; +localparam WBITS = {wbits}; +localparam WORDS = {words}; + +localparam BITS = WBITS * WORDS; + +input wire clk, clken; +input wire wren, rden, rst; +input wire [WORDS-1:0] wben; +input wire [ABITS-1:0] addr; +input wire [BITS-1:0] wdata; +output reg [BITS-1:0] rdata; + +reg [BITS-1:0] mem [0:2**ABITS-1]; + +integer i; +always @(posedge clk) begin +{code} +end +endmodule +""" +#reset_gate in ["ungated", "rst", "rden && rst"] +#clk_en in [True, False] +#rdwr in ["nc", "old", "new", "undef", "newdef"] + +for (testname, reset_gate, rdwr, clk_en, add_logic) in [ + ("no_reset", "", "old", False, 0), + ("gclken", "rst", "old", False, 0), + ("ungated", "ungated", "old", False, 1), # muxes wren with rst + ("gclken_ce", "rst", "old", True, 3), # AND to simulate CLK_EN + ("grden", "rden && rst", "old", False, 1), # selects _clken, simulates _rden + ("grden_ce", "rden && rst", "old", True, 4), # both of the above + ("exclwr", "", "nc", False, 2), # selects new_only and simulates + ("excl_rst", "rst", "nc", False, 3), # as above, extra gate for rst + ("transwr", "", "new", False, 0), + ("trans_rst", "rst", "new", False, 0), +]: + write = "if (wren) \n\t\tmem[addr] <= wdata;" + + if rdwr == "new": + read = """if (rden) + if (wren) + rdata <= wdata; + else + rdata <= mem[addr];""" + else: + read = "if (rden) \n\t\trdata <= mem[addr];" + + if "rst" in reset_gate: + read = f"if ({reset_gate})\n\t\trdata <= 0; \n\telse {read}" + + if reset_gate == "ungated": + outer = "if (rst)\n\trdata <= 0;\nelse " + else: + outer = "" + + if clk_en: + outer = f"{outer}if (clken) " + + code = f"""{outer}begin + {write} + {"else " if rdwr == "nc" else ""}{read} +end""" + + TESTS.append(Test( + testname, PRIORITY.format(code=code, abits=4, wbits=8, words=2), + ["block_sp_full"], ["USE_SRST"], + {"RAM_BLOCK_SP": 1, "$*": add_logic} + )) + +for (testname, reset_gate, defs, rdwr, add_logic) in [ + ("wr_byte", "", ["USE_SRST_BLOCKING"], "old", 0), + ("trans_byte", "", ["USE_SRST_BLOCKING"], "new", 0), + ("wr_rst_byte", "rst", ["USE_SRST"], "old", 2), # expected mux to emulate blocking + ("rst_wr_byte", "rst", ["USE_SRST_BLOCKING"], "old", 2), # should use hardware blocking, doesn't + ("rdenrst_wr_byte", "rden && rst", ["USE_SRST"], "old", 3), +]: + wordsloop = "for (i=0; i Date: Fri, 20 Mar 2026 16:36:36 +0100 Subject: [PATCH 36/36] Fix yml for verific tests --- .github/workflows/test-verific.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-verific.yml b/.github/workflows/test-verific.yml index cd88f547e..0b9ab9493 100644 --- a/.github/workflows/test-verific.yml +++ b/.github/workflows/test-verific.yml @@ -78,7 +78,7 @@ jobs: - name: Run Verific specific Yosys tests run: | make -C tests/sva - cd tests/svtypes && bash run-test.sh + make -C tests/svtypes - name: Run SBY tests if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}