]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blobdiff - hw/decode.vhd
Implement ITT conditional execution
[fpga/lx-cpu1/tumbl.git] / hw / decode.vhd
index c7d9c861adb7259c0ae18dc3a7df8e2aa9fa9fac..17c6781f4ab5a9e3c441ee7409cc8f3f18dcec00 100644 (file)
@@ -25,8 +25,9 @@ USE WORK.mbl_Pkg.all;
 ENTITY decode IS
 --------------------------------------------------------------------------------
     GENERIC (
-        USE_HW_MUL_g : BOOLEAN := FALSE;
-        USE_BARREL_g : BOOLEAN := FALSE
+        USE_HW_MUL_g : BOOLEAN := TRUE;
+        USE_BARREL_g : BOOLEAN := TRUE;
+        COMPATIBILITY_MODE_g : BOOLEAN := FALSE
         );
     PORT (
         IF2ID_i     :  IN IF2ID_Type;
@@ -37,8 +38,8 @@ ENTITY decode IS
         --
         INT_CTRL_i  :  IN INT_CTRL_Type;
         ID2CTRL_o   : OUT ID2CTRL_Type;
-                               --
-                               noLiteOpc_o : OUT STD_LOGIC
+        --
+        noLiteOpc_o : OUT STD_LOGIC
         );
 END ENTITY decode;
 
@@ -72,6 +73,8 @@ p_decode:
         VARIABLE transfer_Size_v : TRANSFER_SIZE_Type;
         VARIABLE wrb_Action_v    : WRB_ACTION_Type;
         VARIABLE int_busy_v      : STD_LOGIC;
+        VARIABLE cmp_Cond_v      : CMP_COND_Type;
+        VARIABLE cmp_Cond_Type_v : CMP_COND_TYPE_Type;
 
     BEGIN
         prog_counter_v  := IF2ID_i.program_counter;
@@ -82,7 +85,12 @@ p_decode:
         rB_v            := instruction_v (15 DOWNTO 11);
         IMM16_v         := instruction_v (15 DOWNTO  0);
         IMM_Lock_v      := '0';
-        delayBit_v      := '0';
+        IF (COMPATIBILITY_MODE_g = TRUE) THEN
+            delayBit_v      := '0';
+        ELSE
+            cmp_cond_v      := COND_ALL;
+            cmp_cond_type_v := COND_TYPE_ALL;
+        END IF;
         alu_Cin_v       := CIN_ZERO;
         alu_Action_v    := A_NOP;
         msr_Action_v    := KEEP_CARRY;
@@ -120,8 +128,8 @@ p_decode:
 
             CASE opcIx_v (5 DOWNTO 4) IS
 
-                WHEN "00" =>                                            -- ADD / RSUB / CMP
-                    IF (opcIx_v(0) = '1') THEN                          -- RSUB / CMP
+                WHEN "00" =>                                            -- ADD / RSUB
+                    IF (opcIx_v(0) = '1') THEN                          -- RSUB
                         alu_Op1_v := ALU_IN_NOT_REGA;
                     END IF;
                     IF (opcIx_v(1) = '0') THEN                          -- xxx
@@ -133,8 +141,8 @@ p_decode:
                     ELSE                                                -- xxxC
                         alu_Cin_v := FROM_MSR;
                     END IF;
-                    IF ((opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
-                    -- special CMP(U) and not RSUB(I)K
+                    IF ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
+                    -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode
                         IF (IMM16_v(1) = '1') THEN                        -- U-bit set, CMPU
                             alu_Action_v := A_CMPU;
                         ELSE
@@ -169,6 +177,48 @@ p_decode:
                             ELSE
                                 noLiteOpc_o <= '1';
                             END IF;
+                        WHEN "010" =>                                             -- CMP / CMPU / CMPI (new format)
+                            IF (COMPATIBILITY_MODE_g = FALSE) THEN
+                                IF (IMM16_v(5) = '1') THEN   -- U-bit set, CMPU
+                                    alu_Action_v := A_CMPU;
+                                ELSE
+                                    alu_Action_v := A_CMP;
+                                END IF;
+
+                                IF (opcIx_v(3) = '0') THEN   -- IT, ITT, ITE is not available to CMPI
+                                    CASE IMM16_v(4 downto 3) IS
+                                        WHEN "00"   =>
+                                            cmp_Cond_Type_v := COND_TYPE_ALL;
+                                        WHEN "01"   =>
+                                            cmp_Cond_Type_v := COND_TYPE_IF_THEN;
+                                        WHEN "10"   =>
+                                            cmp_Cond_Type_v := COND_TYPE_IF_THEN_THEN;
+                                        WHEN "11"   =>
+                                            cmp_Cond_Type_v := COND_TYPE_IF_THEN_ELSE;
+                                        WHEN OTHERS =>
+                                            NULL;
+                                    END CASE;
+
+                                    CASE IMM16_v(2 downto 0) IS
+                                        WHEN "001"  =>
+                                            cmp_Cond_v := COND_EQ;
+                                        WHEN "010"  =>
+                                            cmp_Cond_v := COND_NE;
+                                        WHEN "011"  =>
+                                            cmp_Cond_v := COND_LT;
+                                        WHEN "100"  =>
+                                            cmp_Cond_v := COND_LE;
+                                        WHEN "101"  =>
+                                            cmp_Cond_v := COND_GT;
+                                        WHEN "110"  =>
+                                            cmp_Cond_v := COND_GE;
+                                        WHEN OTHERS =>
+                                            NULL;
+                                    END CASE;
+                                END IF;
+                            ELSE
+                                noLiteOpc_o <= '1';
+                            END IF;
                         WHEN OTHERS =>
                             noLiteOpc_o <= '1';
                     END CASE;
@@ -202,19 +252,19 @@ p_decode:
                         alu_Action_v := A_NOP;
                         wrb_Action_v := NO_WRB;
                     ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN
-                        CASE rD_v IS
-                            WHEN "10001" =>                             -- RTID
+                        CASE rD_v (3 DOWNTO 0) IS
+                            WHEN "0001" =>                              -- RTI(D)
                                 int_busy_v := '0';
-                            WHEN "10000" =>                             -- RTSD
---                          WHEN "10010" =>                             -- RTBD
---                          WHEN "10100" =>                             -- RTED
+                            WHEN "0000" =>                              -- RTS(D)
                             WHEN OTHERS  =>
                                 noLiteOpc_o <= '1';
                         END CASE;
                         alu_Action_v    := A_ADD;
                         branch_Action_v := BR;
                         wrb_Action_v    := NO_WRB;
-                        delayBit_v      := '1';
+                        IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                            delayBit_v  := rD_v(4);
+                        END IF;
                     ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN
                         CASE IMM16_v IS
                             WHEN X"8001" =>                             -- MFS (MSR only)
@@ -241,7 +291,7 @@ p_decode:
                                 ELSE
                                     alu_Op2_v := ALU_IN_NOT_IMM;
                                 END IF;
-                            WHEN "110" =>                               -- BR(I)
+                            WHEN "110" =>                               -- BR(I)(D)
                                 IF (rA_v(2) = '1') THEN
                                     branch_Action_v := BRL;
                                 ELSE
@@ -253,10 +303,10 @@ p_decode:
                                 ELSE
                                     alu_Op1_v := ALU_IN_PC;
                                 END IF;
-                                IF (rA_v(4) = '1') THEN
-                                    delayBit_v  := '1';
-                                END IF;
                                 alu_Action_v    := A_ADD;
+                                IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                                    delayBit_v  := rA_v(4);
+                                END IF;
                             WHEN "111" =>
                                 CASE rD_v(3 DOWNTO 0) IS
                                     WHEN "0000" =>                      -- BEQ
@@ -276,28 +326,35 @@ p_decode:
                                 END CASE;
                                 alu_Action_v := A_ADD;
                                 alu_Op1_v    := ALU_IN_PC;
-                                delayBit_v   := rD_v(4);
-                            wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
+                                IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                                    delayBit_v := rD_v(4);
+                                END IF;
+                                wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
                             WHEN OTHERS =>
                                 noLiteOpc_o  <= '1';
                         END CASE;
                     END IF;
 
                 WHEN "11" =>
-                    alu_Action_v :=  A_ADD;
-                    CASE opcIx_v (1 DOWNTO 0) IS
-                        WHEN "00"   => transfer_Size_v := BYTE;
-                        WHEN "01"   => transfer_Size_v := HALFWORD;
-                        WHEN "10"   => transfer_Size_v := WORD;
-                        WHEN OTHERS =>
-                            noLiteOpc_o <= '1';
-                    END CASE;
-                    IF (opcIx_v(2) = '0') THEN
-                        mem_Action_v := RD_MEM;
-                        wrb_Action_v := WRB_MEM;
-                    ELSE
-                        mem_Action_v := WR_MEM;
+                    IF (opcIx_v (3 DOWNTO 0) = "1111") THEN             -- HALT
+                        alu_Action_v :=  A_HALT;
                         wrb_Action_v := NO_WRB;
+                    ELSE
+                        alu_Action_v :=  A_ADD;
+                        CASE opcIx_v (1 DOWNTO 0) IS
+                            WHEN "00"   => transfer_Size_v := BYTE;
+                            WHEN "01"   => transfer_Size_v := HALFWORD;
+                            WHEN "10"   => transfer_Size_v := WORD;
+                            WHEN OTHERS =>
+                                noLiteOpc_o <= '1';
+                        END CASE;
+                        IF (opcIx_v(2) = '0') THEN
+                            mem_Action_v := RD_MEM;
+                            wrb_Action_v := WRB_MEM;
+                        ELSE
+                            mem_Action_v := WR_MEM;
+                            wrb_Action_v := NO_WRB;
+                        END IF;
                     END IF;
 
                 WHEN OTHERS =>
@@ -327,10 +384,13 @@ p_decode:
         ID2EX_o.transfer_Size    <= transfer_Size_v;
         ID2EX_o.wrb_Action       <= wrb_Action_v;
         --
-        ID2CTRL_o.delayBit      <= delayBit_v;
-        ID2CTRL_o.int_busy      <= int_busy_v;
-
-
+        IF (COMPATIBILITY_MODE_g = TRUE) THEN
+            ID2CTRL_o.delayBit    <= delayBit_v;
+        ELSE
+            ID2EX_o.cmp_Cond      <= cmp_Cond_v;
+            ID2EX_o.cmp_Cond_Type <= cmp_Cond_Type_v;
+        END IF;
+        ID2CTRL_o.int_busy        <= int_busy_v;
 
     END PROCESS;