diff --git a/cMIPS/tests/doTests.sh b/cMIPS/tests/doTests.sh index f75510c544e513a0407fa544d3933b00ce8bb863..2b591e955eb90728b117d828d016bd187914811e 100755 --- a/cMIPS/tests/doTests.sh +++ b/cMIPS/tests/doTests.sh @@ -67,7 +67,7 @@ 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 interr_x2 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_OTH="mult div nullifies mul sll slr movz wsbh_seb extract insert" a_BHW="lbsb lhsh lwsw lwswIncr swlw lwl_lwr" a_MEM="lwSweepRAM" a_CTR="teq_tne teq_jal teq_lw tlt_tlti tltu_tgeu eiDI ll_sc overflow counter" diff --git a/cMIPS/tests/mult.expected b/cMIPS/tests/mult.expected index b8afc80b402cd64493cff68478caf0025ce98954..ce9f06de9856fe46db5243515c024fdcc664a33e 100644 --- a/cMIPS/tests/mult.expected +++ b/cMIPS/tests/mult.expected @@ -1,3 +1,4 @@ +00000000 00000002 00000004 00000006 diff --git a/cMIPS/tests/mult.s b/cMIPS/tests/mult.s index f5815f4a095c5b5b29b4c293cbb2184dbce0c678..570018826c864a901af0c8fccb0c99c6968f1dec 100644 --- a/cMIPS/tests/mult.s +++ b/cMIPS/tests/mult.s @@ -7,7 +7,7 @@ _start: nop la $15, x_IO_BASE_ADDR - li $3, 1 + li $3, 0 li $4, 2 incr: mult $3, $4 mflo $5 diff --git a/cMIPS/tests/nullifies.expected b/cMIPS/tests/nullifies.expected new file mode 100644 index 0000000000000000000000000000000000000000..9bcd9b02ac406ecdd186faf51d708d9b68e04f8b --- /dev/null +++ b/cMIPS/tests/nullifies.expected @@ -0,0 +1,3 @@ +00000540 +08802000 +00000000 diff --git a/cMIPS/tests/nullifies.s b/cMIPS/tests/nullifies.s new file mode 100644 index 0000000000000000000000000000000000000000..dc4b961b435d34adeb7c198002a0e88dc8939b66 --- /dev/null +++ b/cMIPS/tests/nullifies.s @@ -0,0 +1,159 @@ +## +## Test if multiplications are cancelled if and interrupt is taken +## +## + +# 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 + + .global _start + .global _exit + + .set TRUE, 1 + .set FALSE, 0 + + .equ numCy,0xc0000000 # enable counter + + .equ PRINT,$15 + .equ COUNT,$16 + .equ NL,$13 + +_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_reset # 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 ------------------------------------------------ + # + ## + ## stop the counter, print EPC and CAUSE, and return + ## + .org x_EXCEPTION_0200,0 +_excp_200: + sw $zero, 0(COUNT) # stop the counter + + mfc0 $k1, c0_epc # read EPC + sw $k1, 0(PRINT) + addi $k1, $k1, 4 # skip interrupted instruction + nop + mtc0 $k1, c0_epc # write new EPC + + mfc0 $k1, c0_cause # read CAUSE + sw $k1, 0(PRINT) + nop + + eret + # + # end of interrupt handler ---------------------------------------- + # + + .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 + + + ## + ## main ----------------------------------------------------------- + ## + .org x_ENTRY_POINT,0 +main: la PRINT, x_IO_BASE_ADDR + la COUNT, HW_counter_addr + li NL, '\n' + + + ## + ## counter will interrupt right on the MULT instruction + ## MULT is cancelled by the interrupt + ## handler skips the interrupted instruction + ## result of the anulled MULT must be zero, as it was cancelled + ## + li $20, 2 # multiply 2x3 + li $21, 3 + mtlo $zero # clear LO + + li $5, (numCy+4) # interrupt in 4+4 cycles + sw $5, 0(COUNT) # it takes four cycles to start counting + nop # 4 pipestages + nop + nop + + nop # counter starts counting + nop + nop + mult $20, $21 # interrupts on the 4th cycle + # this MULT is cancelled by the handler + mflo $22 + sw $22, 0(PRINT) # should print zero + + + + +here: j exit + nop + + diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 898c1a708363afde65959e4de1fa13132d445dd8..ef51164279578ed585f3d7e98756f62def1a5064 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -1351,7 +1351,7 @@ begin alu_inp_B <= alu_fwd_B when (EX_selB = '0') else EX_displ32; U_ALU: alu port map(clk,rst, - alu_inp_A, alu_inp_B, result, LO, HI, EX_wreg, + alu_inp_A, alu_inp_B, result, LO, HI, annul_twice, alu_move_ok, EX_oper,EX_postn,EX_shamt, ovfl); diff --git a/cMIPS/vhdl/units.vhd b/cMIPS/vhdl/units.vhd index 01600cb4b8a441b012ab7a8e097b04a461b74e62..3505a207ba345c128fddc038baffbcb432390a83 100644 --- a/cMIPS/vhdl/units.vhd +++ b/cMIPS/vhdl/units.vhd @@ -402,17 +402,17 @@ begin wr_hi <= '1'; case fun is when opMULT | opMULTU | opDIV | opDIVU => - wr_lo <= not(wr_hilo); - wr_hi <= not(wr_hilo); + wr_lo <= wr_hilo; + wr_hi <= wr_hilo; inp_HI <= s_HI; inp_LO <= s_LO; when opMTLO => - wr_lo <= not(wr_hilo); + wr_lo <= wr_hilo; inp_LO <= A; wr_hi <= '1'; inp_HI <= (others => 'X'); when opMTHI => - wr_hi <= not(wr_hilo); + wr_hi <= wr_hilo; inp_HI <= A; wr_lo <= '1'; inp_LO <= (others => 'X');