From 9646fe28b089c7f03aeef5d3d32a590652732ec2 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 14 Oct 2019 14:39:23 +1100 Subject: [PATCH] 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 --- common.vhdl | 9 +++++++-- decode1.vhdl | 6 +++--- decode2.vhdl | 29 ++++++++++++++++------------- decode_types.vhdl | 2 +- execute1.vhdl | 14 ++++++-------- execute2.vhdl | 2 ++ writeback.vhdl | 2 ++ 7 files changed, 37 insertions(+), 27 deletions(-) diff --git a/common.vhdl b/common.vhdl index 321cff1..41623af 100644 --- a/common.vhdl +++ b/common.vhdl @@ -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; diff --git a/decode1.vhdl b/decode1.vhdl index 2bdb423..49e37da 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -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 diff --git a/decode2.vhdl b/decode2.vhdl index 524943c..c8dee48 100644 --- a/decode2.vhdl +++ b/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; diff --git a/decode_types.vhdl b/decode_types.vhdl index 982b172..f6b6ca9 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -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, diff --git a/execute1.vhdl b/execute1.vhdl index d0ff461..85bb5e1 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -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))); diff --git a/execute2.vhdl b/execute2.vhdl index de55310..97b4103 100644 --- a/execute2.vhdl +++ b/execute2.vhdl @@ -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; diff --git a/writeback.vhdl b/writeback.vhdl index ba88970..4bae8f7 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -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;