]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blobdiff - hw/exeq.vhd
Implement ITT conditional execution
[fpga/lx-cpu1/tumbl.git] / hw / exeq.vhd
index fc338b8c341b8ea6f7b66fb2e3423d166983dd3e..12357951fb2ec7f59e17c6c60773a3311c136830 100644 (file)
@@ -31,12 +31,14 @@ ENTITY exeq IS
 ----------------------------------------------------------
     GENERIC (
         USE_HW_MUL_g : BOOLEAN := TRUE;
-        USE_BARREL_g : BOOLEAN := TRUE
+        USE_BARREL_g : BOOLEAN := TRUE;
+        COMPATIBILITY_MODE_g : BOOLEAN := FALSE
         );
     PORT (
         ID2EX_i      :  IN ID2EX_Type;
         GPRF2EX_i    :  IN GPRF2EX_Type;
         EX2IF_o      : OUT EX2IF_Type;
+        EX2CTRL_o    : OUT EX2CTRL_Type;
         HALT_o       : OUT HALT_Type;
         --
         EX_WRB_i     :  IN WRB_Type;
@@ -79,45 +81,52 @@ p_exeq:
             RETURN reversed_v;
         END;
 
-        VARIABLE data_rA_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE data_rB_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE data_rD_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE in1_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE in2_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE hi16_v        : STD_LOGIC_VECTOR (15 DOWNTO 0);
-        VARIABLE IMM32_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE carry_i_v     : STD_LOGIC;
-        VARIABLE result_v      : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE carry_o_v     : STD_LOGIC;
-        VARIABLE isZero_v      : STD_LOGIC;
-        VARIABLE signBit_in1_v : STD_LOGIC;
-        VARIABLE signBit_in2_v : STD_LOGIC;
-        VARIABLE signBit_rA_v  : STD_LOGIC;
-        VARIABLE rA_eq_ex_rD_v : STD_LOGIC;
-        VARIABLE rB_eq_ex_rD_v : STD_LOGIC;
-        VARIABLE hazard_v      : STD_LOGIC;
-        VARIABLE save_rX_v     : SAVE_REG_Type;
-        VARIABLE data_rX_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE do_branch_v   : STD_LOGIC;
-        VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
-        VARIABLE tmp64_v       : STD_LOGIC_VECTOR (63 DOWNTO 0);
-        VARIABLE padVec_v      : STD_LOGIC_VECTOR (15 DOWNTO 0);
-        VARIABLE halt_v        : STD_LOGIC;
-        VARIABLE halt_code_v   : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        VARIABLE data_rA_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE data_rB_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE data_rD_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE in1_v           : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE in2_v           : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE hi16_v          : STD_LOGIC_VECTOR (15 DOWNTO 0);
+        VARIABLE IMM32_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE carry_i_v       : STD_LOGIC;
+        VARIABLE result_v        : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE carry_o_v       : STD_LOGIC;
+        VARIABLE isZero_v        : STD_LOGIC;
+        VARIABLE cmpResZero_v    : STD_LOGIC;
+        VARIABLE signBit_in1_v   : STD_LOGIC;
+        VARIABLE signBit_in2_v   : STD_LOGIC;
+        VARIABLE signBit_rA_v    : STD_LOGIC;
+        VARIABLE signBit_rD_v    : STD_LOGIC;
+        VARIABLE rA_eq_ex_rD_v   : STD_LOGIC;
+        VARIABLE rB_eq_ex_rD_v   : STD_LOGIC;
+        VARIABLE hazard_v        : STD_LOGIC;
+        VARIABLE save_rX_v       : SAVE_REG_Type;
+        VARIABLE data_rX_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
+        VARIABLE do_branch_v     : STD_LOGIC;
+        VARIABLE byte_Enable_v   : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
+        VARIABLE tmp64_v         : STD_LOGIC_VECTOR (63 DOWNTO 0);
+        VARIABLE padVec_v        : STD_LOGIC_VECTOR (15 DOWNTO 0);
+        VARIABLE halt_v          : STD_LOGIC;
+        VARIABLE halt_code_v     : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
+        VARIABLE do_cmp_cond_v   : STD_LOGIC;
+        VARIABLE cmp_cond_type_v : CMP_COND_TYPE_Type;
 
     BEGIN
 
-        rA_eq_ex_rD_v := '0';
-        rB_eq_ex_rD_v := '0';
-        hazard_v      := '0';
-        save_rX_v     := NO_SAVE;
-        data_rX_v     := data_rB_v;         -- default value for data_rX_v
-        result_v      := (OTHERS => '0');
-        carry_o_v     := '0';
-        do_branch_v   := '0';
-        byte_Enable_v := "0000";
-        halt_v        := '0';
-        halt_code_v   := "00000";
+        rA_eq_ex_rD_v   := '0';
+        rB_eq_ex_rD_v   := '0';
+        hazard_v        := '0';
+        save_rX_v       := NO_SAVE;
+        data_rX_v       := data_rB_v;         -- default value for data_rX_v
+        result_v        := (OTHERS => '0');
+        carry_o_v       := '0';
+        do_branch_v     := '0';
+        byte_Enable_v   := "0000";
+        halt_v          := '0';
+        halt_code_v     := "00000";
+        do_cmp_cond_v   := '0';
+        cmp_cond_type_v := COND_TYPE_ALL;
+        signBit_rD_v    := '0';
 
         -- create some helper variables
         IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN
@@ -200,18 +209,49 @@ p_exeq:
             WHEN OTHERS    =>   carry_i_v := '0';
         END CASE;
 
+        IF (data_rA_v = C_32_ZEROS) THEN
+            isZero_v := '1';
+        ELSE
+            isZero_v := '0';
+        END IF;
+
         CASE ID2EX_i.alu_Action IS
             WHEN A_ADD | A_CMP | A_CMPU =>
                 ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v);
                 IF (id2ex_i.alu_Action = A_CMPU) THEN
                     IF (signBit_in1_v = signBit_in2_v) THEN
-                        result_v(31) := NOT signBit_in1_v;
+                        signBit_rD_v := NOT signBit_in1_v;
                     END IF;
                 ELSIF (id2ex_i.alu_Action = A_CMP) THEN
                     IF (signBit_in1_v = signBit_in2_v) THEN
-                        result_v(31) := signBit_in1_v;
+                        signBit_rD_v := signBit_in1_v;
                     END IF;
                 END IF;
+
+                result_v(31) := signBit_rD_v;
+
+                IF (COMPATIBILITY_MODE_g = FALSE) THEN
+                    IF (ID2EX_i.cmp_Cond /= COND_ALL) THEN
+                        IF (result_v = C_32_ZEROS) THEN
+                            cmpResZero_v := '1';
+                        ELSE
+                            cmpResZero_v := '0';
+                        END IF;
+
+                        CASE ID2EX_i.cmp_Cond IS
+                            WHEN COND_EQ => do_cmp_cond_v := cmpResZero_v;
+                            WHEN COND_NE => do_cmp_cond_v := NOT cmpResZero_v;
+                            WHEN COND_LT => do_cmp_cond_v := signBit_rD_v;
+                            WHEN COND_LE => do_cmp_cond_v := signBit_rD_v OR cmpResZero_v;
+                            WHEN COND_GT => do_cmp_cond_v := NOT (signBit_rD_v OR cmpResZero_v);
+                            WHEN COND_GE => do_cmp_cond_v := NOT signBit_rD_v;
+                            WHEN OTHERS  => NULL;
+                        END CASE;
+
+                        cmp_cond_type_v := ID2EX_i.cmp_Cond_Type;
+                    END IF;
+                END IF;
+
             WHEN A_OR      =>
                 result_v  := in1_v  OR in2_v;
             WHEN A_AND    =>
@@ -281,11 +321,6 @@ p_exeq:
                 NULL;
         END CASE;
 
-        IF (data_rA_v = C_32_ZEROS) THEN
-            isZero_v := '1';
-        ELSE
-            isZero_v := '0';
-        END IF;
         CASE ID2EX_i.branch_Action IS
             WHEN BR     => do_branch_v := '1';
             WHEN BRL    => do_branch_v := '1';
@@ -305,6 +340,26 @@ p_exeq:
             EX2IF_o.branch_target <= C_32_ZEROS;
         END IF;
 
+        -- CMP conditioning
+        IF (COMPATIBILITY_MODE_g = FALSE) THEN
+            CASE cmp_cond_type_v IS
+                WHEN COND_TYPE_ALL          =>
+                    EX2CTRL_o.flush_first  <= '0';
+                    EX2CTRL_o.flush_second <= '0';
+                WHEN COND_TYPE_IF_THEN      =>
+                    EX2CTRL_o.flush_first  <= not do_cmp_cond_v;
+                    EX2CTRL_o.flush_second <= '0';
+                WHEN COND_TYPE_IF_THEN_THEN =>
+                    EX2CTRL_o.flush_first  <= not do_cmp_cond_v;
+                    EX2CTRL_o.flush_second <= not do_cmp_cond_v;
+                WHEN COND_TYPE_IF_THEN_ELSE =>
+                    EX2CTRL_o.flush_first  <= not do_cmp_cond_v;
+                    EX2CTRL_o.flush_second <= do_cmp_cond_v;
+                WHEN OTHERS                 =>
+                    NULL;
+            END CASE;
+        END IF;
+
         -- Halting
         HALT_o.halt      <= halt_v;
         HALT_o.halt_code <= halt_code_v;