Merge pull request #78 from paulusmack/new-decode

New decode
pull/81/head
Anton Blanchard 5 years ago committed by GitHub
commit 3a2c4b8978
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,7 +2,8 @@ GHDL=ghdl
GHDLFLAGS=--std=08 -Psim-unisim
CFLAGS=-O2 -Wall

all = core_tb simple_ram_behavioural_tb soc_reset_tb icache_tb multiply_tb dmi_dtm_tb divider_tb
all = core_tb simple_ram_behavioural_tb soc_reset_tb icache_tb multiply_tb dmi_dtm_tb divider_tb \
rotator_tb

# XXX
# loadstore_tb fetch_tb
@ -22,7 +23,7 @@ crhelpers.o: common.o
decode1.o: common.o decode_types.o
decode2.o: decode_types.o common.o helpers.o insn_helpers.o
decode_types.o:
execute1.o: decode_types.o common.o helpers.o crhelpers.o ppc_fx_insns.o
execute1.o: decode_types.o common.o helpers.o crhelpers.o ppc_fx_insns.o insn_helpers.o rotator.o
execute2.o: common.o crhelpers.o ppc_fx_insns.o
fetch1.o: common.o
fetch2.o: common.o wishbone_types.o
@ -40,6 +41,8 @@ divider_tb.o: decode_types.o common.o glibc_random.o ppc_fx_insns.o divider.o
divider.o: common.o decode_types.o crhelpers.o
ppc_fx_insns.o: helpers.o
register_file.o: common.o
rotator.o: common.o
rotator_tb.o: common.o glibc_random.o ppc_fx_insns.o insn_helpers.o rotator.o
sim_console.o:
simple_ram_behavioural_helpers.o:
simple_ram_behavioural_tb.o: wishbone_types.o simple_ram_behavioural.o
@ -81,6 +84,9 @@ multiply_tb: multiply_tb.o
divider_tb: divider_tb.o
$(GHDL) -e $(GHDLFLAGS) $@

rotator_tb: rotator_tb.o
$(GHDL) -e $(GHDLFLAGS) $@

simple_ram_tb: simple_ram_tb.o
$(GHDL) -e $(GHDLFLAGS) $@


@ -52,18 +52,23 @@ package common is
read_reg2: std_ulogic_vector(4 downto 0);
read_data1: std_ulogic_vector(63 downto 0);
read_data2: std_ulogic_vector(63 downto 0);
const1: std_ulogic_vector(7 downto 0);
const2: std_ulogic_vector(5 downto 0);
const3: std_ulogic_vector(4 downto 0);
read_data3: std_ulogic_vector(63 downto 0);
cr: std_ulogic_vector(31 downto 0);
lr: std_ulogic;
rc: std_ulogic;
input_carry: std_ulogic;
invert_a: std_ulogic;
input_carry: carry_in_t;
output_carry: std_ulogic;
input_cr: std_ulogic;
output_cr: std_ulogic;
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type := (valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', input_carry => '0', output_carry => '0', input_cr => '0', output_cr => '0', others => (others => '0'));
is_32bit: std_ulogic;
is_signed: std_ulogic;
insn: std_ulogic_vector(31 downto 0);
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
(valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', invert_a => '0',
input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0',
is_32bit => '0', is_signed => '0', others => (others => '0'));

type Decode2ToMultiplyType is record
valid: std_ulogic;

File diff suppressed because it is too large Load Diff

@ -62,16 +62,11 @@ architecture behaviour of decode2 is
function decode_input_reg_a (t : input_reg_a_t; insn_in : std_ulogic_vector(31 downto 0);
reg_data : std_ulogic_vector(63 downto 0)) return decode_input_reg_t is
begin
case t is
when RA =>
if t = RA or (t = RA_OR_ZERO and insn_ra(insn_in) /= "00000") then
return ('1', insn_ra(insn_in), reg_data);
when RA_OR_ZERO =>
return ('1', insn_ra(insn_in), ra_or_zero(reg_data, insn_ra(insn_in)));
when RS =>
return ('1', insn_rs(insn_in), reg_data);
when NONE =>
else
return ('0', (others => '0'), (others => '0'));
end case;
end if;
end;

function decode_input_reg_b (t : input_reg_b_t; insn_in : std_ulogic_vector(31 downto 0);
@ -80,8 +75,6 @@ architecture behaviour of decode2 is
case t is
when RB =>
return ('1', insn_rb(insn_in), reg_data);
when RS =>
return ('1', insn_rs(insn_in), reg_data);
when CONST_UI =>
return ('0', (others => '0'), std_ulogic_vector(resize(unsigned(insn_ui(insn_in)), 64)));
when CONST_SI =>
@ -96,6 +89,12 @@ architecture behaviour of decode2 is
return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_bd(insn_in)) & "00", 64)));
when CONST_DS =>
return ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_ds(insn_in)) & "00", 64)));
when CONST_M1 =>
return ('0', (others => '0'), x"FFFFFFFFFFFFFFFF");
when CONST_SH =>
return ('0', (others => '0'), x"00000000000000" & "00" & insn_in(1) & insn_in(15 downto 11));
when CONST_SH32 =>
return ('0', (others => '0'), x"00000000000000" & "000" & insn_in(15 downto 11));
when NONE =>
return ('0', (others => '0'), (others => '0'));
end case;
@ -124,58 +123,6 @@ architecture behaviour of decode2 is
end case;
end;

function decode_const_a (t : constant_a_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
begin
case t is
when SH =>
return "00" & insn_sh(insn_in);
when SH32 =>
return "000" & insn_sh32(insn_in);
when FXM =>
return insn_fxm(insn_in);
when BO =>
return "000" & insn_bo(insn_in);
when BF =>
return "00000" & insn_bf(insn_in);
when TOO =>
return "000" & insn_to(insn_in);
when BC =>
return "000" & insn_bc(insn_in);
when NONE =>
return "00000000";
end case;
end;

function decode_const_b (t : constant_b_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
begin
case t is
when MB =>
return insn_mb(insn_in);
when ME =>
return insn_me(insn_in);
when MB32 =>
return "0" & insn_mb32(insn_in);
when BI =>
return "0" & insn_bi(insn_in);
when L =>
return "00000" & insn_l(insn_in);
when NONE =>
return "000000";
end case;
end;

function decode_const_c (t : constant_c_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
begin
case t is
when ME32 =>
return insn_me32(insn_in);
when BH =>
return "000" & insn_bh(insn_in);
when NONE =>
return "00000";
end case;
end;

function decode_rc (t : rc_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic is
begin
case t is
@ -202,17 +149,9 @@ begin
end if;
end process;

r_out.read1_reg <= insn_ra(d_in.insn) when (d_in.decode.input_reg_a = RA) else
insn_ra(d_in.insn) when d_in.decode.input_reg_a = RA_OR_ZERO else
insn_rs(d_in.insn) when d_in.decode.input_reg_a = RS else
(others => '0');

r_out.read2_reg <= insn_rb(d_in.insn) when d_in.decode.input_reg_b = RB else
insn_rs(d_in.insn) when d_in.decode.input_reg_b = RS else
(others => '0');

r_out.read3_reg <= insn_rs(d_in.insn) when d_in.decode.input_reg_c = RS else
(others => '0');
r_out.read1_reg <= insn_ra(d_in.insn);
r_out.read2_reg <= insn_rb(d_in.insn);
r_out.read3_reg <= insn_rs(d_in.insn);

c_out.read <= d_in.decode.input_cr;

@ -257,17 +196,19 @@ begin
v.e.read_data1 := decoded_reg_a.data;
v.e.read_reg2 := decoded_reg_b.reg;
v.e.read_data2 := decoded_reg_b.data;
v.e.read_data3 := decoded_reg_c.data;
v.e.write_reg := decode_output_reg(d_in.decode.output_reg_a, d_in.insn);
v.e.rc := decode_rc(d_in.decode.rc, d_in.insn);
v.e.cr := c_in.read_cr_data;
v.e.invert_a := d_in.decode.invert_a;
v.e.input_carry := d_in.decode.input_carry;
v.e.output_carry := d_in.decode.output_carry;
v.e.is_32bit := d_in.decode.is_32bit;
v.e.is_signed := d_in.decode.is_signed;
if d_in.decode.lr = '1' then
v.e.lr := insn_lk(d_in.insn);
end if;
v.e.const1 := decode_const_a(d_in.decode.const_a, d_in.insn);
v.e.const2 := decode_const_b(d_in.decode.const_b, d_in.insn);
v.e.const3 := decode_const_c(d_in.decode.const_c, d_in.insn);
v.e.insn := d_in.insn;

-- multiply unit
v.m.insn_type := d_in.decode.insn_type;
@ -276,8 +217,8 @@ begin
v.m.write_reg := decode_output_reg(d_in.decode.output_reg_a, d_in.insn);
v.m.rc := decode_rc(d_in.decode.rc, d_in.insn);

if d_in.decode.mul_32bit = '1' then
if d_in.decode.mul_signed = '1' then
if d_in.decode.is_32bit = '1' then
if d_in.decode.is_signed = '1' then
v.m.data1 := (others => mul_a(31));
v.m.data1(31 downto 0) := mul_a(31 downto 0);
v.m.data2 := (others => mul_b(31));
@ -287,7 +228,7 @@ begin
v.m.data2 := '0' & x"00000000" & mul_b(31 downto 0);
end if;
else
if d_in.decode.mul_signed = '1' then
if d_in.decode.is_signed = '1' then
v.m.data1 := mul_a(63) & mul_a;
v.m.data2 := mul_b(63) & mul_b;
else

@ -2,71 +2,30 @@ library ieee;
use ieee.std_logic_1164.all;

package decode_types is
type ppc_insn_t is (PPC_ILLEGAL, PPC_ADD, PPC_ADDC, PPC_ADDE,
PPC_ADDEX, PPC_ADDI, PPC_ADDIC, PPC_ADDIC_RC, PPC_ADDIS,
PPC_ADDME, PPC_ADDPCIS, PPC_ADDZE, PPC_AND, PPC_ANDC,
PPC_ANDI_RC, PPC_ANDIS_RC, PPC_ATTN, PPC_B, PPC_BA, PPC_BC,
PPC_BCA, PPC_BCCTR, PPC_BCLA, PPC_BCLR, PPC_BCTAR, PPC_BPERM,
PPC_CMP, PPC_CMPB, PPC_CMPEQB, PPC_CMPI, PPC_CMPL, PPC_CMPLI,
PPC_CMPRB, PPC_CNTLZD, PPC_CNTLZW, PPC_CNTTZD, PPC_CNTTZW,
PPC_CRAND, PPC_CRANDC, PPC_CREQV, PPC_CRNAND, PPC_CRNOR,
PPC_CROR, PPC_CRORC, PPC_CRXOR, PPC_DARN, PPC_DCBF, PPC_DCBST,
PPC_DCBT, PPC_DCBTST, PPC_DCBZ, PPC_DIV,
PPC_EQV, PPC_EXTSB, PPC_EXTSH, PPC_EXTSW,
PPC_EXTSWSLI, PPC_ICBI, PPC_ICBT, PPC_ISEL, PPC_ISYNC,
PPC_LBARX, PPC_LBZ, PPC_LBZU, PPC_LBZUX, PPC_LBZX, PPC_LD,
PPC_LDARX, PPC_LDBRX, PPC_LDU, PPC_LDUX, PPC_LDX, PPC_LHA,
PPC_LHARX, PPC_LHAU, PPC_LHAUX, PPC_LHAX, PPC_LHBRX, PPC_LHZ,
PPC_LHZU, PPC_LHZUX, PPC_LHZX, PPC_LWA, PPC_LWARX, PPC_LWAUX,
PPC_LWAX, PPC_LWBRX, PPC_LWZ, PPC_LWZU, PPC_LWZUX, PPC_LWZX,
PPC_MADDHD, PPC_MADDHDU, PPC_MADDLD, PPC_MCRF, PPC_MCRXR,
PPC_MCRXRX, PPC_MFCR, PPC_MFOCRF, PPC_MFSPR, PPC_MFTB,
PPC_MOD, PPC_MTCRF,
PPC_MFCTR, PPC_MTCTR, PPC_MFLR, PPC_MTLR, PPC_MTOCRF,
PPC_MTSPR, PPC_MULHD, PPC_MULHDU, PPC_MULHW, PPC_MULHWU,
PPC_MULLD, PPC_MULLI, PPC_MULLW, PPC_NAND, PPC_NEG, PPC_NOR, PPC_NOP,
PPC_OR, PPC_ORC, PPC_ORI, PPC_ORIS, PPC_POPCNTB, PPC_POPCNTD,
PPC_POPCNTW, PPC_PRTYD, PPC_PRTYW, PPC_RLDCL, PPC_RLDCR,
PPC_RLDIC, PPC_RLDICL, PPC_RLDICR, PPC_RLDIMI, PPC_RLWIMI,
PPC_RLWINM, PPC_RLWNM, PPC_SETB, PPC_SLD, PPC_SLW, PPC_SRAD,
PPC_SRADI, PPC_SRAW, PPC_SRAWI, PPC_SRD, PPC_SRW, PPC_STB,
PPC_STBCX, PPC_STBU, PPC_STBUX, PPC_STBX, PPC_STD, PPC_STDBRX,
PPC_STDCX, PPC_STDU, PPC_STDUX, PPC_STDX, PPC_STH, PPC_STHBRX,
PPC_STHCX, PPC_STHU, PPC_STHUX, PPC_STHX, PPC_STW, PPC_STWBRX,
PPC_STWCX, PPC_STWU, PPC_STWUX, PPC_STWX, PPC_SUBF, PPC_SUBFC,
PPC_SUBFE, PPC_SUBFIC, PPC_SUBFME, PPC_SUBFZE, PPC_SYNC, PPC_TD,
PPC_TDI, PPC_TW, PPC_TWI, PPC_XOR, PPC_XORI, PPC_XORIS,
PPC_SIM_CONFIG);

type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD, OP_ADDE, OP_ADDEX, OP_ADDME,
OP_ADDPCIS, OP_AND, OP_ANDC, OP_ATTN, OP_B, OP_BA, OP_BC,
OP_BCA, OP_BCCTR, OP_BCLA, OP_BCLR, OP_BCTAR, OP_BPERM, OP_CMP,
OP_CMPB, OP_CMPEQB, OP_CMPL, OP_CMPRB,
type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD,
OP_ADDPCIS, OP_AND, OP_ANDC, OP_ATTN, OP_B, OP_BC, OP_BCREG,
OP_BPERM, OP_CMP, OP_CMPB, OP_CMPEQB, OP_CMPL, OP_CMPRB,
OP_CNTLZD, OP_CNTLZW, OP_CNTTZD, OP_CNTTZW, OP_CRAND,
OP_CRANDC, OP_CREQV, OP_CRNAND, OP_CRNOR, OP_CROR, OP_CRORC,
OP_CRXOR, OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST,
OP_DCBZ, OP_DIV, OP_EQV, OP_EXTSB, OP_EXTSH,
OP_EXTSW, OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC,
OP_LOAD, OP_STORE, OP_MADDHD, OP_MADDHDU, OP_MADDLD, OP_MCRF,
OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFOCRF, OP_MFCTR, OP_MFLR,
OP_MFTB, OP_MFSPR, OP_MOD,
OP_MTCRF, OP_MTOCRF, OP_MTCTR, OP_MTLR, OP_MTSPR, OP_MUL_L64,
OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFSPR, OP_MOD,
OP_MTCRF, OP_MTSPR, OP_MUL_L64,
OP_MUL_H64, OP_MUL_H32, OP_NAND, OP_NEG, OP_NOR, OP_OR,
OP_ORC, OP_POPCNTB, OP_POPCNTD, OP_POPCNTW, OP_PRTYD,
OP_PRTYW, OP_RLDCL, OP_RLDCR, OP_RLDIC, OP_RLDICL, OP_RLDICR,
OP_RLDIMI, OP_RLWIMI, OP_RLWINM, OP_RLWNM, OP_SETB, OP_SLD,
OP_SLW, OP_SRAD, OP_SRADI, OP_SRAW, OP_SRAWI, OP_SRD, OP_SRW,
OP_SUBF, OP_SUBFE, OP_SUBFME, OP_SYNC, OP_TD, OP_TDI, OP_TW,
OP_PRTYW, OP_RLC, OP_RLCL, OP_RLCR, OP_SETB,
OP_SHL, OP_SHR,
OP_SYNC, OP_TD, OP_TDI, OP_TW,
OP_TWI, OP_XOR, OP_SIM_CONFIG);

type input_reg_a_t is (NONE, RA, RA_OR_ZERO, RS);
type input_reg_b_t is (NONE, RB, RS, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS);
type input_reg_a_t is (NONE, RA, RA_OR_ZERO);
type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS, CONST_M1, CONST_SH, CONST_SH32);
type input_reg_c_t is (NONE, RS);
type output_reg_a_t is (NONE, RT, RA);
type constant_a_t is (NONE, SH, SH32, FXM, BO, BF, TOO, BC);
type constant_b_t is (NONE, MB, ME, MB32, BI, L);
type constant_c_t is (NONE, ME32, BH);
type rc_t is (NONE, ONE, RC);
type carry_in_t is (ZERO, CA, ONE);

constant SH_OFFSET : integer := 0;
constant MB_OFFSET : integer := 1;
@ -97,14 +56,11 @@ package decode_types is
input_reg_c : input_reg_c_t;
output_reg_a : output_reg_a_t;

const_a : constant_a_t;
const_b : constant_b_t;
const_c : constant_c_t;

input_cr : std_ulogic;
output_cr : std_ulogic;

input_carry : std_ulogic;
invert_a : std_ulogic;
input_carry : carry_in_t;
output_carry : std_ulogic;

-- load/store signals
@ -114,9 +70,9 @@ package decode_types is
update : std_ulogic;
reserve : std_ulogic;

-- multiplier signals
mul_32bit : std_ulogic;
mul_signed : std_ulogic;
-- multiplier and ALU signals
is_32bit : std_ulogic;
is_signed : std_ulogic;

rc : rc_t;
lr : std_ulogic;
@ -126,12 +82,11 @@ package decode_types is
constant decode_rom_init : decode_rom_t := (unit => NONE,
insn_type => OP_ILLEGAL, input_reg_a => NONE,
input_reg_b => NONE, input_reg_c => NONE,
output_reg_a => NONE, const_a => NONE, const_b => NONE,
const_c => NONE, input_cr => '0', output_cr => '0',
input_carry => '0', output_carry => '0',
output_reg_a => NONE, input_cr => '0', output_cr => '0',
invert_a => '0', input_carry => ZERO, output_carry => '0',
length => NONE, byte_reverse => '0', sign_extend => '0',
update => '0', reserve => '0', mul_32bit => '0',
mul_signed => '0', rc => NONE, lr => '0', sgl_pipe => '0');
update => '0', reserve => '0', is_32bit => '0',
is_signed => '0', rc => NONE, lr => '0', sgl_pipe => '0');

end decode_types;


@ -7,6 +7,7 @@ use work.decode_types.all;
use work.common.all;
use work.helpers.all;
use work.crhelpers.all;
use work.insn_helpers.all;
use work.ppc_fx_insns.all;

entity execute1 is
@ -40,7 +41,39 @@ architecture behaviour of execute1 is

signal ctrl: ctrl_t := (carry => '0', others => (others => '0'));
signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0'));

signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
signal rotator_result: std_ulogic_vector(63 downto 0);
signal rotator_carry: std_ulogic;

function decode_input_carry (carry_sel : carry_in_t; ca_in : std_ulogic) return std_ulogic is
begin
case carry_sel is
when ZERO =>
return '0';
when CA =>
return ca_in;
when ONE =>
return '1';
end case;
end;
begin

rotator_0: entity work.rotator
port map (
rs => e_in.read_data3,
ra => e_in.read_data1,
shift => e_in.read_data2(6 downto 0),
insn => e_in.insn,
is_32bit => e_in.is_32bit,
right_shift => right_shift,
arith => e_in.is_signed,
clear_left => rot_clear_left,
clear_right => rot_clear_right,
result => rotator_result,
carry_out => rotator_carry
);

execute1_0: process(clk)
begin
if rising_edge(clk) then
@ -51,11 +84,19 @@ begin

execute1_1: process(all)
variable v : reg_type;
variable a_inv : std_ulogic_vector(63 downto 0);
variable result : std_ulogic_vector(63 downto 0);
variable newcrf : std_ulogic_vector(3 downto 0);
variable result_with_carry : std_ulogic_vector(64 downto 0);
variable result_en : integer;
variable crnum : integer;
variable scrnum : integer;
variable lo, hi : integer;
variable sh, mb, me : std_ulogic_vector(5 downto 0);
variable sh32, mb32, me32 : std_ulogic_vector(4 downto 0);
variable bo, bi : std_ulogic_vector(4 downto 0);
variable bf, bfa : std_ulogic_vector(2 downto 0);
variable l : std_ulogic;
begin
result := (others => '0');
result_with_carry := (others => '0');
@ -72,6 +113,11 @@ begin
terminate_out <= '0';
f_out <= Execute1ToFetch1TypeInit;

-- rotator control signals
right_shift <= '1' when e_in.insn_type = OP_SHR else '0';
rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0';
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';

if e_in.valid = '1' then

v.e.valid := '1';
@ -85,232 +131,218 @@ begin
when OP_NOP =>
-- Do nothing
when OP_ADD =>
result := ppc_add(e_in.read_data1, e_in.read_data2);
result_en := 1;
when OP_ADDE =>
result_with_carry := ppc_adde(e_in.read_data1, e_in.read_data2, ctrl.carry and e_in.input_carry);
if e_in.invert_a = '0' then
a_inv := e_in.read_data1;
else
a_inv := not e_in.read_data1;
end if;
result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry));
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry;
if e_in.output_carry then
ctrl_tmp.carry <= result_with_carry(64);
end if;
result_en := 1;
when OP_AND =>
result := ppc_and(e_in.read_data1, e_in.read_data2);
result := ppc_and(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_ANDC =>
result := ppc_andc(e_in.read_data1, e_in.read_data2);
result := ppc_andc(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_B =>
f_out.redirect <= '1';
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
if (insn_aa(e_in.insn)) then
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
else
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
end if;
when OP_BC =>
if e_in.const1(4-2) = '0' then
bo := insn_bo(e_in.insn);
bi := insn_bi(e_in.insn);
if bo(4-2) = '0' then
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
end if;
if ppc_bc_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr, ctrl.ctr) = 1 then
if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
f_out.redirect <= '1';
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
if (insn_aa(e_in.insn)) then
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
else
f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
end if;
end if;
when OP_BCLR =>
if e_in.const1(4-2) = '0' then
when OP_BCREG =>
-- bits 10 and 6 distinguish between bclr, bcctr and bctar
bo := insn_bo(e_in.insn);
bi := insn_bi(e_in.insn);
if bo(4-2) = '0' and e_in.insn(10) = '0' then
ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
end if;
if ppc_bc_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr, ctrl.ctr) = 1 then
f_out.redirect <= '1';
f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
end if;
when OP_BCCTR =>
if ppc_bcctr_taken(e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.cr) = 1 then
if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
f_out.redirect <= '1';
f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
if e_in.insn(10) = '0' then
f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
else
f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
end if;
end if;
when OP_CMPB =>
result := ppc_cmpb(e_in.read_data1, e_in.read_data2);
result := ppc_cmpb(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_CMP =>
bf := insn_bf(e_in.insn);
l := insn_l(e_in.insn);
v.e.write_cr_enable := '1';
crnum := to_integer(unsigned(e_in.const1(2 downto 0)));
crnum := to_integer(unsigned(bf));
v.e.write_cr_mask := num_to_fxm(crnum);
for i in 0 to 7 loop
lo := i*4;
hi := lo + 3;
v.e.write_cr_data(hi downto lo) := ppc_cmp(e_in.const2(0), e_in.read_data1, e_in.read_data2);
v.e.write_cr_data(hi downto lo) := ppc_cmp(l, e_in.read_data1, e_in.read_data2);
end loop;
when OP_CMPL =>
bf := insn_bf(e_in.insn);
l := insn_l(e_in.insn);
v.e.write_cr_enable := '1';
crnum := to_integer(unsigned(e_in.const1(2 downto 0)));
crnum := to_integer(unsigned(bf));
v.e.write_cr_mask := num_to_fxm(crnum);
for i in 0 to 7 loop
lo := i*4;
hi := lo + 3;
v.e.write_cr_data(hi downto lo) := ppc_cmpl(e_in.const2(0), e_in.read_data1, e_in.read_data2);
v.e.write_cr_data(hi downto lo) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2);
end loop;
when OP_CNTLZW =>
result := ppc_cntlzw(e_in.read_data1);
result := ppc_cntlzw(e_in.read_data3);
result_en := 1;
when OP_CNTTZW =>
result := ppc_cnttzw(e_in.read_data1);
result := ppc_cnttzw(e_in.read_data3);
result_en := 1;
when OP_CNTLZD =>
result := ppc_cntlzd(e_in.read_data1);
result := ppc_cntlzd(e_in.read_data3);
result_en := 1;
when OP_CNTTZD =>
result := ppc_cnttzd(e_in.read_data1);
result := ppc_cnttzd(e_in.read_data3);
result_en := 1;
when OP_EXTSB =>
result := ppc_extsb(e_in.read_data1);
result := ppc_extsb(e_in.read_data3);
result_en := 1;
when OP_EXTSH =>
result := ppc_extsh(e_in.read_data1);
result := ppc_extsh(e_in.read_data3);
result_en := 1;
when OP_EXTSW =>
result := ppc_extsw(e_in.read_data1);
result := ppc_extsw(e_in.read_data3);
result_en := 1;
when OP_EQV =>
result := ppc_eqv(e_in.read_data1, e_in.read_data2);
result := ppc_eqv(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_ISEL =>
crnum := to_integer(unsigned(e_in.const1));
crnum := to_integer(unsigned(insn_bc(e_in.insn)));
if e_in.cr(31-crnum) = '1' then
result := e_in.read_data1;
else
result := e_in.read_data2;
end if;
result_en := 1;
when OP_MFCTR =>
result := ctrl.ctr;
result_en := 1;
when OP_MFLR =>
result := ctrl.lr;
result_en := 1;
when OP_MFTB =>
result := ctrl.tb;
result_en := 1;
when OP_MTCTR =>
ctrl_tmp.ctr <= e_in.read_data1;
when OP_MTLR =>
ctrl_tmp.lr <= e_in.read_data1;
when OP_MFCR =>
result := x"00000000" & e_in.cr;
result_en := 1;
when OP_MFOCRF =>
crnum := fxm_to_num(e_in.const1(7 downto 0));
result := (others => '0');
when OP_MCRF =>
bf := insn_bf(e_in.insn);
bfa := insn_bfa(e_in.insn);
v.e.write_cr_enable := '1';
crnum := to_integer(unsigned(bf));
scrnum := to_integer(unsigned(bfa));
v.e.write_cr_mask := num_to_fxm(crnum);
for i in 0 to 7 loop
lo := (7-i)*4;
hi := lo + 3;
if i = scrnum then
newcrf := e_in.cr(hi downto lo);
end if;
end loop;
for i in 0 to 7 loop
lo := (7-i)*4;
lo := i*4;
hi := lo + 3;
if crnum = i then
result(hi downto lo) := e_in.cr(hi downto lo);
end if;
v.e.write_cr_data(hi downto lo) := newcrf;
end loop;
when OP_MFSPR =>
if std_match(e_in.insn(20 downto 11), "0100100000") then
result := ctrl.ctr;
result_en := 1;
elsif std_match(e_in.insn(20 downto 11), "0100000000") then
result := ctrl.lr;
result_en := 1;
elsif std_match(e_in.insn(20 downto 11), "0110001000") then
result := ctrl.tb;
result_en := 1;
end if;
when OP_MFCR =>
if e_in.insn(20) = '0' then
-- mfcr
result := x"00000000" & e_in.cr;
else
-- mfocrf
crnum := fxm_to_num(insn_fxm(e_in.insn));
result := (others => '0');
for i in 0 to 7 loop
lo := (7-i)*4;
hi := lo + 3;
if crnum = i then
result(hi downto lo) := e_in.cr(hi downto lo);
end if;
end loop;
end if;
result_en := 1;
when OP_MTCRF =>
v.e.write_cr_enable := '1';
v.e.write_cr_mask := e_in.const1(7 downto 0);
v.e.write_cr_data := e_in.read_data1(31 downto 0);
when OP_MTOCRF =>
v.e.write_cr_enable := '1';
-- We require one hot priority encoding here
crnum := fxm_to_num(e_in.const1(7 downto 0));
v.e.write_cr_mask := num_to_fxm(crnum);
v.e.write_cr_data := e_in.read_data1(31 downto 0);
if e_in.insn(20) = '0' then
-- mtcrf
v.e.write_cr_mask := insn_fxm(e_in.insn);
else
-- mtocrf: We require one hot priority encoding here
crnum := fxm_to_num(insn_fxm(e_in.insn));
v.e.write_cr_mask := num_to_fxm(crnum);
end if;
v.e.write_cr_data := e_in.read_data3(31 downto 0);
when OP_MTSPR =>
if std_match(e_in.insn(20 downto 11), "0100100000") then
ctrl_tmp.ctr <= e_in.read_data3;
elsif std_match(e_in.insn(20 downto 11), "0100000000") then
ctrl_tmp.lr <= e_in.read_data3;
end if;
when OP_NAND =>
result := ppc_nand(e_in.read_data1, e_in.read_data2);
result := ppc_nand(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_NEG =>
result := ppc_neg(e_in.read_data1);
result_en := 1;
when OP_NOR =>
result := ppc_nor(e_in.read_data1, e_in.read_data2);
result := ppc_nor(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_OR =>
result := ppc_or(e_in.read_data1, e_in.read_data2);
result := ppc_or(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_ORC =>
result := ppc_orc(e_in.read_data1, e_in.read_data2);
result := ppc_orc(e_in.read_data3, e_in.read_data2);
result_en := 1;
when OP_POPCNTB =>
result := ppc_popcntb(e_in.read_data1);
result := ppc_popcntb(e_in.read_data3);
result_en := 1;
when OP_POPCNTW =>
result := ppc_popcntw(e_in.read_data1);
result := ppc_popcntw(e_in.read_data3);
result_en := 1;
when OP_POPCNTD =>
result := ppc_popcntd(e_in.read_data1);
result := ppc_popcntd(e_in.read_data3);
result_en := 1;
when OP_PRTYD =>
result := ppc_prtyd(e_in.read_data1);
result := ppc_prtyd(e_in.read_data3);
result_en := 1;
when OP_PRTYW =>
result := ppc_prtyw(e_in.read_data1);
result := ppc_prtyw(e_in.read_data3);
result_en := 1;
when OP_RLDCL =>
result := ppc_rldcl(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0));
result_en := 1;
when OP_RLDCR =>
result := ppc_rldcr(e_in.read_data1, e_in.read_data2, e_in.const2(5 downto 0));
result_en := 1;
when OP_RLDICL =>
result := ppc_rldicl(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
result_en := 1;
when OP_RLDICR =>
result := ppc_rldicr(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
result_en := 1;
when OP_RLWNM =>
result := ppc_rlwnm(e_in.read_data1, e_in.read_data2, e_in.const2(4 downto 0), e_in.const3(4 downto 0));
result_en := 1;
when OP_RLWINM =>
result := ppc_rlwinm(e_in.read_data1, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0));
result_en := 1;
when OP_RLDIC =>
result := ppc_rldic(e_in.read_data1, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
result_en := 1;
when OP_RLDIMI =>
result := ppc_rldimi(e_in.read_data1, e_in.read_data2, e_in.const1(5 downto 0), e_in.const2(5 downto 0));
result_en := 1;
when OP_RLWIMI =>
result := ppc_rlwimi(e_in.read_data1, e_in.read_data2, e_in.const1(4 downto 0), e_in.const2(4 downto 0), e_in.const3(4 downto 0));
result_en := 1;
when OP_SLD =>
result := ppc_sld(e_in.read_data1, e_in.read_data2);
result_en := 1;
when OP_SLW =>
result := ppc_slw(e_in.read_data1, e_in.read_data2);
result_en := 1;
when OP_SRAW =>
result_with_carry := ppc_sraw(e_in.read_data1, e_in.read_data2);
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SRAWI =>
result_with_carry := ppc_srawi(e_in.read_data1, e_in.const1(5 downto 0));
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SRAD =>
result_with_carry := ppc_srad(e_in.read_data1, e_in.read_data2);
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SRADI =>
result_with_carry := ppc_sradi(e_in.read_data1, e_in.const1(5 downto 0));
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64);
result_en := 1;
when OP_SRD =>
result := ppc_srd(e_in.read_data1, e_in.read_data2);
result_en := 1;
when OP_SRW =>
result := ppc_srw(e_in.read_data1, e_in.read_data2);
result_en := 1;
when OP_SUBF =>
result := ppc_subf(e_in.read_data1, e_in.read_data2);
result_en := 1;
when OP_SUBFE =>
result_with_carry := ppc_subfe(e_in.read_data1, e_in.read_data2, ctrl.carry or not(e_in.input_carry));
result := result_with_carry(63 downto 0);
ctrl_tmp.carry <= result_with_carry(64) and e_in.output_carry;
when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR =>
result := rotator_result;
if e_in.output_carry = '1' then
ctrl_tmp.carry <= rotator_carry;
end if;
result_en := 1;
when OP_XOR =>
result := ppc_xor(e_in.read_data1, e_in.read_data2);
result := ppc_xor(e_in.read_data3, e_in.read_data2);
result_en := 1;

when OP_SIM_CONFIG =>

@ -14,9 +14,11 @@ package insn_helpers is
function insn_me32 (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_li (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_lk (insn_in : std_ulogic_vector) return std_ulogic;
function insn_aa (insn_in : std_ulogic_vector) return std_ulogic;
function insn_rc (insn_in : std_ulogic_vector) return std_ulogic;
function insn_bd (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_bf (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_bfa (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_bo (insn_in : std_ulogic_vector) return std_ulogic_vector;
function insn_bi (insn_in : std_ulogic_vector) return std_ulogic_vector;
@ -91,6 +93,11 @@ package body insn_helpers is
return insn_in(0);
end;

function insn_aa (insn_in : std_ulogic_vector) return std_ulogic is
begin
return insn_in(1);
end;

function insn_rc (insn_in : std_ulogic_vector) return std_ulogic is
begin
return insn_in(0);
@ -106,6 +113,11 @@ package body insn_helpers is
return insn_in(25 downto 23);
end;

function insn_bfa (insn_in : std_ulogic_vector) return std_ulogic_vector is
begin
return insn_in(20 downto 18);
end;

function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector is
begin
return insn_in(19 downto 12);

@ -24,6 +24,7 @@ filesets:
- loadstore2.vhdl
- multiply.vhdl
- divider.vhdl
- rotator.vhdl
- writeback.vhdl
- insn_helpers.vhdl
- core.vhdl

@ -89,7 +89,6 @@ package ppc_fx_insns is
function ppc_divd (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
function ppc_divwu (ra, rb: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;

function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector;
function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer;
function ppc_bcctr_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0)) return integer;
end package ppc_fx_insns;
@ -779,11 +778,6 @@ package body ppc_fx_insns is
return std_ulogic_vector(resize(tmp, ra'length));
end;

function ppc_b (nia: std_ulogic_vector(63 downto 0); bd: std_ulogic_vector(23 downto 0)) return std_ulogic_vector is
begin
return std_ulogic_vector(signed(nia) + signed(bd & "00"));
end;

function ppc_bc_taken(bo, bi: std_ulogic_vector(4 downto 0); cr: std_ulogic_vector(31 downto 0); ctr: std_ulogic_vector(63 downto 0)) return integer is
variable crfield: integer;
variable crbit_match: std_ulogic;

@ -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…
Cancel
Save