Separate issue control into its own unit
authorAnton Blanchard <anton@linux.ibm.com>
Mon, 14 Oct 2019 01:40:23 +0000 (12:40 +1100)
committerAnton Blanchard <anton@ozlabs.org>
Mon, 14 Oct 2019 02:05:30 +0000 (13:05 +1100)
Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
Makefile
control.vhdl [new file with mode: 0644]
decode2.vhdl
microwatt.core

index 26945566a40eeefa62e061226535e55f6e5877e6..a895e5cee8f690af8e2a6f6c3e3ab2b3c758dc72 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ countzero.o:
 cr_file.o: common.o
 crhelpers.o: common.o
 decode1.o: common.o decode_types.o
-decode2.o: decode_types.o common.o helpers.o insn_helpers.o
+decode2.o: decode_types.o common.o helpers.o insn_helpers.o control.o
 decode_types.o:
 execute1.o: decode_types.o common.o helpers.o crhelpers.o insn_helpers.o ppc_fx_insns.o rotator.o logical.o countzero.o
 execute2.o: common.o crhelpers.o ppc_fx_insns.o
diff --git a/control.vhdl b/control.vhdl
new file mode 100644 (file)
index 0000000..35a7e17
--- /dev/null
@@ -0,0 +1,113 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity control is
+    generic (
+        PIPELINE_DEPTH : natural := 2
+        );
+    port (
+        clk         : in std_ulogic;
+        rst         : in std_ulogic;
+
+        complete_in : in std_ulogic;
+        valid_in    : in std_ulogic;
+        flush_in    : in std_ulogic;
+        sgl_pipe_in : in std_ulogic;
+        stop_mark_in : in std_ulogic;
+
+        valid_out   : out std_ulogic;
+        stall_out   : out std_ulogic;
+        stopped_out : out std_ulogic
+        );
+end entity control;
+
+architecture rtl of control is
+    type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
+
+    type reg_internal_type is record
+        state : state_type;
+        outstanding : integer range -1 to PIPELINE_DEPTH+1;
+    end record;
+    constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
+
+    signal r_int, rin_int : reg_internal_type := reg_internal_init;
+begin
+    control0: process(clk)
+    begin
+        if rising_edge(clk) then
+            r_int <= rin_int;
+        end if;
+    end process;
+
+    control1 : process(all)
+        variable v_int : reg_internal_type;
+        variable valid_tmp : std_ulogic;
+    begin
+        v_int := r_int;
+
+        -- asynchronous
+        valid_tmp := valid_in and not flush_in;
+        stall_out <= '0';
+
+        if complete_in = '1' then
+            assert r_int.outstanding <= 1 report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
+            v_int.outstanding := r_int.outstanding - 1;
+        end if;
+
+        -- Handle debugger stop
+        stopped_out <= '0';
+        if stop_mark_in = '1' and v_int.outstanding = 0 then
+            stopped_out <= '1';
+        end if;
+
+        -- state machine to handle instructions that must be single
+        -- through the pipeline.
+        case r_int.state is
+            when IDLE =>
+                if (flush_in = '0') and (valid_tmp = '1') and (sgl_pipe_in = '1') then
+                    if v_int.outstanding /= 0 then
+                        v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
+                        valid_tmp := '0';
+                        stall_out <= '1';
+                    else
+                        -- send insn out and wait on it to complete
+                        v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
+                    end if;
+                end if;
+
+            when WAIT_FOR_PREV_TO_COMPLETE =>
+                if v_int.outstanding = 0 then
+                    -- send insn out and wait on it to complete
+                    v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
+                else
+                    valid_tmp := '0';
+                    stall_out <= '1';
+                end if;
+
+            when WAIT_FOR_CURR_TO_COMPLETE =>
+                if v_int.outstanding = 0 then
+                    v_int.state := IDLE;
+                else
+                    valid_tmp := '0';
+                    stall_out <= '1';
+                end if;
+        end case;
+
+        -- track outstanding instructions
+        if valid_tmp = '1' then
+            v_int.outstanding := v_int.outstanding + 1;
+        end if;
+
+        if rst = '1' then
+            v_int.state := IDLE;
+            v_int.outstanding := 0;
+            stall_out <= '0';
+        end if;
+
+        -- update outputs
+        valid_out <= valid_tmp;
+
+        -- update registers
+        rin_int <= v_int;
+    end process;
+end;
index 05819eead4c11c8261a34af2dedfd0afa388ddca..3ba1079780d92f93df29078951ec00c85f3012b5 100644 (file)
@@ -36,13 +36,6 @@ entity decode2 is
 end entity decode2;
 
 architecture behaviour of decode2 is
-       type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
-
-       type reg_internal_type is record
-               state : state_type;
-               outstanding : integer range -1 to 2;
-       end record;
-
        type reg_type is record
                e : Decode2ToExecute1Type;
                m : Decode2ToMultiplyType;
@@ -50,7 +43,6 @@ architecture behaviour of decode2 is
                l : Decode2ToLoadstore1Type;
        end record;
 
-       signal r_int, rin_int : reg_internal_type;
        signal r, rin : reg_type;
 
        type decode_input_reg_t is record
@@ -134,18 +126,37 @@ architecture behaviour of decode2 is
                        return '0';
                end case;
        end;
+
+       signal control_valid_in : std_ulogic;
+       signal control_valid_out : std_ulogic;
+       signal control_sgl_pipe : std_logic;
 begin
+       control_0: entity work.control
+       generic map (
+               PIPELINE_DEPTH => 2
+       )
+       port map (
+               clk         => clk,
+               rst         => rst,
+
+               complete_in => complete_in,
+               valid_in    => control_valid_in,
+               flush_in    => flush_in,
+               sgl_pipe_in => control_sgl_pipe,
+               stop_mark_in => d_in.stop_mark,
+
+               valid_out   => control_valid_out,
+               stall_out   => stall_out,
+               stopped_out => stopped_out
+       );
 
        decode2_0: process(clk)
        begin
                if rising_edge(clk) then
-                       assert r_int.outstanding <= 1 report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
-
                        if rin.e.valid = '1' or rin.l.valid = '1' or rin.m.valid = '1' or rin.d.valid = '1' then
                                report "execute " & to_hstring(rin.e.nia);
                        end if;
                        r <= rin;
-                       r_int <= rin_int;
                end if;
        end process;
 
@@ -157,17 +168,14 @@ begin
 
        decode2_1: process(all)
                variable v : reg_type;
-               variable v_int : reg_internal_type;
                variable mul_a : std_ulogic_vector(63 downto 0);
                variable mul_b : std_ulogic_vector(63 downto 0);
                variable decoded_reg_a : decode_input_reg_t;
                variable decoded_reg_b : decode_input_reg_t;
                variable decoded_reg_c : decode_input_reg_t;
                 variable signed_division: std_ulogic;
-               variable is_valid : std_ulogic;
        begin
                v := r;
-               v_int := r_int;
 
                v.e := Decode2ToExecute1Init;
                v.l := Decode2ToLoadStore1Init;
@@ -311,53 +319,9 @@ begin
                v.l.sign_extend := d_in.decode.sign_extend;
                v.l.update := d_in.decode.update;
 
-               -- single issue
-
-               if complete_in = '1' then
-                       v_int.outstanding := v_int.outstanding - 1;
-               end if;
-
-               -- state machine to handle instructions that must be single
-               -- through the pipeline.
-               stall_out <= '0';
-               is_valid := d_in.valid;
-
-               -- Handle debugger stop
-               stopped_out <= '0';
-               if d_in.stop_mark = '1' and v_int.outstanding = 0 then
-                   stopped_out <= '1';
-               end if;
-
-               case v_int.state is
-               when IDLE =>
-                       if (flush_in = '0') and (is_valid = '1') and (d_in.decode.sgl_pipe = '1') then
-                               if v_int.outstanding /= 0 then
-                                       v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
-                                       stall_out <= '1';
-                                       is_valid := '0';
-                               else
-                                       -- send insn out and wait on it to complete
-                                       v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
-                               end if;
-                       end if;
-
-               when WAIT_FOR_PREV_TO_COMPLETE =>
-                       if v_int.outstanding = 0 then
-                               -- send insn out and wait on it to complete
-                               v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
-                       else
-                               stall_out <= '1';
-                               is_valid := '0';
-                       end if;
-
-               when WAIT_FOR_CURR_TO_COMPLETE =>
-                       if v_int.outstanding = 0 then
-                               v_int.state := IDLE;
-                       else
-                               stall_out <= '1';
-                               is_valid := '0';
-                       end if;
-               end case;
+               -- issue control
+               control_valid_in <= d_in.valid;
+               control_sgl_pipe <= d_in.decode.sgl_pipe;
 
                v.e.valid := '0';
                v.m.valid := '0';
@@ -365,33 +329,19 @@ begin
                v.l.valid := '0';
                case d_in.decode.unit is
                when ALU =>
-                       v.e.valid := is_valid;
+                       v.e.valid := control_valid_out;
                when LDST =>
-                       v.l.valid := is_valid;
+                       v.l.valid := control_valid_out;
                when MUL =>
-                       v.m.valid := is_valid;
+                       v.m.valid := control_valid_out;
                 when DIV =>
-                        v.d.valid := is_valid;
+                        v.d.valid := control_valid_out;
                when NONE =>
-                       v.e.valid := is_valid;
+                       v.e.valid := control_valid_out;
                        v.e.insn_type := OP_ILLEGAL;
                end case;
 
-               if flush_in = '1' then
-                       v.e.valid := '0';
-                       v.m.valid := '0';
-                        v.d.valid := '0';
-                       v.l.valid := '0';
-               end if;
-
-               -- track outstanding instructions
-               if v.e.valid = '1' or v.l.valid = '1' or v.m.valid = '1' or v.d.valid = '1' then
-                       v_int.outstanding := v_int.outstanding + 1;
-               end if;
-
                if rst = '1' then
-                       v_int.state := IDLE;
-                       v_int.outstanding := 0;
                        v.e := Decode2ToExecute1Init;
                        v.l := Decode2ToLoadStore1Init;
                        v.m := Decode2ToMultiplyInit;
@@ -400,7 +350,6 @@ begin
 
                -- Update registers
                rin <= v;
-               rin_int <= v_int;
 
                -- Update outputs
                e_out <= r.e;
index 2124896589c20fad1a3aa01280a423ae83781f7a..508145306c15ee1e07d41ab5d9b3a63c55cba0a0 100644 (file)
@@ -20,6 +20,7 @@ filesets:
       - sim_console.vhdl
       - logical.vhdl
       - countzero.vhdl
+      - control.vhdl
       - execute1.vhdl
       - execute2.vhdl
       - loadstore1.vhdl