mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-29 02:54:49 +00:00
core: Simplify operand presentation for hash instructions
This removes the cases in the decode stages which allowed the C register address to come from the RB field for the hash instructions (hashst[p], hashchk[p]), and generated a negative immediate value for the B operand. The motivation is to simpify the logic for the C register address. Instead the unusual construction of the address for the hash instructions is handled in the loadstore1_in process, and the hash computation uses the A and B operands rather than A and C. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
14
decode1.vhdl
14
decode1.vhdl
@@ -199,10 +199,10 @@ architecture behaviour of decode1 is
|
||||
INSN_fsubs => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', '0', NONE),
|
||||
INSN_ftdiv => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', '0', NONE),
|
||||
INSN_ftsqrt => (FPU, FPU, OP_FP_CMP, NONE, FRB, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', '0', NONE),
|
||||
INSN_hashchk => (LDST, NONE, OP_LOAD, RA, IMM, CONST_DSX, RBC, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '0', '0', NONE),
|
||||
INSN_hashchkp => (LDST, NONE, OP_LOAD, RA, IMM, CONST_DSX, RBC, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '1', '0', NONE),
|
||||
INSN_hashst => (LDST, NONE, OP_STORE, RA, IMM, CONST_DSX, RBC, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '0', '0', NONE),
|
||||
INSN_hashstp => (LDST, NONE, OP_STORE, RA, IMM, CONST_DSX, RBC, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '1', '0', NONE),
|
||||
INSN_hashchk => (LDST, NONE, OP_LOAD, RA, RB, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '0', '0', NONE),
|
||||
INSN_hashchkp => (LDST, NONE, OP_LOAD, RA, RB, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '1', '0', NONE),
|
||||
INSN_hashst => (LDST, NONE, OP_STORE, RA, RB, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '0', '0', NONE),
|
||||
INSN_hashstp => (LDST, NONE, OP_STORE, RA, RB, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '1', NONE, '0', '1', '0', NONE),
|
||||
INSN_icbi => (ALU, NONE, OP_ICBI, NONE, IMM, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', '1', NONE),
|
||||
INSN_icbt => (ALU, NONE, OP_ICBT, NONE, IMM, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', '0', NONE),
|
||||
INSN_isel => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', '0', NONE),
|
||||
@@ -726,12 +726,6 @@ begin
|
||||
if (icode = INSN_stq or icode = INSN_stqcx) and f_in.big_endian = '0' then
|
||||
vr.reg_3_addr(0) := '1';
|
||||
end if;
|
||||
-- See if this is an instruction where we need to use the RS/RC
|
||||
-- read port to read the RB operand, because we want to get an
|
||||
-- immediate operand to execute1 via read_data2.
|
||||
if (icode = INSN_hashst or icode = INSN_hashchk or icode = INSN_hashstp or icode = INSN_hashchkp) then
|
||||
vr.reg_3_addr := '0' & insn_rb(f_in.insn);
|
||||
end if;
|
||||
vr.read_1_enable := f_in.valid;
|
||||
vr.read_2_enable := f_in.valid and maybe_rb;
|
||||
vr.read_3_enable := f_in.valid;
|
||||
|
||||
@@ -140,8 +140,6 @@ architecture behaviour of decode2 is
|
||||
ret := x"00000000000000" & "00" & insn_in(1) & insn_in(15 downto 11);
|
||||
when CONST_SH32 =>
|
||||
ret := x"00000000000000" & "000" & insn_in(15 downto 11);
|
||||
when CONST_DSX =>
|
||||
ret := 55x"7FFFFFFFFFFFFF" & insn_in(0) & insn_in(25 downto 21) & "000";
|
||||
when others =>
|
||||
ret := (others => '0');
|
||||
end case;
|
||||
@@ -188,8 +186,6 @@ architecture behaviour of decode2 is
|
||||
else
|
||||
return ('0', (others => '0'));
|
||||
end if;
|
||||
when RBC =>
|
||||
return ('1', gpr_to_gspr(insn_rb(insn_in)));
|
||||
when NONE =>
|
||||
return ('0', (others => '0'));
|
||||
end case;
|
||||
|
||||
@@ -420,9 +420,8 @@ package decode_types is
|
||||
type input_reg_a_t is (NONE, RA, RA_OR_ZERO, RA0_OR_CIA, CIA, FRA);
|
||||
type input_reg_b_t is (IMM, RB, FRB);
|
||||
type const_sel_t is (NONE, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD,
|
||||
CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, CONST_PSI,
|
||||
CONST_DSX);
|
||||
type input_reg_c_t is (NONE, RS, RCR, RBC, FRC, FRS);
|
||||
CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, CONST_PSI);
|
||||
type input_reg_c_t is (NONE, RS, RCR, FRC, FRS);
|
||||
type output_reg_a_t is (NONE, RT, RA, FRT);
|
||||
type rc_t is (NONE, ONE, RC, RCOE);
|
||||
type carry_in_t is (ZERO, CA, OV, ONE);
|
||||
|
||||
@@ -108,6 +108,7 @@ architecture behave of loadstore1 is
|
||||
two_dwords : std_ulogic;
|
||||
incomplete : std_ulogic;
|
||||
ea_valid : std_ulogic;
|
||||
hash_addr : std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
constant request_init : request_t := (addr => (others => '0'),
|
||||
byte_sel => x"00", second_bytes => x"00",
|
||||
@@ -116,6 +117,7 @@ architecture behave of loadstore1 is
|
||||
elt_length => x"0", brev_mask => "000",
|
||||
xerc => xerc_init,
|
||||
sprsel => "0000", ric => "00",
|
||||
hash_addr => 64x"0",
|
||||
others => '0');
|
||||
|
||||
type reg_stage1_t is record
|
||||
@@ -529,7 +531,7 @@ begin
|
||||
-- start a new hash process
|
||||
hv.z0 := 31x"7D12B0E6"; -- 0xFA2561CD >> 1
|
||||
ra := l_in.addr1;
|
||||
rb := l_in.data;
|
||||
rb := l_in.addr2;
|
||||
key := l_in.hashkey;
|
||||
for lane in 0 to 3 loop
|
||||
j := lane * 16;
|
||||
@@ -566,6 +568,7 @@ begin
|
||||
variable misaligned : std_ulogic;
|
||||
variable addr_mask : std_ulogic_vector(2 downto 0);
|
||||
variable hash_nop : std_ulogic;
|
||||
variable disp : std_ulogic_vector(63 downto 0);
|
||||
begin
|
||||
v := request_init;
|
||||
sprn := l_in.insn(15 downto 11) & l_in.insn(20 downto 16);
|
||||
@@ -598,6 +601,9 @@ begin
|
||||
v.sprsel := "100" & sprn(8);
|
||||
end if;
|
||||
|
||||
disp := l_in.addr2;
|
||||
if l_in.hash = '1' then
|
||||
end if;
|
||||
lsu_sum := std_ulogic_vector(unsigned(l_in.addr1) + unsigned(l_in.addr2));
|
||||
|
||||
if HAS_FPU and l_in.is_32bit = '1' then
|
||||
@@ -615,8 +621,13 @@ begin
|
||||
addr := std_ulogic_vector(unsigned(r1.addr0(63 downto 3)) + not l_in.update) &
|
||||
r1.addr0(2 downto 0);
|
||||
end if;
|
||||
-- Hash instructions have a short immediate displacement field,
|
||||
-- interpreted as a negative multiple of 8
|
||||
disp := 55x"7FFFFFFFFFFFFF" & l_in.insn(0) & l_in.insn(25 downto 21) & "000";
|
||||
v.hash_addr := std_ulogic_vector(unsigned(l_in.addr1) + unsigned(disp));
|
||||
if l_in.mode_32bit = '1' then
|
||||
addr(63 downto 32) := (others => '0');
|
||||
v.hash_addr(63 downto 32) := (others => '0');
|
||||
end if;
|
||||
v.addr := addr;
|
||||
v.ea_valid := l_in.valid;
|
||||
@@ -812,6 +823,9 @@ begin
|
||||
-- need to initiate and then wait for the hash computation
|
||||
hash_start <= not r1.busy;
|
||||
v.busy := not hash_r.done;
|
||||
if r1.busy = '1' then
|
||||
v.req.addr := r1.req.hash_addr;
|
||||
end if;
|
||||
if hash_r.done = '0' then
|
||||
issue := '0';
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user