diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 2367c9cb8b755e71d949380bd163eb5fdbf8e47d..521938323bc181106c7229235fcfd8037aed0ae9 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -124,7 +124,11 @@ architecture rtl of core is EX_interrupt: in std_logic; MM_interrupt: out std_logic; EX_int_req: in reg8; - MM_int_req: out reg8); + MM_int_req: out reg8; + EX_is_SC: in boolean; + MM_is_SC: out boolean; + EX_is_MFC0: in boolean; + MM_is_MFC0: out boolean); end component reg_excp_EX_MM; component reg_excp_MM_WB is @@ -143,7 +147,7 @@ architecture rtl of core is signal interrupt,MM_interrupt, exception_stall : std_logic; signal exception_taken, interrupt_taken : std_logic; signal nullify_fetch, nullify, MM_nullify : boolean; - signal addrError, MM_addrError, abort_ref, MM_mfc0 : boolean; + signal addrError, MM_addrError, abort_ref : boolean; signal PC_abort, RF_PC_abort, EX_PC_abort, MM_PC_abort : boolean; signal IF_excp_type,RF_excp_type: exception_type; signal mem_excp_type, MM_mem_excp_type : exception_type; @@ -176,6 +180,7 @@ architecture rtl of core is signal cop0_inp, RF_cop0_val,MM_cop0_val,WB_cop0_val : reg32; signal BadVAddr, BadVAddr_inp : reg32; signal BadVAddr_update : std_logic; + signal is_SC, MM_is_SC, is_MFC0, MM_is_MFC0 : boolean; -- MMU signals -- signal INDEX, index_inp, RANDOM, WIRED, wired_inp : reg32; @@ -936,26 +941,26 @@ begin RF_FORWARDING_BRANCH: process (a_rs,a_rt,EX_wreg,EX_a_c,MM_wreg,MM_a_c, - MM_aVal,MM_result,MM_cop0_val,MM_mfc0, + MM_aVal,MM_result,MM_cop0_val,MM_is_MFC0, regs_A,regs_B,is_branch, - EX_exception, LL_SC_abort) + is_SC, LL_SC_abort) variable rs_stall, rt_stall : boolean; begin if ( (is_branch = '1') and -- forward_A (EX_wreg = '0') and (EX_a_c = a_rs) and (EX_a_c /= b"00000") ) then - if EX_exception = exSC then + if is_SC then eq_fwd_A <= x"0000000" & b"000" & not(LL_SC_abort); rs_stall := FALSE; else eq_fwd_A <= regs_A; rs_stall := TRUE; end if; - elsif ( (MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000") ) then + elsif ( (MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000") ) then if ( (MM_aVal = '0') and (is_branch = '1') ) then -- LW load-delay slot - rs_stall := TRUE; eq_fwd_A <= regs_A; - elsif MM_mfc0 then -- non-LW + rs_stall := TRUE; + elsif MM_is_MFC0 then -- non-LW eq_fwd_A <= MM_cop0_val; rs_stall := FALSE; else @@ -969,18 +974,18 @@ begin if ( (is_branch = '1') and -- forward_B (EX_wreg = '0') and (EX_a_c = a_rt) and (EX_a_c /= b"00000") ) then - if EX_exception = exSC then - eq_fwd_A <= x"0000000" & b"000" & not(LL_SC_abort); - rs_stall := FALSE; + if is_SC then + eq_fwd_B <= x"0000000" & b"000" & not(LL_SC_abort); + rt_stall := FALSE; else eq_fwd_B <= regs_B; - rs_stall := TRUE; + rt_stall := TRUE; end if; elsif ( (MM_wreg = '0') and (MM_a_c = a_rt) and (MM_a_c /= b"00000") ) then if ( (MM_aVal = '0') and (is_branch = '1') ) then -- LW load-delay slot - rt_stall := TRUE; eq_fwd_B <= regs_B; - elsif MM_mfc0 then -- non-LW + rt_stall := TRUE; + elsif MM_is_MFC0 then -- non-LW eq_fwd_B <= MM_cop0_val; rt_stall := FALSE; else @@ -992,7 +997,7 @@ begin rt_stall := FALSE; end if; - br_stall <= BOOL2SL(rs_stall or rt_stall); + br_stall <= BOOL2SL(rs_stall or rt_stall); end process RF_FORWARDING_BRANCH; @@ -1254,16 +1259,16 @@ begin -- EXECUTION --------------------------------------------- EX_FORWARDING_ALU: process (EX_a_rs,EX_a_rt,EX_a_c, EX_A,EX_B, - EX_exception, is_exception, LL_SC_abort_d, + is_exception, LL_SC_abort_d, MM_a_c,MM_wreg,WB_a_c,WB_wreg, - MM_mfc0,MM_cop0_val, MM_result,WB_C) + MM_is_MFC0,MM_cop0_val, MM_result,WB_C) variable i_A,i_B : reg32; begin FORWARD_A: if ((MM_wreg = '0')and(MM_a_c /= b"00000")and(MM_a_c = EX_a_rs)) then - if MM_mfc0 then + if MM_is_MFC0 then i_A := MM_cop0_val; - elsif is_exception = exSC then + elsif MM_is_SC then i_A := x"0000000" & b"000" & not(LL_SC_abort_d); else i_A := MM_result; @@ -1280,9 +1285,9 @@ begin FORWARD_B: if ((MM_wreg = '0')and(MM_a_c /= b"00000")and(MM_a_c = EX_a_rt)) then - if MM_mfc0 then + if MM_is_MFC0 then i_B := MM_cop0_val; - elsif is_exception = exSC then + elsif MM_is_SC then i_B := x"0000000" & b"000" & not(LL_SC_abort_d); else i_B := MM_result; @@ -1716,8 +1721,7 @@ begin trap_taken <= i_take_trap; end process RF_EVALUATE_TRAPS; - - -- ---------------------------------------------------------------------- + -- ---------------------------------------------------------------------- PIPESTAGE_EXCP_RF_EX: reg_excp_RF_EX port map (clk, rst, excp_RF_EX_ld, cop0_reg,EX_cop0_reg, cop0_sel,EX_cop0_sel, @@ -1744,6 +1748,9 @@ begin -- check for overflow in EX, send it to MM for later processing EX_ovfl <= (EX_can_trap = b"10" and ovfl = '1'); + is_SC <= (EX_exception = exSC); -- is StoreConditional? (alu_fwd) + is_mfc0 <= (EX_exception = exMFC0); -- is MFC0? (alu_fwd) + -- ---------------------------------------------------------------------- PIPESTAGE_EXCP_EX_MM: reg_excp_EX_MM port map (clk, rst, excp_EX_MM_ld, @@ -1756,8 +1763,8 @@ begin EX_PC_abort,MM_PC_abort, EX_exception,MM_exception, tlb_exception,MM_tlb_exception, tlb_stage_mm,MM_tlb_stage_mm, TLB_excp_type,MM_TLB_excp_type, - EX_nmi,MM_nmi, interrupt,MM_interrupt, int_req,MM_int_req); - + EX_nmi,MM_nmi, interrupt,MM_interrupt, int_req,MM_int_req, + is_SC, MM_is_SC, is_MFC0, MM_is_MFC0); @@ -1770,14 +1777,13 @@ begin exception_num <= exception_type'pos(is_exception); -- for debugging only - MM_mfc0 <= (is_exception = exMFC0); -- STATUS -- pg 79 -- cop0_12 -------------------- COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS: process (MM_a_rt, is_exception, cop0_inp, MM_cop0_reg, MM_cop0_sel, MM_nmi, MM_interrupt,MM_int_req, RF_is_delayslot, EX_is_delayslot, MM_is_delayslot, WB_is_delayslot, - rom_stall,ram_stall, MM_mfc0, + rom_stall,ram_stall, MM_is_mfc0, INDEX, RANDOM, EntryLo0, EntryLo1, CONTEXT, PAGEMASK, WIRED, EntryHi, COUNT, COMPARE, STATUS, CAUSE, EPC, BadVAddr) @@ -1840,14 +1846,14 @@ begin i_update := '1'; i_update_r := cop0reg_STATUS; i_COP0_rd := STATUS; - i_stall := '1'; + i_stall := '0'; when exDI => -- disable interrupts newSTATUS(STATUS_IE) := '0'; i_update := '1'; i_update_r := cop0reg_STATUS; i_COP0_rd := STATUS; - i_stall := '1'; + i_stall := '0'; when exMFC0 => -- move from COP-0 i_stall := '0'; @@ -2041,54 +2047,49 @@ begin i_epc_update := '0'; i_nullify := TRUE; -- nullify instructions in IF,RF,EX - when exTLBdblFaultIF | exTLBdblFaultRD | exTLBdblFaultWR | - exTLBinvalIF | exTLBinvalRD | exTLBinvalWR | exTLBmod => + when exTLBdblFaultIF | exTLBinvalIF => + ExcCode <= cop0code_TLBL; + if RF_is_delayslot = '1' then -- instr is in delay slot + i_epc_source := EPC_src_RF; -- RF_PC, re-execute branch/jump + is_delayslot <= RF_is_delayslot; + else + i_epc_source := EPC_src_PC; -- PC + is_delayslot <= '0'; + end if; + newSTATUS(STATUS_EXL) := '1'; -- at exception level + newSTATUS(STATUS_IE) := '0'; -- disable interrupts + i_update := '1'; + i_update_r := cop0reg_STATUS; + i_epc_update := '0'; + i_nullify := TRUE; -- nullify instructions in IF,RF,EX + + + when exTLBdblFaultRD | exTLBdblFaultWR | + exTLBinvalRD | exTLBinvalWR | exTLBmod => case is_exception is - when exTLBinvalIF | exTLBdblFaultIF => - ExcCode <= cop0code_TLBL; - if RF_is_delayslot = '1' then -- instr is in delay slot - i_epc_source := EPC_src_RF; -- RF_PC, re-execute branch/jump - is_delayslot <= RF_is_delayslot; - else - i_epc_source := EPC_src_PC; -- PC - is_delayslot <= '0'; - end if; when exTLBinvalRD | exTLBdblFaultRD => ExcCode <= cop0code_TLBL; - if WB_is_delayslot = '1' then -- instr is in delay slot - i_epc_source := EPC_src_WB; -- MM_PC, re-execute branch/jump - is_delayslot <= WB_is_delayslot; - else - i_epc_source := EPC_src_MM; -- EX_PC - is_delayslot <= MM_is_delayslot; - end if; when exTLBinvalWR | exTLBdblFaultWR => ExcCode <= cop0code_TLBS; - if WB_is_delayslot = '1' then -- instr is in delay slot - i_epc_source := EPC_src_WB; -- MM_PC, re-execute branch/jump - is_delayslot <= WB_is_delayslot; - else - i_epc_source := EPC_src_MM; -- EX_PC - is_delayslot <= MM_is_delayslot; - end if; when exTLBmod => ExcCode <= cop0code_Mod; - if WB_is_delayslot = '1' then -- instr is in delay slot - i_epc_source := EPC_src_WB; -- MM_PC, re-execute branch/jump - is_delayslot <= WB_is_delayslot; - else - i_epc_source := EPC_src_MM; -- EX_PC - is_delayslot <= MM_is_delayslot; - end if; when others => null; end case; + if WB_is_delayslot = '1' then -- instr is in delay slot + i_epc_source := EPC_src_WB; -- MM_PC, re-execute branch/jump + is_delayslot <= WB_is_delayslot; + else + i_epc_source := EPC_src_MM; -- EX_PC + is_delayslot <= MM_is_delayslot; + end if; newSTATUS(STATUS_EXL) := '1'; -- at exception level newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; i_nullify := TRUE; -- nullify instructions in IF,RF,EX - + + when others => -- interrupt pending? if ( (MM_nmi = '1') and (STATUS(STATUS_ERL) = '0') ) then @@ -2105,7 +2106,7 @@ begin i_stall := '0'; i_epc_update := '0'; i_nullify := TRUE; -- nullify instructions in IF,RF,EX - if EX_is_delayslot = '1' then -- instr is in delay slot + if MM_is_delayslot = '1' then -- instr is in delay slot i_epc_source := EPC_src_MM; -- re-execute branch/jump is_delayslot <= MM_is_delayslot; else @@ -2164,8 +2165,6 @@ begin variable i_excp_PCsel : reg3; begin - i_excp_PCsel := PCsel_EXC_none; -- PC <= normal processing PC - case is_exception is when exERET => -- exception return diff --git a/cMIPS/vhdl/exception.vhd b/cMIPS/vhdl/exception.vhd index 5ee2f2be4b2b4693f3f8cec7aee3a3db92f9da60..5d4ff468ba84d98a824541b5515a8e52ddd43234 100644 --- a/cMIPS/vhdl/exception.vhd +++ b/cMIPS/vhdl/exception.vhd @@ -157,8 +157,12 @@ entity reg_excp_EX_MM is EX_interrupt: in std_logic; MM_interrupt: out std_logic; EX_int_req: in reg8; - MM_int_req: out reg8); -end reg_excp_EX_MM; + MM_int_req: out reg8; + EX_is_SC: in boolean; + MM_is_SC: out boolean; + EX_is_MFC0: in boolean; + MM_is_MFC0: out boolean); + end reg_excp_EX_MM; architecture funcional of reg_excp_EX_MM is begin @@ -195,6 +199,8 @@ begin MM_nmi <= EX_nmi ; MM_interrupt <= EX_interrupt ; MM_int_req <= EX_int_req ; + MM_is_SC <= EX_is_SC ; + MM_is_MFC0 <= EX_is_MFC0 ; end if; end if; end process;