diff --git a/cMIPS/docs/cMIPS.pdf b/cMIPS/docs/cMIPS.pdf index 3924fd64071144d8f56e7a032b2242fbf0544998..86f57878f3b57c5420e6714db6763ca5b637cc4b 100644 Binary files a/cMIPS/docs/cMIPS.pdf and b/cMIPS/docs/cMIPS.pdf differ diff --git a/cMIPS/include/handlers.s b/cMIPS/include/handlers.s index 99241605e6fef8ae3d1a73d89dce0bb60aeb51e3..27fb96946ac36adf6e6171cf56612fe9f5740bb1 100644 --- a/cMIPS/include/handlers.s +++ b/cMIPS/include/handlers.s @@ -12,6 +12,7 @@ .bss .align 2 + .set noreorder .global _counter_val # accumulate number of interrupts .comm _counter_val 4 .comm _counter_saves 8*4 # area to save up to 8 registers @@ -31,9 +32,10 @@ extCounter: #---------------------------------- # save additional registers - # la $k1, _counter_saves - # sw $a0, 0*4($k1) - # sw $a1, 1*4($k1) + # lui $k1, %hi(_counter_saves) + # ori $k1, $k1, %lo(_counter_saves) + # sw $a0, 0*4($k1) + # sw $a1, 1*4($k1) #---------------------------------- lui $k1, %hi(HW_counter_value) @@ -48,10 +50,11 @@ extCounter: sw $k1,0($k0) #---------------------------------- - # and then restore same registers - # la $k1, _counter_saves - # lw $a0, 0*4($k1) - # lw $a1, 1*4($k1) + # and then restore those same registers + # lui $k1, %hi(_counter_saves) + # ori $k1, $k1, %lo(_counter_saves) + # lw $a0, 0*4($k1) + # lw $a1, 1*4($k1) #---------------------------------- mfc0 $k0, cop0_STATUS # Read STATUS register @@ -68,7 +71,8 @@ extCounter: # interrupt handler for UART attached to IP6=HW4 .bss - .align 2 + .align 2 + .set noreorder .global rx_queue,rx_hd,rx_tl # reception queue and pointers .comm rx_queue 16 .comm rx_hd 4 @@ -201,4 +205,3 @@ cmips_delay: nop .end cmips_delay #---------------------------------------------------------------- - diff --git a/cMIPS/tests/extCounter.c b/cMIPS/tests/extCounter.c index 1b4e373733c82fb2ec59023e59b280e0786bf737..75a0b628bf73151a16f471763ae83c66e2290045 100644 --- a/cMIPS/tests/extCounter.c +++ b/cMIPS/tests/extCounter.c @@ -14,13 +14,12 @@ void main(void) { int i, increased, new, old, newValue; newValue = CNT_VALUE; - startCounter(newValue, 0); // no interrupts for (i=0; i < N; i++) { // repeat N rounds print(i); // print number of round newValue = CNT_VALUE + (i<<3); - startCounter(newValue, 0); // num cycles increases with i + startCounter(newValue, 0); // num cycles increases with i, no interrupts increased = TRUE; old = 0; diff --git a/cMIPS/tests/teq_tne.expected b/cMIPS/tests/teq_tne.expected index 0b8d7af318c61f72b91c6ed28faa3fecbb02450c..6e0ad2ce9f67180098fc15e2fc4a36a4d0a7b388 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 fc58e3270efa53eb34c87c47faae00752caf0e20..47c38b45505025618a8276f428386423064e1754 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 f7f8131e40f14b8f221b642fd9c3078b5a27f3cb..e7de610e1808bbae7dcbb3a804e6e6221116249e 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 bb50ef997ce79e22d40fa9630978d9dd9a4e3eea..8dc25ddc2e7e963665a074751c06fcec3e0a2a89 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 3dca4c48cb922c0689b5f1a0489ba4b1b6371e57..200a1b4a7b9eb9b73e30ac221698eb5af9573f5d 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 3fbde78534021eb51613f1e4bcf929919f6e1631..88f6031eb9f31f86f74164daa60c0ea6887fa045 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/tests/uarttx.c b/cMIPS/tests/uarttx.c index 36a44e98adb9348ec84987ea05887b4a70c77d12..ba59e25fd1b4b029b8db2c2ab452b49fce295f48 100644 --- a/cMIPS/tests/uarttx.c +++ b/cMIPS/tests/uarttx.c @@ -44,7 +44,7 @@ typedef struct serial { #define LONG_STRING 1 #if LONG_STRING -char *dog = "\n\tthe quick brown fox jumps over the lazy dog\n"; +char *dog = "\tthe quick brown fox jumps over the lazy dog"; char s[32]; #else char s[32]; // = "123"; diff --git a/cMIPS/tests/uarttx.expected b/cMIPS/tests/uarttx.expected index 55747baac2bce6b6340fa2ffd40bfe2386392a75..50c330a807644d3c27c8afd026624b13efdf144a 100644 Binary files a/cMIPS/tests/uarttx.expected and b/cMIPS/tests/uarttx.expected differ diff --git a/cMIPS/vhdl/altera.vhd b/cMIPS/vhdl/altera.vhd index 38bdea44cfe7f2ca8abe31669dbd09e199745e07..928586d3ef9903a81e01e13430d7c6da7df7fbde 100644 --- a/cMIPS/vhdl/altera.vhd +++ b/cMIPS/vhdl/altera.vhd @@ -183,7 +183,7 @@ entity mf_altpll is port ( areset : IN STD_LOGIC; inclk0 : IN STD_LOGIC; -- 50MHz input c0 : OUT STD_LOGIC; -- 50MHz, 25% duty cycle, phase 0 - c1 : OUT STD_LOGIC; -- 50MHz, 25% duty cycle, phase 225 + c1 : OUT STD_LOGIC; -- 50MHz, 25% duty cycle, phase 120 c2 : OUT STD_LOGIC; -- 50MHz, 25% duty cycle, phase 180 c3 : OUT STD_LOGIC; -- 50MHz, 25% duty cycle, phase 270 c4 : OUT STD_LOGIC); -- 50MHz, 50% duty cycle, phase 0 @@ -215,12 +215,12 @@ begin U_4PHASE_CLOCK: count4phases port map (clk4x, areset, phi0,phi1,phi2,phi3); - U_DELAY_PHI2: FFD port map (clk4x, areset, '1', phi2, phi2_dlyd); + -- U_DELAY_PHI2: FFD port map (clk4x, areset, '1', phi2, phi2_dlyd); - c0 <= phi0; - c1 <= phi2_dlyd; + c0 <= phi3; + c1 <= phi0; c2 <= phi1; - c3 <= phi3; + c3 <= phi2; c4 <= inclk0; end architecture functional; diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 4bc95f977f98d535fe076dc0a9cb9cb4dfe68e82..750ebf0c9fb503c2250f7d2d1c443789fc4fed41 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -30,7 +30,9 @@ entity core is port ( rst : in std_logic; clk : in std_logic; + phi1 : in std_logic; phi2 : in std_logic; + phi3 : in std_logic; i_aVal : out std_logic; i_wait : in std_logic; i_addr : out std_logic_vector; @@ -83,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 @@ -107,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; @@ -136,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; @@ -163,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; @@ -597,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 @@ -781,9 +782,8 @@ begin -- uncomment this when making use of the TLB i_addr <= phy_i_addr; - instr_fetched <= instr when (nullify = '0' and abort = '0' - and PC(1 downto 0) = b"00") else - NULL_INSTRUCTION; -- x"fc000000"; + instr_fetched <= instr when (nullify = '0' and abort = '0' and not(PC_abort)) + else NULL_INSTRUCTION; -- x"fc000000"; PIPESTAGE_IF_RF: reg_IF_RF @@ -878,8 +878,8 @@ begin move <= funct_word.move when opcode = b"000000" else '0'; - U_regs: reg_bank - port map (clk, phi2, WB_wreg, a_rs,a_rt, WB_a_c,WB_C, regs_A,regs_B); + U_regs: reg_bank -- phi1=read_early, clk=write_late + port map (clk, phi1, WB_wreg, a_rs,a_rt, WB_a_c,WB_C, regs_A,regs_B); -- U_PC_plus_8: adder32 port map (x"00000004", RF_PCincd, pc_p8); -- (PC+4)+4 @@ -930,7 +930,8 @@ begin RF_FORWARDING_BRANCH: process (a_rs,a_rt,EX_wreg,EX_a_c,MM_wreg,MM_a_c, - MM_aVal,MM_result,regs_A,regs_B,is_branch) + MM_aVal,MM_result,MM_mfc0,MM_cop0_val, + regs_A,regs_B,is_branch) begin br_stall <= '0'; @@ -938,41 +939,41 @@ begin (EX_wreg = '0') and (EX_a_c = a_rs) and (EX_a_c /= b"00000") ) then br_stall <= '1'; eq_fwd_A <= regs_A; - elsif ((MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000") - and (MM_aVal = '0')) then -- LW load-delay slot - if (is_branch = '1') then - br_stall <= '1'; - end if; - elsif ((MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000") - and (MM_aVal = '1')) then -- non-LW - if MM_mfc0 /= '1' then - eq_fwd_A <= MM_result; - else - eq_fwd_A <= MM_cop0_val; + elsif ((MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000")) then + if (MM_aVal = '0') then -- LW load-delay slot + if (is_branch = '1') then + br_stall <= '1'; + end if; + eq_fwd_A <= regs_A; + else -- non-LW + if MM_mfc0 /= '1' then + eq_fwd_A <= MM_result; + else + eq_fwd_A <= MM_cop0_val; + end if; end if; - -- eq_fwd_A <= MM_result; else eq_fwd_A <= regs_A; end if; + if ( (is_branch = '1') and -- forward_B: (EX_wreg = '0') and (EX_a_c = a_rt) and (EX_a_c /= b"00000") ) then br_stall <= '1'; eq_fwd_B <= regs_B; - elsif ((MM_wreg = '0') and (MM_a_c = a_rt) and (MM_a_c /= b"00000") - and (MM_aVal = '0')) then -- LW load-delay slot - if (is_branch = '1') then - br_stall <= '1'; - end if; - eq_fwd_B <= regs_B; - elsif ((MM_wreg = '0') and (MM_a_c = a_rt) and (MM_a_c /= b"00000") - and (MM_aVal = '1')) then -- non-LW - if MM_mfc0 /= '1' then - eq_fwd_B <= MM_result; - else - eq_fwd_B <= MM_cop0_val; + elsif ((MM_wreg = '0') and (MM_a_c = a_rt) and (MM_a_c /= b"00000")) then + if (MM_aVal = '0') then -- LW load-delay slot + if (is_branch = '1') then + br_stall <= '1'; + end if; + eq_fwd_B <= regs_B; + else -- non-LW + if MM_mfc0 /= '1' then + eq_fwd_B <= MM_result; + else + eq_fwd_B <= MM_cop0_val; + end if; end if; - -- eq_fwd_B <= MM_result; else eq_fwd_B <= regs_B; end if; @@ -1043,7 +1044,7 @@ begin RF_DECODE_FUNCT: process (opcode,IF_RF_ld,ctrl_word,funct_word,rimm_word, func,shamt, a_rs,a_rd, STATUS, addrError, - RF_excp_type,MM_excp_type) + RF_excp_type,RF_instruction,MM_excp_type) variable i_wreg : std_logic; variable i_csel : reg2; variable i_oper : t_alu_fun := opNOP; @@ -1078,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; @@ -1092,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 @@ -1242,6 +1243,7 @@ begin EX_FORWARDING_ALU: process (EX_a_rs,EX_a_rt,EX_a_c, MM_a_c,MM_wreg,WB_a_c,WB_wreg, + MM_mfc0,MM_cop0_val, EX_A,EX_B,MM_result,WB_C) variable i_A,i_B : reg32; begin @@ -1297,7 +1299,6 @@ begin or abort; -- abort ref if exception in MEM abort <= '1' when (addrError or (tlb_exception and tlb_stage_mm)) else '0'; - -- abort <= '1' when (addrError) else '0'; -- this adder performs address calculation so the TLB can be checked during @@ -1485,11 +1486,11 @@ begin -- forwarding for LWL, LWR - MM_FWD_LWLR: process (MM_aVal,MM_wreg_cond,MM_a_rt,WB_a_c,WB_wreg,WB_C,MM_B) + MM_FWD_LWLR: process (MM_aVal,MM_wreg,MM_a_rt,WB_a_c,WB_wreg,WB_C,MM_B) variable f_m: std_logic; variable i_data : reg32; begin - FORWARD_M: if ( (MM_wreg_cond = '0') and (MM_aVal = '0') and + FORWARD_M: if ( (MM_wreg = '0') and (MM_aVal = '0') and (MM_a_rt = WB_a_c) and (WB_wreg = '0') and (WB_a_c /= b"00000") ) then f_m := '1'; -- forward from WB @@ -1515,7 +1516,7 @@ begin MM_a_c,WB_a_c, MM_wreg_cond,WB_wreg, MM_muxC,WB_muxC, MM_A,WB_A, MM_result,WB_result, MM_HI,WB_HI,MM_LO,WB_LO, rd_data,WB_rd_data, MM_B_data,WB_B_data, - MM_result(1 downto 0),WB_addr2, MM_mem_t(3 downto 2),WB_mem_t, + MM_addr(1 downto 0),WB_addr2, MM_mem_t(3 downto 2),WB_mem_t, MM_pc_p8,WB_pc_p8); -- WRITE BACK ----------------------------------------------------------- @@ -1604,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, @@ -1627,15 +1617,15 @@ begin (EX_wreg = '0') and (EX_a_c = a_rs) and (EX_a_c /= b"00000") ) then tr_stall <= '1'; tr_fwd_A <= regs_A; - elsif ((MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000") - and (MM_aVal = '0')) then -- LW load-delay slot - if (is_trap = '1') then - tr_stall <= '1'; + elsif ((MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000")) then + if (MM_aVal = '0') then -- LW load-delay slot + if (is_trap = '1') then + tr_stall <= '1'; + end if; + tr_fwd_A <= regs_A; + else -- non-LW + tr_fwd_A <= MM_result; end if; - tr_fwd_A <= regs_A; - elsif ((MM_wreg = '0') and (MM_a_c = a_rs) and (MM_a_c /= b"00000") - and (MM_aVal = '1')) then -- non-LW - tr_fwd_A <= MM_result; else tr_fwd_A <= regs_A; end if; @@ -1646,21 +1636,53 @@ begin (EX_wreg = '0') and (EX_a_c = a_rt) and (EX_a_c /= b"00000") ) then tr_stall <= '1'; tr_fwd_B <= regs_B; - elsif ((MM_wreg = '0') and (MM_a_c = a_rt) and (MM_a_c /= b"00000") - and (MM_aVal = '0')) then -- LW load-delay slot - if (is_trap = '1') then - tr_stall <= '1'; + elsif ((MM_wreg = '0') and (MM_a_c = a_rt) and (MM_a_c /= b"00000")) then + if (MM_aVal = '0') then -- LW load-delay slot + if (is_trap = '1') then + tr_stall <= '1'; + end if; + tr_fwd_B <= regs_B; + else -- non-LW + tr_fwd_B <= MM_result; end if; - tr_fwd_B <= regs_B; - elsif ((MM_wreg = '0') and (MM_a_c = a_rt) and (MM_a_c /= b"00000") - and (MM_aVal = '1')) then -- non-LW - tr_fwd_B <= MM_result; else tr_fwd_B <= regs_B; 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, @@ -1669,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 @@ -1690,38 +1713,34 @@ 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; - variable i_excp_PCsel : reg3; begin newSTATUS := STATUS; i_epc_update := '1'; i_epc_source := EPC_src_PC; - i_excp_PCsel := PCsel_EXC_none; -- PC <= normal processing PC i_update := '0'; i_update_r := b"00000"; i_a_c := b"00000"; 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,67 +1821,62 @@ 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; i_stall := '0'; -- do not stall - i_excp_PCsel := PCsel_EXC_EPC; -- PC <= EPC 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; - i_excp_PCsel := PCsel_EXC_0180;-- PC <= exception_180 + 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 @@ -1878,7 +1892,6 @@ begin i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; - i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_0180 ExcCode <= cop0code_Ov; i_nullify := '1'; -- nullify instructions in IF,RF nullify_EX <= '1'; -- and instruction in EX @@ -1899,7 +1912,6 @@ begin i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; - i_excp_PCsel := PCsel_EXC_0180; if is_exception = MMaddressErrorST then ExcCode <= cop0code_AdES; else @@ -1955,7 +1967,6 @@ begin newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; - i_excp_PCsel := PCsel_EXC_0000; -- PC <= exception_0000 i_epc_update := '0'; @@ -2004,7 +2015,6 @@ begin newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; - i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_0180 i_epc_update := '0'; @@ -2032,7 +2042,6 @@ begin i_epc_source := EPC_src_RF; -- RF_PC is_delayslot <= RF_is_delayslot; end if; - i_excp_PCsel := PCsel_EXC_0000; -- PC <= exception_0000 elsif ( (STATUS(STATUS_EXL) = '0') and (STATUS(STATUS_ERL) = '0') and (STATUS(STATUS_IE) = '1') and (EX_interrupt = '1') and @@ -2056,11 +2065,6 @@ begin i_epc_source := EPC_src_RF; -- RF_PC is_delayslot <= RF_is_delayslot; end if; - if CAUSE(CAUSE_IV) = '1' then - i_excp_PCsel := PCsel_EXC_0200; -- PC <= exception_0200 - else - i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_0180 - end if; end if; -- NMI or else interrupt @@ -2078,7 +2082,6 @@ begin epc_update <= i_epc_update OR STATUS(STATUS_EXL); end if; epc_source <= i_epc_source; - excp_PCsel <= i_excp_PCsel; exception_stall <= i_stall; nullify <= i_nullify; @@ -2086,6 +2089,63 @@ begin end process COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS; + -- Select input to PC on an exception -------------------- + COP0_SEL_EPC: process (is_exception, EX_nmi, EX_interrupt, STATUS, CAUSE, + EX_trapped, rom_stall, ram_stall) + variable i_excp_PCsel : reg3; + begin + + i_excp_PCsel := PCsel_EXC_none; -- PC <= normal processing PC + + case is_exception is + + when exERET => -- exception return + i_excp_PCsel := PCsel_EXC_EPC; -- PC <= EPC + + when exSYSCALL | exBREAK | exRESV_INSTR | exOvfl + | IFaddressError | MMaddressErrorLD | MMaddressErrorST + | exTLBdblFaultIF | exTLBdblFaultRD | exTLBdblFaultWR + | exTLBinvalIF | exTLBinvalRD | exTLBinvalWR | exTLBmod => + i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_180 + + 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 + + when others => -- interrupt pending? + + if ( (EX_nmi = '1') and (STATUS(STATUS_ERL) = '0') ) then + -- non maskable interrupt + i_excp_PCsel := PCsel_EXC_0000; -- PC <= exception_0000 + + elsif ( (STATUS(STATUS_EXL) = '0') and (STATUS(STATUS_ERL) = '0') and + (STATUS(STATUS_IE) = '1') and (EX_interrupt = '1') and + (rom_stall = '0' and ram_stall = '0')) then + -- normal interrupt + if CAUSE(CAUSE_IV) = '1' then + i_excp_PCsel := PCsel_EXC_0200; -- PC <= exception_0200 + else + i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_0180 + end if; + else + i_excp_PCsel := PCsel_EXC_none; -- should never get here + end if; -- NMI or interrupt + + end case; + + excp_PCsel <= i_excp_PCsel; + + end process COP0_SEL_EPC; + + + + COP0_FORWARDING: process (EX_a_rt,EX_a_c, MM_a_c,MM_wreg,MM_result, WB_a_c,WB_wreg, WB_C,EX_B, MM_cop0_val, MM_cop0_a_c,EX_cop0_a_c) @@ -2093,17 +2153,13 @@ begin begin if ((MM_wreg = '0')and(MM_a_c /= b"00000")and(MM_a_c = EX_a_rt)) then i_B := MM_result; - -- assert false report "FWD_cop0 MM: inp="&SLV32HEX(cop0_inp); -- DEBUG - elsif ((WB_wreg = '0')and(WB_a_c /= b"00000")and(WB_a_c = EX_a_rt)) then - i_B := WB_C; - -- assert false report "FWD_cop0 WB: inp="&SLV32HEX(cop0_inp); -- DEBUG elsif ((MM_wreg = '0')and (MM_cop0_a_c /= b"00000")and(MM_cop0_a_c = EX_cop0_a_c)) then i_B := MM_cop0_val; - -- assert false report "FWD_cop0 CP: inp="&SLV32HEX(cop0_inp); -- DEBUG + elsif ((WB_wreg = '0')and(WB_a_c /= b"00000")and(WB_a_c = EX_a_rt)) then + i_B := WB_C; else i_B := EX_B; - -- assert false report "FWD_cop0 EX: inp="&SLV32HEX(cop0_inp); -- DEBUG end if; cop0_inp <= i_B; end process COP0_FORWARDING; @@ -2122,7 +2178,7 @@ begin -- CAUSE -- pg 92-- cop0_13 -------------------------- COP0_COMPUTE_CAUSE: process(rst, update,update_reg, EX_int_req, ExcCode, cop0_inp, is_delayslot, - count_eq_compare,count_enable, CAUSE) + count_eq_compare,count_enable, STATUS, CAUSE) variable newCAUSE : reg32; begin @@ -2247,11 +2303,11 @@ begin LL_SC_abort <= (LL_SC_differ or EX_LLbit) when (is_exception = exSC) else '0'; - COP0_LLbit: process(rst,phi2) + COP0_LLbit: process(rst,clk) begin if rst = '0' then EX_LLbit <= '0'; -- break SC -> LL - elsif rising_edge(phi2) then + elsif rising_edge(clk) then case is_exception is when exERET => EX_LLbit <= '0'; -- break SC -> LL @@ -2306,16 +2362,16 @@ begin -- MMU Random -- cop0_1 ------------------------ MMU_Random: process(clk, rst, WIRED, wired_update) - variable count : integer range -1 to MMU_CAPACITY-1; + variable count : integer range -1 to MMU_CAPACITY-1 := MMU_CAPACITY-1; begin - if rst = '0' or wired_update = '0' then - count := MMU_CAPACITY - 1 ; + if rst = '0' then + count := MMU_CAPACITY - 1; elsif rising_edge(clk) then count := count - 1; - if count = to_integer(unsigned(WIRED))-1 then + if count = to_integer(unsigned(WIRED))-1 or wired_update = '0' then count := MMU_CAPACITY - 1; end if; - end if; + end if; RANDOM <= std_logic_vector(to_signed(count, 32)); end process MMU_Random; @@ -2402,7 +2458,7 @@ begin -- -- pg 41 ---------------------------------- - MMU_exceptions: process(EX_wrmem, EX_aVal, tlb_miss, hit_mm, hit_pc, + MMU_exceptions: process(iaVal, EX_wrmem, EX_aVal, tlb_miss, hit_mm, hit_pc, hit_mm_v, hit_mm_d, hit_pc_v, STATUS) variable i_stage_mm : boolean; begin @@ -2461,6 +2517,7 @@ begin else TLB_excp_type <= exNOP; + i_stage_mm := FALSE; end if; tlb_stage_MM <= i_stage_mm; @@ -2497,29 +2554,29 @@ begin tlb_dat5_updt <= '1'; tlb_dat6_updt <= '1'; tlb_dat7_updt <= '1'; - tlb_read <= '0'; - tlb_probe <= '0'; - + case EX_exception is when exTLBP => tlb_probe <= '1'; + tlb_read <= '0'; + i_tlb_adr := 0; when exTLBR => + tlb_probe <= '0'; tlb_read <= '1'; i_tlb_adr := to_integer(unsigned(INDEX(MMU_CAPACITY-1 downto 0))); when exTLBWI | exTLBWR => - case EX_exception is - when exTLBWI => - i_tlb_adr := to_integer(unsigned(INDEX(MMU_CAPACITY-1 downto 0))); - when exTLBWR => - i_tlb_adr := to_integer(unsigned(RANDOM)); - when others => null; - end case; - + tlb_probe <= '0'; + tlb_read <= '0'; + if EX_exception = exTLBWI then + i_tlb_adr := to_integer(unsigned(INDEX(MMU_CAPACITY-1 downto 0))); + else + i_tlb_adr := to_integer(unsigned(RANDOM)); + end if; case i_tlb_adr is when 0 => tlb_tag0_updt <= '0'; tlb_dat0_updt <= '0'; when 1 => tlb_tag1_updt <= '0'; tlb_dat1_updt <= '0'; @@ -2532,10 +2589,13 @@ begin when others => null; end case; - when others => null; + when others => + tlb_probe <= '0'; + tlb_read <= '0'; + i_tlb_adr := 0; end case; - + tlb_adr <= i_tlb_adr; end process MMU_CONTROL; ------------------------------------------------ @@ -2898,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 f8f3789f4141eb97c91c3687ea46a806753feee5..6cf8343b0fa6ec1de17e4ee1c8f9aaef09a60cf2 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 d8143e47a13e7b86271c11b8d7b98a27b7a07bf0..f1fc694e67e684d2336cc26888ca0d0097f98f7f 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. diff --git a/cMIPS/vhdl/tb_cMIPS.vhd b/cMIPS/vhdl/tb_cMIPS.vhd index b6557a1c3a22249246f6654ec0e6729abbbabb49..9ac9957136e640ad1080c3f48befac2fc8fa3d45 100644 --- a/cMIPS/vhdl/tb_cMIPS.vhd +++ b/cMIPS/vhdl/tb_cMIPS.vhd @@ -358,7 +358,9 @@ architecture TB of tb_cMIPS is component core is port (rst : in std_logic; clk : in std_logic; + phi1 : in std_logic; phi2 : in std_logic; + phi3 : in std_logic; i_aVal : out std_logic; i_wait : in std_logic; i_addr : out std_logic_vector; @@ -399,14 +401,14 @@ architecture TB of tb_cMIPS is signal clock_50mhz, clk,clkin : std_logic; signal clk4x,clk4x0, clk4x180, clk2x : std_logic; - signal phi0,phi1,phi2,phi3,phi0in,phi2in,phi3in, phi2_dlyd : std_logic; + signal phi0,phi1,phi2,phi3,phi0in,phi1in,phi2in,phi3in, phi2_dlyd : std_logic; signal rst,ic_reset,a_rst1,a_rst2,a_rst3, cpu_reset : std_logic; signal a_reset, async_reset : std_logic; signal cpu_i_aVal, cpu_i_wait, wr, cpu_d_aVal, cpu_d_wait : std_logic; signal nmi : std_logic; signal irq : reg6; signal inst_aVal, inst_wait, rom_rdy : std_logic := '1'; - signal data_aVal, data_wait, ram_rdy, mem_wr, mem_strobe : std_logic; + signal data_aVal, data_wait, ram_rdy, mem_wr : std_logic; signal cpu_xfer, mem_xfer, dev_select, dev_select_ram, dev_select_io : reg4; signal io_print_sel, io_print_wait : std_logic := '1'; signal io_stdout_sel, io_stdout_wait : std_logic := '1'; @@ -452,7 +454,7 @@ begin -- TB pll : mf_altpll port map (areset => a_reset, inclk0 => clock_50mhz, - c0 => phi0in, c1 => mem_strobe, c2 => phi2in, c3 => phi3in, c4 => clkin); + c0 => phi0in, c1 => phi1in, c2 => phi2in, c3 => phi3in, c4 => clkin); -- clk and clk4x must be in opposite phases pll_io : mf_altpll_io port map (areset => a_reset, inclk0 => clock_50mhz, @@ -464,9 +466,10 @@ begin -- TB mf_altclkctrl_inst_clk4x : mf_altclkctrl port map ( inclk => clk4x180, outclk => clk4x); - phi1 <= '0'; mf_altclkctrl_inst_phi0 : mf_altclkctrl port map ( inclk => phi0in, outclk => phi0); + mf_altclkctrl_inst_phi1 : mf_altclkctrl port map ( + inclk => phi1in, outclk => phi1); mf_altclkctrl_inst_phi2 : mf_altclkctrl port map ( inclk => phi2in, outclk => phi2); mf_altclkctrl_inst_phi3 : mf_altclkctrl port map ( @@ -499,7 +502,7 @@ begin -- TB nmi <= '0'; -- input port to TB - U_CORE: core port map (cpu_reset, clk, phi2, + U_CORE: core port map (cpu_reset, clk, phi1,phi2,phi3, cpu_i_aVal, cpu_i_wait, i_addr, cpu_instr, cpu_d_aVal, cpu_d_wait, d_addr, cpu_data_inp, cpu_data, wr, cpu_xfer, nmi, irq); @@ -516,10 +519,10 @@ begin -- TB U_ROM: simul_ROM generic map ("prog.bin") -- U_ROM: fpga_ROM generic map ("prog.bin") - port map (rst, clk, mem_i_sel,rom_rdy, phi2, mem_i_addr,datrom); + port map (rst, clk, mem_i_sel,rom_rdy, phi3, mem_i_addr,datrom); U_IO_ADDR_DEC: io_addr_decode - port map (phi3,rst, cpu_d_aVal, d_addr, dev_select_io, + port map (phi0,rst, cpu_d_aVal, d_addr, dev_select_io, io_print_sel, io_stdout_sel, io_stdin_sel,io_read_sel, io_write_sel, io_counter_sel, io_fpu_sel, io_uart_sel, io_sstats_sel, io_7seg_sel, io_keys_sel, io_lcd_sel, @@ -554,7 +557,7 @@ begin -- TB U_RAM: simul_RAM generic map ("data.bin", "dump.data") -- U_RAM: fpga_RAM generic map ("data.bin", "dump.data") - port map (rst, clk, mem_d_sel, ram_rdy, mem_wr, phi2, + port map (rst, clk, mem_d_sel, ram_rdy, mem_wr, phi3, mem_addr, datram_out, datram_inp, mem_xfer, dump_ram); U_read_inp: read_data_file generic map ("input.data") diff --git a/cMIPS/vhdl/units.vhd b/cMIPS/vhdl/units.vhd index 1da323d208a4ea65abdd80abb847183715f08040..e5cb7063313659983c640626f75daf2c0f0c23dd 100644 --- a/cMIPS/vhdl/units.vhd +++ b/cMIPS/vhdl/units.vhd @@ -252,7 +252,7 @@ begin operation <= t_alu_fun'pos(fun); -- for debugging only U_alu: process (A,B, fun, sh_left,sh_right,sh_lft_ins, - mask, loc_HI,loc_LO, summ_diff, overflow) + mask, loc_HI,loc_LO, summ_diff, summ_diff_u, overflow) variable i_C, i_and, i_or: reg32; variable i_move_ok, B_is_zero : std_logic := 'L'; begin