1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-01-11 23:43:15 +00:00
antonblanchard.microwatt/multiply_tb.vhdl
Paul Mackerras 9880fc7435 multiply: Move selection of result bits into execute1
This puts the logic that selects which bits of the multiplier result
get written into the destination GPR into execute1, moved out from
multiply.

The multiplier is now expected to do an unsigned multiplication of
64-bit operands, optionally negate the result, detect 32-bit
or 64-bit signed overflow of the result, and return a full 128-bit
result.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
2020-06-13 20:08:47 +10:00

265 lines
7.5 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
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;
entity multiply_tb is
end multiply_tb;
architecture behave of multiply_tb is
signal clk : std_ulogic;
constant clk_period : time := 10 ns;
constant pipeline_depth : integer := 4;
signal m1 : Execute1ToMultiplyType := Execute1ToMultiplyInit;
signal m2 : MultiplyToExecute1Type;
function absval(x: std_ulogic_vector) return std_ulogic_vector is
begin
if x(x'left) = '1' then
return std_ulogic_vector(- signed(x));
else
return x;
end if;
end;
begin
multiply_0: entity work.multiply
generic map (PIPELINE_DEPTH => pipeline_depth)
port map (clk => clk, m_in => m1, m_out => m2);
clk_process: process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stim_process: process
variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0);
variable si: std_ulogic_vector(15 downto 0);
begin
wait for clk_period;
m1.valid <= '1';
m1.data1 <= x"0000000000001000";
m1.data2 <= x"0000000000001111";
wait for clk_period;
assert m2.valid = '0';
m1.valid <= '0';
wait for clk_period;
assert m2.valid = '0';
wait for clk_period;
assert m2.valid = '0';
wait for clk_period;
assert m2.valid = '1';
assert m2.result = x"00000000000000000000000001111000";
wait for clk_period;
assert m2.valid = '0';
m1.valid <= '1';
wait for clk_period;
assert m2.valid = '0';
m1.valid <= '0';
wait for clk_period * (pipeline_depth-1);
assert m2.valid = '1';
assert m2.result = x"00000000000000000000000001111000";
-- test mulld
mulld_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);
behave_rt := ppc_mulld(ra, rb);
m1.data1 <= absval(ra);
m1.data2 <= absval(rb);
m1.neg_result <= ra(63) xor rb(63);
m1.valid <= '1';
wait for clk_period;
m1.valid <= '0';
wait for clk_period * (pipeline_depth-1);
assert m2.valid = '1';
assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0))
report "bad mulld expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0));
end loop;
-- test mulhdu
mulhdu_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);
behave_rt := ppc_mulhdu(ra, rb);
m1.data1 <= ra;
m1.data2 <= rb;
m1.neg_result <= '0';
m1.valid <= '1';
wait for clk_period;
m1.valid <= '0';
wait for clk_period * (pipeline_depth-1);
assert m2.valid = '1';
assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64))
report "bad mulhdu expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64));
end loop;
-- test mulhd
mulhd_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);
behave_rt := ppc_mulhd(ra, rb);
m1.data1 <= absval(ra);
m1.data2 <= absval(rb);
m1.neg_result <= ra(63) xor rb(63);
m1.valid <= '1';
wait for clk_period;
m1.valid <= '0';
wait for clk_period * (pipeline_depth-1);
assert m2.valid = '1';
assert to_hstring(behave_rt) = to_hstring(m2.result(127 downto 64))
report "bad mulhd expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(127 downto 64));
end loop;
-- test mullw
mullw_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);
behave_rt := ppc_mullw(ra, rb);
m1.data1 <= (others => '0');
m1.data1(31 downto 0) <= absval(ra(31 downto 0));
m1.data2 <= (others => '0');
m1.data2(31 downto 0) <= absval(rb(31 downto 0));
m1.neg_result <= ra(31) xor rb(31);
m1.valid <= '1';
wait for clk_period;
m1.valid <= '0';
wait for clk_period * (pipeline_depth-1);
assert m2.valid = '1';
assert to_hstring(behave_rt) = to_hstring(m2.result(63 downto 0))
report "bad mullw expected " & to_hstring(behave_rt) & " got " & to_hstring(m2.result(63 downto 0));
end loop;
-- test mulhw
mulhw_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);
behave_rt := ppc_mulhw(ra, rb);
m1.data1 <= (others => '0');
m1.data1(31 downto 0) <= absval(ra(31 downto 0));
m1.data2 <= (others => '0');
m1.data2(31 downto 0) <= absval(rb(31 downto 0));
m1.neg_result <= ra(31) xor rb(31);
m1.valid <= '1';
wait for clk_period;
m1.valid <= '0';
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 mulhw expected " & to_hstring(behave_rt) & " got " &
to_hstring(m2.result(63 downto 32) & m2.result(63 downto 32));
end loop;
-- test mulhwu
mulhwu_loop : for i in 0 to 1000 loop
ra := pseudorand(ra'length);
rb := pseudorand(rb'length);
behave_rt := ppc_mulhwu(ra, rb);
m1.data1 <= (others => '0');
m1.data1(31 downto 0) <= ra(31 downto 0);
m1.data2 <= (others => '0');
m1.data2(31 downto 0) <= rb(31 downto 0);
m1.neg_result <= '0';
m1.valid <= '1';
wait for clk_period;
m1.valid <= '0';
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);
behave_rt := ppc_mulli(ra, si);
m1.data1 <= absval(ra);
m1.data2 <= (others => '0');
m1.data2(15 downto 0) <= absval(si);
m1.neg_result <= ra(63) xor si(15);
m1.valid <= '1';
wait for clk_period;
m1.valid <= '0';
wait for clk_period * (pipeline_depth-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));
end loop;
std.env.finish;
wait;
end process;
end behave;