Do sign-extension instructions in writeback instead of execute1

This makes the exts[bhw] instructions do the sign extension in the
writeback stage using the sign-extension logic there instead of
having unique sign extension logic in execute1.  This requires
passing the data length and sign extend flag from decode2 down
through execute1 and execute2 and into writeback.  As a side bonus
we reduce the number of values in insn_type_t by two.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
jtag-port
Paul Mackerras 5 years ago
parent 374f4c536d
commit 9646fe28b0

@ -64,6 +64,7 @@ package common is
is_32bit: std_ulogic;
is_signed: std_ulogic;
insn: std_ulogic_vector(31 downto 0);
data_len: std_ulogic_vector(3 downto 0);
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
(valid => '0', insn_type => OP_ILLEGAL, lr => '0', rc => '0', invert_a => '0',
@ -168,12 +169,14 @@ package common is
write_enable : std_ulogic;
write_reg: std_ulogic_vector(4 downto 0);
write_data: std_ulogic_vector(63 downto 0);
write_len : std_ulogic_vector(3 downto 0);
write_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
rc : std_ulogic;
sign_extend: std_ulogic;
end record;
constant Execute1ToExecute2Init : Execute1ToExecute2Type := (valid => '0', write_enable => '0', write_cr_enable => '0', rc => '0', others => (others => '0'));
constant Execute1ToExecute2Init : Execute1ToExecute2Type := (valid => '0', write_enable => '0', write_cr_enable => '0', rc => '0', sign_extend => '0', others => (others => '0'));

type Execute2ToWritebackType is record
valid: std_ulogic;
@ -181,11 +184,13 @@ package common is
write_enable : std_ulogic;
write_reg: std_ulogic_vector(4 downto 0);
write_data: std_ulogic_vector(63 downto 0);
write_len : std_ulogic_vector(3 downto 0);
write_cr_enable : std_ulogic;
write_cr_mask : std_ulogic_vector(7 downto 0);
write_cr_data : std_ulogic_vector(31 downto 0);
sign_extend: std_ulogic;
end record;
constant Execute2ToWritebackInit : Execute2ToWritebackType := (valid => '0', rc => '0', write_enable => '0', write_cr_enable => '0', others => (others => '0'));
constant Execute2ToWritebackInit : Execute2ToWritebackType := (valid => '0', rc => '0', write_enable => '0', write_cr_enable => '0', sign_extend => '0', others => (others => '0'));

type MultiplyToWritebackType is record
valid: std_ulogic;

@ -164,9 +164,9 @@ architecture behaviour of decode1 is
2#0111101001# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divd
2#0111101011# => (DIV, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), -- divw
2#0100011100# => (ALU, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- eqv
2#1110111010# => (ALU, OP_EXTSB, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsb
2#1110011010# => (ALU, OP_EXTSH, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsh
2#1111011010# => (ALU, OP_EXTSW, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsw
2#1110111010# => (ALU, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsb
2#1110011010# => (ALU, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsh
2#1111011010# => (ALU, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsw
-- 2#110111101-# extswsli
2#1111010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbi
2#0000010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt

@ -208,6 +208,7 @@ begin
variable decoded_reg_b : decode_input_reg_t;
variable decoded_reg_c : decode_input_reg_t;
variable signed_division: std_ulogic;
variable length : std_ulogic_vector(3 downto 0);
begin
v := r;

@ -231,6 +232,19 @@ begin
r_out.read2_enable <= decoded_reg_b.reg_valid;
r_out.read3_enable <= decoded_reg_c.reg_valid;

case d_in.decode.length is
when is1B =>
length := "0001";
when is2B =>
length := "0010";
when is4B =>
length := "0100";
when is8B =>
length := "1000";
when NONE =>
length := "0000";
end case;

-- execute unit
v.e.nia := d_in.nia;
v.e.insn_type := d_in.decode.insn_type;
@ -252,6 +266,7 @@ begin
v.e.lr := insn_lk(d_in.insn);
end if;
v.e.insn := d_in.insn;
v.e.data_len := length;

-- multiply unit
v.m.insn_type := d_in.decode.insn_type;
@ -336,19 +351,7 @@ begin
v.l.load := '0';
end if;

case d_in.decode.length is
when is1B =>
v.l.length := "0001";
when is2B =>
v.l.length := "0010";
when is4B =>
v.l.length := "0100";
when is8B =>
v.l.length := "1000";
when NONE =>
v.l.length := "0000";
end case;

v.l.length := length;
v.l.byte_reverse := d_in.decode.byte_reverse;
v.l.sign_extend := d_in.decode.sign_extend;
v.l.update := d_in.decode.update;

@ -8,7 +8,7 @@ package decode_types is
OP_CNTZ, 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_EXTSB, OP_EXTSH, OP_EXTSW,
OP_DCBZ, OP_DIV, OP_EXTS,
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_MFSPR, OP_MOD,

@ -143,6 +143,8 @@ begin

v.e.valid := '1';
v.e.write_reg := e_in.write_reg;
v.e.write_len := x"8";
v.e.sign_extend := '0';

case_0: case e_in.insn_type is

@ -230,14 +232,10 @@ begin
when OP_CNTZ =>
result := countzero_result;
result_en := 1;
when OP_EXTSB =>
result := ppc_extsb(e_in.read_data3);
result_en := 1;
when OP_EXTSH =>
result := ppc_extsh(e_in.read_data3);
result_en := 1;
when OP_EXTSW =>
result := ppc_extsw(e_in.read_data3);
when OP_EXTS =>
v.e.write_len := e_in.data_len;
v.e.sign_extend := '1';
result := e_in.read_data3;
result_en := 1;
when OP_ISEL =>
crnum := to_integer(unsigned(insn_bc(e_in.insn)));

@ -40,6 +40,8 @@ begin
v.write_cr_mask := e_in.write_cr_mask;
v.write_cr_data := e_in.write_cr_data;
v.rc := e_in.rc;
v.write_len := e_in.write_len;
v.sign_extend := e_in.sign_extend;

-- Update registers
rin <= v;

@ -100,6 +100,8 @@ begin
w_out.write_reg <= e_in.write_reg;
data_in <= e_in.write_data;
w_out.write_enable <= '1';
data_len <= unsigned(e_in.write_len);
sign_extend <= e_in.sign_extend;
rc <= e_in.rc;
end if;


Loading…
Cancel
Save