Commit 5f697227 authored by Roberto Hexsel's avatar Roberto Hexsel

tested and fixed: HI and LO updated only if MULT/DIV/MOD were not nullified

parent ac8cf6f0
......@@ -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"
......
00000000
00000002
00000004
00000006
......
......@@ -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
......
00000540
08802000
00000000
##
## 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
......@@ -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);
......
......@@ -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');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment