You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			277 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			VHDL
		
	
			
		
		
	
	
			277 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			VHDL
		
	
| 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.decode_types.all;
 | |
| use work.common.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
 | |
|     signal clk              : std_ulogic;
 | |
|     constant clk_period     : time := 10 ns;
 | |
| 
 | |
|     constant pipeline_depth : integer := 4;
 | |
| 
 | |
|     signal m1               : MultiplyInputType := MultiplyInputInit;
 | |
|     signal m2               : MultiplyOutputType;
 | |
| 
 | |
|     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);
 | |
|         variable sign: std_ulogic;
 | |
|         variable rnd : RandomPType;
 | |
|     begin
 | |
|         rnd.InitSeed(stim_process'path_name);
 | |
| 
 | |
|         test_runner_setup(runner, runner_cfg);
 | |
| 
 | |
|         while test_suite loop
 | |
|             if run("Test interface") then
 | |
|                 wait for clk_period;
 | |
| 
 | |
|                 m1.valid <= '1';
 | |
|                 m1.data1 <= x"0000000000001000";
 | |
|                 m1.data2 <= x"0000000000001111";
 | |
| 
 | |
|                 wait for clk_period;
 | |
|                 check_false(?? m2.valid, result("for valid"));
 | |
| 
 | |
|                 m1.valid <= '0';
 | |
| 
 | |
|                 wait for clk_period;
 | |
|                 check_false(?? m2.valid, result("for valid"));
 | |
| 
 | |
|                 wait for clk_period;
 | |
|                 check_false(?? m2.valid, result("for valid"));
 | |
| 
 | |
|                 wait for clk_period;
 | |
|                 check_true(?? m2.valid, result("for valid"));
 | |
|                 check_equal(m2.result, 16#1111000#);
 | |
| 
 | |
|                 wait for clk_period;
 | |
|                 check_false(?? m2.valid, result("for valid"));
 | |
| 
 | |
|                 m1.valid <= '1';
 | |
| 
 | |
|                 wait for clk_period;
 | |
|                 check_false(?? m2.valid, result("for valid"));
 | |
| 
 | |
|                 m1.valid <= '0';
 | |
| 
 | |
|                 wait for clk_period * (pipeline_depth-1);
 | |
|                 check_true(?? m2.valid, result("for valid"));
 | |
|                 check_equal(m2.result, 16#1111000#);
 | |
| 
 | |
|             elsif run("Test mulld") then
 | |
|                 mulld_loop : for i in 0 to 1000 loop
 | |
|                     ra := rnd.RandSlv(ra'length);
 | |
|                     rb := rnd.RandSlv(rb'length);
 | |
| 
 | |
|                     behave_rt := ppc_mulld(ra, rb);
 | |
| 
 | |
|                     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;
 | |
| 
 | |
|                     m1.valid <= '0';
 | |
| 
 | |
|                     wait for clk_period * (pipeline_depth-1);
 | |
| 
 | |
|                     check_true(?? m2.valid, result("for valid"));
 | |
|                     check_equal(m2.result(63 downto 0), behave_rt, result("for mulld " & to_hstring(behave_rt)));
 | |
|                 end loop;
 | |
| 
 | |
|             elsif run("Test mulhdu") then
 | |
|                 mulhdu_loop : for i in 0 to 1000 loop
 | |
|                     ra := rnd.RandSlv(ra'length);
 | |
|                     rb := rnd.RandSlv(rb'length);
 | |
| 
 | |
|                     behave_rt := ppc_mulhdu(ra, rb);
 | |
| 
 | |
|                     m1.data1 <= ra;
 | |
|                     m1.data2 <= rb;
 | |
|                     m1.not_result <= '0';
 | |
|                     m1.addend <= (others => '0');
 | |
|                     m1.valid <= '1';
 | |
| 
 | |
|                     wait for clk_period;
 | |
| 
 | |
|                     m1.valid <= '0';
 | |
| 
 | |
|                     wait for clk_period * (pipeline_depth-1);
 | |
| 
 | |
|                     check_true(?? m2.valid, result("for valid"));
 | |
|                     check_equal(m2.result(127 downto 64), behave_rt, result("for mulhdu " & to_hstring(behave_rt)));
 | |
|                 end loop;
 | |
| 
 | |
|             elsif run("Test mulhd") then
 | |
|                 mulhd_loop : for i in 0 to 1000 loop
 | |
|                     ra := rnd.RandSlv(ra'length);
 | |
|                     rb := rnd.RandSlv(rb'length);
 | |
| 
 | |
|                     behave_rt := ppc_mulhd(ra, rb);
 | |
| 
 | |
|                     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;
 | |
| 
 | |
|                     m1.valid <= '0';
 | |
| 
 | |
|                     wait for clk_period * (pipeline_depth-1);
 | |
| 
 | |
|                     check_true(?? m2.valid, result("for valid"));
 | |
|                     check_equal(m2.result(127 downto 64), behave_rt, result("for mulhd " & to_hstring(behave_rt)));
 | |
|                 end loop;
 | |
| 
 | |
|             elsif run("Test mullw") then
 | |
|                 mullw_loop : for i in 0 to 1000 loop
 | |
|                     ra := rnd.RandSlv(ra'length);
 | |
|                     rb := rnd.RandSlv(rb'length);
 | |
| 
 | |
|                     behave_rt := ppc_mullw(ra, rb);
 | |
| 
 | |
|                     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;
 | |
| 
 | |
|                     m1.valid <= '0';
 | |
| 
 | |
|                     wait for clk_period * (pipeline_depth-1);
 | |
| 
 | |
|                     check_true(?? m2.valid, result("for valid"));
 | |
|                     check_equal(m2.result(63 downto 0), behave_rt, result("for mullw " & to_hstring(behave_rt)));
 | |
|                 end loop;
 | |
| 
 | |
|             elsif run("Test mulhw") then
 | |
|                 mulhw_loop : for i in 0 to 1000 loop
 | |
|                     ra := rnd.RandSlv(ra'length);
 | |
|                     rb := rnd.RandSlv(rb'length);
 | |
| 
 | |
|                     behave_rt := ppc_mulhw(ra, rb);
 | |
| 
 | |
|                     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;
 | |
| 
 | |
|                     m1.valid <= '0';
 | |
| 
 | |
|                     wait for clk_period * (pipeline_depth-1);
 | |
| 
 | |
|                     check_true(?? m2.valid, result("for valid"));
 | |
|                     check_equal(m2.result(63 downto 32) & m2.result(63 downto 32), behave_rt, result("for mulhw " & to_hstring(behave_rt)));
 | |
|                 end loop;
 | |
| 
 | |
|             elsif run("Test mulhwu") then
 | |
|                 mulhwu_loop : for i in 0 to 1000 loop
 | |
|                     ra := rnd.RandSlv(ra'length);
 | |
|                     rb := rnd.RandSlv(rb'length);
 | |
| 
 | |
|                     behave_rt := ppc_mulhwu(ra, rb);
 | |
| 
 | |
|                     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;
 | |
| 
 | |
|                     m1.valid <= '0';
 | |
| 
 | |
|                     wait for clk_period * (pipeline_depth-1);
 | |
| 
 | |
|                     check_true(?? m2.valid, result("for valid"));
 | |
|                     check_equal(m2.result(63 downto 32) & m2.result(63 downto 32), behave_rt, result("for mulhwu " & to_hstring(behave_rt)));
 | |
|                 end loop;
 | |
| 
 | |
|             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);
 | |
| 
 | |
|                     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;
 | |
| 
 | |
|                     m1.valid <= '0';
 | |
| 
 | |
|                     wait for clk_period * (pipeline_depth-1);
 | |
| 
 | |
|                     check_true(?? m2.valid, result("for valid"));
 | |
|                     check_equal(m2.result(63 downto 0), behave_rt, result("for mulli " & to_hstring(behave_rt)));
 | |
|                 end loop;
 | |
|             end if;
 | |
|         end loop;
 | |
| 
 | |
|         test_runner_cleanup(runner);
 | |
|         wait;
 | |
|     end process;
 | |
| end behave;
 |