Merge pull request #295 from LarsAsplund/master

Run VHDL tests with VUnit
remove-potato-uart
Michael Neuling 3 years ago committed by GitHub
commit ff7421c54e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -33,7 +33,6 @@ jobs:
max-parallel: 3 max-parallel: 3
matrix: matrix:
task: [ task: [
"tests_unit",
"tests_console", "tests_console",
"{1..99}", "{1..99}",
"{100..199}", "{100..199}",
@ -52,6 +51,14 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: bash -c "make -j$(nproc) ${{ matrix.task }}" - 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: symbiflow:
strategy: strategy:
fail-fast: false fail-fast: false

@ -39,8 +39,8 @@ ECPPACK = $(DOCKERBIN) $(DOCKERARGS) hdlc/prjtrellis ecppack
OPENOCD = $(DOCKERBIN) $(DOCKERARGS) --device /dev/bus/usb hdlc/prog openocd OPENOCD = $(DOCKERBIN) $(DOCKERARGS) --device /dev/bus/usb hdlc/prog openocd
endif endif


all = core_tb icache_tb dcache_tb multiply_tb dmi_dtm_tb divider_tb \ all = core_tb icache_tb dcache_tb dmi_dtm_tb \
rotator_tb countzero_tb wishbone_bram_tb soc_reset_tb wishbone_bram_tb soc_reset_tb


all: $(all) 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 \ 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_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl \
sim_16550_uart.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 \ soc_sim_c_files = sim_vhpi_c.c sim_bram_helpers_c.c sim_console_c.c \
sim_jtag_socket_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) $^ $(GHDL) -i --std=08 --work=unisim --workdir=$(unisim_dir) $^
GHDLFLAGS += -P$(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_tbs = core_tb icache_tb dcache_tb dmi_dtm_tb wishbone_bram_tb
soc_flash_tbs = core_flash_tb soc_flash_tbs = core_flash_tb
soc_dram_tbs = dram_tb core_dram_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 $(soc_tbs): %: $(soc_sim_files) $(soc_sim_obj_files) $(unisim_lib) %.vhdl
$(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(soc_sim_files) $@.vhdl -e $@ $(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 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 $@ $(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 test_micropython_long: core_tb
@./scripts/test_micropython_long.py @./scripts/test_micropython_long.py


tests_core_tb = $(patsubst %_tb,%_tb_test,$(core_tbs))
tests_soc_tb = $(patsubst %_tb,%_tb_test,$(soc_tbs)) tests_soc_tb = $(patsubst %_tb,%_tb_test,$(soc_tbs))


%_test: % %_test: %
./$< --assert-level=error > /dev/null ./$< --assert-level=error > /dev/null


tests_core: $(tests_core_tb)

tests_soc: $(tests_soc_tb) tests_soc: $(tests_soc_tb)


# FIXME SOC tests have bit rotted, so disable for now # FIXME SOC tests have bit rotted, so disable for now
#tests_unit: tests_core tests_soc #tests_unit: tests_soc
tests_unit: tests_core


TAGS: TAGS:
find . -name '*.vhdl' | xargs ./scripts/vhdltags find . -name '*.vhdl' | xargs ./scripts/vhdltags

@ -1,12 +1,18 @@
library vunit_lib;
context vunit_lib.vunit_context;

library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;


library work; library work;
use work.common.all; use work.common.all;
use work.glibc_random.all;
library osvvm;
use osvvm.RandomPkg.all;


entity countzero_tb is entity countzero_tb is
generic (runner_cfg : string := runner_cfg_default);
end countzero_tb; end countzero_tb;


architecture behave of countzero_tb is architecture behave of countzero_tb is
@ -37,78 +43,85 @@ begin


stim_process: process stim_process: process
variable r: std_ulogic_vector(63 downto 0); variable r: std_ulogic_vector(63 downto 0);
variable rnd : RandomPType;
begin begin
-- test with input = 0 rnd.InitSeed(stim_process'path_name);
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"; test_runner_setup(runner, runner_cfg);
count_right <= '0';
for j in 0 to 100 loop
r := pseudorand(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;


report "test cnttzd/w"; while test_suite loop
count_right <= '1'; if run("Test with input = 0") then
for j in 0 to 100 loop rs <= (others => '0');
r := pseudorand(64);
r(0) := '1';
for i in 0 to 63 loop
rs <= r;
is_32bit <= '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; wait for clk_period;
assert to_integer(unsigned(result)) = i assert result = x"0000000000000040"
report "bad cnttzd " & to_hstring(rs) & " -> " & to_hstring(result); report "bad cnttzd 0 = " & to_hstring(result);
is_32bit <= '1'; 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; wait for clk_period;
if i < 32 then assert result = x"0000000000000020"
assert to_integer(unsigned(result)) = i report "bad cnttzw 0 = " & to_hstring(result);
report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result);
else elsif run("Test cntlzd/w") then
assert to_integer(unsigned(result)) = 32 count_right <= '0';
report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result); for j in 0 to 100 loop
end if; r := rnd.RandSlv(64);
r := r(62 downto 0) & '0'; r(63) := '1';
end loop; 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; end loop;


std.env.finish; test_runner_cleanup(runner);
end process; end process;
end behave; end behave;

@ -1,3 +1,6 @@
library vunit_lib;
context vunit_lib.vunit_context;

library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
@ -5,10 +8,13 @@ use ieee.numeric_std.all;
library work; library work;
use work.decode_types.all; use work.decode_types.all;
use work.common.all; use work.common.all;
use work.glibc_random.all;
use work.ppc_fx_insns.all; use work.ppc_fx_insns.all;


library osvvm;
use osvvm.RandomPkg.all;

entity divider_tb is entity divider_tb is
generic (runner_cfg : string := runner_cfg_default);
end divider_tb; end divider_tb;


architecture behave of divider_tb is architecture behave of divider_tb is
@ -37,516 +43,493 @@ begin
variable q128: std_ulogic_vector(127 downto 0); variable q128: std_ulogic_vector(127 downto 0);
variable q64: std_ulogic_vector(63 downto 0); variable q64: std_ulogic_vector(63 downto 0);
variable rem32: std_ulogic_vector(31 downto 0); variable rem32: std_ulogic_vector(31 downto 0);
variable rnd : RandomPType;
begin begin
rst <= '1'; rnd.InitSeed(stim_process'path_name);
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; test_runner_setup(runner, runner_cfg);
assert d2.valid = '0';


d1.valid <= '0'; while test_suite loop

rst <= '1';
for j in 0 to 66 loop
wait for clk_period; wait for clk_period;
if d2.valid = '1' then rst <= '0';
exit;
end if;
end loop;


assert d2.valid = '1'; d1.is_signed <= '0';
assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data); d1.neg_result <= '0';
d1.is_extended <= '0';
d1.is_32bit <= '0';
d1.is_modulus <= '0';
d1.valid <= '0';


wait for clk_period; if run("Test interface") then
assert d2.valid = '0' report "valid"; 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; d1.valid <= '0';
assert d2.valid = '0' report "valid";


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 assert d2.valid = '1';
wait for clk_period; assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
if d2.valid = '1' then
exit;
end if;
end loop;


assert d2.valid = '1'; wait for clk_period;
assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data); assert d2.valid = '0' report "valid";


wait for clk_period; d1.valid <= '1';
assert d2.valid = '0';


-- test divd wait for clk_period;
report "test divd"; assert d2.valid = '0' report "valid";
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));


d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.valid <= '0';
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';


for j in 0 to 66 loop
wait for clk_period; wait for clk_period;

if d2.valid = '1' then
d1.valid <= '0'; exit;
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; 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;
end loop;


-- test divdu assert d2.valid = '1';
report "test divdu"; assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
divdu_loop : for dlength in 1 to 8 loop
for vlength in 1 to dlength loop wait for clk_period;
for i in 0 to 100 loop assert d2.valid = '0';
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64)); elsif run("Test divd") then

divd_loop : for dlength in 1 to 8 loop
d1.dividend <= ra; for vlength in 1 to dlength loop
d1.divisor <= rb; for i in 0 to 100 loop
d1.is_signed <= '0'; ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64));
d1.neg_result <= '0'; rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64));
d1.valid <= '1';

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
wait for clk_period; d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));

d1.is_signed <= '1';
d1.valid <= '0'; d1.neg_result <= ra(63) xor rb(63);
for j in 0 to 66 loop d1.valid <= '1';
wait for clk_period;
if d2.valid = '1' then wait for clk_period;
exit;
end if; 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; 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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(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'; elsif run("Test divdu") then
for j in 0 to 66 loop divdu_loop : for dlength in 1 to 8 loop
wait for clk_period; for vlength in 1 to dlength loop
if d2.valid = '1' then for i in 0 to 100 loop
exit; ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64));
end if; 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; 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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(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'; elsif run("Test divde") then
for j in 0 to 66 loop divde_loop : for vlength in 1 to 8 loop
wait for clk_period; for dlength in 1 to vlength loop
if d2.valid = '1' then for i in 0 to 100 loop
exit; ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64));
end if; 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; 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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(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'; elsif run("Test divdeu") then
for j in 0 to 66 loop divdeu_loop : for vlength in 1 to 8 loop
wait for clk_period; for dlength in 1 to vlength loop
if d2.valid = '1' then for i in 0 to 100 loop
exit; ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64));
end if; 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; 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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(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; elsif run("Test divw") then

divw_loop : for dlength in 1 to 4 loop
d1.valid <= '0'; for vlength in 1 to dlength loop
for j in 0 to 66 loop for i in 0 to 100 loop
wait for clk_period; ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64));
if d2.valid = '1' then rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64));
exit;
end if; 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; 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;
end loop;


-- test divwe elsif run("Test divwu") then
report "test divwe"; divwu_loop : for dlength in 1 to 4 loop
divwe_loop : for vlength in 1 to 4 loop for vlength in 1 to dlength loop
for dlength in 1 to vlength loop for i in 0 to 100 loop
for i in 0 to 100 loop ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64));
ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000"; rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));

d1.dividend <= ra;
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); d1.divisor <= rb;
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); d1.is_32bit <= '1';
d1.is_signed <= '1'; d1.valid <= '1';
d1.neg_result <= ra(63) xor rb(63);
d1.is_extended <= '0'; wait for clk_period;
d1.is_32bit <= '1';
d1.valid <= '1'; d1.valid <= '0';

for j in 0 to 66 loop
wait for clk_period; wait for clk_period;

if d2.valid = '1' then
d1.valid <= '0'; exit;
for j in 0 to 66 loop end if;
wait for clk_period; end loop;
if d2.valid = '1' then assert d2.valid = '1';
exit;
end if; 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;
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;
end loop;


-- test divweu elsif run("Test divwe") then
report "test divweu"; divwe_loop : for vlength in 1 to 4 loop
divweu_loop : for vlength in 1 to 4 loop for dlength in 1 to vlength loop
for dlength in 1 to vlength loop for i in 0 to 100 loop
for i in 0 to 100 loop ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 32)) & x"00000000";
ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 32)) & x"00000000"; rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));

d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
d1.dividend <= ra; d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
d1.divisor <= rb; d1.is_signed <= '1';
d1.is_signed <= '0'; d1.neg_result <= ra(63) xor rb(63);
d1.neg_result <= '0'; d1.is_32bit <= '1';
d1.is_extended <= '0'; d1.valid <= '1';
d1.is_32bit <= '1';
d1.valid <= '1'; wait for clk_period;


wait for clk_period; d1.valid <= '0';

for j in 0 to 66 loop
d1.valid <= '0'; wait for clk_period;
for j in 0 to 66 loop if d2.valid = '1' then
wait for clk_period; exit;
if d2.valid = '1' then end if;
exit; end loop;
end if; 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;
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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(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; elsif run("Test divweu") then

divweu_loop : for vlength in 1 to 4 loop
d1.valid <= '0'; for dlength in 1 to vlength loop
for j in 0 to 66 loop for i in 0 to 100 loop
wait for clk_period; ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 32)) & x"00000000";
if d2.valid = '1' then rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64));
exit;
end if; 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; 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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(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'; elsif run("Test modsd") then
for j in 0 to 66 loop modsd_loop : for dlength in 1 to 8 loop
wait for clk_period; for vlength in 1 to dlength loop
if d2.valid = '1' then for i in 0 to 100 loop
exit; ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64));
end if; 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; 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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(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'; elsif run("Test modud") then
for j in 0 to 66 loop modud_loop : for dlength in 1 to 8 loop
wait for clk_period; for vlength in 1 to dlength loop
if d2.valid = '1' then for i in 0 to 100 loop
exit; ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64));
end if; 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; 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;
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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(unsigned(pseudorand(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'; elsif run("Test modsw") then
for j in 0 to 66 loop modsw_loop : for dlength in 1 to 4 loop
wait for clk_period; for vlength in 1 to dlength loop
if d2.valid = '1' then for i in 0 to 100 loop
exit; ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64));
end if; 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; end loop;
assert d2.valid = '1'; end loop;


behave_rt := (others => '0'); elsif run("Test moduw") then
if rb /= x"0000000000000000" then moduw_loop : for dlength in 1 to 4 loop
behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0))); for vlength in 1 to dlength loop
end if; for i in 0 to 100 loop
assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0) ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64));
report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data); 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 loop; end if;
end loop; end loop;


std.env.finish; test_runner_cleanup(runner);
end process; end process;
end behave; end behave;

@ -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;

@ -1,3 +1,6 @@
library vunit_lib;
context vunit_lib.vunit_context;

library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;
@ -5,10 +8,13 @@ use ieee.numeric_std.all;
library work; library work;
use work.decode_types.all; use work.decode_types.all;
use work.common.all; use work.common.all;
use work.glibc_random.all;
use work.ppc_fx_insns.all; use work.ppc_fx_insns.all;


library osvvm;
use osvvm.RandomPkg.all;

entity multiply_tb is entity multiply_tb is
generic (runner_cfg : string := runner_cfg_default);
end multiply_tb; end multiply_tb;


architecture behave of multiply_tb is architecture behave of multiply_tb is
@ -46,232 +52,241 @@ begin
variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0); variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0);
variable si: std_ulogic_vector(15 downto 0); variable si: std_ulogic_vector(15 downto 0);
variable sign: std_ulogic; variable sign: std_ulogic;
variable rnd : RandomPType;
begin begin
wait for clk_period; rnd.InitSeed(stim_process'path_name);


m1.valid <= '1'; test_runner_setup(runner, runner_cfg);
m1.data1 <= x"0000000000001000";
m1.data2 <= x"0000000000001111";


wait for clk_period; while test_suite loop
assert m2.valid = '0'; if run("Test interface") then
wait for clk_period;


m1.valid <= '0'; m1.valid <= '1';
m1.data1 <= x"0000000000001000";
m1.data2 <= x"0000000000001111";


wait for clk_period; wait for clk_period;
assert m2.valid = '0'; assert m2.valid = '0';


wait for clk_period; m1.valid <= '0';
assert m2.valid = '0';


wait for clk_period; wait for clk_period;
assert m2.valid = '1'; assert m2.valid = '0';
assert m2.result = x"00000000000000000000000001111000";


wait for clk_period; wait for clk_period;
assert m2.valid = '0'; assert m2.valid = '0';


m1.valid <= '1'; wait for clk_period;
assert m2.valid = '1';
assert m2.result = x"00000000000000000000000001111000";


wait for clk_period; wait for clk_period;
assert m2.valid = '0'; assert m2.valid = '0';


m1.valid <= '0'; m1.valid <= '1';


wait for clk_period * (pipeline_depth-1); wait for clk_period;
assert m2.valid = '1'; assert m2.valid = '0';
assert m2.result = x"00000000000000000000000001111000";


-- test mulld m1.valid <= '0';
mulld_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);


behave_rt := ppc_mulld(ra, rb); wait for clk_period * (pipeline_depth-1);
assert m2.valid = '1';
assert m2.result = x"00000000000000000000000001111000";


m1.data1 <= absval(ra); elsif run("Test mulld") then
m1.data2 <= absval(rb); mulld_loop : for i in 0 to 1000 loop
sign := ra(63) xor rb(63); ra := rnd.RandSlv(ra'length);
m1.not_result <= sign; rb := rnd.RandSlv(rb'length);
m1.addend <= (others => sign);
m1.valid <= '1';


wait for clk_period; behave_rt := ppc_mulld(ra, rb);


m1.valid <= '0'; 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 * (pipeline_depth-1); wait for clk_period;


assert m2.valid = '1'; m1.valid <= '0';


assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) wait for clk_period * (pipeline_depth-1);
report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0));
end loop;


-- test mulhdu assert m2.valid = '1';
mulhdu_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);


behave_rt := ppc_mulhdu(ra, rb); 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;


m1.data1 <= ra; elsif run("Test mulhdu") then
m1.data2 <= rb; mulhdu_loop : for i in 0 to 1000 loop
m1.not_result <= '0'; ra := rnd.RandSlv(ra'length);
m1.addend <= (others => '0'); rb := rnd.RandSlv(rb'length);
m1.valid <= '1';


wait for clk_period; behave_rt := ppc_mulhdu(ra, rb);


m1.valid <= '0'; m1.data1 <= ra;
m1.data2 <= rb;
m1.not_result <= '0';
m1.addend <= (others => '0');
m1.valid <= '1';


wait for clk_period * (pipeline_depth-1); wait for clk_period;


assert m2.valid = '1'; m1.valid <= '0';


assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64)) wait for clk_period * (pipeline_depth-1);
report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64));
end loop;


-- test mulhd assert m2.valid = '1';
mulhd_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);


behave_rt := ppc_mulhd(ra, rb); 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;


m1.data1 <= absval(ra); elsif run("Test mulhd") then
m1.data2 <= absval(rb); mulhd_loop : for i in 0 to 1000 loop
sign := ra(63) xor rb(63); ra := rnd.RandSlv(ra'length);
m1.not_result <= sign; rb := rnd.RandSlv(rb'length);
m1.addend <= (others => sign);
m1.valid <= '1';


wait for clk_period; behave_rt := ppc_mulhd(ra, rb);


m1.valid <= '0'; 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 * (pipeline_depth-1); wait for clk_period;


assert m2.valid = '1'; m1.valid <= '0';


assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64)) wait for clk_period * (pipeline_depth-1);
report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64));
end loop;


-- test mullw assert m2.valid = '1';
mullw_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);


behave_rt := ppc_mullw(ra, rb); 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;


m1.data1 <= (others => '0'); elsif run("Test mullw") then
m1.data1(31 downto 0) <= absval(ra(31 downto 0)); mullw_loop : for i in 0 to 1000 loop
m1.data2 <= (others => '0'); ra := rnd.RandSlv(ra'length);
m1.data2(31 downto 0) <= absval(rb(31 downto 0)); rb := rnd.RandSlv(rb'length);
sign := ra(31) xor rb(31);
m1.not_result <= sign;
m1.addend <= (others => sign);
m1.valid <= '1';


wait for clk_period; behave_rt := ppc_mullw(ra, rb);


m1.valid <= '0'; 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 * (pipeline_depth-1); wait for clk_period;


assert m2.valid = '1'; m1.valid <= '0';


assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0)) wait for clk_period * (pipeline_depth-1);
report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0));
end loop;


-- test mulhw assert m2.valid = '1';
mulhw_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);


behave_rt := ppc_mulhw(ra, rb); 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;


m1.data1 <= (others => '0'); elsif run("Test mulhw") then
m1.data1(31 downto 0) <= absval(ra(31 downto 0)); mulhw_loop : for i in 0 to 1000 loop
m1.data2 <= (others => '0'); ra := rnd.RandSlv(ra'length);
m1.data2(31 downto 0) <= absval(rb(31 downto 0)); rb := rnd.RandSlv(rb'length);
sign := ra(31) xor rb(31);
m1.not_result <= sign;
m1.addend <= (others => sign);
m1.valid <= '1';


wait for clk_period; behave_rt := ppc_mulhw(ra, rb);


m1.valid <= '0'; 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 * (pipeline_depth-1); wait for clk_period;


assert m2.valid = '1'; m1.valid <= '0';


assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)) wait for clk_period * (pipeline_depth-1);
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 assert m2.valid = '1';
mulhwu_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);


behave_rt := ppc_mulhwu(ra, rb); 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;


m1.data1 <= (others => '0'); elsif run("Test mulhwu") then
m1.data1(31 downto 0) <= ra(31 downto 0); mulhwu_loop : for i in 0 to 1000 loop
m1.data2 <= (others => '0'); ra := rnd.RandSlv(ra'length);
m1.data2(31 downto 0) <= rb(31 downto 0); rb := rnd.RandSlv(rb'length);
m1.not_result <= '0';
m1.addend <= (others => '0');
m1.valid <= '1';


wait for clk_period; behave_rt := ppc_mulhwu(ra, rb);


m1.valid <= '0'; 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 * (pipeline_depth-1); wait for clk_period;


assert m2.valid = '1'; m1.valid <= '0';


assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)) wait for clk_period * (pipeline_depth-1);
report "bad mulhwu expected " & to_hstring(behave_rt) & " got " &
to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32)); assert m2.valid = '1';
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 elsif run("Test mulli") then
mulli_loop : for i in 0 to 1000 loop mulli_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length); ra := rnd.RandSlv(ra'length);
si := pseudorand(si'length); si := rnd.RandSlv(si'length);


behave_rt := ppc_mulli(ra, si); behave_rt := ppc_mulli(ra, si);


m1.data1 <= absval(ra); m1.data1 <= absval(ra);
m1.data2 <= (others => '0'); m1.data2 <= (others => '0');
m1.data2(15 downto 0) <= absval(si); m1.data2(15 downto 0) <= absval(si);
sign := ra(63) xor si(15); sign := ra(63) xor si(15);
m1.not_result <= sign; m1.not_result <= sign;
m1.addend <= (others => sign); m1.addend <= (others => sign);
m1.valid <= '1'; 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)) 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)); report "bad mulli expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0));
end loop;
end if;
end loop; end loop;


std.env.finish; test_runner_cleanup(runner);
wait; wait;
end process; end process;
end behave; end behave;

@ -1,3 +1,6 @@
library vunit_lib;
context vunit_lib.vunit_context;

library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;


@ -6,6 +9,7 @@ use work.common.all;
use work.wishbone_types.all; use work.wishbone_types.all;


entity plru_tb is entity plru_tb is
generic (runner_cfg : string := runner_cfg_default);
end plru_tb; end plru_tb;


architecture behave of plru_tb is architecture behave of plru_tb is
@ -50,6 +54,8 @@ begin


stim: process stim: process
begin begin
test_runner_setup(runner, runner_cfg);

wait for 4*clk_period; wait for 4*clk_period;


report "accessing 1:"; report "accessing 1:";
@ -103,6 +109,6 @@ begin
wait for clk_period; wait for clk_period;
report "lru:" & to_hstring(lru); report "lru:" & to_hstring(lru);


std.env.finish; test_runner_cleanup(runner);
end process; end process;
end; end;

@ -2,8 +2,8 @@ library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;


library work; library osvvm;
use work.glibc_random.all; use osvvm.RandomPkg.all;


entity random is entity random is
port ( port (
@ -20,9 +20,10 @@ begin


process(clk) process(clk)
variable rand : std_ulogic_vector(63 downto 0); variable rand : std_ulogic_vector(63 downto 0);
variable rnd : RandomPType;
begin begin
if rising_edge(clk) then if rising_edge(clk) then
rand := pseudorand(64); rand := rnd.RandSlv(64);
data <= rand; data <= rand;
raw <= rand; raw <= rand;
end if; end if;

@ -1,14 +1,20 @@
library vunit_lib;
context vunit_lib.vunit_context;

library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all; use ieee.numeric_std.all;


library work; library work;
use work.common.all; use work.common.all;
use work.glibc_random.all;
use work.ppc_fx_insns.all; use work.ppc_fx_insns.all;
use work.insn_helpers.all; use work.insn_helpers.all;


library osvvm;
use osvvm.RandomPkg.all;

entity rotator_tb is entity rotator_tb is
generic (runner_cfg : string := runner_cfg_default);
end rotator_tb; end rotator_tb;


architecture behave of rotator_tb is architecture behave of rotator_tb is
@ -41,256 +47,250 @@ begin
stim_process: process stim_process: process
variable behave_ra: std_ulogic_vector(63 downto 0); variable behave_ra: std_ulogic_vector(63 downto 0);
variable behave_ca_ra: std_ulogic_vector(64 downto 0); variable behave_ca_ra: std_ulogic_vector(64 downto 0);
variable rnd : RandomPType;
begin begin
-- rlwinm, rlwnm rnd.InitSeed(stim_process'path_name);
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 <= pseudorand(64);
shift <= pseudorand(7);
insn <= x"00000" & '0' & pseudorand(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 test_runner_setup(runner, runner_cfg);
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 <= pseudorand(64);
ra <= pseudorand(64);
shift <= "00" & pseudorand(5);
insn <= x"00000" & '0' & pseudorand(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 while test_suite loop
report "test rld[i]cl"; if run("Test rlw[i]nm") then
ra <= (others => '0'); ra <= (others => '0');
is_32bit <= '0'; is_32bit <= '1';
right_shift <= '0'; right_shift <= '0';
arith <= '0'; arith <= '0';
clear_left <= '1'; clear_left <= '1';
clear_right <= '0'; clear_right <= '1';
rldicl_loop : for i in 0 to 1000 loop extsw <= '0';
rs <= pseudorand(64); rlwnm_loop : for i in 0 to 1000 loop
shift <= pseudorand(7); rs <= rnd.RandSlv(64);
insn <= x"00000" & '0' & pseudorand(10) & '0'; shift <= rnd.RandSlv(7);
wait for clk_period; insn <= x"00000" & '0' & rnd.RandSlv(10) & '0';
behave_ra := ppc_rldicl(rs, shift(5 downto 0), insn_mb(insn)); wait for clk_period;
assert behave_ra = result behave_ra := ppc_rlwinm(rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn));
report "bad rldicl expected " & to_hstring(behave_ra) & " got " & to_hstring(result); assert behave_ra = result
end loop; report "bad rlwnm expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
end loop;


-- rldicr, rldcr elsif run("Test rlwimi") then
report "test rld[i]cr"; is_32bit <= '1';
ra <= (others => '0'); right_shift <= '0';
is_32bit <= '0'; arith <= '0';
right_shift <= '0'; clear_left <= '1';
arith <= '0'; clear_right <= '1';
clear_left <= '0'; rlwimi_loop : for i in 0 to 1000 loop
clear_right <= '1'; rs <= rnd.RandSlv(64);
rldicr_loop : for i in 0 to 1000 loop ra <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= "00" & rnd.RandSlv(5);
shift <= pseudorand(7); insn <= x"00000" & '0' & rnd.RandSlv(10) & '0';
insn <= x"00000" & '0' & pseudorand(10) & '0'; wait for clk_period;
wait for clk_period; behave_ra := ppc_rlwimi(ra, rs, shift(4 downto 0), insn_mb32(insn), insn_me32(insn));
behave_ra := ppc_rldicr(rs, shift(5 downto 0), insn_me(insn)); assert behave_ra = result
--report "rs = " & to_hstring(rs); report "bad rlwimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
--report "ra = " & to_hstring(ra); end loop;
--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 elsif run("Test rld[i]cl") then
report "test rldic"; ra <= (others => '0');
ra <= (others => '0'); is_32bit <= '0';
is_32bit <= '0'; right_shift <= '0';
right_shift <= '0'; arith <= '0';
arith <= '0'; clear_left <= '1';
clear_left <= '1'; clear_right <= '0';
clear_right <= '1'; rldicl_loop : for i in 0 to 1000 loop
rldic_loop : for i in 0 to 1000 loop rs <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= rnd.RandSlv(7);
shift <= '0' & pseudorand(6); insn <= x"00000" & '0' & rnd.RandSlv(10) & '0';
insn <= x"00000" & '0' & pseudorand(10) & '0'; wait for clk_period;
wait for clk_period; behave_ra := ppc_rldicl(rs, shift(5 downto 0), insn_mb(insn));
behave_ra := ppc_rldic(rs, shift(5 downto 0), insn_mb(insn)); assert behave_ra = result
assert behave_ra = result report "bad rldicl expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
report "bad rldic expected " & to_hstring(behave_ra) & " got " & to_hstring(result); end loop;
end loop;


-- rldimi elsif run("Test rld[i]cr") then
report "test rldimi"; ra <= (others => '0');
is_32bit <= '0'; is_32bit <= '0';
right_shift <= '0'; right_shift <= '0';
arith <= '0'; arith <= '0';
clear_left <= '1'; clear_left <= '0';
clear_right <= '1'; clear_right <= '1';
rldimi_loop : for i in 0 to 1000 loop rldicr_loop : for i in 0 to 1000 loop
rs <= pseudorand(64); rs <= rnd.RandSlv(64);
ra <= pseudorand(64); shift <= rnd.RandSlv(7);
shift <= '0' & pseudorand(6); insn <= x"00000" & '0' & rnd.RandSlv(10) & '0';
insn <= x"00000" & '0' & pseudorand(10) & '0'; wait for clk_period;
wait for clk_period; behave_ra := ppc_rldicr(rs, shift(5 downto 0), insn_me(insn));
behave_ra := ppc_rldimi(ra, rs, shift(5 downto 0), insn_mb(insn)); --report "rs = " & to_hstring(rs);
assert behave_ra = result --report "ra = " & to_hstring(ra);
report "bad rldimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result); --report "shift = " & to_hstring(shift);
end loop; --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;


-- slw elsif run("Test rldic") then
report "test slw"; ra <= (others => '0');
ra <= (others => '0'); is_32bit <= '0';
is_32bit <= '1'; right_shift <= '0';
right_shift <= '0'; arith <= '0';
arith <= '0'; clear_left <= '1';
clear_left <= '0'; clear_right <= '1';
clear_right <= '0'; rldic_loop : for i in 0 to 1000 loop
slw_loop : for i in 0 to 1000 loop rs <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= '0' & rnd.RandSlv(6);
shift <= pseudorand(7); insn <= x"00000" & '0' & rnd.RandSlv(10) & '0';
wait for clk_period; wait for clk_period;
behave_ra := ppc_slw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); behave_ra := ppc_rldic(rs, shift(5 downto 0), insn_mb(insn));
assert behave_ra = result assert behave_ra = result
report "bad slw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); report "bad rldic expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
end loop; end loop;


-- sld elsif run("Test rldimi") then
report "test sld"; is_32bit <= '0';
ra <= (others => '0'); right_shift <= '0';
is_32bit <= '0'; arith <= '0';
right_shift <= '0'; clear_left <= '1';
arith <= '0'; clear_right <= '1';
clear_left <= '0'; rldimi_loop : for i in 0 to 1000 loop
clear_right <= '0'; rs <= rnd.RandSlv(64);
sld_loop : for i in 0 to 1000 loop ra <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= '0' & rnd.RandSlv(6);
shift <= pseudorand(7); insn <= x"00000" & '0' & rnd.RandSlv(10) & '0';
wait for clk_period; wait for clk_period;
behave_ra := ppc_sld(rs, std_ulogic_vector(resize(unsigned(shift), 64))); behave_ra := ppc_rldimi(ra, rs, shift(5 downto 0), insn_mb(insn));
assert behave_ra = result assert behave_ra = result
report "bad sld expected " & to_hstring(behave_ra) & " got " & to_hstring(result); report "bad rldimi expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
end loop; end loop;


-- srw elsif run("Test slw") then
report "test srw"; ra <= (others => '0');
ra <= (others => '0'); is_32bit <= '1';
is_32bit <= '1'; right_shift <= '0';
right_shift <= '1'; arith <= '0';
arith <= '0'; clear_left <= '0';
clear_left <= '0'; clear_right <= '0';
clear_right <= '0'; slw_loop : for i in 0 to 1000 loop
srw_loop : for i in 0 to 1000 loop rs <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= rnd.RandSlv(7);
shift <= pseudorand(7); wait for clk_period;
wait for clk_period; behave_ra := ppc_slw(rs, std_ulogic_vector(resize(unsigned(shift), 64)));
behave_ra := ppc_srw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result
assert behave_ra = result report "bad slw expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
report "bad srw expected " & to_hstring(behave_ra) & " got " & to_hstring(result); end loop;
end loop;


-- srd elsif run("Test sld") then
report "test srd"; ra <= (others => '0');
ra <= (others => '0'); is_32bit <= '0';
is_32bit <= '0'; right_shift <= '0';
right_shift <= '1'; arith <= '0';
arith <= '0'; clear_left <= '0';
clear_left <= '0'; clear_right <= '0';
clear_right <= '0'; sld_loop : for i in 0 to 1000 loop
srd_loop : for i in 0 to 1000 loop rs <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= rnd.RandSlv(7);
shift <= pseudorand(7); wait for clk_period;
wait for clk_period; behave_ra := ppc_sld(rs, std_ulogic_vector(resize(unsigned(shift), 64)));
behave_ra := ppc_srd(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result
assert behave_ra = result report "bad sld expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
report "bad srd expected " & to_hstring(behave_ra) & " got " & to_hstring(result); end loop;
end loop;


-- sraw[i] elsif run("Test srw") then
report "test sraw[i]"; ra <= (others => '0');
ra <= (others => '0'); is_32bit <= '1';
is_32bit <= '1'; right_shift <= '1';
right_shift <= '1'; arith <= '0';
arith <= '1'; clear_left <= '0';
clear_left <= '0'; clear_right <= '0';
clear_right <= '0'; srw_loop : for i in 0 to 1000 loop
sraw_loop : for i in 0 to 1000 loop rs <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= rnd.RandSlv(7);
shift <= '0' & pseudorand(6); wait for clk_period;
wait for clk_period; behave_ra := ppc_srw(rs, std_ulogic_vector(resize(unsigned(shift), 64)));
behave_ca_ra := ppc_sraw(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result
--report "rs = " & to_hstring(rs); report "bad srw expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
--report "ra = " & to_hstring(ra); end loop;
--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] elsif run("Test srd") then
report "test srad[i]"; ra <= (others => '0');
ra <= (others => '0'); is_32bit <= '0';
is_32bit <= '0'; right_shift <= '1';
right_shift <= '1'; arith <= '0';
arith <= '1'; clear_left <= '0';
clear_left <= '0'; clear_right <= '0';
clear_right <= '0'; srd_loop : for i in 0 to 1000 loop
srad_loop : for i in 0 to 1000 loop rs <= rnd.RandSlv(64);
rs <= pseudorand(64); shift <= rnd.RandSlv(7);
shift <= pseudorand(7); wait for clk_period;
wait for clk_period; behave_ra := ppc_srd(rs, std_ulogic_vector(resize(unsigned(shift), 64)));
behave_ca_ra := ppc_srad(rs, std_ulogic_vector(resize(unsigned(shift), 64))); assert behave_ra = result
--report "rs = " & to_hstring(rs); report "bad srd expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
--report "ra = " & to_hstring(ra); end loop;
--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 elsif run("Test sraw[i]") then
report "test extswsli"; ra <= (others => '0');
ra <= (others => '0'); is_32bit <= '1';
is_32bit <= '0'; right_shift <= '1';
right_shift <= '0'; arith <= '1';
arith <= '0'; clear_left <= '0';
clear_left <= '0'; clear_right <= '0';
clear_right <= '0'; sraw_loop : for i in 0 to 1000 loop
extsw <= '1'; rs <= rnd.RandSlv(64);
extswsli_loop : for i in 0 to 1000 loop shift <= '0' & rnd.RandSlv(6);
rs <= pseudorand(64); wait for clk_period;
shift <= '0' & pseudorand(6); behave_ca_ra := ppc_sraw(rs, std_ulogic_vector(resize(unsigned(shift), 64)));
wait for clk_period; --report "rs = " & to_hstring(rs);
behave_ra := rs; --report "ra = " & to_hstring(ra);
behave_ra(63 downto 32) := (others => rs(31)); --report "shift = " & to_hstring(shift);
behave_ra := std_ulogic_vector(shift_left(unsigned(behave_ra), --report "result = " & to_hstring(carry_out & result);
to_integer(unsigned(shift)))); assert behave_ca_ra(63 downto 0) = result and behave_ca_ra(64) = carry_out
--report "rs = " & to_hstring(rs); report "bad sraw expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result);
--report "ra = " & to_hstring(ra); end loop;
--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;


std.env.finish; 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;

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 process;
end behave; end behave;

@ -0,0 +1,27 @@
from pathlib import Path
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. 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")

prj.main()
Loading…
Cancel
Save