From 815a5e935a18d9840a01b63e75147eff60523e80 Mon Sep 17 00:00:00 2001 From: Roberto Hexsel <roberto@inf.ufpr.br> Date: Fri, 22 May 2015 10:47:45 -0300 Subject: [PATCH] fixes to trap handling --- cMIPS/tests/teq_tne.expected | 26 ++--- cMIPS/tests/teq_tne.s | 47 ++++++-- cMIPS/tests/tlt_tlti.expected | 44 ++++--- cMIPS/tests/tlt_tlti.s | 200 ++++++++++++++++++++----------- cMIPS/tests/tltu_tgeu.expected | 8 +- cMIPS/tests/tltu_tgeu.s | 68 +++++++---- cMIPS/vhdl/core.vhd | 208 ++++++++++++++++++--------------- cMIPS/vhdl/exception.vhd | 38 +++--- cMIPS/vhdl/packageMemory.vhd | 4 +- 9 files changed, 383 insertions(+), 260 deletions(-) diff --git a/cMIPS/tests/teq_tne.expected b/cMIPS/tests/teq_tne.expected index 0b8d7af..6e0ad2c 100644 --- a/cMIPS/tests/teq_tne.expected +++ b/cMIPS/tests/teq_tne.expected @@ -3,42 +3,42 @@ 00000004 00000006 00000008 -08800034 +34 00000000 00000002 00000004 00000006 00000008 -08800034 +34 00000000 00000002 00000004 00000006 00000008 -08800034 +34 00000004 -08800034 +34 00000003 -08800034 +34 00000002 -08800034 +34 00000001 -08800034 +34 0000000a 00000008 00000006 00000004 -08800034 +34 00000005 -08800034 +34 00000004 -08800034 +34 00000003 -08800034 +34 00000002 -08800034 +34 00000001 -08800034 +34 diff --git a/cMIPS/tests/teq_tne.s b/cMIPS/tests/teq_tne.s index fc58e32..47c38b4 100644 --- a/cMIPS/tests/teq_tne.s +++ b/cMIPS/tests/teq_tne.s @@ -13,10 +13,13 @@ ## _start: nop li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 - la $k0, main - mtc0 $k0, cop0_EPC - ehb - eret # go into user mode, all else disabled + + la $k0, cop0_STATUS_reset # go into user mode + addi $k0, $k0, -2 + addi $k0, $k0, 0b10000 + mtc0 $k0, cop0_STATUS + + j main nop exit: _exit: nop # flush pipeline @@ -38,9 +41,24 @@ _excp_180: ## print CAUSE, reset counter, decrement iteration control ## mfc0 $k0, cop0_CAUSE - sw $k0,0($15) # print CAUSE - li $5,0 - addiu $7,$7,-1 # decrement iteration control + andi $k1, $k0, 0x0030 + srl $k1, $k1, 4 + addi $k1, $k1, '0' + sw $k1, x_IO_ADDR_RANGE($15) + andi $k1, $k0, 0x000f # keep only exception code + addi $k1, $k1, '0' + sw $k1, x_IO_ADDR_RANGE($15) # print CAUSE.exCode + li $k1, '\n' + sw $k1, x_IO_ADDR_RANGE($15) + li $5, 0 + addiu $7, $7, -1 # decrement iteration control + + mfc0 $k1, cop0_EPC # move EPC forward to next instruction + addi $k1, $k1, 4 + mtc0 $k1, cop0_EPC # move EPC forward to next instruction + mfc0 $k0, cop0_STATUS # go back to user mode + ori $k0, $k0, 0x0010 + mtc0 $k0, cop0_STATUS excp_180ret: eret .end _excp_180 @@ -55,11 +73,16 @@ _excp_200: ## li $28,-1 sw $28, 0($15) # signal exception to std_out - sw $28, 0($15) mfc0 $k0, cop0_CAUSE + li $k1, 'e' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, 'r' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, 'r' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, '\n' + sw $k1, x_IO_ADDR_RANGE($15) sw $k0, 0($15) # print CAUSE - sw $28, 0($15) - sw $28, 0($15) eret # and return nop .end _excp_200 @@ -74,8 +97,9 @@ main: la $15, x_IO_BASE_ADDR # print out address (simulator's stdout) ## ## print sequence 2,4,6,8,cause=34, three times ## -here: sw $5, 0($15) # print out value: 3x(2,4,6,8,34) +here: sw $5, 0($15) # print out value: 3 times (0,2,4,6,8,34) addiu $5, $5, 2 # value += 2 + nop # do not cause TRAP to stall on $5 teq $5, $6 # trap if value = 10, handler does $7-- beq $7, $zero, there # if done 3 rounds, go on to next test nop @@ -127,4 +151,3 @@ then2: sw $7, 0($15) # print out values: (5,34,4,34,3,34,2,34,1,34) nop j exit nop - \ No newline at end of file diff --git a/cMIPS/tests/tlt_tlti.expected b/cMIPS/tests/tlt_tlti.expected index f7f8131..e7de610 100644 --- a/cMIPS/tests/tlt_tlti.expected +++ b/cMIPS/tests/tlt_tlti.expected @@ -1,40 +1,36 @@ 00000000 -08800034 +34 00000002 -08800034 +34 00000004 -08800034 +34 00000006 -08800034 +34 + 00000000 -00000000 -00000000 -08800034 +34 00000002 -08800034 +34 00000004 -08800034 +34 00000006 -08800034 -00000000 +34 00000000 -00000000 -0000000a -08800034 -00000008 -08800034 + 00000006 -08800034 +34 00000004 -08800034 -00000000 -00000000 +34 +00000002 +34 +00000001 + 0000000a -08800034 +34 00000008 -08800034 +34 00000006 -08800034 +34 00000004 -08800034 +34 00000000 diff --git a/cMIPS/tests/tlt_tlti.s b/cMIPS/tests/tlt_tlti.s index bb50ef9..8dc25dd 100644 --- a/cMIPS/tests/tlt_tlti.s +++ b/cMIPS/tests/tlt_tlti.s @@ -5,98 +5,166 @@ .include "cMIPS.s" .text .align 2 + .set noreorder # assembler should not reorder instructions + .global _start .global _exit .global exit - .ent _start + .global _excp_180 + .global excp_180 + .global _excp_200 + .global excp_200 ## ## reset leaves processor in kernel mode, all else disabled ## + .ent _start _start: nop li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 - la $k0, main - mtc0 $k0, cop0_EPC - eret # go into user mode, all else disabled - nop + + la $k0, cop0_STATUS_reset # go into user mode + addi $k0, $k0, -2 + addi $k0, $k0, 0b10000 + mtc0 $k0, cop0_STATUS + + j main + nop exit: -_exit: nop # flush pipeline +_exit: nop # flush pipeline nop nop nop nop - wait 0x3ff # and then stop VHDL simulation + wait # and then stop VHDL simulation nop nop .end _start + + ## + ## print CAUSE, decrement iteration control + ## .org x_EXCEPTION_0180,0 # exception vector_180 at 0x00000060 - .global _excp_180 - .global excp_180 - .global _excp_200 - .global excp_200 .ent _excp_180 -excp_180: _excp_180: -excp_200: -_excp_200: mfc0 $k0, cop0_CAUSE - sw $k0,0($15) # print CAUSE to stdout - addiu $7,$7,-1 # and decrement $7 + andi $k1, $k0, 0x0030 + srl $k1, $k1, 4 + addi $k1, $k1, '0' + sw $k1, x_IO_ADDR_RANGE($15) + andi $k1, $k0, 0x000f # keep only exception code + addi $k1, $k1, '0' + sw $k1, x_IO_ADDR_RANGE($15) # print CAUSE.exCode + li $k1, '\n' + sw $k1, x_IO_ADDR_RANGE($15) + addiu $7, $7, -1 # decrement iteration control + + mfc0 $k1, cop0_EPC # move EPC forward to next instruction + addi $k1, $k1, 4 + mtc0 $k1, cop0_EPC + mfc0 $k0, cop0_STATUS # go back into user mode + ori $k0, $k0, 0x0010 + mtc0 $k0, cop0_STATUS excp_180ret: - eret - .end _excp_180 - -# .org (end_excp_180 + 0x20),0 -# .ent _excp_200 -#excp_200: -#_excp_200: -# eret -# nop -# .end _excp_200 - - .org x_ENTRY_POINT,0 # normal code starts at 0x0000.0100 -main: la $15,x_IO_BASE_ADDR - li $7,4 - li $6,10 - li $5,0 -here: sw $5, 0($15) - addiu $5,$5,2 - tlt $5,$6 + eret + .end _excp_180 + + + ## + ## this exception should not happen + ## + .org x_EXCEPTION_0200,0 + .ent _excp_200 +_excp_200: + li $28,-1 + sw $28, 0($15) # signal exception to std_out + mfc0 $k0, cop0_CAUSE + li $k1, 'e' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, 'r' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, 'r' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, '\n' + sw $k1, x_IO_ADDR_RANGE($15) + sw $k0, 0($15) # print CAUSE + eret # and return + nop + .end _excp_200 + + + + + .org x_ENTRY_POINT,0 # normal code start +main: la $15, x_IO_BASE_ADDR # simulator's stdout + li $7, 4 # do loop 4 times + li $6, 10 # limit = 10 + li $5, 0 # value to print + + ## + ## print sequence 0,34, 2,34, 4,34, 6,cause=34 + ## +here: sw $5, 0($15) + addiu $5, $5, 2 + nop # so trap will not stall on $5 + tlt $5, $6 beq $7,$zero, there - b here - -there: sw $zero, 0($15) - sw $zero, 0($15) - li $5,0 - li $7,4 -then: sw $5, 0($15) - addiu $5,$5,2 - tlti $5,10 - bnez $7,then nop - sw $7, 0($15) + b here + nop + + ## print out '\n' to separate tests +there: li $28, '\n' + sw $28, x_IO_ADDR_RANGE($15) + + ## + ## print sequence 2,34, 4,34, 6,34, 8,cause=34, 0 + ## + li $5, 0 + li $7, 4 +then: sw $5, 0($15) + addiu $5, $5, 2 + tlti $5, 10 + bnez $7, then + nop + sw $7, 0($15) - sw $zero, 0($15) - sw $zero, 0($15) - li $5,1 - li $7,4 - li $6,10 + ## print out '\n' to separate tests + li $28, '\n' + sw $28, x_IO_ADDR_RANGE($15) + + ## + ## print sequence 6,34, 4,34, 2,34, 1 + ## + li $5, 1 + li $7, 4 + li $6, 6 here2: sw $6, 0($15) - tge $6,$5 - addiu $6,$6,-2 - beq $7,$zero, there2 - b here2 - -there2: sw $zero, 0($15) - sw $zero, 0($15) - li $6,10 - li $7,4 -then2: sw $6, 0($15) - tgei $6,1 - addiu $6,$6,-2 - bnez $7,then2 + tge $6, $5 + addiu $6, $6, -2 + beq $6, $zero, there2 nop - sw $7, 0($15) - j exit + b here2 + nop + +there2: sw $7, 0($15) # trapped 3 times: 4-3=1 + ## print out '\n' to separate tests + li $28, '\n' + sw $28, x_IO_ADDR_RANGE($15) + + ## + ## print sequence a,34, 8,34, 6,34, 4,cause=34 + ## + li $6, 10 + li $7, 4 +then2: sw $6, 0($15) + nop + tgei $6, 1 + addiu $6, $6, -2 + bnez $7, then2 + nop + + sw $7, 0($15) + j exit + nop diff --git a/cMIPS/tests/tltu_tgeu.expected b/cMIPS/tests/tltu_tgeu.expected index 3dca4c4..200a1b4 100644 --- a/cMIPS/tests/tltu_tgeu.expected +++ b/cMIPS/tests/tltu_tgeu.expected @@ -5,16 +5,16 @@ 00000004 -08800034 +34 00000003 -08800034 +34 00000002 -08800034 +34 00000001 -08800034 +34 00000000 00000000 diff --git a/cMIPS/tests/tltu_tgeu.s b/cMIPS/tests/tltu_tgeu.s index 3fbde78..88f6031 100644 --- a/cMIPS/tests/tltu_tgeu.s +++ b/cMIPS/tests/tltu_tgeu.s @@ -16,12 +16,13 @@ ## _start: nop li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 - la $k0, main - mtc0 $k0, cop0_EPC - nop - nop - nop - eret # go into user mode, all else disabled + + la $k0, cop0_STATUS_reset # go into user mode + addi $k0, $k0, -2 + addi $k0, $k0, 0b10000 + mtc0 $k0, cop0_STATUS + + j main nop exit: @@ -37,15 +38,32 @@ _exit: nop # flush pipeline .org x_EXCEPTION_0180,0 # exception vector_180 .ent _excp_180 -excp_180: + ## + ## print CAUSE, reset counter, decrement iteration control + ## _excp_180: mfc0 $k0, cop0_CAUSE - addiu $7,$7,-1 # decrement iteration control - sw $k0,0($15) # print CAUSE - #li $k0, 0x18000000 # disable interrupts - #mtc0 $k0, cop0_STATUS - eret - .end _excp_180 + andi $k1, $k0, 0x0030 + srl $k1, $k1, 4 + addi $k1, $k1, '0' + sw $k1, x_IO_ADDR_RANGE($15) + andi $k1, $k0, 0x000f # keep only exception code + addi $k1, $k1, '0' + sw $k1, x_IO_ADDR_RANGE($15) # print CAUSE.exCode + li $k1, '\n' + sw $k1, x_IO_ADDR_RANGE($15) + li $5, 0 + addiu $7, $7, -1 # decrement iteration control + + mfc0 $k1, cop0_EPC # move EPC forward to next instruction + addi $k1, $k1, 4 + mtc0 $k1, cop0_EPC + mfc0 $k0, cop0_STATUS # go back into user mode + ori $k0, $k0, 0x0010 + mtc0 $k0, cop0_STATUS +excp_180ret: + eret + .end _excp_180 .org x_EXCEPTION_0200,0 # exception vector_200 @@ -55,19 +73,23 @@ _excp_200: ## ## this exception should not happen ## - li $28,'\n' - sw $28, x_IO_ADDR_RANGE($15) # signal exception to std_out - sw $28, x_IO_ADDR_RANGE($15) # print two \n - mfc0 $k0, cop0_CAUSE - sw $k0,0($15) # print CAUSE - sw $28, x_IO_ADDR_RANGE($15) - sw $28, x_IO_ADDR_RANGE($15) - eret # and return + mfc0 $k0, cop0_CAUSE # signal exception to std_out + li $k1, 'e' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, 'r' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, 'r' + sw $k1, x_IO_ADDR_RANGE($15) + li $k1, '\n' + sw $k1, x_IO_ADDR_RANGE($15) + sw $k0, 0($15) # print CAUSE + eret # and return .end _excp_200 - .org x_ENTRY_POINT,0 # normal code -main: la $15,x_IO_BASE_ADDR + + .org x_ENTRY_POINT,0 # normal code +main: la $15,x_IO_BASE_ADDR # simulator's stdout la $18, 0x80000000 # signed largest negative la $19, 0x80000001 # signed largest negative but one diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 3113e47..750ebf0 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -85,10 +85,8 @@ architecture rtl of core is EX_interrupt: out std_logic; RF_int_req: in std_logic_vector; EX_int_req: out std_logic_vector; - RF_tr_is_equal: in std_logic; - EX_tr_is_equal: out std_logic; - RF_tr_less_than: in std_logic; - EX_tr_less_than: out std_logic); + RF_trap_taken: in boolean; + EX_trapped: out boolean); end component reg_excp_RF_EX; component reg_excp_EX_MM is @@ -109,8 +107,8 @@ architecture rtl of core is MM_cop0_a_c: out std_logic_vector; EX_cop0_val: in std_logic_vector; MM_cop0_val: out std_logic_vector; - EX_trapped: in std_logic; - MM_ex_trapped: out std_logic; + EX_ovfl: in boolean; + MM_ex_ovfl: out boolean; EX_mfc0: in std_logic; MM_mfc0: out std_logic); end component reg_excp_EX_MM; @@ -138,22 +136,23 @@ architecture rtl of core is signal i_addr_error : std_logic; signal interrupt,EX_interrupt, exception_stall : std_logic; - signal exception_taken, interrupt_taken, trap_taken : std_logic; + signal exception_taken, interrupt_taken : std_logic; signal nullify, nullify_EX, abort : std_logic; - signal addrError, MM_abort, WB_abort : boolean; + signal addrError, MM_abort, WB_abort: boolean; signal PC_abort, RF_PC_abort, EX_PC_abort : boolean; 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,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 LL_update,LL_SC_abort,LL_SC_differ: std_logic; + signal EX_trapped, EX_ovfl,MM_ex_ovfl, trap_taken: boolean; signal int_req, EX_int_req: reg8; signal RF_nmi,EX_nmi : std_logic; signal EX_mfc0, MM_mfc0 : std_logic; signal can_trap,EX_can_trap,MM_can_trap,WB_can_trap: reg2; signal is_trap, tr_signed, tr_stall: std_logic; - signal tr_is_equal,EX_tr_is_equal, tr_less_than,EX_tr_less_than: std_logic; + signal tr_is_equal, tr_less_than: std_logic; signal tr_fwd_A, tr_fwd_B, tr_result : reg32; signal excp_IF_RF_ld,excp_RF_EX_ld,excp_EX_MM_ld,excp_MM_WB_ld: std_logic; signal update, not_stalled: std_logic; @@ -165,7 +164,7 @@ architecture rtl of core is signal count_eq_compare,count_update,count_enable : std_logic; 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 exception_num,exception_dec,TLB_excp_num,trap_dec: integer; -- debugging 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; @@ -599,13 +598,13 @@ architecture rtl of core is (NIL, '1','0',opNOP, "001",'0','0','0',"00","00"), --45 (NIL, '1','0',opNOP, "001",'0','0','0',"00","00"), --46 (NIL, '1','0',opNOP, "001",'0','0','0',"00","00"), --47 - (TGE, '1','0',trGEQ, "001",'1','0','0',"00","01"), --tge=48 - (TGEU, '1','0',trGEU, "001",'1','0','0',"00","01"), --tgeu=49 - (TLT, '1','0',trLTH, "001",'1','0','0',"00","01"), --tlt=50 - (TLTU, '1','0',trLTU, "001",'1','0','0',"00","01"), --tltu=51 - (TEQ, '1','0',trEQU, "001",'1','0','0',"00","01"), --teq=52 + (TGE, '1','0',trGEQ, "001",'1','0','0',"00","10"), --tge=48 + (TGEU, '1','0',trGEU, "001",'1','0','0',"00","10"), --tgeu=49 + (TLT, '1','0',trLTH, "001",'1','0','0',"00","10"), --tlt=50 + (TLTU, '1','0',trLTU, "001",'1','0','0',"00","10"), --tltu=51 + (TEQ, '1','0',trEQU, "001",'1','0','0',"00","10"), --teq=52 (NIL, '1','0',opNOP, "001",'0','0','0',"00","00"), --53 - (TNE, '1','0',trNEQ, "001",'1','0','0',"00","01"), --tne=54 + (TNE, '1','0',trNEQ, "001",'1','0','0',"00","10"), --tne=54 (NIL, '1','0',opNOP, "001",'0','0','0',"00","00"), --55 (NIL, '1','0',opNOP, "001",'0','0','0',"00","00"), --56 (NIL, '1','0',opNOP, "001",'0','0','0',"00","00"), --57 @@ -1080,7 +1079,7 @@ begin if RF_instruction = x"000000c0" then i_exception := exEHB; end if; - when others => i_exception := exTRAP; + when others => i_exception := exNOP; end case; end if; @@ -1094,7 +1093,7 @@ begin i_oper := opNOP; -- no ALU operation if (rimm_word.trap = '1') then -- traps - i_exception := exTRAP; + i_exception := exNOP; end if; when b"010000" => -- COP-0 @@ -1606,18 +1605,7 @@ begin interrupt <= int_req(7) or int_req(6) or int_req(5) or int_req(4) or int_req(3) or int_req(2) or int_req(1) or int_req(0); - tr_signed <= '0' when ((funct_word.trap = '1' and - ((funct_word.oper = trGEU)or(funct_word.oper = trLTU))) - or - (rimm_word.trap = '1' and - ((rimm_word.br_t = tGEU)or(rimm_word.br_t = tLTU)))) - else '1'; - - tr_is_equal <= '1' when (tr_fwd_A = tr_fwd_B) else '0'; - - U_COMP_TRAP: subtr32 - port map (tr_fwd_A, tr_fwd_B, tr_result, tr_signed, open, tr_less_than); - + RF_FORWARDING_TRAPS: process (a_rs,a_rt,rimm_word,displ32, EX_wreg,EX_a_c,MM_wreg,MM_a_c, @@ -1662,7 +1650,39 @@ begin end if; end process RF_FORWARDING_TRAPS; + tr_signed <= '0' when ((funct_word.trap = '1' and + ((funct_word.oper = trGEU)or(funct_word.oper = trLTU))) + or + (rimm_word.trap = '1' and + ((rimm_word.br_t = tGEU)or(rimm_word.br_t = tLTU)))) + else '1'; + + tr_is_equal <= '1' when (tr_fwd_A = tr_fwd_B) else '0'; + + U_COMP_TRAP: subtr32 + port map (tr_fwd_A, tr_fwd_B, tr_result, tr_signed, open, tr_less_than); + + trap_dec <= instr_type'pos(trap_instr); -- debugging only + + RF_EVALUATE_TRAPS: process (trap_instr, tr_is_equal, tr_less_than) + variable i_take_trap : boolean; + begin + case trap_instr is + when TEQ | TEQI => + i_take_trap := tr_is_equal = '1'; + when TNE | TNEI => + i_take_trap := tr_is_equal = '0'; + when TLT | TLTI | TLTU | TLTIU => + i_take_trap := tr_less_than = '1'; + when TGE | TGEI | TGEU | TGEIU => + i_take_trap := tr_less_than = '0'; + when others => + i_take_trap := FALSE; + end case; + 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, can_trap,EX_can_trap, @@ -1671,20 +1691,21 @@ begin 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); + trap_taken,EX_trapped); -- EX execute exception --------------------------------------------- - + -- 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'; + EX_ovfl <= (EX_can_trap = b"10" and ovfl = '1'); - is_exception <= TLB_excp_type when tlb_exception else - MM_excp_type when addrError else - exOvfl when MM_ex_trapped = '1' else - IFaddressError when EX_PC_abort else + is_exception <= TLB_excp_type when tlb_exception else + MM_excp_type when addrError else + exTrap when Ex_trapped else + exOvfl when MM_ex_ovfl else + IFaddressError when EX_PC_abort else EX_exception; exception_num <= exception_type'pos(is_exception); -- for debugging only @@ -1692,16 +1713,15 @@ begin -- STATUS -- pg 79 -- cop0_12 -------------------- COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS: - process (EX_a_rt, is_exception, EX_trap_instr, + process (EX_a_rt, is_exception, cop0_inp, EX_cop0_reg, EX_cop0_sel, EX_nmi, EX_interrupt,EX_int_req, 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, rom_stall,ram_stall) variable newSTATUS, i_COP0_rd : reg32; - variable i_update,i_epc_update,i_stall,i_nullify,i_take_trap : std_logic; + variable i_update,i_epc_update,i_stall,i_nullify : std_logic; variable i_a_c,i_update_r : reg5; variable i_epc_source : reg3; @@ -1716,12 +1736,11 @@ begin i_COP0_rd := x"00000000"; i_stall := '0'; i_nullify := '0'; - i_take_trap := '0'; + nullify_EX <= '0'; exception_taken <= '0'; -- for debugging only interrupt_taken <= '0'; - trap_taken <= '0'; ExcCode <= cop0code_NULL; EX_mfc0 <= '0'; is_delayslot <= '0'; @@ -1802,7 +1821,7 @@ begin i_stall := '0'; EX_mfc0 <= '1'; - when exERET => -- exception return + when exERET => -- EXCEPTION RETURN newSTATUS(STATUS_EXL) := '0'; -- leave exception level i_update := '1'; i_update_r := cop0reg_STATUS; @@ -1810,57 +1829,54 @@ begin i_nullify := '1'; -- nullify instructions in IF,RF - when exTRAP | exSYSCALL | exBREAK => -- trap instruction + when exSYSCALL | exBREAK => -- SYSCALL, BREAK i_stall := '0'; - case EX_trap_instr is - when TEQ | TEQI => - i_take_trap := EX_tr_is_equal; - when TNE | TNEI => - i_take_trap := not(EX_tr_is_equal); - when TLT | TLTI | TLTU | TLTIU => - i_take_trap := EX_tr_less_than; - when TGE | TGEI | TGEU | TGEIU => - i_take_trap := not(EX_tr_less_than); - when SYSCALL => - i_take_trap := '1'; - when BREAK => - i_take_trap := '1'; - when others => - i_take_trap := '0'; - end case; - if i_take_trap = '1' then - trap_taken <= '1'; - case EX_trap_instr is - when TEQ | TEQI | TNE | TNEI | TLT | TLTI | TLTU | TLTIU | - TGE | TGEI | TGEU | TGEIU => ExcCode <= cop0code_Tr; - when SYSCALL => ExcCode <= cop0code_Sys; - when BREAK => ExcCode <= cop0code_Bp; - when others => null; - end case; - newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_UM) := '0'; -- enter kernel mode - newSTATUS(STATUS_IE) := '0'; -- disable interrupts - i_update := '1'; - i_update_r := cop0reg_STATUS; - i_stall := '0'; - 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 := EPC_src_EX; -- EX_PC, re-execute branch/jump - is_delayslot <= EX_is_delayslot; - else - i_epc_source := EPC_src_RF; -- RF_PC - is_delayslot <= RF_is_delayslot; - end if; + if is_exception = exSYSCALL then + ExcCode <= cop0code_Sys; + else + ExcCode <= cop0code_Bp; + end if; + newSTATUS(STATUS_EXL) := '1'; -- at exception level + newSTATUS(STATUS_UM) := '0'; -- enter kernel mode + newSTATUS(STATUS_IE) := '0'; -- disable interrupts + i_update := '1'; + i_update_r := cop0reg_STATUS; + i_stall := '0'; -- do not stall + 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 := EPC_src_EX; -- EX_PC, re-execute branch/jump + is_delayslot <= EX_is_delayslot; else - trap_taken <= '0'; + i_epc_source := EPC_src_RF; -- RF_PC + is_delayslot <= RF_is_delayslot; end if; + + when exTRAP => -- TRAP detected one cycle earlier + ExcCode <= cop0code_Tr; + newSTATUS(STATUS_EXL) := '1'; -- at exception level + newSTATUS(STATUS_UM) := '0'; -- enter kernel mode + newSTATUS(STATUS_IE) := '0'; -- disable interrupts + i_update := '1'; + i_update_r := cop0reg_STATUS; + i_stall := '0'; + 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 := EPC_src_MM; -- EX_PC, re-execute branch/jump + is_delayslot <= EX_is_delayslot; + else + i_epc_source := EPC_src_EX; -- RF_PC + is_delayslot <= RF_is_delayslot; + end if; + + when exLL => -- load linked (not a real exception) i_update := '1'; i_update_r := cop0reg_LLaddr; - -- when exSC => null; if treated here, SC might delay an interrupt + -- when exSC => null; if treated here, SC might delay an interrupt when exRESV_INSTR => -- reserved instruction ABORT SIMULATION @@ -2075,7 +2091,7 @@ begin -- Select input to PC on an exception -------------------- COP0_SEL_EPC: process (is_exception, EX_nmi, EX_interrupt, STATUS, CAUSE, - trap_taken, rom_stall, ram_stall) + EX_trapped, rom_stall, ram_stall) variable i_excp_PCsel : reg3; begin @@ -2092,12 +2108,12 @@ begin | exTLBinvalIF | exTLBinvalRD | exTLBinvalWR | exTLBmod => i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_180 - when exTRAP => - if trap_taken = '1' then - i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_180 - else - i_excp_PCsel := PCsel_EXC_none; - end if; + when exTRAP => + if EX_trapped then + i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_180 + else + i_excp_PCsel := PCsel_EXC_none; + end if; when exTLBrefillIF | exTLBrefillRD | exTLBrefillWR => i_excp_PCsel := PCsel_EXC_0000; -- PC <= exception_0000 @@ -2119,7 +2135,7 @@ begin end if; else i_excp_PCsel := PCsel_EXC_none; -- should never get here - end if; -- NMI or else interrupt + end if; -- NMI or interrupt end case; @@ -2942,7 +2958,7 @@ begin 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); + EX_ovfl, MM_ex_ovfl, EX_mfc0,MM_mfc0); -- ---------------------------------------------------------------------- diff --git a/cMIPS/vhdl/exception.vhd b/cMIPS/vhdl/exception.vhd index f8f3789..6cf8343 100644 --- a/cMIPS/vhdl/exception.vhd +++ b/cMIPS/vhdl/exception.vhd @@ -85,10 +85,8 @@ entity reg_excp_RF_EX is EX_interrupt: out std_logic; RF_int_req: in reg8; EX_int_req: out reg8; - RF_tr_is_equal: in std_logic; - EX_tr_is_equal: out std_logic; - RF_tr_less_than: in std_logic; - EX_tr_less_than: out std_logic); + RF_trap_taken: in boolean; + EX_trapped: out boolean); end reg_excp_RF_EX; architecture funcional of reg_excp_RF_EX is @@ -98,6 +96,7 @@ begin if rst = '0' then EX_can_trap <= b"00"; EX_is_delayslot <= '0'; + EX_trapped <= FALSE; elsif rising_edge(clk) then if ld = '0' then EX_can_trap <= RF_can_trap ; @@ -111,8 +110,7 @@ begin EX_nmi <= RF_nmi ; EX_interrupt <= RF_interrupt ; EX_int_req <= RF_int_req ; - EX_tr_is_equal <= RF_tr_is_equal ; - EX_tr_less_than <= RF_tr_less_than ; + EX_trapped <= RF_trap_taken ; end if; end if; end process; @@ -145,8 +143,8 @@ entity reg_excp_EX_MM is MM_cop0_a_c: out reg5; EX_cop0_val: in reg32; MM_cop0_val: out reg32; - EX_trapped: in std_logic; - MM_ex_trapped: out std_logic; + EX_ovfl: in boolean; + MM_ex_ovfl: out boolean; EX_mfc0: in std_logic; MM_mfc0: out std_logic); end reg_excp_EX_MM; @@ -158,19 +156,19 @@ begin if rst = '0' then MM_can_trap <= b"00"; MM_cop0_LLbit <= '0'; - MM_ex_trapped <= '0'; + MM_ex_ovfl <= FALSE; 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_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 ; + MM_cop0_a_c <= EX_cop0_a_c ; + MM_cop0_val <= EX_cop0_val ; + MM_ex_ovfl <= EX_ovfl ; + MM_mfc0 <= EX_mfc0 ; end if; end if; end process; @@ -191,8 +189,8 @@ 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_PC: in reg32; + WB_PC: out reg32; MM_cop0_LLbit: in std_logic; WB_cop0_LLbit: out std_logic; MM_abort: in boolean; diff --git a/cMIPS/vhdl/packageMemory.vhd b/cMIPS/vhdl/packageMemory.vhd index d8143e4..f1fc694 100644 --- a/cMIPS/vhdl/packageMemory.vhd +++ b/cMIPS/vhdl/packageMemory.vhd @@ -29,9 +29,9 @@ package p_MEMORY is -- which means having an adder in the critical path. Not good. -- The address ranges for ROM, RAM and I/O must be distinct in the - -- uppermost 12 bits of the address (bits 31..20). + -- uppermost 12 bits of the address (bits 31..16). constant HI_SEL_BITS : integer := 31; - constant LO_SEL_BITS : integer := 20; + constant LO_SEL_BITS : integer := 16; -- x_IO_ADDR_RANGE can have only ONE bit set, thus being a power of 2. -- GitLab