Plumb loadstore1 input from execute1 not decode2
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 13 Jan 2020 23:28:45 +0000 (10:28 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 14 Jan 2020 11:44:59 +0000 (22:44 +1100)
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 <paulus@ozlabs.org>
common.vhdl
core.vhdl
decode2.vhdl
execute1.vhdl
loadstore1.vhdl

index 9c8a9420a1a01b2330876bc696e932cb82c184c7..ffddb0b68a4975292998c7c48997003f64c73e18 100644 (file)
@@ -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;
index aa86689729307f822f1597c6782809533f1f28a4..bc0b16fecaefd93d06a7161f0496bb70e3ce47bf 100644 (file)
--- 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
             );
 
index 6e3bd8ae03695034f7b2fa3a0836c95b681c4b6b..582fa5b2d48077b7883a37d4930d3a67e723babd 100644 (file)
@@ -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;
index d63697cc29dad927d1be26c84bead0d68f270263..e49494f4d1c19865009dc84f43b5085510d16b8c 100644 (file)
@@ -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;
index 1c16c461bf43399db0ae7bf0b4a16c6ca726999e..5b61d4c48cf840253ff052764c59a53d6c14382c 100644 (file)
@@ -13,7 +13,7 @@ entity loadstore1 is
     port (
         clk   : in std_ulogic;
 
-        l_in  : in Decode2ToLoadstore1Type;
+        l_in  : in Execute1ToLoadstore1Type;
 
         l_out : out Loadstore1ToDcacheType
         );