From 8f15121bd781ce710a4bea9c4bb9b4975b556e2e Mon Sep 17 00:00:00 2001 From: Martin Meloun Date: Wed, 25 Sep 2013 15:46:41 +0200 Subject: [PATCH] Implement ITT conditional execution Signed-off-by: Martin Meloun --- hw/core_ctrl.vhd | 19 +++++-- hw/decode.vhd | 44 ++++++++++++++- hw/exeq.vhd | 143 ++++++++++++++++++++++++++++++++--------------- hw/mbl_Pkg.vhd | 14 ++++- 4 files changed, 167 insertions(+), 53 deletions(-) diff --git a/hw/core_ctrl.vhd b/hw/core_ctrl.vhd index a0d7143..55c5344 100644 --- a/hw/core_ctrl.vhd +++ b/hw/core_ctrl.vhd @@ -51,6 +51,7 @@ ENTITY core_ctrl IS -- exeq to fetch feedback registers EX2IF_REG_i : IN EX2IF_Type; EX2IF_REG_o : OUT EX2IF_Type; + EX2CTRL_REG_i : IN EX2CTRL_Type; -- exeq to core (halting) exeq_halt_i : IN STD_LOGIC; -- exeq to mem pipeline registers @@ -85,12 +86,13 @@ ARCHITECTURE rtl OF core_ctrl IS SIGNAL rst_r : STD_LOGIC; SIGNAL reset_s : STD_LOGIC; - SIGNAL core_clken_s : STD_LOGIC; + SIGNAL core_clken_s : STD_LOGIC; SIGNAL ID2EX_REG_r : ID2EX_Type; SIGNAL EX2IF_REG_r : EX2IF_Type; SIGNAL IMM_LOCK_r : IMM_LOCK_Type; SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type; + SIGNAL flush_second_r : STD_LOGIC; SIGNAL delayBit_r : STD_LOGIC; SIGNAL clken_s : STD_LOGIC; SIGNAL clken_pipe_s : STD_LOGIC; @@ -118,7 +120,7 @@ BEGIN gprf_clken_o <= clken_s; -- signals for clearing the ID2EX and EX2MEM registers during branches flush_ID2EX_s <= ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE - ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch); + ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR flush_second_r); flush_EX2MEM_s <= HAZARD_WRB_i.hazard; -- outputs that need to be readable too, so needing shadowing signals ID2EX_REG_o <= ID2EX_REG_r; @@ -137,7 +139,7 @@ regd_proc: flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i, MEM_REG_i, ID2CTRL_i, int_i, MSR_i, int_busy_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r, - EX2IF_REG_i, EX_WRB_i, EX2MEM_REG_i ) + EX2IF_REG_i, EX2CTRL_REG_i, EX_WRB_i, EX2MEM_REG_i ) -- some local procedures PROCEDURE lp_rst_IF2ID_REG IS @@ -229,7 +231,9 @@ regd_proc: lp_rst_MEM_REG; IF (COMPATIBILITY_MODE_g = TRUE) THEN - delayBit_r <= '0'; + delayBit_r <= '0'; + ELSE + flush_second_r <= '0'; END IF; flush_ID2EX_r <= '0'; @@ -241,6 +245,9 @@ regd_proc: IF2ID_REG_o <= IF2ID_REG_i; END IF; flush_ID2EX_r <= flush_ID2EX_s; + IF (COMPATIBILITY_MODE_g = FALSE) THEN + flush_second_r <= EX2CTRL_REG_i.flush_second; + END IF; HAZARD_WRB_r <= HAZARD_WRB_i; MEM_REG_o <= MEM_REG_i; int_busy_r <= ID2CTRL_i.int_busy; @@ -279,8 +286,8 @@ regd_proc: lp_rst_IMM_LOCK; ELSE IF (clken_pipe_s = '1') THEN - EX2IF_REG_r <= EX2IF_REG_i; - EX_WRB_o <= EX_WRB_i; + EX2IF_REG_r <= EX2IF_REG_i; + EX_WRB_o <= EX_WRB_i; END IF; IF (clken_s = '1') THEN -- next test to prevent a flush from disrupting diff --git a/hw/decode.vhd b/hw/decode.vhd index 9d02421..17c6781 100644 --- a/hw/decode.vhd +++ b/hw/decode.vhd @@ -73,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; @@ -85,6 +87,9 @@ p_decode: IMM_Lock_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; @@ -179,6 +184,38 @@ p_decode: 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; @@ -348,9 +385,12 @@ p_decode: ID2EX_o.wrb_Action <= wrb_Action_v; -- IF (COMPATIBILITY_MODE_g = TRUE) THEN - ID2CTRL_o.delayBit <= delayBit_v; + 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; + ID2CTRL_o.int_busy <= int_busy_v; END PROCESS; diff --git a/hw/exeq.vhd b/hw/exeq.vhd index fc338b8..1235795 100644 --- a/hw/exeq.vhd +++ b/hw/exeq.vhd @@ -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; diff --git a/hw/mbl_Pkg.vhd b/hw/mbl_Pkg.vhd index 2b53585..c81f642 100644 --- a/hw/mbl_Pkg.vhd +++ b/hw/mbl_Pkg.vhd @@ -55,6 +55,8 @@ PACKAGE mbl_Pkg IS TYPE MEM_ACTION_Type IS (NO_MEM, WR_MEM, RD_MEM); TYPE TRANSFER_SIZE_Type IS (WORD, HALFWORD, BYTE); TYPE SAVE_REG_Type IS (NO_SAVE, SAVE_RA, SAVE_RB); + TYPE CMP_COND_Type IS (COND_ALL, COND_EQ, COND_NE, COND_LT, COND_LE, COND_GT, COND_GE); + TYPE CMP_COND_TYPE_Type IS (COND_TYPE_ALL, COND_TYPE_IF_THEN, COND_TYPE_IF_THEN_THEN, COND_TYPE_IF_THEN_ELSE); -- TYPE IF2ID_Type IS RECORD program_counter : STD_LOGIC_VECTOR (31 DOWNTO 0); @@ -76,6 +78,8 @@ PACKAGE mbl_Pkg IS mem_Action : MEM_ACTION_Type; -- rd_mem implies writeback transfer_Size : TRANSFER_SIZE_Type; wrb_Action : WRB_ACTION_Type; + cmp_Cond : CMP_COND_Type; + cmp_Cond_Type : CMP_COND_TYPE_Type; END RECORD; TYPE ID2GPRF_Type IS RECORD @@ -116,6 +120,11 @@ PACKAGE mbl_Pkg IS branch_target : STD_LOGIC_VECTOR (31 DOWNTO 0); END RECORD; + TYPE EX2CTRL_Type IS RECORD + flush_first : STD_LOGIC; + flush_second : STD_LOGIC; + END RECORD; + TYPE HALT_Type IS RECORD halt : STD_LOGIC; halt_code : STD_LOGIC_VECTOR ( 4 DOWNTO 0); @@ -223,12 +232,14 @@ PACKAGE mbl_Pkg IS COMPONENT exeq IS GENERIC ( USE_HW_MUL_g : BOOLEAN := FALSE; - USE_BARREL_g : BOOLEAN := FALSE + USE_BARREL_g : BOOLEAN := FALSE; + 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; @@ -291,6 +302,7 @@ PACKAGE mbl_Pkg IS -- exeq to fetch feedback registers EX2IF_REG_i : IN EX2IF_Type; EX2IF_REG_o : OUT EX2IF_Type; + EX2CTRL_REG_i : IN EX2CTRL_Type; -- exeq to core (halting) exeq_halt_i : IN STD_LOGIC; -- exeq to mem pipeline registers -- 2.39.2