diff --git a/cMIPS/tests/overflow.expected b/cMIPS/tests/overflow.expected index 3695f814613effc47b8db5f2a6ec372122ddfff6..826ab51c7a8052ca9b7045d090233b5111c8e96d 100644 --- a/cMIPS/tests/overflow.expected +++ b/cMIPS/tests/overflow.expected @@ -1,20 +1,24 @@ -08800030 +overflow 80000000 -ffffffff +00000001 80000000 -ffffffff +00000001 00000000 -08800030 +overflow 7fffffff 7fffffff 00000000 -08800030 +overflow 80000000 + +overflow +80000000 + diff --git a/cMIPS/tests/overflow.s b/cMIPS/tests/overflow.s index 9faab0a5e14d04482568d5df54788f90da05af25..7501f4503213f85ef411b494fa34739201af6edf 100644 --- a/cMIPS/tests/overflow.s +++ b/cMIPS/tests/overflow.s @@ -2,6 +2,7 @@ .include "cMIPS.s" .text .align 2 + .set noreorder .global _start .global _exit .global exit @@ -13,8 +14,9 @@ _start: nop li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 la $k0, main - nop mtc0 $k0, cop0_EPC + li $k1, 2 + mtc0 $k1, cop0_Wired nop eret # go into user mode, all else disabled nop @@ -28,102 +30,143 @@ _exit: nop # flush pipeline nop nop .end _start - - .org x_EXCEPTION_0180,0 # exception vector_180 at 0x00000060 + + .org x_EXCEPTION_0180,0 # exception vector_180 .global _excp_180 - .global excp_180 .ent _excp_180 -excp_180: _excp_180: - mfc0 $k0, cop0_CAUSE - #sw $k0, 0($15) # print CAUSE = 0000.0030 - #sw $k0, 0($15) # print CAUSE = 0000.0030 - sw $k0, 0($15) # print CAUSE = 0000.0030 - li $k0, 0x18000302 # disable interrupts - mtc0 $k0, cop0_STATUS # and return - nop + + li $30, 'o' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'v' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'e' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'r' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'f' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'l' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'o' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'w' + sw $30, x_IO_ADDR_RANGE($15) + li $30, '\n' + sw $30, x_IO_ADDR_RANGE($15) + + li $k1, 0x18000008 # disable interrupts, go into user level + + mfc0 $k0, cop0_CAUSE # ovfl was in a delay slot? + srl $k0, $k0, 31 # YES: add 8 to EPC to skip offending add + + mtc0 $k1, cop0_STATUS + + beq $k0, $zero, plus4 + mfc0 $k1, cop0_EPC +plus8: j return + addiu $k1, $k1, 8 # fix EPC to jump over 2 instr: branch & add +plus4: addiu $k1, $k1, 4 # fix EPC to jump over offending instruction + +return: mtc0 $k1, cop0_EPC eret .end _excp_180 - .org x_ENTRY_POINT,0 # normal code starts at 0x0000.0100 -main: la $15,x_IO_BASE_ADDR - la $16,x_IO_BASE_ADDR+x_IO_ADDR_RANGE + #----------------------------------------------------------------- + .org x_ENTRY_POINT,0 # user code starts here +main: la $15, x_IO_BASE_ADDR + la $16, x_IO_BASE_ADDR+x_IO_ADDR_RANGE li $17, '\n' # signed overflow - li $3,0x7FFFFFFF # positive +s positive -> positive - li $4,0x00000001 - add $5,$3,$4 + li $3, 0x7FFFFFFF # positive +s positive -> positive + li $4, 0x00000001 + add $5, $3, $4 + nop # handler skips add on returning, otw loops sw $5, 0($15) # ===exception=== 0x8000.0000 == negative - - nop - sw $17, 0($16) + sw $17, 0($16) - # no overflow - li $6,0xFFFFFFFe # negative + positive -> no overflow - addi $7,$6,1 - sw $7, 0($15) # 0xffff.ffff == negative - + # add signed, no overflow + li $6, 0xFFFFFFFe # negative + positive -> no overflow + addi $7, $6, 3 nop - sw $17, 0($16) + sw $7, 0($15) # 0xffff.ffff == negative + sw $17, 0($16) # add unsigned, no overflow - li $3,0x7FFFFFFF # positive +u positive -> positive - li $4,0x00000001 - addu $5,$3,$4 - sw $5, 0($15) # 0x8000.0000 == unsigned positive - + li $3, 0x7FFFFFFF # positive +u positive -> positive + li $4, 0x00000001 + addu $5, $3, $4 nop - sw $17, 0($16) + sw $5, 0($15) # 0x8000.0000 == unsigned positive + sw $17, 0($16) # add unsigned, no overflow - li $6,0xFFFFFFFe # negative +u positive -> positive - addiu $7,$6,1 - sw $7, 0($15) # 0xffff.ffff == unsigned positive - + li $6, 0xFFFFFFFe # negative +u positive -> positive + addiu $7, $6, 3 nop - sw $17, 0($16) + sw $7, 0($15) # 0xffff.ffff == unsigned positive + sw $17, 0($16) - # no overflow - li $3,0xFFFFFFFF # negative +s positive -> negative - li $4,0x00000001 - add $5,$3,$4 - sw $5, 0($15) # 0x0000.0000 - + # add signed, no overflow + li $3, 0xFFFFFFFF # negative +s positive -> negative + li $4, 0x00000001 + add $5, $3, $4 nop - sw $17, 0($16) + sw $5, 0($15) # 0x0000.0000 + sw $17, 0($16) - # signed overflow - li $6,0x80000000 # negative -s negative -> negative - addi $7,$6,-1 - sw $7, 0($15) # ===exception=== 0x7fff.ffff == positive - + # add signed, overflow + li $6, 0x80000000 # negative -s negative -> negative + addi $7, $6, -1 nop - sw $17, 0($16) + sw $7, 0($15) # ===exception=== 0x7fff.ffff == positive + sw $17, 0($16) - # unsigned overflow - li $6,0x80000000 # positive -u negative -> positive - addiu $7,$6,-1 - sw $7, 0($15) # 0x7fff.ffff == positive - + # add unsigned, no overflow + li $6, 0x80000000 # positive -u negative -> positive + addiu $7, $6, -1 nop - sw $17, 0($16) + sw $7, 0($15) # 0x7fff.ffff == positive + sw $17, 0($16) # no overflow, unsigned - li $3,0xFFFFFFFF # positive +u positive -> positive - li $4,0x00000001 - addu $5,$3,$4 - sw $5, 0($15) # 0x0000.0000 ok since instr is an addU - + li $3, 0xFFFFFFFF # positive +u positive -> positive + li $4, 0x00000001 + addu $5, $3, $4 nop - sw $17, 0($16) + sw $5, 0($15) # 0x0000.0000 ok since instr is an addU + sw $17, 0($16) - # signed overflow + # add signed, overflow + li $6,0x7FFFFFFe # positive +s positive -> positive + addi $7,$6,2 + nop + sw $7, 0($15) # ===exception=== 0x8000.0000 == negative + sw $17, 0($16) + + # signed, overflow, same as last, add is on a branch delay slot li $6,0x7FFFFFFe # positive +s positive -> positive + nop # remove stall on $6 + beq $6, $zero, there addi $7,$6,2 + nop # handler will return here: EPC += 8 sw $7, 0($15) # ===exception=== 0x8000.0000 == negative + sw $17, 0($16) + j exit nop + + +there: li $30, 'e' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'r' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'r' + sw $30, x_IO_ADDR_RANGE($15) + li $30, '\n' + sw $30, x_IO_ADDR_RANGE($15) + end: j exit - \ No newline at end of file + nop diff --git a/cMIPS/tlb.sav b/cMIPS/tlb.sav new file mode 100644 index 0000000000000000000000000000000000000000..7c49bdc2d5cadc0d2e767b52c80501623f029176 --- /dev/null +++ b/cMIPS/tlb.sav @@ -0,0 +1,147 @@ +[*] +[*] GTKWave Analyzer v3.3.37 (w)1999-2012 BSI +[*] Sun May 17 11:56:41 2015 +[*] +[dumpfile] "/home/roberto/cMIPS/v_cMIPS.vcd" +[dumpfile_mtime] "Sun May 17 11:56:25 2015" +[dumpfile_size] 2177591 +[savefile] "/home/roberto/cMIPS/tlb.sav" +[timestart] 1137200000 +[size] 1213 1026 +[pos] -1 -1 +*-25.727983 1188300000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] u_core. +[treeopen] u_core.u_alu. +[sst_width] 210 +[signals_width] 213 +[sst_expanded] 1 +[sst_vpaned_height] 331 +@28 +clk +@22 +u_core.pc[31:0] +u_core.phy_i_addr[31:0] +u_core.instr_fetched[31:0] +@28 +u_core.pcsel[1:0] +u_core.excp_pcsel[2:0] +u_core.exception_stall +u_core.nullify +u_core.abort +@200 +- decode, reg fetch +@22 +u_core.rf_instruction[31:0] +@24 +u_core.a_rs[4:0] +u_core.a_rt[4:0] +u_core.a_rd[4:0] +u_core.exception_dec[31:0] +@200 +- exec +@28 +u_core.ex_wreg +@24 +u_core.u_alu.operation[31:0] +@22 +u_core.alu_inp_a[31:0] +u_core.alu_inp_b[31:0] +u_core.result[31:0] +u_core.v_addr[31:0] +@200 +- memory +@28 +u_core.mm_aval +u_core.b_sel[3:0] +@22 +u_core.data_inp[31:0] +u_core.data_out[31:0] +d_addr[31:0] +@28 +cpu_d_aval +wr +@200 +- COP-0 +@24 +u_core.exccode[4:0] +u_core.exception_num[31:0] +@22 +u_core.cause[31:0] +u_core.status[31:0] +u_core.epc[31:0] +@29 +u_core.is_delayslot +@22 +u_core.badvaddr[31:0] +u_core.context[31:0] +@200 +- +@28 +u_core.tlb_exception +@24 +u_core.tlb_excp_num[31:0] +@200 +- +@22 +u_core.tlb_entryhi[31:0] +u_core.tlb_excp_va[31:13] +@28 +u_core.tlb_read +@22 +u_core.entryhi_inp[31:0] +@28 +u_core.entryhi_update +@22 +u_core.tlb_entryhi[31:0] +u_core.entryhi[31:0] +u_core.tlb_entrylo0[31:0] +u_core.tlb_dat0_inp[25:0] +u_core.entrylo0[31:0] +u_core.tlb_entrylo1[31:0] +u_core.tlb_dat1_inp[25:0] +u_core.entrylo1[31:0] +@200 +- +@22 +u_core.index[31:0] +@28 +u_core.hit_mm_d +u_core.hit_mm_v +u_core.hit_mm +@24 +u_core.hit_mm_adr[31:0] +@28 +u_core.tlb_miss +@22 +u_core.tlb_tag0[31:0] +u_core.tlb_tag1[31:0] +u_core.tlb_tag2[31:0] +u_core.tlb_tag3[31:0] +u_core.tlb_tag4[31:0] +u_core.tlb_dat4_0[25:0] +u_core.tlb_dat4_1[25:0] +u_core.tlb_tag5[31:0] +u_core.tlb_tag6[31:0] +u_core.tlb_dat6_0[25:0] +u_core.tlb_dat6_1[25:0] +u_core.tlb_tag7[31:0] +u_core.tlb_dat7_0[25:0] +u_core.tlb_dat7_1[25:0] +@28 +u_core.hit_pc +@24 +u_core.hit_pc_adr[31:0] +@200 +- write-back +@28 +u_core.wb_wreg +@24 +u_core.wb_a_c[4:0] +@22 +u_core.wb_cop0_val[31:0] +@28 +u_core.wb_muxc[2:0] +@22 +u_core.wb_c[31:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 765149446e44ad767795dc45152dda22ec5372cb..0b9fce3079b0bfdc9751a5af5d2e6927d3c2ca0c 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -101,6 +101,8 @@ architecture rtl of core is MM_cop0_LLbit: out std_logic; addrError: in boolean; MM_abort: out boolean; + EX_is_delayslot: in std_logic; + MM_is_delayslot: out std_logic; EX_cop0_a_c: in std_logic_vector; MM_cop0_a_c: out std_logic_vector; EX_cop0_val: in std_logic_vector; @@ -117,10 +119,14 @@ architecture rtl of core is WB_can_trap: out std_logic_vector; MM_excp_type: in exception_type; WB_excp_type: out exception_type; + MM_PC: in std_logic_vector; + WB_PC: out std_logic_vector; MM_cop0_LLbit: in std_logic; WB_cop0_LLbit: out std_logic; MM_abort: in boolean; WB_abort: out boolean; + MM_is_delayslot: in std_logic; + WB_is_delayslot: out std_logic; MM_cop0_a_c: in std_logic_vector; WB_cop0_a_c: out std_logic_vector; MM_cop0_val: in std_logic_vector; @@ -137,7 +143,7 @@ architecture rtl of core is signal IF_excp_type,RF_excp_type,EX_excp_type,WB_excp_type: exception_type := exNOP; signal MM_excp_type, MM_excp_type_i, TLB_excp_type : exception_type; signal trap_instr,EX_trap_instr: instr_type; - signal RF_PC,EX_PC,MM_PC, LLaddr: reg32; + signal RF_PC,EX_PC,MM_PC,WB_PC, LLaddr: reg32; signal EX_LLbit,MM_LLbit,WB_LLbit: std_logic; signal LL_update,LL_SC_abort,LL_SC_differ,EX_trapped,MM_ex_trapped: std_logic; signal int_req, EX_int_req: reg8; @@ -158,7 +164,7 @@ architecture rtl of core is signal exception,EX_exception,is_exception : exception_type := exNOP; signal ExcCode : reg5 := cop0code_NULL; signal exception_num,exception_dec,TLB_excp_num : integer; -- for debugging only - signal next_instr_in_delay_slot,EX_is_delayslot, is_delayslot : std_logic; + signal RF_is_delayslot,EX_is_delayslot,MM_is_delayslot,WB_is_delayslot,is_delayslot : std_logic; signal cop0_sel, EX_cop0_sel, epc_source : reg3; signal cop0_reg,EX_cop0_reg : reg5; signal cop0_inp, RF_cop0_val,EX_cop0_val,MM_cop0_val,WB_cop0_val : reg32; @@ -816,10 +822,10 @@ begin is_trap <= '1' when ((funct_word.trap = '1')or(rimm_word.trap = '1')) else '0'; - next_instr_in_delay_slot <= '1' when ((ctrl_word.PCsel /= "00") or - (funct_word.PCsel /= "00") or - (rimm_word.PCsel /= "00")) - else '0'; + RF_is_delayslot <= '1' when ((ctrl_word.PCsel /= "00") or + (funct_word.PCsel /= "00") or + (rimm_word.PCsel /= "00")) + else '0'; RF_STOP_SIMULATION: process (rst, phi2, opcode, func, @@ -1353,8 +1359,8 @@ begin EX_addr <= phy_d_addr; -- with TLB - assert true or ( (phy_d_addr = v_addr) and (EX_aVal = '0') ) -- DEBUG - report "mapping mismatch V:P "& SLV32HEX(v_addr) &":"& SLV32HEX(phy_d_addr); + -- assert ( (phy_d_addr = v_addr) and (EX_aVal = '0') ) -- DEBUG + -- report "mapping mismatch V:P "& SLV32HEX(v_addr) &":"& SLV32HEX(phy_d_addr); -- ---------------------------------------------------------------------- @@ -1660,7 +1666,7 @@ begin port map (clk, rst, excp_RF_EX_ld, can_trap,EX_can_trap, exception,EX_exception, trap_instr,EX_trap_instr, cop0_reg,EX_cop0_reg, cop0_sel,EX_cop0_sel, - next_instr_in_delay_slot,EX_is_delayslot, + RF_is_delayslot,EX_is_delayslot, RF_PC_abort,EX_PC_abort, RF_PC,EX_PC, RF_nmi,EX_nmi, interrupt,EX_interrupt, int_req,EX_int_req, tr_is_equal,EX_tr_is_equal, tr_less_than,EX_tr_less_than); @@ -1668,13 +1674,10 @@ begin -- EX execute exception --------------------------------------------- - U_HOLD_DELAY_SLOT: FFD port map (clk,rst,'1',EX_is_delayslot, is_delayslot); - -- check for overflow in EX, send it to MM for later processing ex_trapped <= '1' when (EX_can_trap = b"10" and ovfl = '1') else '0'; - is_exception <= TLB_excp_type when tlb_exception else MM_excp_type when addrError else @@ -1684,11 +1687,12 @@ begin exception_num <= exception_type'pos(is_exception); -- for debugging only + -- STATUS -- pg 79 -- cop0_12 -------------------- COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS: process (EX_a_rt, is_exception, EX_trap_instr, EX_cop0_reg, EX_cop0_sel, EX_nmi, EX_interrupt,EX_int_req, - next_instr_in_delay_slot, EX_is_delayslot, is_delayslot, + RF_is_delayslot, EX_is_delayslot, MM_is_delayslot, WB_is_delayslot, cop0_inp, EX_tr_is_equal, EX_tr_less_than, INDEX, RANDOM, EntryLo0, EntryLo1, CONTEXT, PAGEMASK, WIRED, EntryHi, COUNT, COMPARE, STATUS, CAUSE, EPC, BadVAddr, @@ -1720,7 +1724,8 @@ begin trap_taken <= '0'; ExcCode <= cop0code_NULL; EX_mfc0 <= '0'; - + is_delayslot <= '0'; + newSTATUS := STATUS; -- preserve as needed newSTATUS(STATUS_BEV) := '0'; -- interrupts at offset 0x200 newSTATUS(STATUS_CU3) := '0'; -- COP-3 absent (always) @@ -1842,9 +1847,11 @@ begin i_epc_update := '0'; i_nullify := '1'; -- nullify instructions in IF,RF if EX_is_delayslot = '1' then -- instr is in delay slot - i_epc_source := b"010"; -- EX_PC, re-execute branch/jump + i_epc_source := b"010"; -- EX_PC, re-execute branch/jump + is_delayslot <= EX_is_delayslot; else - i_epc_source := b"001"; -- RF_PC + i_epc_source := b"001"; -- RF_PC + is_delayslot <= RF_is_delayslot; end if; i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_180 else @@ -1875,18 +1882,24 @@ begin ExcCode <= cop0code_Ov; i_nullify := '1'; -- nullify instructions in IF,RF nullify_EX <= '1'; -- and instruction in EX - i_epc_source := b"010"; -- bad address is in EXCP_EX_PC + if WB_is_delayslot = '1' then -- instr is in delay slot + i_epc_source := b"101"; -- WB_PC, re-execute branch/jump + is_delayslot <= WB_is_delayslot; + else + i_epc_source := b"011"; -- offending instr PC is in MM_PC + is_delayslot <= MM_is_delayslot; + end if; when IFaddressError | MMaddressErrorLD | MMaddressErrorST => - -- fetch/load/store from UNALIGNED ADDRESS + -- fetch/load/store from/to UNALIGNED ADDRESS newSTATUS(STATUS_EXL) := '1'; -- at exception level newSTATUS(STATUS_IE) := '0'; -- disable interrupts exception_taken <= '1'; i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; - i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_0180 + i_excp_PCsel := PCsel_EXC_0180; if is_exception = MMaddressErrorST then ExcCode <= cop0code_AdES; else @@ -1896,6 +1909,7 @@ begin i_nullify := '1'; -- nullify instructions in IF,RF end if; i_epc_source := b"010"; -- bad address is in EXCP_EX_PC + is_delayslot <= EX_is_delayslot; when exEHB => -- stall processor to clear hazards i_stall := '1'; @@ -1910,24 +1924,30 @@ begin case is_exception is when exTLBrefillIF => ExcCode <= cop0code_TLBL; - if next_instr_in_delay_slot = '1' then -- instr is in delay slot + if RF_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"001"; -- RF_PC, re-execute branch/jump + is_delayslot <= RF_is_delayslot; else i_epc_source := b"000"; -- PC + is_delayslot <= '0'; end if; when exTLBrefillRD => ExcCode <= cop0code_TLBL; - if is_delayslot = '1' then -- instr is in delay slot - i_epc_source := b"011"; -- EX_PC, re-execute branch/jump + if MM_is_delayslot = '1' then -- instr is in delay slot + i_epc_source := b"011"; -- MM_PC, re-execute branch/jump + is_delayslot <= MM_is_delayslot; else - i_epc_source := b"010"; -- RF_PC + i_epc_source := b"010"; -- EX_PC + is_delayslot <= EX_is_delayslot; end if; when exTLBrefillWR => ExcCode <= cop0code_TLBS; - if is_delayslot = '1' then -- instr is in delay slot + if MM_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"011"; -- EX_PC, re-execute branch/jump + is_delayslot <= MM_is_delayslot; else i_epc_source := b"010"; -- RF_PC + is_delayslot <= EX_is_delayslot; end if; when others => null; end case; @@ -1944,38 +1964,46 @@ begin case is_exception is when exTLBinvalIF | exTLBdblFaultIF => ExcCode <= cop0code_TLBL; - if next_instr_in_delay_slot = '1' then -- instr is in delay slot + if RF_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"001"; -- RF_PC, re-execute branch/jump + is_delayslot <= RF_is_delayslot; else i_epc_source := b"000"; -- PC + is_delayslot <= '0'; end if; when exTLBinvalRD | exTLBdblFaultRD => ExcCode <= cop0code_TLBL; - if is_delayslot = '1' then -- instr is in delay slot + if MM_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"011"; -- MM_PC, re-execute branch/jump + is_delayslot <= MM_is_delayslot; else i_epc_source := b"010"; -- EX_PC + is_delayslot <= EX_is_delayslot; end if; when exTLBinvalWR | exTLBdblFaultWR => ExcCode <= cop0code_TLBS; - if is_delayslot = '1' then -- instr is in delay slot + if MM_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"011"; -- MM_PC, re-execute branch/jump + is_delayslot <= MM_is_delayslot; else i_epc_source := b"010"; -- EX_PC + is_delayslot <= EX_is_delayslot; end if; when exTLBmod => ExcCode <= cop0code_Mod; - if is_delayslot = '1' then -- instr is in delay slot + if MM_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"011"; -- MM_PC, re-execute branch/jump + is_delayslot <= MM_is_delayslot; else i_epc_source := b"010"; -- EX_PC + is_delayslot <= EX_is_delayslot; end if; when others => null; end case; newSTATUS(STATUS_EXL) := '1'; -- at exception level newSTATUS(STATUS_IE) := '0'; -- disable interrupts - i_update := '1'; - i_update_r := cop0reg_STATUS; + i_update := '1'; + i_update_r := cop0reg_STATUS; i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_0180 i_epc_update := '0'; @@ -1999,8 +2027,10 @@ begin i_nullify := '1'; -- nullify instructions in IF,RF if EX_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"010"; -- EX_PC, re-execute branch/jump + is_delayslot <= EX_is_delayslot; else i_epc_source := b"001"; -- RF_PC + is_delayslot <= RF_is_delayslot; end if; i_excp_PCsel := PCsel_EXC_0000; -- PC <= exception_0000 @@ -2021,8 +2051,10 @@ begin i_nullify := '1'; -- nullify instructions in IF,RF if EX_is_delayslot = '1' then -- instr is in delay slot i_epc_source := b"010"; -- EX_PC, re-execute branch/jump + is_delayslot <= EX_is_delayslot; else i_epc_source := b"001"; -- RF_PC + is_delayslot <= RF_is_delayslot; end if; if CAUSE(CAUSE_IV) = '1' then i_excp_PCsel := PCsel_EXC_0200; -- PC <= exception_0200 @@ -2085,19 +2117,19 @@ begin COP0_STATUS: register32 generic map (RESET_STATUS) port map (clk, rst, status_update, STATUSinp, STATUS); + -- CAUSE -- pg 92-- cop0_13 -------------------------- COP0_COMPUTE_CAUSE: process(rst, update,update_reg, - EX_int_req, ExcCode, cop0_inp, - EX_is_delayslot, + EX_int_req, ExcCode, cop0_inp, is_delayslot, count_eq_compare,count_enable, CAUSE) variable newCAUSE : reg32; begin if STATUS(STATUS_EXL) = '0' then - newCAUSE(CAUSE_BD) := EX_is_delayslot; -- instr is in delay slot + newCAUSE(CAUSE_BD) := is_delayslot; -- instr is in delay slot else - newCAUSE(CAUSE_BD) := CAUSE(CAUSE_BD); -- hold it in a double fault + newCAUSE(CAUSE_BD) := CAUSE(CAUSE_BD); -- hold it on a double fault end if; newCAUSE(CAUSE_TI) := count_eq_compare; newCAUSE(CAUSE_CE1) := '0'; @@ -2155,7 +2187,8 @@ begin RF_PC when b"001", -- invalid instr exception EX_PC when b"010", -- interrupt, eret, overflow MM_PC when b"011", -- data memory exception - alu_fwd_B when others; -- b"100", -- mtc0 + alu_fwd_B when b"100", -- mtc0 + WB_PC when others; -- overflow in a branch delay slot -- (others => 'X') when others; -- invalid selection COP0_EPC: register32 generic map (x"00000000") @@ -2863,6 +2896,7 @@ begin port map (clk, rst, excp_EX_MM_ld, EX_can_trap,MM_can_trap, EX_excp_type,MM_excp_type_i, EX_PC,MM_PC, EX_LLbit,MM_LLbit, addrError,MM_abort, + EX_is_delayslot,MM_is_delayslot, EX_cop0_a_c,MM_cop0_a_c, EX_cop0_val,MM_cop0_val, EX_trapped, MM_ex_trapped, EX_mfc0,MM_mfc0); @@ -2870,8 +2904,9 @@ begin -- ---------------------------------------------------------------------- PIPESTAGE_EXCP_MM_WB: reg_excp_MM_WB port map (clk, rst, excp_MM_WB_ld, MM_can_trap,WB_can_trap, - MM_excp_type, WB_excp_type, + MM_excp_type, WB_excp_type, MM_PC,WB_PC, MM_LLbit,WB_LLbit, MM_abort,WB_abort, + MM_is_delayslot,WB_is_delayslot, MM_cop0_a_c,WB_cop0_a_c, MM_cop0_val,WB_cop0_val); diff --git a/cMIPS/vhdl/exception.vhd b/cMIPS/vhdl/exception.vhd index 86d78a7c8d2d8f3b07c1ed09d48b656bc43f2112..f8f3789f4141eb97c91c3687ea46a806753feee5 100644 --- a/cMIPS/vhdl/exception.vhd +++ b/cMIPS/vhdl/exception.vhd @@ -139,6 +139,8 @@ entity reg_excp_EX_MM is MM_cop0_LLbit: out std_logic; addrError: in boolean; MM_abort: out boolean; + EX_is_delayslot: in std_logic; + MM_is_delayslot: out std_logic; EX_cop0_a_c: in reg5; MM_cop0_a_c: out reg5; EX_cop0_val: in reg32; @@ -159,15 +161,16 @@ begin MM_ex_trapped <= '0'; elsif rising_edge(clk) then if ld = '0' then - MM_excp_type <= EX_excp_type ; - MM_can_trap <= EX_can_trap ; - MM_PC <= EX_PC ; - MM_cop0_LLbit <= EX_cop0_LLbit ; - MM_abort <= addrError ; - MM_cop0_a_c <= EX_cop0_a_c ; - MM_cop0_val <= EX_cop0_val ; - MM_ex_trapped <= EX_trapped ; - MM_mfc0 <= EX_mfc0 ; + MM_excp_type <= EX_excp_type ; + MM_can_trap <= EX_can_trap ; + MM_PC <= EX_PC ; + MM_cop0_LLbit <= EX_cop0_LLbit ; + MM_abort <= addrError ; + MM_is_delayslot <= EX_is_delayslot; + MM_cop0_a_c <= EX_cop0_a_c ; + MM_cop0_val <= EX_cop0_val ; + MM_ex_trapped <= EX_trapped ; + MM_mfc0 <= EX_mfc0 ; end if; end if; end process; @@ -188,10 +191,14 @@ entity reg_excp_MM_WB is WB_can_trap: out reg2; MM_excp_type: in exception_type; WB_excp_type: out exception_type; + MM_PC: in std_logic_vector; + WB_PC: out std_logic_vector; MM_cop0_LLbit: in std_logic; WB_cop0_LLbit: out std_logic; MM_abort: in boolean; WB_abort: out boolean; + MM_is_delayslot: in std_logic; + WB_is_delayslot: out std_logic; MM_cop0_a_c: in reg5; WB_cop0_a_c: out reg5; MM_cop0_val: in reg32; @@ -208,12 +215,14 @@ begin WB_abort <= FALSE; elsif rising_edge(clk) then if ld = '0' then - WB_excp_type <= MM_excp_type ; - WB_can_trap <= MM_can_trap ; - WB_cop0_LLbit <= MM_cop0_LLbit ; - WB_abort <= MM_abort ; - WB_cop0_a_c <= MM_cop0_a_c ; - WB_cop0_val <= MM_cop0_val ; + WB_excp_type <= MM_excp_type ; + WB_PC <= MM_PC ; + WB_can_trap <= MM_can_trap ; + WB_cop0_LLbit <= MM_cop0_LLbit ; + WB_abort <= MM_abort ; + WB_is_delayslot <= MM_is_delayslot; + WB_cop0_a_c <= MM_cop0_a_c ; + WB_cop0_val <= MM_cop0_val ; end if; end if; end process;