diff --git a/cMIPS/include/cMIPS.s b/cMIPS/include/cMIPS.s index fd744cd9451a1271fddea0363c067f07fe118eac..c9d5283d26a93c51554e37af9c15060b77e27a7c 100644 --- a/cMIPS/include/cMIPS.s +++ b/cMIPS/include/cMIPS.s @@ -45,9 +45,31 @@ .set cop0_LLAddr, $17 .set cop0_ErrorPC, $30 + .set c0_index, $0 + .set c0_random, $1 + .set c0_entrylo0,$2 + .set c0_entrylo1,$3 + .set c0_context ,$4 + .set c0_pagemask,$5 + .set c0_wired, $6 + .set c0_badvaddr,$8 + .set c0_count ,$9 + .set c0_entryhi ,$10 + .set c0_compare ,$11 + .set c0_status ,$12 + .set c0_cause ,$13 + .set c0_epc, $14 + .set c0_config, $16 + .set c0_config_f0,0 + .set c0_config_f1,1 + .set c0_lladdr, $17 + .set c0_errorpc, $30 + # reset: COP0 present, at exception level, all else disabled .set cop0_STATUS_reset,0x10000002 + .set c0_status_reset, cop0_STATUS_reset # reset: COUNTER stopped, use special interrVector, no interrupts .set cop0_CAUSE_reset, 0x0880007c + .set c0_cause_reset, cop0_CAUSE_reset diff --git a/cMIPS/include/start.s b/cMIPS/include/start.s index fdc6747be645bc543e0e27c50830e50bf2554391..7aad3ea3541b6dd57345b5c0918495589d26a706 100644 --- a/cMIPS/include/start.s +++ b/cMIPS/include/start.s @@ -275,8 +275,11 @@ _excp_0200: jr $k1 nop + + ## the code for each handler must repeat the exception return + ## sequence shown below in excp_0200ret. handlers_tbl: - j Dismiss # no request: 000 + j dismiss # no request: 000 nop j extCounter # lowest priority, IRQ5: 001 @@ -297,7 +300,7 @@ handlers_tbl: nop -Dismiss: # No pending request, must have been noise +dismiss: # No pending request, must have been noise # do nothing and return excp_0200ret: diff --git a/cMIPS/tests/doTests.sh b/cMIPS/tests/doTests.sh index 852946d3d83a9875cc4be4222511a80f34cdc3df..53714666c46e370469f9f3f11e72af234cca342f 100755 --- a/cMIPS/tests/doTests.sh +++ b/cMIPS/tests/doTests.sh @@ -65,7 +65,7 @@ touch input.data serial.inp a_FWD="fwdAddAddAddSw fwd_SW lwFWDsw lwFWDsw2 slt32 slt_u_32 slt_s_32 reg0" a_CAC="dCacheTst lhUshUCache lbUsbUCache lbsbCache dCacheTstH dCacheTstB" -a_BEQ="lw-bne bXtz sltbeq beq_dlySlot jr_dlySlot" +a_BEQ="lw-bne bXtz sltbeq beq_dlySlot jr_dlySlot interrJR_dlySlot" a_FUN="jaljr jr_2 jal_fun_jr jalr_jr jallwjr bltzal_fun_jr" a_OTH="mult div mul sll slr movz wsbh_seb extract insert" a_BHW="lbsb lhsh lwsw lwswIncr swlw lwl_lwr" diff --git a/cMIPS/tests/interrJR_dlySlot.expected b/cMIPS/tests/interrJR_dlySlot.expected new file mode 100644 index 0000000000000000000000000000000000000000..b43db36ce7487894d2ed390d050bfb823124cd15 --- /dev/null +++ b/cMIPS/tests/interrJR_dlySlot.expected @@ -0,0 +1,5 @@ +00000013 +c0808000 +0000003f +00000046 +c0808000 diff --git a/cMIPS/tests/interrJR_dlySlot.s b/cMIPS/tests/interrJR_dlySlot.s new file mode 100644 index 0000000000000000000000000000000000000000..fdaebaa0148ad4f6ad5b3b4c31308a8b9eaa8e9c --- /dev/null +++ b/cMIPS/tests/interrJR_dlySlot.s @@ -0,0 +1,272 @@ +# Testing the internal counter is difficult because it counts clock cycles +# rather than instructions -- if the I/O or memory latencies change then +# the simulation output also changes and comparisons are impossible. + + .include "cMIPS.s" + .text + .align 2 + .set noat + .set noreorder + .set numCy, 64 + .global _start + .global _exit + + .set c0_cause_rst, 0x0880007c # disable counter, separate IntVector + +_start: nop + li $k0, c0_status_reset # RESET, kernel mode, all else disabled + mtc0 $k0, c0_status + li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 + li $k0, 0x1800ff01 # RESET_STATUS, kernel mode, interr enabled + mtc0 $k0, c0_status + li $k0, c0_cause_rst # RESET, disable counter + mtc0 $k0, c0_cause + + la $15,x_IO_BASE_ADDR + nop + j main + nop +exit: +_exit: nop # flush pipeline + nop + nop + nop + nop + wait # then stop VHDL simulation + nop + nop + + #---------------------------------------------------------------- + .org x_EXCEPTION_0000,0 +_excp_0000: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, c0_cause + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x01 + nop + #---------------------------------------------------------------- + .org x_EXCEPTION_0100,0 +_excp_0100: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, c0_cause + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x02 + nop + #---------------------------------------------------------------- + .org x_EXCEPTION_0180,0 +_excp_180: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, c0_cause + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x03 + nop + + + + # + # interrupt handler ============================================= + # + .org x_EXCEPTION_0200,0 +_excp_200: + mfc0 $k1, c0_count # read current COUNT + sw $k1, 0($15) + + mfc0 $k0, c0_cause # read CAUSE and + nop + sw $k0, 0($15) # print CAUSE + li $k0, 0 # remove IRQ + mtc0 $k0, c0_compare + + move $19, $24 # write part of JALR performed? + + li $k0, 0x10008001 # CP0active, enable COUNT interrupts + mtc0 $k0, c0_status + ehb + eret + # + #================================================================ + # + + + #---------------------------------------------------------------- + .org x_EXCEPTION_BFC0,0 +_excp_BFC0: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, c0_cause + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x04 + nop + + + ## + ##----------------------------------------------------------------- + ## + .set TRUE, 1 + .set FALSE, 0 + + .org x_ENTRY_POINT,0 +main: la $15, x_IO_BASE_ADDR + li $13, '\n' + li $11, 0 # used with the identifiable NOPs + + # + # let us cause an interrupt on a stalled JALR + # + .set numCy, 12 # magic number: cycles needed to ensure + # interrupt hits the JALR + +two_instr: + li $5, numCy # interrupt again in numCy cycles + mtc0 $5, c0_compare + + # enable Counter + mfc0 $5, c0_cause + li $6, 0xf7ffffff # CAUSE.DisableCount <= false + and $5, $5, $6 + mtc0 $5, c0_cause # enable counter + nop + + li $24, 0 + la $20, x_DATA_BASE_ADDR + la $21, one_instr + la $12, err0 + sw $12, 4($20) # write error message to memory + nop # align COUNT==COMPARE with JR + sw $21, 0($20) # store jump target + li $11, 0 # this is a NOP + li $11, 1 # this is a NOP + lw $23, 0($20) # load target address to cause delay slot + li $11, 2 # this is a NOP in the 2-cycle delay slot + jalr $24, $23 # save ra in $24 + li $11, 3 # this is a NOP +two: li $11, 4 # this is a NOP, return address from jalr + li $11, 5 # this is a NOP + +one_instr: + li $11, 6 # this is a NOP + + # $19 must be zero + # handler copies $24 -> $19 + nop # to ensure JALR did not change $24 + bne $zero, $19, err2 # check if return addess was changed + nop + + + # + # let us cause an interrupt on a JR, delayed by a LW + # + .set numCy, 22 # magic number: cycles needed to ensure + # interrupt hits the JALR + + mfc0 $6, c0_count + addiu $5, $6, numCy # interrupt again in numCy cycles + mtc0 $5, c0_compare + move $9, $5 + + # enable Counter + mfc0 $5, c0_cause + li $6, 0xf7ffffff # CAUSE.DisableCount <= false + and $5, $5, $6 + mtc0 $5, c0_cause # enable counter + nop + + sw $9, 0($15) # show old+numCycles + + li $24, 0 + la $20, x_DATA_BASE_ADDR + la $21, zero_instr + la $12, err0 + sw $12, 4($20) # write error message to memory + sw $21, 0($20) # store jump target + li $11, 10 # this is a NOP + li $11, 11 # this is a NOP + li $11, 12 # this is a NOP + lw $23, 0($20) # load target address to cause delay slot + jalr $24, $23 # save ra in $24 + li $11, 13 # this is a NOP +one: li $11, 14 # this is a NOP + li $11, 15 # this is a NOP + +zero_instr: + li $11, 16 # this is a NOP + + # $19 must be zero + # handler copies $24 -> $19 + nop # to ensure JALR did not change $24 + bne $zero, $19, err1 # check if return addess was changed + nop + + li $11, 16 # this is a NOP + li $11, 17 # this is a NOP + + nop + wait 0xff # end of test + nop + + +err2: li $30, 'E' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'R' + sw $30, x_IO_ADDR_RANGE($15) + sw $30, x_IO_ADDR_RANGE($15) + li $30, ' ' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 't' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'w' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'o' + sw $30, x_IO_ADDR_RANGE($15) + li $30, '\n' + j exit + sw $30, x_IO_ADDR_RANGE($15) # print a newline + +err1: li $30, 'E' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'R' + sw $30, x_IO_ADDR_RANGE($15) + sw $30, x_IO_ADDR_RANGE($15) + li $30, ' ' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'o' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'n' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'e' + sw $30, x_IO_ADDR_RANGE($15) + li $30, '\n' + j exit + sw $30, x_IO_ADDR_RANGE($15) # print a newline + +err0: li $30, 'E' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'R' + sw $30, x_IO_ADDR_RANGE($15) + sw $30, x_IO_ADDR_RANGE($15) + li $30, ' ' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'o' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'v' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'r' + sw $30, x_IO_ADDR_RANGE($15) + li $30, 'w' + sw $30, x_IO_ADDR_RANGE($15) + li $30, '\n' + j exit + sw $30, x_IO_ADDR_RANGE($15) # print a newline + + diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index c866635a1584241f8cb303ff49da9b26f3fbf11b..6686491671d2dd59ad20404627d7a9e10e0be6d3 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -2409,7 +2409,7 @@ begin disable_count <= CAUSE(CAUSE_DC) when (cause_update='0' and CAUSE(CAUSE_DC) /= count_enable) else count_enable; -- load new CAUSE(CAUSE_DC) - COP0_DISABLE_COUNT: FFD port map (clk,'1',rst,disable_count, count_enable); + COP0_DISABLE_COUNT: FFD port map (clk,'1',rst, disable_count, count_enable); -- BadVAddr -- pg 74 ---------------------------