Merge pull request #257 from antonblanchard/nofpu-fix
[microwatt.git] / control.vhdl
index 3caf6fd3a878092502e9c5e9b781802a8f5d2225..4f67ad46f21893e52121ece2db54858e656a797e 100644 (file)
@@ -1,6 +1,9 @@
 library ieee;
 use ieee.std_logic_1164.all;
 
+library work;
+use work.common.all;
+
 entity control is
     generic (
         PIPELINE_DEPTH : natural := 2
@@ -12,24 +15,39 @@ entity control is
         complete_in         : in std_ulogic;
         valid_in            : in std_ulogic;
         flush_in            : in std_ulogic;
+       busy_in             : in std_ulogic;
+        deferred            : in std_ulogic;
         sgl_pipe_in         : in std_ulogic;
         stop_mark_in        : in std_ulogic;
 
         gpr_write_valid_in  : in std_ulogic;
-        gpr_write_in        : in std_ulogic_vector(4 downto 0);
+        gpr_write_in        : in gspr_index_t;
+        gpr_bypassable      : in std_ulogic;
+
+        update_gpr_write_valid : in std_ulogic;
+        update_gpr_write_reg : in gspr_index_t;
 
         gpr_a_read_valid_in : in std_ulogic;
-        gpr_a_read_in       : in std_ulogic_vector(4 downto 0);
+        gpr_a_read_in       : in gspr_index_t;
 
         gpr_b_read_valid_in : in std_ulogic;
-        gpr_b_read_in       : in std_ulogic_vector(4 downto 0);
+        gpr_b_read_in       : in gspr_index_t;
 
         gpr_c_read_valid_in : in std_ulogic;
-        gpr_c_read_in       : in std_ulogic_vector(4 downto 0);
+        gpr_c_read_in       : in gspr_index_t;
+
+        cr_read_in          : in std_ulogic;
+        cr_write_in         : in std_ulogic;
+        cr_bypassable       : in std_ulogic;
 
         valid_out           : out std_ulogic;
         stall_out           : out std_ulogic;
-        stopped_out         : out std_ulogic
+        stopped_out         : out std_ulogic;
+
+        gpr_bypass_a        : out std_ulogic;
+        gpr_bypass_b        : out std_ulogic;
+        gpr_bypass_c        : out std_ulogic;
+        cr_bypass           : out std_ulogic
         );
 end entity control;
 
@@ -44,59 +62,115 @@ architecture rtl of control is
 
     signal r_int, rin_int : reg_internal_type := reg_internal_init;
 
-    signal stall_a_out, stall_b_out, stall_c_out : std_ulogic;
+    signal stall_a_out  : std_ulogic;
+    signal stall_b_out  : std_ulogic;
+    signal stall_c_out  : std_ulogic;
+    signal cr_stall_out : std_ulogic;
 
     signal gpr_write_valid : std_ulogic := '0';
+    signal cr_write_valid  : std_ulogic := '0';
+
 begin
     gpr_hazard0: entity work.gpr_hazard
         generic map (
-            PIPELINE_DEPTH => 2
+            PIPELINE_DEPTH => PIPELINE_DEPTH
             )
         port map (
             clk                => clk,
+            busy_in            => busy_in,
+           deferred           => deferred,
+            complete_in        => complete_in,
+            flush_in           => flush_in,
+            issuing            => valid_out,
 
             gpr_write_valid_in => gpr_write_valid,
             gpr_write_in       => gpr_write_in,
+            bypass_avail       => gpr_bypassable,
             gpr_read_valid_in  => gpr_a_read_valid_in,
             gpr_read_in        => gpr_a_read_in,
 
-            stall_out          => stall_a_out
+            ugpr_write_valid   => update_gpr_write_valid,
+            ugpr_write_reg     => update_gpr_write_reg,
+
+            stall_out          => stall_a_out,
+            use_bypass         => gpr_bypass_a
             );
 
     gpr_hazard1: entity work.gpr_hazard
         generic map (
-            PIPELINE_DEPTH => 2
+            PIPELINE_DEPTH => PIPELINE_DEPTH
             )
         port map (
             clk                => clk,
+            busy_in            => busy_in,
+           deferred           => deferred,
+            complete_in        => complete_in,
+            flush_in           => flush_in,
+            issuing            => valid_out,
 
             gpr_write_valid_in => gpr_write_valid,
             gpr_write_in       => gpr_write_in,
+            bypass_avail       => gpr_bypassable,
             gpr_read_valid_in  => gpr_b_read_valid_in,
             gpr_read_in        => gpr_b_read_in,
 
-            stall_out          => stall_b_out
+            ugpr_write_valid   => update_gpr_write_valid,
+            ugpr_write_reg     => update_gpr_write_reg,
+
+            stall_out          => stall_b_out,
+            use_bypass         => gpr_bypass_b
             );
 
     gpr_hazard2: entity work.gpr_hazard
         generic map (
-            PIPELINE_DEPTH => 2
+            PIPELINE_DEPTH => PIPELINE_DEPTH
             )
         port map (
             clk                => clk,
+            busy_in            => busy_in,
+           deferred           => deferred,
+            complete_in        => complete_in,
+            flush_in           => flush_in,
+            issuing            => valid_out,
 
             gpr_write_valid_in => gpr_write_valid,
             gpr_write_in       => gpr_write_in,
+            bypass_avail       => gpr_bypassable,
             gpr_read_valid_in  => gpr_c_read_valid_in,
             gpr_read_in        => gpr_c_read_in,
 
-            stall_out          => stall_c_out
+            ugpr_write_valid   => update_gpr_write_valid,
+            ugpr_write_reg     => update_gpr_write_reg,
+
+            stall_out          => stall_c_out,
+            use_bypass         => gpr_bypass_c
+            );
+
+    cr_hazard0: entity work.cr_hazard
+        generic map (
+            PIPELINE_DEPTH => PIPELINE_DEPTH
+            )
+        port map (
+            clk                => clk,
+            busy_in            => busy_in,
+           deferred           => deferred,
+            complete_in        => complete_in,
+            flush_in           => flush_in,
+            issuing            => valid_out,
+
+            cr_read_in         => cr_read_in,
+            cr_write_in        => cr_write_valid,
+            bypassable         => cr_bypassable,
+
+            stall_out          => cr_stall_out,
+            use_bypass         => cr_bypass
             );
 
     control0: process(clk)
     begin
         if rising_edge(clk) then
-            assert r_int.outstanding >= 0 and r_int.outstanding <= (PIPELINE_DEPTH+1) report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
+            assert rin_int.outstanding >= 0 and rin_int.outstanding <= (PIPELINE_DEPTH+1)
+                report "Outstanding bad " & integer'image(rin_int.outstanding) severity failure;
             r_int <= rin_int;
         end if;
     end process;
@@ -112,10 +186,18 @@ begin
         valid_tmp := valid_in and not flush_in;
         stall_tmp := '0';
 
-        if complete_in = '1' then
+        if flush_in = '1' then
+            -- expect to see complete_in next cycle
+            v_int.outstanding := 1;
+        elsif complete_in = '1' then
             v_int.outstanding := r_int.outstanding - 1;
         end if;
 
+        if rst = '1' then
+            v_int := reg_internal_init;
+            valid_tmp := '0';
+        end if;
+
         -- Handle debugger stop
         stopped_out <= '0';
         if stop_mark_in = '1' and v_int.outstanding = 0 then
@@ -137,7 +219,7 @@ begin
                         end if;
                     else
                         -- let it go out if there are no GPR hazards
-                        stall_tmp := stall_a_out or stall_b_out or stall_c_out;
+                        stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
                     end if;
                 end if;
 
@@ -164,7 +246,7 @@ begin
                             end if;
                         else
                             -- let it go out if there are no GPR hazards
-                            stall_tmp := stall_a_out or stall_b_out or stall_c_out;
+                            stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
                         end if;
                     end if;
                 else
@@ -177,21 +259,19 @@ begin
         end if;
 
         if valid_tmp = '1' then
-            v_int.outstanding := v_int.outstanding + 1;
+            if deferred = '0' then
+                v_int.outstanding := v_int.outstanding + 1;
+            end if;
             gpr_write_valid <= gpr_write_valid_in;
+            cr_write_valid <= cr_write_in;
         else
             gpr_write_valid <= '0';
-        end if;
-
-        if rst = '1' then
-            v_int.state := IDLE;
-            v_int.outstanding := 0;
-            stall_tmp := '0';
+            cr_write_valid <= '0';
         end if;
 
         -- update outputs
         valid_out <= valid_tmp;
-        stall_out <= stall_tmp;
+        stall_out <= stall_tmp or deferred;
 
         -- update registers
         rin_int <= v_int;