mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-29 02:54:49 +00:00
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>
This commit is contained in:
@@ -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
|
||||
|
||||
29
decode2.vhdl
29
decode2.vhdl
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user