From 41d57e614858457001bcef4fc03f1019f93ac9f6 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Mon, 7 Jun 2021 22:05:57 +0200 Subject: [PATCH 1/4] Added VUnit run script. The VUnit run script will find all VHDL files based on given search patterns, figure out their dependencies, and support incremental compile based on the dependencies. The same script is used for all VUnit supported simulators. Supporting several simulators simplifies the adoption of this project. At this point only compilation is performed. Coming commits will enable simulation of VHDL testbenches. Signed-off-by: Lars Asplund --- run.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 run.py diff --git a/run.py b/run.py new file mode 100644 index 0000000..7a98338 --- /dev/null +++ b/run.py @@ -0,0 +1,20 @@ +from pathlib import Path +from vunit import VUnit +from glob import glob + +prj = VUnit.from_argv() +root = Path(__file__).parent + +lib = prj.add_library("lib") +lib.add_source_files(root / "litedram/extras/*.vhdl") +lib.add_source_files(root / "litedram/generated/sim/*.vhdl") + +# Use multiply.vhd and not xilinx-mult.vhd +vhdl_files_in_root = glob(str(root / "*.vhdl")) +vhdl_files_to_use = [src_file for src_file in vhdl_files_in_root if "xilinx-mult" not in src_file] +lib.add_source_files(vhdl_to_use) + +unisim = prj.add_library("unisim") +unisim.add_source_files(root / "sim-unisim/*.vhdl") + +prj.main() From 08c0c4c1b41b3e7d18b9c3fa4a9bdfa42b5f491c Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Mon, 7 Jun 2021 22:34:00 +0200 Subject: [PATCH 2/4] Make core testbenches recognized by VUnit This commit also removes the dependencies these testbenches have on VHPIDIRECT. The use of VHPIDIRECT limits the number of available simulators for the project. Rather than using foreign functions the testbenches can be implemented entirely in VHDL where equivalent functionality exists. For these testbenches the VHPIDIRECT-based randomization functions were replaced with VHDL-based functions. The testbenches recognized by VUnit can be executed in parallel threads for better simulation performance using the -p option to the run.py script Signed-off-by: Lars Asplund --- .github/workflows/test.yml | 1 - Makefile | 16 ++------ countzero_tb.vhdl | 19 +++++++-- divider_tb.vhdl | 63 +++++++++++++++++------------ foreign_random.vhdl | 30 ++++++++++++++ multiply_tb.vhdl | 43 ++++++++++++-------- plru_tb.vhdl | 8 +++- random.vhdl | 7 ++-- rotator_tb.vhdl | 83 +++++++++++++++++++++----------------- run.py | 15 +++++-- 10 files changed, 182 insertions(+), 103 deletions(-) create mode 100644 foreign_random.vhdl diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c40139c..544d618 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,6 @@ jobs: max-parallel: 3 matrix: task: [ - "tests_unit", "tests_console", "{1..99}", "{100..199}", diff --git a/Makefile b/Makefile index 1b1f714..3bf5528 100644 --- a/Makefile +++ b/Makefile @@ -39,8 +39,8 @@ ECPPACK = $(DOCKERBIN) $(DOCKERARGS) hdlc/prjtrellis ecppack OPENOCD = $(DOCKERBIN) $(DOCKERARGS) --device /dev/bus/usb hdlc/prog openocd endif -all = core_tb icache_tb dcache_tb multiply_tb dmi_dtm_tb divider_tb \ - rotator_tb countzero_tb wishbone_bram_tb soc_reset_tb +all = core_tb icache_tb dcache_tb dmi_dtm_tb \ + wishbone_bram_tb soc_reset_tb all: $(all) @@ -62,7 +62,7 @@ uart_files = $(wildcard uart16550/*.v) soc_sim_files = $(core_files) $(soc_files) sim_console.vhdl sim_pp_uart.vhdl sim_bram_helpers.vhdl \ sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl \ sim_16550_uart.vhdl \ - random.vhdl glibc_random.vhdl glibc_random_helpers.vhdl + foreign_random.vhdl glibc_random.vhdl glibc_random_helpers.vhdl soc_sim_c_files = sim_vhpi_c.c sim_bram_helpers_c.c sim_console_c.c \ sim_jtag_socket_c.c @@ -79,7 +79,6 @@ $(unisim_lib): $(unisim_lib_files) $(GHDL) -i --std=08 --work=unisim --workdir=$(unisim_dir) $^ GHDLFLAGS += -P$(unisim_dir) -core_tbs = multiply_tb divider_tb rotator_tb countzero_tb soc_tbs = core_tb icache_tb dcache_tb dmi_dtm_tb wishbone_bram_tb soc_flash_tbs = core_flash_tb soc_dram_tbs = dram_tb core_dram_tb @@ -105,9 +104,6 @@ $(soc_flash_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) $(fmf_l $(soc_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) %.vhdl $(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(soc_sim_files) $@.vhdl -e $@ -$(core_tbs): %: $(core_files) glibc_random.vhdl glibc_random_helpers.vhdl %.vhdl - $(GHDL) -c $(GHDLFLAGS) $(core_files) glibc_random.vhdl glibc_random_helpers.vhdl $@.vhdl -e $@ - soc_reset_tb: fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl $(GHDL) -c $(GHDLFLAGS) fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl -e $@ @@ -236,19 +232,15 @@ test_micropython: core_tb test_micropython_long: core_tb @./scripts/test_micropython_long.py -tests_core_tb = $(patsubst %_tb,%_tb_test,$(core_tbs)) tests_soc_tb = $(patsubst %_tb,%_tb_test,$(soc_tbs)) %_test: % ./$< --assert-level=error > /dev/null -tests_core: $(tests_core_tb) - tests_soc: $(tests_soc_tb) # FIXME SOC tests have bit rotted, so disable for now -#tests_unit: tests_core tests_soc -tests_unit: tests_core +#tests_unit: tests_soc TAGS: find . -name '*.vhdl' | xargs ./scripts/vhdltags diff --git a/countzero_tb.vhdl b/countzero_tb.vhdl index 14868c6..671cda3 100644 --- a/countzero_tb.vhdl +++ b/countzero_tb.vhdl @@ -1,12 +1,18 @@ +library vunit_lib; +context vunit_lib.vunit_context; + library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; use work.common.all; -use work.glibc_random.all; + +library osvvm; +use osvvm.RandomPkg.all; entity countzero_tb is + generic (runner_cfg : string := runner_cfg_default); end countzero_tb; architecture behave of countzero_tb is @@ -37,7 +43,12 @@ begin stim_process: process variable r: std_ulogic_vector(63 downto 0); + variable rnd : RandomPType; begin + rnd.InitSeed(stim_process'path_name); + + test_runner_setup(runner, runner_cfg); + -- test with input = 0 report "test zero input"; rs <= (others => '0'); @@ -63,7 +74,7 @@ begin report "test cntlzd/w"; count_right <= '0'; for j in 0 to 100 loop - r := pseudorand(64); + r := rnd.RandSlv(64); r(63) := '1'; for i in 0 to 63 loop rs <= r; @@ -88,7 +99,7 @@ begin report "test cnttzd/w"; count_right <= '1'; for j in 0 to 100 loop - r := pseudorand(64); + r := rnd.RandSlv(64); r(0) := '1'; for i in 0 to 63 loop rs <= r; @@ -109,6 +120,6 @@ begin end loop; end loop; - std.env.finish; + test_runner_cleanup(runner); end process; end behave; diff --git a/divider_tb.vhdl b/divider_tb.vhdl index 01d1d81..e41d80f 100644 --- a/divider_tb.vhdl +++ b/divider_tb.vhdl @@ -1,3 +1,6 @@ +library vunit_lib; +context vunit_lib.vunit_context; + library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; @@ -5,10 +8,13 @@ use ieee.numeric_std.all; library work; use work.decode_types.all; use work.common.all; -use work.glibc_random.all; use work.ppc_fx_insns.all; +library osvvm; +use osvvm.RandomPkg.all; + entity divider_tb is + generic (runner_cfg : string := runner_cfg_default); end divider_tb; architecture behave of divider_tb is @@ -37,7 +43,12 @@ begin variable q128: std_ulogic_vector(127 downto 0); variable q64: std_ulogic_vector(63 downto 0); variable rem32: std_ulogic_vector(31 downto 0); + variable rnd : RandomPType; begin + rnd.InitSeed(stim_process'path_name); + + test_runner_setup(runner, runner_cfg); + rst <= '1'; wait for clk_period; rst <= '0'; @@ -94,8 +105,8 @@ begin divd_loop : for dlength in 1 to 8 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); @@ -129,8 +140,8 @@ begin divdu_loop : for dlength in 1 to 8 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra; d1.divisor <= rb; @@ -164,8 +175,8 @@ begin divde_loop : for vlength in 1 to 8 loop for dlength in 1 to vlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); @@ -205,8 +216,8 @@ begin divdeu_loop : for vlength in 1 to 8 loop for dlength in 1 to vlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra; d1.divisor <= rb; @@ -243,8 +254,8 @@ begin divw_loop : for dlength in 1 to 4 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); @@ -280,8 +291,8 @@ begin divwu_loop : for dlength in 1 to 4 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra; d1.divisor <= rb; @@ -317,8 +328,8 @@ begin divwe_loop : for vlength in 1 to 4 loop for dlength in 1 to vlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000"; - rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); @@ -358,8 +369,8 @@ begin divweu_loop : for vlength in 1 to 4 loop for dlength in 1 to vlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 32)) & x"00000000"; - rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra; d1.divisor <= rb; @@ -395,8 +406,8 @@ begin modsd_loop : for dlength in 1 to 8 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); @@ -433,8 +444,8 @@ begin modud_loop : for dlength in 1 to 8 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra; d1.divisor <= rb; @@ -471,8 +482,8 @@ begin modsw_loop : for dlength in 1 to 4 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); @@ -514,8 +525,8 @@ begin moduw_loop : for dlength in 1 to 4 loop for vlength in 1 to dlength loop for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64)); + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); d1.dividend <= ra; d1.divisor <= rb; @@ -547,6 +558,6 @@ begin end loop; end loop; - std.env.finish; + test_runner_cleanup(runner); end process; end behave; diff --git a/foreign_random.vhdl b/foreign_random.vhdl new file mode 100644 index 0000000..063c30e --- /dev/null +++ b/foreign_random.vhdl @@ -0,0 +1,30 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.glibc_random.all; + +entity random is + port ( + clk : in std_ulogic; + data : out std_ulogic_vector(63 downto 0); + raw : out std_ulogic_vector(63 downto 0); + err : out std_ulogic + ); +end entity random; + +architecture behaviour of random is +begin + err <= '0'; + + process(clk) + variable rand : std_ulogic_vector(63 downto 0); + begin + if rising_edge(clk) then + rand := pseudorand(64); + data <= rand; + raw <= rand; + end if; + end process; +end behaviour; diff --git a/multiply_tb.vhdl b/multiply_tb.vhdl index 884b828..7458c33 100644 --- a/multiply_tb.vhdl +++ b/multiply_tb.vhdl @@ -1,3 +1,6 @@ +library vunit_lib; +context vunit_lib.vunit_context; + library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; @@ -5,10 +8,13 @@ use ieee.numeric_std.all; library work; use work.decode_types.all; use work.common.all; -use work.glibc_random.all; use work.ppc_fx_insns.all; +library osvvm; +use osvvm.RandomPkg.all; + entity multiply_tb is + generic (runner_cfg : string := runner_cfg_default); end multiply_tb; architecture behave of multiply_tb is @@ -46,7 +52,12 @@ begin variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0); variable si: std_ulogic_vector(15 downto 0); variable sign: std_ulogic; + variable rnd : RandomPType; begin + rnd.InitSeed(stim_process'path_name); + + test_runner_setup(runner, runner_cfg); + wait for clk_period; m1.valid <= '1'; @@ -84,8 +95,8 @@ begin -- test mulld mulld_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulld(ra, rb); @@ -110,8 +121,8 @@ begin -- test mulhdu mulhdu_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhdu(ra, rb); @@ -135,8 +146,8 @@ begin -- test mulhd mulhd_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhd(ra, rb); @@ -161,8 +172,8 @@ begin -- test mullw mullw_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); behave_rt := ppc_mullw(ra, rb); @@ -189,8 +200,8 @@ begin -- test mulhw mulhw_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhw(ra, rb); @@ -218,8 +229,8 @@ begin -- test mulhwu mulhwu_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - rb := pseudorand(rb'length); + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhwu(ra, rb); @@ -246,8 +257,8 @@ begin -- test mulli mulli_loop : for i in 0 to 1000 loop - ra := pseudorand(ra'length); - si := pseudorand(si'length); + ra := rnd.RandSlv(ra'length); + si := rnd.RandSlv(si'length); behave_rt := ppc_mulli(ra, si); @@ -271,7 +282,7 @@ begin report "bad mulli expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0)); end loop; - std.env.finish; + test_runner_cleanup(runner); wait; end process; end behave; diff --git a/plru_tb.vhdl b/plru_tb.vhdl index 751542c..78f0e94 100644 --- a/plru_tb.vhdl +++ b/plru_tb.vhdl @@ -1,3 +1,6 @@ +library vunit_lib; +context vunit_lib.vunit_context; + library ieee; use ieee.std_logic_1164.all; @@ -6,6 +9,7 @@ use work.common.all; use work.wishbone_types.all; entity plru_tb is + generic (runner_cfg : string := runner_cfg_default); end plru_tb; architecture behave of plru_tb is @@ -50,6 +54,8 @@ begin stim: process begin + test_runner_setup(runner, runner_cfg); + wait for 4*clk_period; report "accessing 1:"; @@ -103,6 +109,6 @@ begin wait for clk_period; report "lru:" & to_hstring(lru); - std.env.finish; + test_runner_cleanup(runner); end process; end; diff --git a/random.vhdl b/random.vhdl index 063c30e..ec34e22 100644 --- a/random.vhdl +++ b/random.vhdl @@ -2,8 +2,8 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -library work; -use work.glibc_random.all; +library osvvm; +use osvvm.RandomPkg.all; entity random is port ( @@ -20,9 +20,10 @@ begin process(clk) variable rand : std_ulogic_vector(63 downto 0); + variable rnd : RandomPType; begin if rising_edge(clk) then - rand := pseudorand(64); + rand := rnd.RandSlv(64); data <= rand; raw <= rand; end if; diff --git a/rotator_tb.vhdl b/rotator_tb.vhdl index fa68994..2849ccf 100644 --- a/rotator_tb.vhdl +++ b/rotator_tb.vhdl @@ -1,14 +1,20 @@ +library vunit_lib; +context vunit_lib.vunit_context; + library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; use work.common.all; -use work.glibc_random.all; use work.ppc_fx_insns.all; use work.insn_helpers.all; +library osvvm; +use osvvm.RandomPkg.all; + entity rotator_tb is + generic (runner_cfg : string := runner_cfg_default); end rotator_tb; architecture behave of rotator_tb is @@ -41,7 +47,12 @@ begin stim_process: process variable behave_ra: std_ulogic_vector(63 downto 0); variable behave_ca_ra: std_ulogic_vector(64 downto 0); + variable rnd : RandomPType; begin + rnd.InitSeed(stim_process'path_name); + + test_runner_setup(runner, runner_cfg); + -- rlwinm, rlwnm report "test rlw[i]nm"; ra <= (others => '0'); @@ -52,9 +63,9 @@ begin clear_right <= '1'; extsw <= '0'; rlwnm_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); - insn <= x"00000" & '0' & pseudorand(10) & '0'; + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; wait for clk_period; behave_ra := ppc_rlwinm(rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); assert behave_ra = result @@ -69,10 +80,10 @@ begin clear_left <= '1'; clear_right <= '1'; rlwimi_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - ra <= pseudorand(64); - shift <= "00" & pseudorand(5); - insn <= x"00000" & '0' & pseudorand(10) & '0'; + rs <= rnd.RandSlv(64); + ra <= rnd.RandSlv(64); + shift <= "00" & rnd.RandSlv(5); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; wait for clk_period; behave_ra := ppc_rlwimi(ra, rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); assert behave_ra = result @@ -88,9 +99,9 @@ begin clear_left <= '1'; clear_right <= '0'; rldicl_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); - insn <= x"00000" & '0' & pseudorand(10) & '0'; + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; wait for clk_period; behave_ra := ppc_rldicl(rs, shift(5 downto 0), insn_mb(insn)); assert behave_ra = result @@ -106,9 +117,9 @@ begin clear_left <= '0'; clear_right <= '1'; rldicr_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); - insn <= x"00000" & '0' & pseudorand(10) & '0'; + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; wait for clk_period; behave_ra := ppc_rldicr(rs, shift(5 downto 0), insn_me(insn)); --report "rs = " & to_hstring(rs); @@ -129,9 +140,9 @@ begin clear_left <= '1'; clear_right <= '1'; rldic_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= '0' & pseudorand(6); - insn <= x"00000" & '0' & pseudorand(10) & '0'; + rs <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; wait for clk_period; behave_ra := ppc_rldic(rs, shift(5 downto 0), insn_mb(insn)); assert behave_ra = result @@ -146,10 +157,10 @@ begin clear_left <= '1'; clear_right <= '1'; rldimi_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - ra <= pseudorand(64); - shift <= '0' & pseudorand(6); - insn <= x"00000" & '0' & pseudorand(10) & '0'; + rs <= rnd.RandSlv(64); + ra <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; wait for clk_period; behave_ra := ppc_rldimi(ra, rs, shift(5 downto 0), insn_mb(insn)); assert behave_ra = result @@ -165,8 +176,8 @@ begin clear_left <= '0'; clear_right <= '0'; slw_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); wait for clk_period; behave_ra := ppc_slw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result @@ -182,8 +193,8 @@ begin clear_left <= '0'; clear_right <= '0'; sld_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); wait for clk_period; behave_ra := ppc_sld(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result @@ -199,8 +210,8 @@ begin clear_left <= '0'; clear_right <= '0'; srw_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); wait for clk_period; behave_ra := ppc_srw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result @@ -216,8 +227,8 @@ begin clear_left <= '0'; clear_right <= '0'; srd_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); wait for clk_period; behave_ra := ppc_srd(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result @@ -233,8 +244,8 @@ begin clear_left <= '0'; clear_right <= '0'; sraw_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= '0' & pseudorand(6); + rs <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); wait for clk_period; behave_ca_ra := ppc_sraw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); --report "rs = " & to_hstring(rs); @@ -254,8 +265,8 @@ begin clear_left <= '0'; clear_right <= '0'; srad_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= pseudorand(7); + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); wait for clk_period; behave_ca_ra := ppc_srad(rs, std_ulogic_vector(resize(unsigned(shift), 64))); --report "rs = " & to_hstring(rs); @@ -276,8 +287,8 @@ begin clear_right <= '0'; extsw <= '1'; extswsli_loop : for i in 0 to 1000 loop - rs <= pseudorand(64); - shift <= '0' & pseudorand(6); + rs <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); wait for clk_period; behave_ra := rs; behave_ra(63 downto 32) := (others => rs(31)); @@ -291,6 +302,6 @@ begin report "bad extswsli expected " & to_hstring(behave_ra) & " got " & to_hstring(result); end loop; - std.env.finish; + test_runner_cleanup(runner); end process; end behave; diff --git a/run.py b/run.py index 7a98338..4d78f0f 100644 --- a/run.py +++ b/run.py @@ -3,16 +3,23 @@ from vunit import VUnit from glob import glob prj = VUnit.from_argv() +prj.add_osvvm() root = Path(__file__).parent lib = prj.add_library("lib") lib.add_source_files(root / "litedram/extras/*.vhdl") lib.add_source_files(root / "litedram/generated/sim/*.vhdl") -# Use multiply.vhd and not xilinx-mult.vhd -vhdl_files_in_root = glob(str(root / "*.vhdl")) -vhdl_files_to_use = [src_file for src_file in vhdl_files_in_root if "xilinx-mult" not in src_file] -lib.add_source_files(vhdl_to_use) +# Use multiply.vhd and not xilinx-mult.vhd. Use VHDL-based random. +vhdl_files = glob(str(root / "*.vhdl")) +vhdl_files = [ + src_file + for src_file in vhdl_files + if ("xilinx-mult" not in src_file) + and ("foreign_random" not in src_file) + and ("nonrandom" not in src_file) +] +lib.add_source_files(vhdl_files) unisim = prj.add_library("unisim") unisim.add_source_files(root / "sim-unisim/*.vhdl") From 0940b8a9d3e77b6f9a6f10d632d674cde0ac47ac Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Tue, 8 Jun 2021 22:32:57 +0200 Subject: [PATCH 3/4] Organized VUnit testbenches into test cases. Several of the testbenches have stimuli code divided into sections preceded with a header comment explaining what is being tested. These sections have been made into VUnit test cases. The default behavior of VUnit is to run each test case in a separate simulation which comes with a number of benefits: * A failing test case doesn't prevent other test cases to be executed * Test cases are independent. A test case cannot fail as a side-effect to a problem with another test case * Test execution can be more parallelized and the overall test execution time reduced Signed-off-by: Lars Asplund --- countzero_tb.vhdl | 130 +++---- divider_tb.vhdl | 888 ++++++++++++++++++++++------------------------ multiply_tb.vhdl | 314 ++++++++-------- rotator_tb.vhdl | 461 ++++++++++++------------ 4 files changed, 880 insertions(+), 913 deletions(-) diff --git a/countzero_tb.vhdl b/countzero_tb.vhdl index 671cda3..c51d4a7 100644 --- a/countzero_tb.vhdl +++ b/countzero_tb.vhdl @@ -49,75 +49,77 @@ begin test_runner_setup(runner, runner_cfg); - -- test with input = 0 - report "test zero input"; - rs <= (others => '0'); - is_32bit <= '0'; - count_right <= '0'; - wait for clk_period; - assert result = x"0000000000000040" - report "bad cntlzd 0 = " & to_hstring(result); - count_right <= '1'; - wait for clk_period; - assert result = x"0000000000000040" - report "bad cnttzd 0 = " & to_hstring(result); - is_32bit <= '1'; - count_right <= '0'; - wait for clk_period; - assert result = x"0000000000000020" - report "bad cntlzw 0 = " & to_hstring(result); - count_right <= '1'; - wait for clk_period; - assert result = x"0000000000000020" - report "bad cnttzw 0 = " & to_hstring(result); - - report "test cntlzd/w"; - count_right <= '0'; - for j in 0 to 100 loop - r := rnd.RandSlv(64); - r(63) := '1'; - for i in 0 to 63 loop - rs <= r; + while test_suite loop + if run("Test with input = 0") then + rs <= (others => '0'); is_32bit <= '0'; + count_right <= '0'; wait for clk_period; - assert to_integer(unsigned(result)) = i - report "bad cntlzd " & to_hstring(rs) & " -> " & to_hstring(result); - rs <= r(31 downto 0) & r(63 downto 32); - is_32bit <= '1'; + assert result = x"0000000000000040" + report "bad cntlzd 0 = " & to_hstring(result); + count_right <= '1'; wait for clk_period; - if i < 32 then - assert to_integer(unsigned(result)) = i - report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result); - else - assert to_integer(unsigned(result)) = 32 - report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result); - end if; - r := '0' & r(63 downto 1); - end loop; - end loop; - - report "test cnttzd/w"; - count_right <= '1'; - for j in 0 to 100 loop - r := rnd.RandSlv(64); - r(0) := '1'; - for i in 0 to 63 loop - rs <= r; - is_32bit <= '0'; - wait for clk_period; - assert to_integer(unsigned(result)) = i - report "bad cnttzd " & to_hstring(rs) & " -> " & to_hstring(result); + assert result = x"0000000000000040" + report "bad cnttzd 0 = " & to_hstring(result); is_32bit <= '1'; + count_right <= '0'; + wait for clk_period; + assert result = x"0000000000000020" + report "bad cntlzw 0 = " & to_hstring(result); + count_right <= '1'; wait for clk_period; - if i < 32 then - assert to_integer(unsigned(result)) = i - report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result); - else - assert to_integer(unsigned(result)) = 32 - report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result); - end if; - r := r(62 downto 0) & '0'; - end loop; + assert result = x"0000000000000020" + report "bad cnttzw 0 = " & to_hstring(result); + + elsif run("Test cntlzd/w") then + count_right <= '0'; + for j in 0 to 100 loop + r := rnd.RandSlv(64); + r(63) := '1'; + for i in 0 to 63 loop + rs <= r; + is_32bit <= '0'; + wait for clk_period; + assert to_integer(unsigned(result)) = i + report "bad cntlzd " & to_hstring(rs) & " -> " & to_hstring(result); + rs <= r(31 downto 0) & r(63 downto 32); + is_32bit <= '1'; + wait for clk_period; + if i < 32 then + assert to_integer(unsigned(result)) = i + report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result); + else + assert to_integer(unsigned(result)) = 32 + report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result); + end if; + r := '0' & r(63 downto 1); + end loop; + end loop; + + elsif run("Test cnttzd/w") then + count_right <= '1'; + for j in 0 to 100 loop + r := rnd.RandSlv(64); + r(0) := '1'; + for i in 0 to 63 loop + rs <= r; + is_32bit <= '0'; + wait for clk_period; + assert to_integer(unsigned(result)) = i + report "bad cnttzd " & to_hstring(rs) & " -> " & to_hstring(result); + is_32bit <= '1'; + wait for clk_period; + if i < 32 then + assert to_integer(unsigned(result)) = i + report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result); + else + assert to_integer(unsigned(result)) = 32 + report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result); + end if; + r := r(62 downto 0) & '0'; + end loop; + end loop; + end if; end loop; test_runner_cleanup(runner); diff --git a/divider_tb.vhdl b/divider_tb.vhdl index e41d80f..4fee8f7 100644 --- a/divider_tb.vhdl +++ b/divider_tb.vhdl @@ -49,513 +49,485 @@ begin test_runner_setup(runner, runner_cfg); - rst <= '1'; - wait for clk_period; - rst <= '0'; - - d1.valid <= '1'; - d1.dividend <= x"0000000010001000"; - d1.divisor <= x"0000000000001111"; - d1.is_signed <= '0'; - d1.is_32bit <= '0'; - d1.is_extended <= '0'; - d1.is_modulus <= '0'; - d1.neg_result <= '0'; - - wait for clk_period; - assert d2.valid = '0'; - - d1.valid <= '0'; - - for j in 0 to 66 loop + while test_suite loop + rst <= '1'; wait for clk_period; - if d2.valid = '1' then - exit; - end if; - end loop; + rst <= '0'; - assert d2.valid = '1'; - assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data); + d1.is_signed <= '0'; + d1.neg_result <= '0'; + d1.is_extended <= '0'; + d1.is_32bit <= '0'; + d1.is_modulus <= '0'; + d1.valid <= '0'; - wait for clk_period; - assert d2.valid = '0' report "valid"; + if run("Test interface") then + d1.valid <= '1'; + d1.dividend <= x"0000000010001000"; + d1.divisor <= x"0000000000001111"; - d1.valid <= '1'; + wait for clk_period; + assert d2.valid = '0'; - wait for clk_period; - assert d2.valid = '0' report "valid"; + d1.valid <= '0'; - d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; - end loop; + assert d2.valid = '1'; + assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data); - assert d2.valid = '1'; - assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data); + wait for clk_period; + assert d2.valid = '0' report "valid"; - wait for clk_period; - assert d2.valid = '0'; + d1.valid <= '1'; - -- test divd - report "test divd"; - divd_loop : for dlength in 1 to 8 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); + wait for clk_period; + assert d2.valid = '0' report "valid"; - d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); - d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); - d1.is_signed <= '1'; - d1.neg_result <= ra(63) xor rb(63); - d1.valid <= '1'; + d1.valid <= '0'; + for j in 0 to 66 loop wait for clk_period; - - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; - end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" and (ra /= x"8000000000000000" or rb /= x"ffffffffffffffff") then - behave_rt := ppc_divd(ra, rb); + if d2.valid = '1' then + exit; end if; - assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) - report "bad divd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); end loop; - end loop; - end loop; - -- test divdu - report "test divdu"; - divdu_loop : for dlength in 1 to 8 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra; - d1.divisor <= rb; - d1.is_signed <= '0'; - d1.neg_result <= '0'; - d1.valid <= '1'; - - wait for clk_period; - - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + assert d2.valid = '1'; + assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data); + + wait for clk_period; + assert d2.valid = '0'; + + elsif run("Test divd") then + divd_loop : for dlength in 1 to 8 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); + d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); + d1.is_signed <= '1'; + d1.neg_result <= ra(63) xor rb(63); + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" and (ra /= x"8000000000000000" or rb /= x"ffffffffffffffff") then + behave_rt := ppc_divd(ra, rb); + end if; + assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) + report "bad divd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - behave_rt := ppc_divdu(ra, rb); - end if; - assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) - report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); end loop; - end loop; - end loop; - - -- test divde - report "test divde"; - divde_loop : for vlength in 1 to 8 loop - for dlength in 1 to vlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); - d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); - d1.is_signed <= '1'; - d1.neg_result <= ra(63) xor rb(63); - d1.is_extended <= '1'; - d1.valid <= '1'; - - wait for clk_period; - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test divdu") then + divdu_loop : for dlength in 1 to 8 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra; + d1.divisor <= rb; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + behave_rt := ppc_divdu(ra, rb); + end if; + assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) + report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - d128 := ra & x"0000000000000000"; - q128 := std_ulogic_vector(signed(d128) / signed(rb)); - if q128(127 downto 63) = x"0000000000000000" & '0' or - q128(127 downto 63) = x"ffffffffffffffff" & '1' then - behave_rt := q128(63 downto 0); - end if; - end if; - assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) - report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); end loop; - end loop; - end loop; - - -- test divdeu - report "test divdeu"; - divdeu_loop : for vlength in 1 to 8 loop - for dlength in 1 to vlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra; - d1.divisor <= rb; - d1.is_signed <= '0'; - d1.neg_result <= '0'; - d1.is_extended <= '1'; - d1.valid <= '1'; - - wait for clk_period; - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test divde") then + divde_loop : for vlength in 1 to 8 loop + for dlength in 1 to vlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); + d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); + d1.is_signed <= '1'; + d1.neg_result <= ra(63) xor rb(63); + d1.is_extended <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + d128 := ra & x"0000000000000000"; + q128 := std_ulogic_vector(signed(d128) / signed(rb)); + if q128(127 downto 63) = x"0000000000000000" & '0' or + q128(127 downto 63) = x"ffffffffffffffff" & '1' then + behave_rt := q128(63 downto 0); + end if; + end if; + assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) + report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if unsigned(rb) > unsigned(ra) then - d128 := ra & x"0000000000000000"; - q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb)); - behave_rt := q128(63 downto 0); - end if; - assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) - report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); end loop; - end loop; - end loop; - - -- test divw - report "test divw"; - divw_loop : for dlength in 1 to 4 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); - d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); - d1.is_signed <= '1'; - d1.neg_result <= ra(63) xor rb(63); - d1.is_extended <= '0'; - d1.is_32bit <= '1'; - d1.valid <= '1'; - - wait for clk_period; - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test divdeu") then + divdeu_loop : for vlength in 1 to 8 loop + for dlength in 1 to vlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra; + d1.divisor <= rb; + d1.is_extended <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if unsigned(rb) > unsigned(ra) then + d128 := ra & x"0000000000000000"; + q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb)); + behave_rt := q128(63 downto 0); + end if; + assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data) + report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then - behave_rt := ppc_divw(ra, rb); - end if; - assert behave_rt = d2.write_reg_data - report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); end loop; - end loop; - end loop; - - -- test divwu - report "test divwu"; - divwu_loop : for dlength in 1 to 4 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra; - d1.divisor <= rb; - d1.is_signed <= '0'; - d1.neg_result <= '0'; - d1.is_extended <= '0'; - d1.is_32bit <= '1'; - d1.valid <= '1'; - wait for clk_period; - - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test divw") then + divw_loop : for dlength in 1 to 4 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); + d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); + d1.is_signed <= '1'; + d1.neg_result <= ra(63) xor rb(63); + d1.is_32bit <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then + behave_rt := ppc_divw(ra, rb); + end if; + assert behave_rt = d2.write_reg_data + report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - behave_rt := ppc_divwu(ra, rb); - end if; - assert behave_rt = d2.write_reg_data - report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); end loop; - end loop; - end loop; - -- test divwe - report "test divwe"; - divwe_loop : for vlength in 1 to 4 loop - for dlength in 1 to vlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; - rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); - d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); - d1.is_signed <= '1'; - d1.neg_result <= ra(63) xor rb(63); - d1.is_extended <= '0'; - d1.is_32bit <= '1'; - d1.valid <= '1'; - - wait for clk_period; - - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test divwu") then + divwu_loop : for dlength in 1 to 4 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra; + d1.divisor <= rb; + d1.is_32bit <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + behave_rt := ppc_divwu(ra, rb); + end if; + assert behave_rt = d2.write_reg_data + report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - q64 := std_ulogic_vector(signed(ra) / signed(rb)); - if q64(63 downto 31) = x"00000000" & '0' or - q64(63 downto 31) = x"ffffffff" & '1' then - behave_rt := x"00000000" & q64(31 downto 0); - end if; - assert behave_rt = d2.write_reg_data - report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); - end if; end loop; - end loop; - end loop; - -- test divweu - report "test divweu"; - divweu_loop : for vlength in 1 to 4 loop - for dlength in 1 to vlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; - rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra; - d1.divisor <= rb; - d1.is_signed <= '0'; - d1.neg_result <= '0'; - d1.is_extended <= '0'; - d1.is_32bit <= '1'; - d1.valid <= '1'; - - wait for clk_period; - - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test divwe") then + divwe_loop : for vlength in 1 to 4 loop + for dlength in 1 to vlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); + d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); + d1.is_signed <= '1'; + d1.neg_result <= ra(63) xor rb(63); + d1.is_32bit <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + q64 := std_ulogic_vector(signed(ra) / signed(rb)); + if q64(63 downto 31) = x"00000000" & '0' or + q64(63 downto 31) = x"ffffffff" & '1' then + behave_rt := x"00000000" & q64(31 downto 0); + end if; + assert behave_rt = d2.write_reg_data + report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); + end if; + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then - behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb)); - end if; - assert behave_rt = d2.write_reg_data - report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); end loop; - end loop; - end loop; - - -- test modsd - report "test modsd"; - modsd_loop : for dlength in 1 to 8 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); - d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); - d1.is_signed <= '1'; - d1.neg_result <= ra(63); - d1.is_extended <= '0'; - d1.is_32bit <= '0'; - d1.is_modulus <= '1'; - d1.valid <= '1'; - wait for clk_period; - - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test divweu") then + divweu_loop : for vlength in 1 to 4 loop + for dlength in 1 to vlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra; + d1.divisor <= rb; + d1.is_32bit <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then + behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb)); + end if; + assert behave_rt = d2.write_reg_data + report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - behave_rt := std_ulogic_vector(signed(ra) rem signed(rb)); - end if; - assert behave_rt = d2.write_reg_data - report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); end loop; - end loop; - end loop; - - -- test modud - report "test modud"; - modud_loop : for dlength in 1 to 8 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra; - d1.divisor <= rb; - d1.is_signed <= '0'; - d1.neg_result <= '0'; - d1.is_extended <= '0'; - d1.is_32bit <= '0'; - d1.is_modulus <= '1'; - d1.valid <= '1'; - - wait for clk_period; - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test modsd") then + modsd_loop : for dlength in 1 to 8 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); + d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); + d1.is_signed <= '1'; + d1.neg_result <= ra(63); + d1.is_modulus <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + behave_rt := std_ulogic_vector(signed(ra) rem signed(rb)); + end if; + assert behave_rt = d2.write_reg_data + report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb)); - end if; - assert behave_rt = d2.write_reg_data - report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); end loop; - end loop; - end loop; - - -- test modsw - report "test modsw"; - modsw_loop : for dlength in 1 to 4 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); - d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); - d1.is_signed <= '1'; - d1.neg_result <= ra(63); - d1.is_extended <= '0'; - d1.is_32bit <= '1'; - d1.is_modulus <= '1'; - d1.valid <= '1'; - - wait for clk_period; - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test modud") then + modud_loop : for dlength in 1 to 8 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra; + d1.divisor <= rb; + d1.is_modulus <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb)); + end if; + assert behave_rt = d2.write_reg_data + report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; end loop; - assert d2.valid = '1'; - - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0))); - if rem32(31) = '0' then - behave_rt := x"00000000" & rem32; - else - behave_rt := x"ffffffff" & rem32; - end if; - end if; - assert behave_rt = d2.write_reg_data - report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); end loop; - end loop; - end loop; - - -- test moduw - report "test moduw"; - moduw_loop : for dlength in 1 to 4 loop - for vlength in 1 to dlength loop - for i in 0 to 100 loop - ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); - rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); - - d1.dividend <= ra; - d1.divisor <= rb; - d1.is_signed <= '0'; - d1.neg_result <= '0'; - d1.is_extended <= '0'; - d1.is_32bit <= '1'; - d1.is_modulus <= '1'; - d1.valid <= '1'; - - wait for clk_period; - d1.valid <= '0'; - for j in 0 to 66 loop - wait for clk_period; - if d2.valid = '1' then - exit; - end if; + elsif run("Test modsw") then + modsw_loop : for dlength in 1 to 4 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); + d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); + d1.is_signed <= '1'; + d1.neg_result <= ra(63); + d1.is_32bit <= '1'; + d1.is_modulus <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0))); + if rem32(31) = '0' then + behave_rt := x"00000000" & rem32; + else + behave_rt := x"ffffffff" & rem32; + end if; + end if; + assert behave_rt = d2.write_reg_data + report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; end loop; - assert d2.valid = '1'; + end loop; - behave_rt := (others => '0'); - if rb /= x"0000000000000000" then - behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0))); - end if; - assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0) - report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + elsif run("Test moduw") then + moduw_loop : for dlength in 1 to 4 loop + for vlength in 1 to dlength loop + for i in 0 to 100 loop + ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); + rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); + + d1.dividend <= ra; + d1.divisor <= rb; + d1.is_32bit <= '1'; + d1.is_modulus <= '1'; + d1.valid <= '1'; + + wait for clk_period; + + d1.valid <= '0'; + for j in 0 to 66 loop + wait for clk_period; + if d2.valid = '1' then + exit; + end if; + end loop; + assert d2.valid = '1'; + + behave_rt := (others => '0'); + if rb /= x"0000000000000000" then + behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0))); + end if; + assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0) + report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); + end loop; + end loop; end loop; - end loop; + end if; end loop; test_runner_cleanup(runner); diff --git a/multiply_tb.vhdl b/multiply_tb.vhdl index 7458c33..57a9386 100644 --- a/multiply_tb.vhdl +++ b/multiply_tb.vhdl @@ -58,228 +58,232 @@ begin test_runner_setup(runner, runner_cfg); - wait for clk_period; + while test_suite loop + if run("Test interface") then + wait for clk_period; - m1.valid <= '1'; - m1.data1 <= x"0000000000001000"; - m1.data2 <= x"0000000000001111"; + m1.valid <= '1'; + m1.data1 <= x"0000000000001000"; + m1.data2 <= x"0000000000001111"; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - wait for clk_period; - assert m2.valid = '1'; - assert m2.result = x"00000000000000000000000001111000"; + wait for clk_period; + assert m2.valid = '1'; + assert m2.result = x"00000000000000000000000001111000"; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - m1.valid <= '1'; + m1.valid <= '1'; - wait for clk_period; - assert m2.valid = '0'; + wait for clk_period; + assert m2.valid = '0'; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; - assert m2.result = x"00000000000000000000000001111000"; + wait for clk_period * (pipeline_depth-1); + assert m2.valid = '1'; + assert m2.result = x"00000000000000000000000001111000"; - -- test mulld - mulld_loop : for i in 0 to 1000 loop - ra := rnd.RandSlv(ra'length); - rb := rnd.RandSlv(rb'length); + elsif run("Test mulld") then + mulld_loop : for i in 0 to 1000 loop + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); - behave_rt := ppc_mulld(ra, rb); + behave_rt := ppc_mulld(ra, rb); - m1.data1 <= absval(ra); - m1.data2 <= absval(rb); - sign := ra(63) xor rb(63); - m1.not_result <= sign; - m1.addend <= (others => sign); - m1.valid <= '1'; + m1.data1 <= absval(ra); + m1.data2 <= absval(rb); + sign := ra(63) xor rb(63); + m1.not_result <= sign; + m1.addend <= (others => sign); + m1.valid <= '1'; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) - report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0)); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) + report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0)); + end loop; - -- test mulhdu - mulhdu_loop : for i in 0 to 1000 loop - ra := rnd.RandSlv(ra'length); - rb := rnd.RandSlv(rb'length); + elsif run("Test mulhdu") then + mulhdu_loop : for i in 0 to 1000 loop + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); - behave_rt := ppc_mulhdu(ra, rb); + behave_rt := ppc_mulhdu(ra, rb); - m1.data1 <= ra; - m1.data2 <= rb; - m1.not_result <= '0'; - m1.addend <= (others => '0'); - m1.valid <= '1'; + m1.data1 <= ra; + m1.data2 <= rb; + m1.not_result <= '0'; + m1.addend <= (others => '0'); + m1.valid <= '1'; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64)) - report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64)); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64)) + report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64)); + end loop; - -- test mulhd - mulhd_loop : for i in 0 to 1000 loop - ra := rnd.RandSlv(ra'length); - rb := rnd.RandSlv(rb'length); + elsif run("Test mulhd") then + mulhd_loop : for i in 0 to 1000 loop + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); - behave_rt := ppc_mulhd(ra, rb); + behave_rt := ppc_mulhd(ra, rb); - m1.data1 <= absval(ra); - m1.data2 <= absval(rb); - sign := ra(63) xor rb(63); - m1.not_result <= sign; - m1.addend <= (others => sign); - m1.valid <= '1'; + m1.data1 <= absval(ra); + m1.data2 <= absval(rb); + sign := ra(63) xor rb(63); + m1.not_result <= sign; + m1.addend <= (others => sign); + m1.valid <= '1'; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64)) - report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64)); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64)) + report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64)); + end loop; - -- test mullw - mullw_loop : for i in 0 to 1000 loop - ra := rnd.RandSlv(ra'length); - rb := rnd.RandSlv(rb'length); + elsif run("Test mullw") then + mullw_loop : for i in 0 to 1000 loop + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); - behave_rt := ppc_mullw(ra, rb); + behave_rt := ppc_mullw(ra, rb); - m1.data1 <= (others => '0'); - m1.data1(31 downto 0) <= absval(ra(31 downto 0)); - m1.data2 <= (others => '0'); - m1.data2(31 downto 0) <= absval(rb(31 downto 0)); - sign := ra(31) xor rb(31); - m1.not_result <= sign; - m1.addend <= (others => sign); - m1.valid <= '1'; + m1.data1 <= (others => '0'); + m1.data1(31 downto 0) <= absval(ra(31 downto 0)); + m1.data2 <= (others => '0'); + m1.data2(31 downto 0) <= absval(rb(31 downto 0)); + sign := ra(31) xor rb(31); + m1.not_result <= sign; + m1.addend <= (others => sign); + m1.valid <= '1'; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) - report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0)); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) + report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0)); + end loop; - -- test mulhw - mulhw_loop : for i in 0 to 1000 loop - ra := rnd.RandSlv(ra'length); - rb := rnd.RandSlv(rb'length); + elsif run("Test mulhw") then + mulhw_loop : for i in 0 to 1000 loop + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); - behave_rt := ppc_mulhw(ra, rb); + behave_rt := ppc_mulhw(ra, rb); - m1.data1 <= (others => '0'); - m1.data1(31 downto 0) <= absval(ra(31 downto 0)); - m1.data2 <= (others => '0'); - m1.data2(31 downto 0) <= absval(rb(31 downto 0)); - sign := ra(31) xor rb(31); - m1.not_result <= sign; - m1.addend <= (others => sign); - m1.valid <= '1'; + m1.data1 <= (others => '0'); + m1.data1(31 downto 0) <= absval(ra(31 downto 0)); + m1.data2 <= (others => '0'); + m1.data2(31 downto 0) <= absval(rb(31 downto 0)); + sign := ra(31) xor rb(31); + m1.not_result <= sign; + m1.addend <= (others => sign); + m1.valid <= '1'; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)) - report "bad mulhw expected " & to_hstring(behave_rt) & " got " & - to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)) + report "bad mulhw expected " & to_hstring(behave_rt) & " got " & + to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)); + end loop; - -- test mulhwu - mulhwu_loop : for i in 0 to 1000 loop - ra := rnd.RandSlv(ra'length); - rb := rnd.RandSlv(rb'length); + elsif run("Test mulhwu") then + mulhwu_loop : for i in 0 to 1000 loop + ra := rnd.RandSlv(ra'length); + rb := rnd.RandSlv(rb'length); - behave_rt := ppc_mulhwu(ra, rb); + behave_rt := ppc_mulhwu(ra, rb); - m1.data1 <= (others => '0'); - m1.data1(31 downto 0) <= ra(31 downto 0); - m1.data2 <= (others => '0'); - m1.data2(31 downto 0) <= rb(31 downto 0); - m1.not_result <= '0'; - m1.addend <= (others => '0'); - m1.valid <= '1'; + m1.data1 <= (others => '0'); + m1.data1(31 downto 0) <= ra(31 downto 0); + m1.data2 <= (others => '0'); + m1.data2(31 downto 0) <= rb(31 downto 0); + m1.not_result <= '0'; + m1.addend <= (others => '0'); + m1.valid <= '1'; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)) - report "bad mulhwu expected " & to_hstring(behave_rt) & " got " & - to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)); - end loop; + assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)) + report "bad mulhwu expected " & to_hstring(behave_rt) & " got " & + to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)); + end loop; - -- test mulli - mulli_loop : for i in 0 to 1000 loop - ra := rnd.RandSlv(ra'length); - si := rnd.RandSlv(si'length); + elsif run("Test mulli") then + mulli_loop : for i in 0 to 1000 loop + ra := rnd.RandSlv(ra'length); + si := rnd.RandSlv(si'length); - behave_rt := ppc_mulli(ra, si); + behave_rt := ppc_mulli(ra, si); - m1.data1 <= absval(ra); - m1.data2 <= (others => '0'); - m1.data2(15 downto 0) <= absval(si); - sign := ra(63) xor si(15); - m1.not_result <= sign; - m1.addend <= (others => sign); - m1.valid <= '1'; + m1.data1 <= absval(ra); + m1.data2 <= (others => '0'); + m1.data2(15 downto 0) <= absval(si); + sign := ra(63) xor si(15); + m1.not_result <= sign; + m1.addend <= (others => sign); + m1.valid <= '1'; - wait for clk_period; + wait for clk_period; - m1.valid <= '0'; + m1.valid <= '0'; - wait for clk_period * (pipeline_depth-1); + wait for clk_period * (pipeline_depth-1); - assert m2.valid = '1'; + assert m2.valid = '1'; - assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) - report "bad mulli expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0)); + assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) + report "bad mulli expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0)); + end loop; + end if; end loop; test_runner_cleanup(runner); diff --git a/rotator_tb.vhdl b/rotator_tb.vhdl index 2849ccf..781027f 100644 --- a/rotator_tb.vhdl +++ b/rotator_tb.vhdl @@ -53,255 +53,244 @@ begin test_runner_setup(runner, runner_cfg); - -- rlwinm, rlwnm - report "test rlw[i]nm"; - ra <= (others => '0'); - is_32bit <= '1'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '1'; - clear_right <= '1'; - extsw <= '0'; - rlwnm_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; - wait for clk_period; - behave_ra := ppc_rlwinm(rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); - assert behave_ra = result - report "bad rlwnm expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + while test_suite loop + if run("Test rlw[i]nm") then + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + extsw <= '0'; + rlwnm_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; + wait for clk_period; + behave_ra := ppc_rlwinm(rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); + assert behave_ra = result + report "bad rlwnm expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- rlwimi - report "test rlwimi"; - is_32bit <= '1'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '1'; - clear_right <= '1'; - rlwimi_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - ra <= rnd.RandSlv(64); - shift <= "00" & rnd.RandSlv(5); - insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; - wait for clk_period; - behave_ra := ppc_rlwimi(ra, rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); - assert behave_ra = result - report "bad rlwimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test rlwimi") then + is_32bit <= '1'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + rlwimi_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + ra <= rnd.RandSlv(64); + shift <= "00" & rnd.RandSlv(5); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; + wait for clk_period; + behave_ra := ppc_rlwimi(ra, rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn)); + assert behave_ra = result + report "bad rlwimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- rldicl, rldcl - report "test rld[i]cl"; - ra <= (others => '0'); - is_32bit <= '0'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '1'; - clear_right <= '0'; - rldicl_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; - wait for clk_period; - behave_ra := ppc_rldicl(rs, shift(5 downto 0), insn_mb(insn)); - assert behave_ra = result - report "bad rldicl expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test rld[i]cl") then + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '0'; + rldicl_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldicl(rs, shift(5 downto 0), insn_mb(insn)); + assert behave_ra = result + report "bad rldicl expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- rldicr, rldcr - report "test rld[i]cr"; - ra <= (others => '0'); - is_32bit <= '0'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '0'; - clear_right <= '1'; - rldicr_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; - wait for clk_period; - behave_ra := ppc_rldicr(rs, shift(5 downto 0), insn_me(insn)); - --report "rs = " & to_hstring(rs); - --report "ra = " & to_hstring(ra); - --report "shift = " & to_hstring(shift); - --report "insn me = " & to_hstring(insn_me(insn)); - --report "result = " & to_hstring(result); - assert behave_ra = result - report "bad rldicr expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test rld[i]cr") then + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '1'; + rldicr_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldicr(rs, shift(5 downto 0), insn_me(insn)); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "insn me = " & to_hstring(insn_me(insn)); + --report "result = " & to_hstring(result); + assert behave_ra = result + report "bad rldicr expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- rldic - report "test rldic"; - ra <= (others => '0'); - is_32bit <= '0'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '1'; - clear_right <= '1'; - rldic_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= '0' & rnd.RandSlv(6); - insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; - wait for clk_period; - behave_ra := ppc_rldic(rs, shift(5 downto 0), insn_mb(insn)); - assert behave_ra = result - report "bad rldic expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test rldic") then + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + rldic_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldic(rs, shift(5 downto 0), insn_mb(insn)); + assert behave_ra = result + report "bad rldic expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- rldimi - report "test rldimi"; - is_32bit <= '0'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '1'; - clear_right <= '1'; - rldimi_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - ra <= rnd.RandSlv(64); - shift <= '0' & rnd.RandSlv(6); - insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; - wait for clk_period; - behave_ra := ppc_rldimi(ra, rs, shift(5 downto 0), insn_mb(insn)); - assert behave_ra = result - report "bad rldimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test rldimi") then + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '1'; + clear_right <= '1'; + rldimi_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + ra <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); + insn <= x"00000" & '0' & rnd.RandSlv(10) & '0'; + wait for clk_period; + behave_ra := ppc_rldimi(ra, rs, shift(5 downto 0), insn_mb(insn)); + assert behave_ra = result + report "bad rldimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- slw - report "test slw"; - ra <= (others => '0'); - is_32bit <= '1'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '0'; - clear_right <= '0'; - slw_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - wait for clk_period; - behave_ra := ppc_slw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); - assert behave_ra = result - report "bad slw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test slw") then + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + slw_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + wait for clk_period; + behave_ra := ppc_slw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad slw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- sld - report "test sld"; - ra <= (others => '0'); - is_32bit <= '0'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '0'; - clear_right <= '0'; - sld_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - wait for clk_period; - behave_ra := ppc_sld(rs, std_ulogic_vector(resize(unsigned(shift), 64))); - assert behave_ra = result - report "bad sld expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test sld") then + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + sld_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + wait for clk_period; + behave_ra := ppc_sld(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad sld expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- srw - report "test srw"; - ra <= (others => '0'); - is_32bit <= '1'; - right_shift <= '1'; - arith <= '0'; - clear_left <= '0'; - clear_right <= '0'; - srw_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - wait for clk_period; - behave_ra := ppc_srw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); - assert behave_ra = result - report "bad srw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test srw") then + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '1'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + srw_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + wait for clk_period; + behave_ra := ppc_srw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad srw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- srd - report "test srd"; - ra <= (others => '0'); - is_32bit <= '0'; - right_shift <= '1'; - arith <= '0'; - clear_left <= '0'; - clear_right <= '0'; - srd_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - wait for clk_period; - behave_ra := ppc_srd(rs, std_ulogic_vector(resize(unsigned(shift), 64))); - assert behave_ra = result - report "bad srd expected " & to_hstring(behave_ra) & " got " & to_hstring(result); - end loop; + elsif run("Test srd") then + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '1'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + srd_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + wait for clk_period; + behave_ra := ppc_srd(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + assert behave_ra = result + report "bad srd expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; - -- sraw[i] - report "test sraw[i]"; - ra <= (others => '0'); - is_32bit <= '1'; - right_shift <= '1'; - arith <= '1'; - clear_left <= '0'; - clear_right <= '0'; - sraw_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= '0' & rnd.RandSlv(6); - wait for clk_period; - behave_ca_ra := ppc_sraw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); - --report "rs = " & to_hstring(rs); - --report "ra = " & to_hstring(ra); - --report "shift = " & to_hstring(shift); - --report "result = " & to_hstring(carry_out & result); - assert behave_ca_ra(63 downto 0) = result and behave_ca_ra(64) = carry_out - report "bad sraw expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result); - end loop; + elsif run("Test sraw[i]") then + ra <= (others => '0'); + is_32bit <= '1'; + right_shift <= '1'; + arith <= '1'; + clear_left <= '0'; + clear_right <= '0'; + sraw_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); + wait for clk_period; + behave_ca_ra := ppc_sraw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "result = " & to_hstring(carry_out & result); + assert behave_ca_ra(63 downto 0) = result and behave_ca_ra(64) = carry_out + report "bad sraw expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result); + end loop; - -- srad[i] - report "test srad[i]"; - ra <= (others => '0'); - is_32bit <= '0'; - right_shift <= '1'; - arith <= '1'; - clear_left <= '0'; - clear_right <= '0'; - srad_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= rnd.RandSlv(7); - wait for clk_period; - behave_ca_ra := ppc_srad(rs, std_ulogic_vector(resize(unsigned(shift), 64))); - --report "rs = " & to_hstring(rs); - --report "ra = " & to_hstring(ra); - --report "shift = " & to_hstring(shift); - --report "result = " & to_hstring(carry_out & result); - assert behave_ca_ra(63 downto 0) = result and behave_ca_ra(64) = carry_out - report "bad srad expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result); - end loop; + elsif run("Test srad[i]") then + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '1'; + arith <= '1'; + clear_left <= '0'; + clear_right <= '0'; + srad_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= rnd.RandSlv(7); + wait for clk_period; + behave_ca_ra := ppc_srad(rs, std_ulogic_vector(resize(unsigned(shift), 64))); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "result = " & to_hstring(carry_out & result); + assert behave_ca_ra(63 downto 0) = result and behave_ca_ra(64) = carry_out + report "bad srad expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result); + end loop; - -- extswsli - report "test extswsli"; - ra <= (others => '0'); - is_32bit <= '0'; - right_shift <= '0'; - arith <= '0'; - clear_left <= '0'; - clear_right <= '0'; - extsw <= '1'; - extswsli_loop : for i in 0 to 1000 loop - rs <= rnd.RandSlv(64); - shift <= '0' & rnd.RandSlv(6); - wait for clk_period; - behave_ra := rs; - behave_ra(63 downto 32) := (others => rs(31)); - behave_ra := std_ulogic_vector(shift_left(unsigned(behave_ra), - to_integer(unsigned(shift)))); - --report "rs = " & to_hstring(rs); - --report "ra = " & to_hstring(ra); - --report "shift = " & to_hstring(shift); - --report "result = " & to_hstring(carry_out & result); - assert behave_ra = result - report "bad extswsli expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + elsif run("Test extswsli") then + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + extsw <= '1'; + extswsli_loop : for i in 0 to 1000 loop + rs <= rnd.RandSlv(64); + shift <= '0' & rnd.RandSlv(6); + wait for clk_period; + behave_ra := rs; + behave_ra(63 downto 32) := (others => rs(31)); + behave_ra := std_ulogic_vector(shift_left(unsigned(behave_ra), + to_integer(unsigned(shift)))); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "result = " & to_hstring(carry_out & result); + assert behave_ra = result + report "bad extswsli expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + end if; end loop; - test_runner_cleanup(runner); end process; end behave; From 0865704e2198a22d9ee23e58cab200aef6d58a98 Mon Sep 17 00:00:00 2001 From: Lars Asplund Date: Wed, 9 Jun 2021 16:19:24 +0200 Subject: [PATCH 4/4] Run VUnit tests in CI Signed-off-by: Lars Asplund --- .github/workflows/test.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 544d618..4f5fbe6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,6 +51,14 @@ jobs: - uses: actions/checkout@v2 - run: bash -c "make -j$(nproc) ${{ matrix.task }}" + VUnit: + needs: [build] + runs-on: ubuntu-latest + container: ghdl/vunit:llvm + steps: + - uses: actions/checkout@v2 + - run: python3 ./run.py -p10 + symbiflow: strategy: fail-fast: false