Merge pull request #295 from LarsAsplund/master

Run VHDL tests with VUnit
pull/303/head
Michael Neuling 4 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
matrix:
task: [
"tests_unit",
"tests_console",
"{1..99}",
"{100..199}",
@ -52,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

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

@ -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,78 +43,85 @@ begin

stim_process: process
variable r: std_ulogic_vector(63 downto 0);
variable rnd : RandomPType;
begin
-- 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);
rnd.InitSeed(stim_process'path_name);

report "test cntlzd/w";
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;
test_runner_setup(runner, runner_cfg);

report "test cnttzd/w";
count_right <= '1';
for j in 0 to 100 loop
r := pseudorand(64);
r(0) := '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 result = x"0000000000000040"
report "bad cntlzd 0 = " & to_hstring(result);
count_right <= '1';
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;

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

@ -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,516 +43,493 @@ 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
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';
rnd.InitSeed(stim_process'path_name);

wait for clk_period;
assert d2.valid = '0';
test_runner_setup(runner, runner_cfg);

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(pseudorand(dlength * 8)), 64));
rb := std_ulogic_vector(resize(signed(pseudorand(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(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.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(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';
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(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';
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(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';
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(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;

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(pseudorand(dlength * 8)), 32)) & x"00000000";
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';
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(pseudorand(dlength * 8)), 32)) & x"00000000";
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;

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

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(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';
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(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';
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(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';
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;

std.env.finish;
test_runner_cleanup(runner);
end process;
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;
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,232 +52,241 @@ 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
wait for clk_period;
rnd.InitSeed(stim_process'path_name);

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

wait for clk_period;
assert m2.valid = '0';
while test_suite loop
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;
assert m2.valid = '0';
wait for clk_period;
assert m2.valid = '0';

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

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';
wait for clk_period;
assert m2.valid = '0';

m1.valid <= '1';
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 <= '0';
m1.valid <= '1';

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

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

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

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))
report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0));
end loop;
wait for clk_period * (pipeline_depth-1);

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

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

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))
report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64));
end loop;
wait for clk_period * (pipeline_depth-1);

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

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

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))
report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64));
end loop;
wait for clk_period * (pipeline_depth-1);

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

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');
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';
elsif run("Test mullw") then
mullw_loop : for i in 0 to 1000 loop
ra := rnd.RandSlv(ra'length);
rb := rnd.RandSlv(rb'length);

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))
report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0));
end loop;
wait for clk_period * (pipeline_depth-1);

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

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');
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';
elsif run("Test mulhw") then
mulhw_loop : for i in 0 to 1000 loop
ra := rnd.RandSlv(ra'length);
rb := rnd.RandSlv(rb'length);

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))
report "bad mulhw expected " & to_hstring(behave_rt) & " got " &
to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32));
end loop;
wait for clk_period * (pipeline_depth-1);

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

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');
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';
elsif run("Test mulhwu") then
mulhwu_loop : for i in 0 to 1000 loop
ra := rnd.RandSlv(ra'length);
rb := rnd.RandSlv(rb'length);

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))
report "bad mulhwu expected " & to_hstring(behave_rt) & " got " &
to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32));
end loop;
wait for clk_period * (pipeline_depth-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;

-- test mulli
mulli_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
si := pseudorand(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;

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

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

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

@ -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,256 +47,250 @@ 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
-- 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 <= 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;
rnd.InitSeed(stim_process'path_name);

-- 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 <= 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;
test_runner_setup(runner, runner_cfg);

-- 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 <= pseudorand(64);
shift <= pseudorand(7);
insn <= x"00000" & '0' & pseudorand(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;
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;

-- 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 <= pseudorand(64);
shift <= pseudorand(7);
insn <= x"00000" & '0' & pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= '0' & pseudorand(6);
insn <= x"00000" & '0' & pseudorand(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 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;

-- 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 <= pseudorand(64);
ra <= pseudorand(64);
shift <= '0' & pseudorand(6);
insn <= x"00000" & '0' & pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= '0' & pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= pseudorand(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 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;

-- 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 <= pseudorand(64);
shift <= '0' & pseudorand(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;
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;

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