commit
3a2c4b8978
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,183 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.common.all;
|
||||||
|
|
||||||
|
entity rotator is
|
||||||
|
port (rs: in std_ulogic_vector(63 downto 0);
|
||||||
|
ra: in std_ulogic_vector(63 downto 0);
|
||||||
|
shift: in std_ulogic_vector(6 downto 0);
|
||||||
|
insn: in std_ulogic_vector(31 downto 0);
|
||||||
|
is_32bit: in std_ulogic;
|
||||||
|
right_shift: in std_ulogic;
|
||||||
|
arith: in std_ulogic;
|
||||||
|
clear_left: in std_ulogic;
|
||||||
|
clear_right: in std_ulogic;
|
||||||
|
result: out std_ulogic_vector(63 downto 0);
|
||||||
|
carry_out: out std_ulogic
|
||||||
|
);
|
||||||
|
end entity rotator;
|
||||||
|
|
||||||
|
architecture behaviour of rotator is
|
||||||
|
signal repl32: std_ulogic_vector(63 downto 0);
|
||||||
|
signal rot_count: std_ulogic_vector(5 downto 0);
|
||||||
|
signal rot1, rot2, rot: std_ulogic_vector(63 downto 0);
|
||||||
|
signal sh, mb, me: std_ulogic_vector(6 downto 0);
|
||||||
|
signal mr, ml: std_ulogic_vector(63 downto 0);
|
||||||
|
signal output_mode: std_ulogic_vector(1 downto 0);
|
||||||
|
|
||||||
|
-- note BE bit numbering
|
||||||
|
function right_mask(mask_begin: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is
|
||||||
|
variable ret: std_ulogic_vector(63 downto 0);
|
||||||
|
begin
|
||||||
|
ret := (others => '0');
|
||||||
|
for i in 0 to 63 loop
|
||||||
|
if i >= to_integer(unsigned(mask_begin)) then
|
||||||
|
ret(63 - i) := '1';
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function left_mask(mask_end: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is
|
||||||
|
variable ret: std_ulogic_vector(63 downto 0);
|
||||||
|
begin
|
||||||
|
ret := (others => '0');
|
||||||
|
if mask_end(6) = '0' then
|
||||||
|
for i in 0 to 63 loop
|
||||||
|
if i <= to_integer(unsigned(mask_end)) then
|
||||||
|
ret(63 - i) := '1';
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
|
return ret;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
rotator_0: process(all)
|
||||||
|
begin
|
||||||
|
-- First replicate bottom 32 bits to both halves if 32-bit
|
||||||
|
if is_32bit = '1' then
|
||||||
|
repl32 <= rs(31 downto 0) & rs(31 downto 0);
|
||||||
|
else
|
||||||
|
repl32 <= rs;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Negate shift count for right shifts
|
||||||
|
if right_shift = '1' then
|
||||||
|
rot_count <= std_ulogic_vector(- signed(shift(5 downto 0)));
|
||||||
|
else
|
||||||
|
rot_count <= shift(5 downto 0);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Rotator works in 3 stages using 2 bits of the rotate count each
|
||||||
|
-- time. This gives 4:1 multiplexors which is ideal for the 6-input
|
||||||
|
-- LUTs in the Xilinx Artix 7.
|
||||||
|
-- We look at the low bits of the rotate count first because they will
|
||||||
|
-- have less delay through the negation above.
|
||||||
|
-- First rotate by 0, 1, 2, or 3
|
||||||
|
case rot_count(1 downto 0) is
|
||||||
|
when "00" =>
|
||||||
|
rot1 <= repl32;
|
||||||
|
when "01" =>
|
||||||
|
rot1 <= repl32(62 downto 0) & repl32(63);
|
||||||
|
when "10" =>
|
||||||
|
rot1 <= repl32(61 downto 0) & repl32(63 downto 62);
|
||||||
|
when others =>
|
||||||
|
rot1 <= repl32(60 downto 0) & repl32(63 downto 61);
|
||||||
|
end case;
|
||||||
|
-- Next rotate by 0, 4, 8 or 12
|
||||||
|
case rot_count(3 downto 2) is
|
||||||
|
when "00" =>
|
||||||
|
rot2 <= rot1;
|
||||||
|
when "01" =>
|
||||||
|
rot2 <= rot1(59 downto 0) & rot1(63 downto 60);
|
||||||
|
when "10" =>
|
||||||
|
rot2 <= rot1(55 downto 0) & rot1(63 downto 56);
|
||||||
|
when others =>
|
||||||
|
rot2 <= rot1(51 downto 0) & rot1(63 downto 52);
|
||||||
|
end case;
|
||||||
|
-- Lastly rotate by 0, 16, 32 or 48
|
||||||
|
case rot_count(5 downto 4) is
|
||||||
|
when "00" =>
|
||||||
|
rot <= rot2;
|
||||||
|
when "01" =>
|
||||||
|
rot <= rot2(47 downto 0) & rot2(63 downto 48);
|
||||||
|
when "10" =>
|
||||||
|
rot <= rot2(31 downto 0) & rot2(63 downto 32);
|
||||||
|
when others =>
|
||||||
|
rot <= rot2(15 downto 0) & rot2(63 downto 16);
|
||||||
|
end case;
|
||||||
|
|
||||||
|
-- Trim shift count to 6 bits for 32-bit shifts
|
||||||
|
sh <= (shift(6) and not is_32bit) & shift(5 downto 0);
|
||||||
|
|
||||||
|
-- Work out mask begin/end indexes (caution, big-endian bit numbering)
|
||||||
|
if clear_left = '1' then
|
||||||
|
if is_32bit = '1' then
|
||||||
|
mb <= "01" & insn(10 downto 6);
|
||||||
|
else
|
||||||
|
mb <= "0" & insn(5) & insn(10 downto 6);
|
||||||
|
end if;
|
||||||
|
elsif right_shift = '1' then
|
||||||
|
-- this is basically mb <= sh + (is_32bit? 32: 0);
|
||||||
|
if is_32bit = '1' then
|
||||||
|
mb <= sh(5) & not sh(5) & sh(4 downto 0);
|
||||||
|
else
|
||||||
|
mb <= sh;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
mb <= ('0' & is_32bit & "00000");
|
||||||
|
end if;
|
||||||
|
if clear_right = '1' and is_32bit = '1' then
|
||||||
|
me <= "01" & insn(5 downto 1);
|
||||||
|
elsif clear_right = '1' and clear_left = '0' then
|
||||||
|
me <= "0" & insn(5) & insn(10 downto 6);
|
||||||
|
else
|
||||||
|
-- effectively, 63 - sh
|
||||||
|
me <= sh(6) & not sh(5 downto 0);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Calculate left and right masks
|
||||||
|
mr <= right_mask(mb);
|
||||||
|
ml <= left_mask(me);
|
||||||
|
|
||||||
|
-- Work out output mode
|
||||||
|
-- 00 for sl[wd]
|
||||||
|
-- 0w for rlw*, rldic, rldicr, rldimi, where w = 1 iff mb > me
|
||||||
|
-- 10 for rldicl, sr[wd]
|
||||||
|
-- 1z for sra[wd][i], z = 1 if rs is negative
|
||||||
|
if (clear_left = '1' and clear_right = '0') or right_shift = '1' then
|
||||||
|
output_mode(1) <= '1';
|
||||||
|
output_mode(0) <= arith and repl32(63);
|
||||||
|
else
|
||||||
|
output_mode(1) <= '0';
|
||||||
|
if clear_right = '1' and unsigned(mb(5 downto 0)) > unsigned(me(5 downto 0)) then
|
||||||
|
output_mode(0) <= '1';
|
||||||
|
else
|
||||||
|
output_mode(0) <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Generate output from rotated input and masks
|
||||||
|
case output_mode is
|
||||||
|
when "00" =>
|
||||||
|
result <= (rot and (mr and ml)) or (ra and not (mr and ml));
|
||||||
|
when "01" =>
|
||||||
|
result <= (rot and (mr or ml)) or (ra and not (mr or ml));
|
||||||
|
when "10" =>
|
||||||
|
result <= rot and mr;
|
||||||
|
when others =>
|
||||||
|
result <= rot or not mr;
|
||||||
|
end case;
|
||||||
|
|
||||||
|
-- Generate carry output for arithmetic shift right of negative value
|
||||||
|
if output_mode = "11" then
|
||||||
|
carry_out <= or (rs and not ml);
|
||||||
|
else
|
||||||
|
carry_out <= '0';
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
end behaviour;
|
@ -0,0 +1,269 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
entity rotator_tb is
|
||||||
|
end rotator_tb;
|
||||||
|
|
||||||
|
architecture behave of rotator_tb is
|
||||||
|
constant clk_period: time := 10 ns;
|
||||||
|
signal ra, rs: std_ulogic_vector(63 downto 0);
|
||||||
|
signal shift: std_ulogic_vector(6 downto 0) := (others => '0');
|
||||||
|
signal insn: std_ulogic_vector(31 downto 0) := (others => '0');
|
||||||
|
signal is_32bit, right_shift, arith, clear_left, clear_right: std_ulogic := '0';
|
||||||
|
signal result: std_ulogic_vector(63 downto 0);
|
||||||
|
signal carry_out: std_ulogic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
rotator_0: entity work.rotator
|
||||||
|
port map (
|
||||||
|
rs => rs,
|
||||||
|
ra => ra,
|
||||||
|
shift => shift,
|
||||||
|
insn => insn,
|
||||||
|
is_32bit => is_32bit,
|
||||||
|
right_shift => right_shift,
|
||||||
|
arith => arith,
|
||||||
|
clear_left => clear_left,
|
||||||
|
clear_right => clear_right,
|
||||||
|
result => result,
|
||||||
|
carry_out => carry_out
|
||||||
|
);
|
||||||
|
|
||||||
|
stim_process: process
|
||||||
|
variable behave_ra: std_ulogic_vector(63 downto 0);
|
||||||
|
variable behave_ca_ra: std_ulogic_vector(64 downto 0);
|
||||||
|
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';
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
-- 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;
|
||||||
|
|
||||||
|
assert false report "end of test" severity failure;
|
||||||
|
wait;
|
||||||
|
end process;
|
||||||
|
end behave;
|
Loading…
Reference in New Issue