From 5422007f83bff7550e8d3064e9c086fa668eb4d9 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 14 Jan 2020 10:28:45 +1100 Subject: [PATCH] Plumb loadstore1 input from execute1 not decode2 This allows us to use the bypass at the input of execute1 for the address and data operands for loadstore1. Signed-off-by: Paul Mackerras --- common.vhdl | 14 +++++++++----- core.vhdl | 6 +++--- decode2.vhdl | 42 +++++++----------------------------------- execute1.vhdl | 26 ++++++++++++++++++++++++++ loadstore1.vhdl | 2 +- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/common.vhdl b/common.vhdl index 9c8a942..ffddb0b 100644 --- a/common.vhdl +++ b/common.vhdl @@ -127,12 +127,16 @@ package common is is_signed: std_ulogic; insn: std_ulogic_vector(31 downto 0); data_len: std_ulogic_vector(3 downto 0); + byte_reverse : std_ulogic; + sign_extend : std_ulogic; -- do we need to sign extend? + update : std_ulogic; -- is this an update instruction? end record; constant Decode2ToExecute1Init : Decode2ToExecute1Type := (valid => '0', insn_type => OP_ILLEGAL, bypass_data1 => '0', bypass_data2 => '0', bypass_data3 => '0', lr => '0', rc => '0', oe => '0', invert_a => '0', invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', output_cr => '0', - is_32bit => '0', is_signed => '0', xerc => xerc_init, others => (others => '0')); + is_32bit => '0', is_signed => '0', xerc => xerc_init, + byte_reverse => '0', sign_extend => '0', update => '0', others => (others => '0')); type Execute1ToMultiplyType is record valid: std_ulogic; @@ -189,7 +193,7 @@ package common is end record; constant Execute1ToFetch1TypeInit : Execute1ToFetch1Type := (redirect => '0', others => (others => '0')); - type Decode2ToLoadstore1Type is record + type Execute1ToLoadstore1Type is record valid : std_ulogic; load : std_ulogic; -- is this a load or store addr1 : std_ulogic_vector(63 downto 0); @@ -203,9 +207,9 @@ package common is update_reg : gpr_index_t; -- if so, the register to update xerc : xer_common_t; end record; - constant Decode2ToLoadstore1Init : Decode2ToLoadstore1Type := (valid => '0', load => '0', byte_reverse => '0', - sign_extend => '0', update => '0', xerc => xerc_init, - others => (others => '0')); + constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type := (valid => '0', load => '0', byte_reverse => '0', + sign_extend => '0', update => '0', xerc => xerc_init, + others => (others => '0')); type Loadstore1ToDcacheType is record valid : std_ulogic; diff --git a/core.vhdl b/core.vhdl index aa86689..bc0b16f 100644 --- a/core.vhdl +++ b/core.vhdl @@ -60,7 +60,7 @@ architecture behave of core is signal execute1_to_fetch1: Execute1ToFetch1Type; -- load store signals - signal decode2_to_loadstore1: Decode2ToLoadstore1Type; + signal execute1_to_loadstore1: Execute1ToLoadstore1Type; signal loadstore1_to_dcache: Loadstore1ToDcacheType; signal dcache_to_writeback: DcacheToWritebackType; @@ -190,7 +190,6 @@ begin stopped_out => dbg_core_is_stopped, d_in => decode1_to_decode2, e_out => decode2_to_execute1, - l_out => decode2_to_loadstore1, r_in => register_file_to_decode2, r_out => decode2_to_register_file, c_in => cr_file_to_decode2, @@ -233,6 +232,7 @@ begin flush_out => flush, stall_out => ex1_stall_out, e_in => decode2_to_execute1, + l_out => execute1_to_loadstore1, f_out => execute1_to_fetch1, e_out => execute1_to_writeback, icache_inval => ex1_icache_inval, @@ -242,7 +242,7 @@ begin loadstore1_0: entity work.loadstore1 port map ( clk => clk, - l_in => decode2_to_loadstore1, + l_in => execute1_to_loadstore1, l_out => loadstore1_to_dcache ); diff --git a/decode2.vhdl b/decode2.vhdl index 6e3bd8a..582fa5b 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -27,7 +27,6 @@ entity decode2 is d_in : in Decode1ToDecode2Type; e_out : out Decode2ToExecute1Type; - l_out : out Decode2ToLoadstore1Type; r_in : in RegisterFileToDecode2Type; r_out : out Decode2ToRegisterFileType; @@ -40,7 +39,6 @@ end entity decode2; architecture behaviour of decode2 is type reg_type is record e : Decode2ToExecute1Type; - l : Decode2ToLoadstore1Type; end record; signal r, rin : reg_type; @@ -246,7 +244,7 @@ begin decode2_0: process(clk) begin if rising_edge(clk) then - if rin.e.valid = '1' or rin.l.valid = '1' then + if rin.e.valid = '1' then report "execute " & to_hstring(rin.e.nia); end if; r <= rin; @@ -272,7 +270,6 @@ begin v := r; v.e := Decode2ToExecute1Init; - v.l := Decode2ToLoadStore1Init; mul_a := (others => '0'); mul_b := (others => '0'); @@ -331,25 +328,9 @@ begin end if; v.e.insn := d_in.insn; v.e.data_len := length; - - -- load/store unit - v.l.update_reg := gspr_to_gpr(decoded_reg_a.reg); - v.l.addr1 := decoded_reg_a.data; - v.l.addr2 := decoded_reg_b.data; - v.l.data := decoded_reg_c.data; - v.l.write_reg := gspr_to_gpr(decoded_reg_o.reg); - - if d_in.decode.insn_type = OP_LOAD then - v.l.load := '1'; - else - v.l.load := '0'; - end if; - - 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; - v.l.xerc := c_in.read_xerc_data; + v.e.byte_reverse := d_in.decode.byte_reverse; + v.e.sign_extend := d_in.decode.sign_extend; + v.e.update := d_in.decode.update; -- issue control control_valid_in <= d_in.valid; @@ -373,21 +354,13 @@ begin cr_write_valid <= d_in.decode.output_cr or decode_rc(d_in.decode.rc, d_in.insn); - v.e.valid := '0'; - v.l.valid := '0'; - case d_in.decode.unit is - when ALU => - v.e.valid := control_valid_out; - when LDST => - v.l.valid := control_valid_out; - when NONE => - v.e.valid := control_valid_out; + v.e.valid := control_valid_out; + if d_in.decode.unit = NONE then v.e.insn_type := OP_ILLEGAL; - end case; + end if; if rst = '1' then v.e := Decode2ToExecute1Init; - v.l := Decode2ToLoadStore1Init; end if; -- Update registers @@ -395,6 +368,5 @@ begin -- Update outputs e_out <= r.e; - l_out <= r.l; end process; end architecture behaviour; diff --git a/execute1.vhdl b/execute1.vhdl index d63697c..e49494f 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -25,6 +25,7 @@ entity execute1 is e_in : in Decode2ToExecute1Type; -- asynchronous + l_out : out Execute1ToLoadstore1Type; f_out : out Execute1ToFetch1Type; e_out : out Execute1ToWritebackType; @@ -210,6 +211,7 @@ begin variable zerohi, zerolo : std_ulogic; variable msb_a, msb_b : std_ulogic; variable a_lt : std_ulogic; + variable lv : Execute1ToLoadstore1Type; begin result := (others => '0'); result_with_carry := (others => '0'); @@ -667,6 +669,10 @@ begin stall_out <= '1'; x_to_divider.valid <= '1'; + when OP_LOAD | OP_STORE => + -- loadstore/dcache has its own port to writeback + v.e.valid := '0'; + when others => terminate_out <= '1'; report "illegal"; @@ -731,11 +737,31 @@ begin v.e.write_data := result; v.e.write_enable := result_en; + -- Outputs to loadstore1 (async) + lv := Execute1ToLoadstore1Init; + if e_in.valid = '1' and (e_in.insn_type = OP_LOAD or e_in.insn_type = OP_STORE) then + lv.valid := '1'; + end if; + if e_in.insn_type = OP_LOAD then + lv.load := '1'; + end if; + lv.addr1 := a_in; + lv.addr2 := b_in; + lv.data := c_in; + lv.write_reg := gspr_to_gpr(e_in.write_reg); + lv.length := e_in.data_len; + lv.byte_reverse := e_in.byte_reverse; + lv.sign_extend := e_in.sign_extend; + lv.update := e_in.update; + lv.update_reg := gspr_to_gpr(e_in.read_reg1); + lv.xerc := v.e.xerc; + -- Update registers rin <= v; -- update outputs --f_out <= r.f; + l_out <= lv; e_out <= r.e; flush_out <= f_out.redirect; end process; diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 1c16c46..5b61d4c 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -13,7 +13,7 @@ entity loadstore1 is port ( clk : in std_ulogic; - l_in : in Decode2ToLoadstore1Type; + l_in : in Execute1ToLoadstore1Type; l_out : out Loadstore1ToDcacheType );