dcache: Ease timing on calculation of acks remaining
[microwatt.git] / writeback.vhdl
index 5a6bbe4fda4c902d963bda7afcba9092d814410b..d02a0b1d062f27de89f17a6a3e2786002aabe8e8 100644 (file)
@@ -4,91 +4,111 @@ use ieee.numeric_std.all;
 
 library work;
 use work.common.all;
+use work.crhelpers.all;
 
 entity writeback is
-       port (
-               clk          : in std_ulogic;
+    port (
+        clk          : in std_ulogic;
 
-               e_in         : in Execute2ToWritebackType;
-               l_in         : in Loadstore2ToWritebackType;
-               m_in         : in MultiplyToWritebackType;
+        e_in         : in Execute1ToWritebackType;
+        l_in         : in Loadstore1ToWritebackType;
 
-               w_out        : out WritebackToRegisterFileType;
-               c_out        : out WritebackToCrFileType;
+        w_out        : out WritebackToRegisterFileType;
+        c_out        : out WritebackToCrFileType;
 
-               complete_out : out std_ulogic
-       );
+        complete_out : out std_ulogic
+        );
 end entity writeback;
 
 architecture behaviour of writeback is
-       signal e     : Execute2ToWritebackType;
-       signal l     : Loadstore2ToWritebackType;
-       signal m     : MultiplyToWritebackType;
-       signal w_tmp : WritebackToRegisterFileType;
-       signal c_tmp : WritebackToCrFileType;
 begin
-       writeback_0: process(clk)
-       begin
-               if rising_edge(clk) then
-                       e <= e_in;
-                       l <= l_in;
-                       m <= m_in;
-               end if;
-       end process;
-
-       w_out <= w_tmp;
-       c_out <= c_tmp;
-
-       complete_out <= '1' when e.valid or l.valid or m.valid else '0';
-
-       writeback_1: process(all)
-               variable x: std_ulogic_vector(0 downto 0);
-               variable y: std_ulogic_vector(0 downto 0);
-               variable z: std_ulogic_vector(0 downto 0);
-       begin
-               x := "" & e.valid;
-               y := "" & l.valid;
-               z := "" & m.valid;
-               assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) + to_integer(unsigned(z))) <= 1;
-
-               x := "" & e.write_enable;
-               y := "" & l.write_enable;
-               z := "" & m.write_reg_enable;
-               assert (to_integer(unsigned(x)) + to_integer(unsigned(y)) + to_integer(unsigned(z))) <= 1;
-
-               assert not(e.write_cr_enable = '1' and m.write_cr_enable = '1');
-
-               w_tmp <= WritebackToRegisterFileInit;
-               c_tmp <= WritebackToCrFileInit;
-
-               if e.write_enable = '1' then
-                       w_tmp.write_reg <= e.write_reg;
-                       w_tmp.write_data <= e.write_data;
-                       w_tmp.write_enable <= '1';
-               end if;
-
-               if e.write_cr_enable = '1' then
-                       c_tmp.write_cr_enable <= '1';
-                       c_tmp.write_cr_mask <= e.write_cr_mask;
-                       c_tmp.write_cr_data <= e.write_cr_data;
-               end if;
-
-               if l.write_enable = '1' then
-                       w_tmp.write_reg <= l.write_reg;
-                       w_tmp.write_data <= l.write_data;
-                       w_tmp.write_enable <= '1';
-               end if;
-
-               if m.write_reg_enable = '1' then
-                       w_tmp.write_enable <= '1';
-                       w_tmp.write_reg <= m.write_reg_nr;
-                       w_tmp.write_data <= m.write_reg_data;
-               end if;
-
-               if m.write_cr_enable = '1' then
-                       c_tmp.write_cr_enable <= '1';
-                       c_tmp.write_cr_mask <= m.write_cr_mask;
-                       c_tmp.write_cr_data <= m.write_cr_data;
-               end if;
-       end process;
+    writeback_0: process(clk)
+        variable x : std_ulogic_vector(0 downto 0);
+        variable y : std_ulogic_vector(0 downto 0);
+        variable w : std_ulogic_vector(0 downto 0);
+    begin
+        if rising_edge(clk) then
+            -- Do consistency checks only on the clock edge
+            x(0) := e_in.valid;
+            y(0) := l_in.valid;
+            assert (to_integer(unsigned(x)) + to_integer(unsigned(y))) <= 1 severity failure;
+
+            x(0) := e_in.write_enable or e_in.exc_write_enable;
+            y(0) := l_in.write_enable;
+            assert (to_integer(unsigned(x)) + to_integer(unsigned(y))) <= 1 severity failure;
+
+            w(0) := e_in.write_cr_enable;
+            x(0) := (e_in.write_enable and e_in.rc);
+            assert (to_integer(unsigned(w)) + to_integer(unsigned(x))) <= 1 severity failure;
+        end if;
+    end process;
+
+    writeback_1: process(all)
+       variable cf: std_ulogic_vector(3 downto 0);
+        variable zero : std_ulogic;
+        variable sign : std_ulogic;
+       variable scf  : std_ulogic_vector(3 downto 0);
+    begin
+        w_out <= WritebackToRegisterFileInit;
+        c_out <= WritebackToCrFileInit;
+
+        complete_out <= '0';
+        if e_in.valid = '1' or l_in.valid = '1' then
+            complete_out <= '1';
+        end if;
+
+        if e_in.exc_write_enable = '1' then
+            w_out.write_reg <= e_in.exc_write_reg;
+            w_out.write_data <= e_in.exc_write_data;
+            w_out.write_enable <= '1';
+        else
+            if e_in.write_enable = '1' then
+                w_out.write_reg <= e_in.write_reg;
+                w_out.write_data <= e_in.write_data;
+                w_out.write_enable <= '1';
+            end if;
+
+            if e_in.write_cr_enable = '1' then
+                c_out.write_cr_enable <= '1';
+                c_out.write_cr_mask <= e_in.write_cr_mask;
+                c_out.write_cr_data <= e_in.write_cr_data;
+            end if;
+
+            if e_in.write_xerc_enable = '1' then
+                c_out.write_xerc_enable <= '1';
+                c_out.write_xerc_data <= e_in.xerc;
+            end if;
+
+            if l_in.write_enable = '1' then
+                w_out.write_reg <= gpr_to_gspr(l_in.write_reg);
+                w_out.write_data <= l_in.write_data;
+                w_out.write_enable <= '1';
+            end if;
+
+            if l_in.rc = '1' then
+                -- st*cx. instructions
+                scf(3) := '0';
+                scf(2) := '0';
+                scf(1) := l_in.store_done;
+                scf(0) := l_in.xerc.so;
+                c_out.write_cr_enable <= '1';
+                c_out.write_cr_mask <= num_to_fxm(0);
+                c_out.write_cr_data(31 downto 28) <= scf;
+            end if;
+
+            -- Perform CR0 update for RC forms
+            -- Note that loads never have a form with an RC bit, therefore this can test e_in.write_data
+            if e_in.rc = '1' and e_in.write_enable = '1' then
+                sign := e_in.write_data(63);
+                zero := not (or e_in.write_data);
+                c_out.write_cr_enable <= '1';
+                c_out.write_cr_mask <= num_to_fxm(0);
+                cf(3) := sign;
+                cf(2) := not sign and not zero;
+                cf(1) := zero;
+                cf(0) := e_in.xerc.so;
+                c_out.write_cr_data(31 downto 28) <= cf;
+            end if;
+        end if;
+    end process;
 end;