diff --git a/cMIPS/tests/badVAddr.expected b/cMIPS/tests/badVAddr.expected index 3415e2a045f75a8920da1ddbc2b313af01811cd7..fa4d550f325cfdbe852fdc5fae669de990ff3ea8 100644 --- a/cMIPS/tests/badVAddr.expected +++ b/cMIPS/tests/badVAddr.expected @@ -1,8 +1,16 @@ 00000318 +[ 08800010 00000319 +] +00000319 +[ 08800010 0000031a +] +0000031a +[ 08800010 0000031b -08800010 +] +0000031b diff --git a/cMIPS/tests/badVAddr.s b/cMIPS/tests/badVAddr.s index 5f4ac62dbee169e2611671efd56f21ecbee835e6..019289f45f0c256ab7823762843eed37a7417f2f 100644 --- a/cMIPS/tests/badVAddr.s +++ b/cMIPS/tests/badVAddr.s @@ -13,7 +13,7 @@ _start: nop nop mtc0 $k0, cop0_EPC nop - eret # go into user mode, all else disabled + eret # leave exception level, all else disabled nop exit: _exit: nop # flush pipeline @@ -26,40 +26,51 @@ _exit: nop # flush pipeline nop .end _start - .org x_EXCEPTION_0180,0 # exception vector_180 - .global _excp_180 + .org x_EXCEPTION_0180,0 # exception vector_180 .global excp_180 - .ent _excp_180 -excp_180: -_excp_180: + .ent excp_180 +excp_180: + li $k0, '[' # to separate output + sw $k0, x_IO_ADDR_RANGE($14) + li $k0, '\n' + sw $k0, x_IO_ADDR_RANGE($14) + mfc0 $k0, cop0_CAUSE - sw $k0, 0($15) # print CAUSE + sw $k0, 0($14) # print CAUSE mfc0 $k0, cop0_EPC # fix return address + sw $k0, 0($14) # print EPC addiu $7, $7, -1 - srl $k0, $k0, 2 - sll $k0, $k0, 2 - mtc0 $k0, cop0_EPC - nop + + addiu $k1, $zero, -4 # -4 = 0xffff.fffc + and $k1, $k1, $k0 # fix the invalid address + mtc0 $k1, cop0_EPC + + li $k0, ']' # to separate output + sw $k0, x_IO_ADDR_RANGE($14) + li $k0, '\n' + sw $k0, x_IO_ADDR_RANGE($14) + eret - .end _excp_180 + .end excp_180 .org x_ENTRY_POINT,0 # normal code start -main: la $15,x_IO_BASE_ADDR - li $7,4 - la $3,here - nop +main: la $14, x_IO_BASE_ADDR # used by handler + la $15, x_IO_BASE_ADDR + li $7, 3 + la $3, here nop -here: sw $3, 0($15) + +here: sw $3, 0($15) nop # 4th jr is to this address - beq $7,$zero, end + beq $7, $zero, end nop - addiu $3,$3,1 + addiu $3, $3, 1 + nop # do not stall on $3 nop - jr $3 + jr $3 nop nop nop end: j exit nop - \ No newline at end of file diff --git a/cMIPS/tests/badVAddrMM.expected b/cMIPS/tests/badVAddrMM.expected index cbd08c52cb34838faa3b87fb8489b34de18777ec..4afe29f983b4e52c1eef2c25403c226a13743acf 100644 --- a/cMIPS/tests/badVAddrMM.expected +++ b/cMIPS/tests/badVAddrMM.expected @@ -1,53 +1,72 @@ 00000000 +[ +08800014 +00000318 +0f000001 +] 00000001 -00000002 +[ 08800014 00000318 +0f000002 +] 00000002 -00000003 +[ 08800014 00000318 +0f000003 +] 00000003 -00000004 -08800014 -00000318 -00000004 + 00000003 +[ 08800010 -00000354 +00000358 +00400001 +] 00000002 +[ 08800010 -00000354 +00000358 +00400002 +] 00000001 +[ 08800010 -00000354 +00000358 +00400003 +] 00000000 + 00000000 +[ +08800014 +000003a0 +0f000001 +] 00000001 00000002 +[ 08800014 -00000390 -00000002 +000003b8 +0f000003 +] 00000003 -00000004 -08800014 -00000390 -00000004 -00000005 -00000006 -08800014 -00000390 -00000006 + 00000003 +[ 08800010 -000003c8 +000003f0 +00400001 +] +00000002 00000002 +[ 08800010 -000003c8 +00000410 +00400003 +] 00000001 -08800010 -000003c8 -00000000 diff --git a/cMIPS/tests/badVAddrMM.s b/cMIPS/tests/badVAddrMM.s index 112111015f8144235e0dddd054aa7b4b8eacd657..e07e82c5fe4939d2cbf1d0e0d6f43b84b4451254 100644 --- a/cMIPS/tests/badVAddrMM.s +++ b/cMIPS/tests/badVAddrMM.s @@ -13,7 +13,7 @@ _start: nop nop mtc0 $k0, cop0_EPC nop - eret # go into user mode, all else disabled + eret # leave exception level, all else disabled nop nop exit: @@ -27,94 +27,149 @@ _exit: nop # flush pipeline nop .end _start - .org x_EXCEPTION_0180,0 # exception vector_180 - .global _excp_180 + .org x_EXCEPTION_0180,0 # exception vector_180 .global excp_180 - .ent _excp_180 + .ent excp_180 excp_180: -_excp_180: + li $k0, '[' # to separate output + sw $k0, x_IO_ADDR_RANGE($14) + li $k0, '\n' # to separate output + sw $k0, x_IO_ADDR_RANGE($14) + + mfc0 $k0, cop0_CAUSE - sw $k0,0($14) # print CAUSE + sw $k0, 0($14) # print CAUSE + + mfc0 $k0, cop0_EPC # print EPC + sw $k0, 0($14) - mfc0 $k0, cop0_EPC # - sw $k0,0($14) # print EPC - addiu $7,$7,-1 # repetiton counter + mfc0 $k0, cop0_BadVAddr # print BadVAddr + sw $k0, 0($14) - addiu $k1, $zero, -4 # -4 = 0xffff.fffc - and $15,$15,$k1 # fix the invalid address + addiu $7, $7, -1 # repetiton counter + addiu $k1, $zero, -4 # -4 = 0xffff.fffc + and $15, $15, $k1 # fix the invalid address + + li $k0, ']' # to separate output + sw $k0, x_IO_ADDR_RANGE($14) + li $k0, '\n' # to separate output + sw $k0, x_IO_ADDR_RANGE($14) + eret - .end _excp_180 + + .end excp_180 .org x_ENTRY_POINT,0 # normal code start -main: la $14, x_IO_BASE_ADDR - la $15, x_IO_BASE_ADDR - li $7, 3 # do 3 rounds - la $3, -1 + + ## + ## do 4 stores: 1st aligned, 2nd, 3rd, 4th misaligned, + ## hence 3 exceptions of type AddrError store=x14 + ## + +main: la $14, x_IO_BASE_ADDR # used by exception handler + la $15, x_IO_BASE_ADDR # used to generate misaligned references + li $7, 3 # do 4 rounds for each type of exception + li $3, 0 # exception handler decreases $7 nop -here: addiu $3, $3, 1 - sw $3, 0($15) # exception handler decreases $7 - beq $7, $zero, next # there should be 3 exceptions: addr&{01,10,11} - nop # of type AddrError store=x14 - addu $15, $15, $3 - j here +here: nop + sw $3, 0($15) # causes 3 exceptions: addr&{01,10,11} + addiu $3, $3, 1 # 1st is aligned, 2nd,3rd,4th misaligned + beq $7, $zero, next nop + j here + addu $15, $15, $3 + -next: li $29, '\n' # to separate output +next: li $29, '\n' # to separate output sw $29, x_IO_ADDR_RANGE($14) + sw $29, x_IO_ADDR_RANGE($14) + + + ## + ## do 4 loads, 1st aligned, 2nd, 3rd, 4th misaligned + ## hence 3 exceptions of type AddrError if/ld=x10 + ## + la $15, x_DATA_BASE_ADDR la $18, x_IO_BASE_ADDR - li $7, 3 - la $3, -1 + li $7, 3 # do 3 rounds + li $3, 0 sw $7, 0($15) nop -there: addiu $3,$3,1 - lw $3, 0($15) # there should be 3 exceptions: addr&{01,10,11} - sw $7, 0($18) # of type AddrError if/ld=x10 - beq $7, $zero, after - nop - addu $15, $15, $3 - j there - nop +there: nop + lw $5, 0($15) # causes 3 exceptions: addr&{01,10,11} + sw $7, 0($18) # print value changed by handler + # sw $5, 0($18) # print value read from memory + addiu $3, $3, 1 + beq $7, $zero, after + nop + j there + addu $15, $15, $3 after: li $29, '\n' # to separate output sw $29, x_IO_ADDR_RANGE($14) - la $14, x_IO_BASE_ADDR + sw $29, x_IO_ADDR_RANGE($14) + + + ## + ## do 4 half-word stores: 1st,3rd aligned, 2nd,4th misaligned, + ## hence 3 exceptions of type AddrError store=x14 + ## + + la $14, x_IO_BASE_ADDR # used by exception handler la $15, x_IO_BASE_ADDR li $7, 3 - la $3, -1 + li $3, 0 nop -here2: addiu $3, $3, 1 # there should be 3 exceptions: addr&{01,11} - sh $3, 0($15) # of type AddrError store=x14 - beq $7, $zero, next2 - nop - addu $15, $15, $3 - j here2 - nop +here2: sh $3, 0($15) # causes no exception: addr & 00 + addiu $15, $15, 1 # of type AddrError store=x14 + addiu $3 , $3, 1 + sh $3, 0($15) # causes exception: addr & 01 + addiu $15, $15, 2 # handler fixes $15 to addr & 00 + addiu $3 , $3, 1 + sh $3, 0($15) # causes no exception: addr & 10 + addiu $15, $15, 1 + addiu $3 , $3, 1 + sh $3, 0($15) # causes exception: addr & 10 + next2: li $29, '\n' # to separate output + sw $29, x_IO_ADDR_RANGE($14) sw $29, x_IO_ADDR_RANGE($14) la $15, x_DATA_BASE_ADDR la $18, x_IO_BASE_ADDR li $7, 3 - la $3, -1 + la $3, 0 sw $7, 0($15) nop -there2: lh $3, 0($15) # there should be 3 exceptions: addr&{01,11} - sw $7, 0($18) # of type AddrError if/ld=x10 - beq $7, $zero, end - nop - addu $15, $15, $3 - nop - j there2 - nop + + ## + ## do 4 half-word loads: 1st,3rd aligned, 2nd,4th misaligned, + ## hence 3 exceptions of type AddrError if/ld=x10 + ## + +there2: lh $3, 0($15) # causes no exception: addr & 00 + sw $7, 0($18) + addiu $15, $15, 1 + addiu $3 , $3, 1 + lh $3, 0($15) # causes exception: addr & 01 + sw $7, 0($18) + addiu $15, $15, 2 # handler fixes $15 to addr & 00 + addiu $3 , $3, 1 + lh $3, 0($15) # causes no exception: addr & 10 + sw $7, 0($18) + addiu $15, $15, 1 + addiu $3 , $3, 1 + lh $3, 0($15) # causes exception: addr & 10 + sw $7, 0($18) end: j exit nop diff --git a/cMIPS/tests/extCounter.c b/cMIPS/tests/extCounter.c index cfde4a0de56287d18199896b899f12c3a09e6f2f..1b4e373733c82fb2ec59023e59b280e0786bf737 100644 --- a/cMIPS/tests/extCounter.c +++ b/cMIPS/tests/extCounter.c @@ -30,7 +30,7 @@ void main(void) { if ( (new=readCounter()) > old) { increased = increased & TRUE; old = new; - // print(new); // print current count + // print(new); // print current count, not for automated tests } else { increased = FALSE; } diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 8cd9e09838599a52cdb6d420b650c930ae0e668a..eb2a7522c4b55760c60dffdb7ff5ab5f5e30af24 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -53,6 +53,8 @@ architecture rtl of core is port(clk, rst, ld: in std_logic; IF_excp_type: in exception_type; RF_excp_type: out exception_type; + PC_abort: in boolean; + RF_PC_abort: out boolean; IF_PC: in std_logic_vector; RF_PC: out std_logic_vector); end component reg_excp_IF_RF; @@ -71,6 +73,8 @@ architecture rtl of core is EX_cop0_sel: out std_logic_vector; RF_is_delayslot: in std_logic; EX_is_delayslot: out std_logic; + RF_PC_abort: in boolean; + EX_PC_abort: out boolean; RF_PC: in std_logic_vector; EX_PC: out std_logic_vector; RF_nmi: in std_logic; @@ -95,6 +99,8 @@ architecture rtl of core is MM_PC: out std_logic_vector; EX_cop0_LLbit: in std_logic; MM_cop0_LLbit: out std_logic; + addrError: in boolean; + MM_abort: out boolean; EX_cop0_a_c: in std_logic_vector; MM_cop0_a_c: out std_logic_vector; EX_cop0_val: in std_logic_vector; @@ -115,8 +121,8 @@ architecture rtl of core is WB_PC: out std_logic_vector; MM_cop0_LLbit: in std_logic; WB_cop0_LLbit: out std_logic; - MM_abort: in std_logic; - WB_abort: out std_logic; + MM_abort: in boolean; + WB_abort: out boolean; MM_cop0_a_c: in std_logic_vector; WB_cop0_a_c: out std_logic_vector; MM_cop0_val: in std_logic_vector; @@ -127,9 +133,11 @@ architecture rtl of core is signal interrupt,EX_interrupt, exception_stall : std_logic; signal exception_taken, interrupt_taken, trap_taken : std_logic; - signal nullify, nullify_EX, abort, MM_abort,WB_abort : std_logic; + signal nullify, nullify_EX, abort : std_logic; + 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, MM_addr_error, MM_excp_TLB : exception_type; + 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; @@ -158,7 +166,7 @@ architecture rtl of core is signal cop0_inp, RF_cop0_val,EX_cop0_val,MM_cop0_val,WB_cop0_val : reg32; signal EX_cop0_a_c,MM_cop0_a_c,WB_cop0_a_c : reg5; signal BadVAddr, BadVAddr_inp : reg32; - signal BadVAddr_update, BadVAddr_source : std_logic; + signal BadVAddr_update : std_logic; -- MMU signals -- signal INDEX, index_inp, RANDOM, WIRED, wired_inp : reg32; @@ -177,10 +185,11 @@ architecture rtl of core is signal hit4_pc, hit5_pc, hit6_pc, hit7_pc : boolean; signal hit0_mm, hit1_mm, hit2_mm, hit3_mm, hit_mm : boolean; signal hit4_mm, hit5_mm, hit6_mm, hit7_mm : boolean; + signal tlb_miss, tlb_miss_IF, tlb_miss_MM, tlb_exception : boolean; signal hit_mm_v, hit_mm_d, hit_pc_v : std_logic; signal tlb_adr_mm : MMU_idx_bits; signal tlb_probe, probe_hit, hit_mm_bit : std_logic; - signal mm : std_logic_vector(VA_HI_BIT downto VA_LO_BIT); + signal mm, tlb_excp_VA : std_logic_vector(VA_HI_BIT downto VA_LO_BIT); signal tlb_adr,tlb_a0_pc,tlb_a1_pc,tlb_a2_pc : natural range 0 to (MMU_CAPACITY-1); signal hit_pc_adr, hit_mm_adr : natural range 0 to (MMU_CAPACITY-1); signal tlb_a0_mm,tlb_a1_mm,tlb_a2_mm : natural range 0 to (MMU_CAPACITY-1); @@ -700,7 +709,7 @@ begin stalled <= ram_stall or rom_stall; not_stalled <= not(stalled); --- end INSTR_FETCH_STATE_MACHINE -------------------------- + -- end INSTR_FETCH_STATE_MACHINE -------------------------- -- PROGRAM COUNTER AND INSTRUCTION FETCH ------------------ @@ -748,7 +757,9 @@ begin IF_excp_type <= IFaddressError when PC(1 downto 0) /= b"00" else exNOP; - + + PC_abort <= PC(1 downto 0) /= b"00"; + PIPESTAGE_PC: register32 generic map (x_INST_BASE_ADDR) port map (clk, rst, PCload, PCinp, PC); @@ -765,7 +776,7 @@ begin -- uncomment this when making use of the TLB -- i_addr <= phy_i_addr; - abort <= MM_abort or WB_abort; + abort <= '1' when addrError else '0'; instr_fetched <= instr when (nullify = '0' and abort = '0' and PC(1 downto 0) = b"00") else @@ -1019,8 +1030,8 @@ begin RF_DECODE_FUNCT: process (opcode,IF_RF_ld,ctrl_word,funct_word,rimm_word, - func,shamt, a_rs,a_rd, STATUS, MM_abort, - IF_excp_type,RF_excp_type,MM_excp_type) + func,shamt, a_rs,a_rd, STATUS, addrError, + RF_excp_type,MM_excp_type) variable i_wreg : std_logic; variable i_csel : reg2; variable i_oper : t_alu_fun := opNOP; @@ -1142,11 +1153,11 @@ begin when b"110000" => i_exception := exLL; -- not REALLY exceptions when b"111000" => i_exception := exSC; when b"111111" => - if MM_abort = '1' then - i_exception := MM_excp_type; - else - i_exception := RF_excp_type; -- delayed by pipe - end if; + -- if addrError then + -- i_exception := MM_excp_type; + -- else + -- i_exception := RF_excp_type; -- delayed by pipe + -- end if; when others => null; -- i_exception := exRESV_INSTR; end case; i_wreg := ctrl_word.wreg; @@ -1262,8 +1273,7 @@ begin alu_move_ok, EX_oper,EX_postn,EX_shamt, ovfl); EX_wreg <= EX_wreg_pre -- movz,movn, move/DO_NOT move - or nullify_EX -- abort wr if prev excep in EX - or abort; -- abort write if exception in MEM + or nullify_EX; -- abort wr if prev excep in EX EX_wrmem_cond <= EX_wrmem or nullify_EX -- abort write if exception in EX @@ -1276,10 +1286,58 @@ begin -- this adder performs address calculation so the TLB can be checked during - -- EX and signal any exception as early as possible + -- EX so we may signal an exception as early as possible U_VIR_ADDR_ADD: mf_alt_adder port map (alu_inp_A, EX_displ32, v_addr); + U_EX_ADDR_ERR_EXCP: process(EX_mem_t,EX_aVal,EX_wrmem, v_addr) + begin + + case EX_mem_t(1 downto 0) is -- xx,by,hf,wd + when b"11" => + if ( EX_mem_t(3) = '0' and -- normal LOAD, not LWL,LWR + EX_aVal = '0' and v_addr(1 downto 0) /= b"00" ) then + if EX_wrmem = '1' then + MM_excp_type <= MMaddressErrorLD; + else + MM_excp_type <= MMaddressErrorST; + end if; + addrError <= TRUE; + else + MM_excp_type <= exNOP; + addrError <= FALSE; + end if; + + when b"10" => -- LH*, SH + if EX_aVal = '0' and v_addr(0) /= '0' then + if EX_wrmem = '1' then + MM_excp_type <= MMaddressErrorLD; + else + MM_excp_type <= MMaddressErrorST; + end if; + addrError <= TRUE; + else + MM_excp_type <= exNOP; + addrError <= FALSE; + end if; + + when others => -- LB*, SB + MM_excp_type <= exNOP; + addrError <= FALSE; + + end case; + + -- assert MM_excp_type = exNOP -- DEBUG + -- report "SIMULATION ERROR -- data addressing error: " & + -- integer'image(exception_type'pos(MM_excp_type)) & + -- " at address: " & SLV32HEX(v_addr) + -- severity error; + + end process U_EX_ADDR_ERR_EXCP; ---------------------------------- + + + + -- ---------------------------------------------------------------------- PIPESTAGE_EX_MM: reg_EX_MM @@ -1305,7 +1363,7 @@ begin ram_stall <= not(daVal) and not(d_wait); -- end DATA_BUS_STATE_MACHINE ------------------------------------- - wr <= MM_wrmem or abort; + wr <= MM_wrmem; rd_data_raw <= data_inp when (MM_wrmem = '1' and MM_aVal = '0') else (others => 'X'); @@ -1326,25 +1384,12 @@ begin constant c_16_zeros : reg16 := b"0000000000000000"; begin - MM_addr_error <= exNOP; - case MM_mem_t(1 downto 0) is -- 10:xx,by,hf,wd when b"11" => i_byte_sel := b"1111"; -- LW, SW, LWL, LWR bytes_read := rd_data_raw; i_d_addr := MM_result(31 downto 2) & b"00"; -- align reference - if ( MM_mem_t(3) = '0' and -- normal LOAD, not LWL,LWR - MM_aVal = '0' and MM_result(1 downto 0) /= b"00" ) then - if MM_wrmem = '1' then - MM_addr_error <= MMaddressErrorLD; - else - MM_addr_error <= MMaddressErrorST; - end if; - -- else - -- MM_addr_error <= exNOP; - end if; - when b"10" => i_d_addr := MM_result(31 downto 1) & '0' ; -- align reference if MM_result(1) = '0' then -- LH*, SH @@ -1360,16 +1405,6 @@ begin bytes_read := c_16_zeros & i_half; end if; - if MM_aVal = '0' and MM_result(0) /= '0' then - if MM_wrmem = '1' then - MM_addr_error <= MMaddressErrorLD; - else - MM_addr_error <= MMaddressErrorST; - end if; - -- else - -- MM_addr_error <= exNOP; - end if; - when b"01" => -- LB*, SB i_d_addr := MM_result; case MM_result(1 downto 0) is @@ -1387,13 +1422,11 @@ begin else bytes_read := c_24_zeros & i_byte; end if; - -- MM_addr_error <= exNOP; when others => i_d_addr := "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; -- MM_result; i_byte_sel := b"0000"; bytes_read := (others => 'X'); - -- MM_addr_error <= exNOP; end case; @@ -1402,13 +1435,7 @@ begin b_sel <= i_byte_sel; rd_data <= bytes_read; - -- assert MM_addr_error = exNOP -- DEBUG - -- report "SIMULATION ERROR -- data addressing error: " & - -- integer'image(exception_type'pos(MM_addr_error)) & - -- " at address: " & SLV32HEX(MM_result) - -- severity error; - - end process MM_MEM_INTERFACE; + end process MM_MEM_INTERFACE; --------------------------------- -- forwarding for LW -> SW MM_FORWARDING_MEM: process (MM_aVal,MM_wrmem,MM_a_rt,WB_a_c,WB_wreg,WB_C,MM_B) @@ -1430,7 +1457,7 @@ begin end if; fwd_mem <= f_m; -- for debugging data_out <= i_data; - end process MM_FORWARDING_MEM; + end process MM_FORWARDING_MEM; ------------------------------- -- forwarding for LWL, LWR @@ -1452,9 +1479,9 @@ begin end process MM_FWD_LWLR; - MM_wreg_cond <= '1' when ((ram_stall = '1') - or (abort = '1') -- abort write if excptn in MEM - or (MM_move = '1' and MM_alu_move_ok = '0')) + MM_wreg_cond <= '1' when ( (ram_stall = '1') + or MM_abort -- abort regWrite if excptn in MEM + or (MM_move = '1' and MM_alu_move_ok = '0') ) else MM_wreg; @@ -1535,7 +1562,7 @@ begin PIPESTAGE_EXCP_IF_RF: reg_excp_IF_RF port map (clk, rst, excp_IF_RF_ld, - IF_excp_type,RF_excp_type, PC,RF_PC); + IF_excp_type,RF_excp_type, PC_abort,RF_PC_abort, PC,RF_PC); -- RF decode & register fetch --------------------------------------------- @@ -1616,7 +1643,7 @@ begin exception,EX_exception, trap_instr,EX_trap_instr, cop0_reg,EX_cop0_reg, cop0_sel,EX_cop0_sel, next_instr_in_delay_slot,EX_is_delayslot, - RF_PC,EX_PC, RF_nmi,EX_nmi, + 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); @@ -1626,13 +1653,17 @@ begin -- 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'; - - is_exception <= exOvfl when MM_ex_trapped = '1' else EX_exception; + + 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 + EX_exception; COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS: - process (EX_a_rt, is_exception, EX_trap_instr, EX_wreg, + process (EX_a_rt, is_exception, EX_trap_instr, EX_cop0_reg, EX_cop0_sel, EX_nmi, EX_interrupt,EX_int_req, EX_is_delayslot, cop0_inp, EX_tr_is_equal, EX_tr_less_than, INDEX, RANDOM, EntryLo0, EntryLo1, CONTEXT, PAGEMASK, WIRED, @@ -1666,8 +1697,7 @@ begin interrupt_taken <= '0'; trap_taken <= '0'; ExcCode <= cop0code_NULL; - BadVAddr_source <= '0'; - BadVAddr_update <= '1'; + -- BadVAddr_update <= '1'; EX_mfc0 <= '0'; newSTATUS := STATUS; -- preserve as needed @@ -1833,7 +1863,7 @@ begin i_update_r := cop0reg_STATUS; i_epc_update := '0'; i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_0180 - BadVAddr_update <= '0'; + -- BadVAddr_update <= '0'; if is_exception = MMaddressErrorST then ExcCode <= cop0code_AdES; else @@ -1842,10 +1872,8 @@ begin if is_exception = IFaddressError then i_nullify := '1'; -- nullify instructions in IF,RF i_epc_source := b"010"; -- bad address is in EXCP_EX_PC - badVAddr_source <= '0'; -- instruction fetch else - i_epc_source := b"011"; -- bad address is in EXCP_MM_PC - badVAddr_source <= '1'; -- load/store + i_epc_source := b"010"; -- bad address is in EXCP_EX_PC end if; when exEHB => -- stall processor to clear hazards @@ -1855,7 +1883,25 @@ begin when exTLBP | exTLBR | exTLBWI | exTLBWR => -- TLB access i_stall := '1'; -- stall the processor + + when exTLBrefill | exTLBrefillWR => + + case is_exception is + when exTLBrefillWR => ExcCode <= cop0code_TLBS; + when exTLBrefill => ExcCode <= cop0code_TLBL; + when others => null; + end case; + if EX_is_delayslot = '1' then -- instr is in delay slot + i_epc_source := b"010"; -- EX_PC, re-execute branch/jump + else + i_epc_source := b"001"; -- RF_PC + end if; + i_excp_PCsel := PCsel_EXC_0000; -- PC <= exception_0000 + -- BadVAddr_update <= '0'; + + + when others => -- interrupt pending? if ( (EX_nmi = '1') and (STATUS(STATUS_ERL) = '0') ) then @@ -2022,12 +2068,12 @@ begin port map (clk, rst, cause_update, CAUSEinp, CAUSE); - -- EPC ------------------------------ + -- EPC -- pg 97 --------------------- with epc_source select EPCinp <= PC when b"000", -- instr fetch exception RF_PC when b"001", -- invalid instr exception EX_PC when b"010", -- interrupt, eret, overflow - WB_PC when b"011", -- data memory exception + MM_PC when b"011", -- data memory exception alu_fwd_B when others; -- b"100", -- mtc0 -- (others => 'X') when others; -- invalid selection @@ -2035,7 +2081,7 @@ begin port map (clk, rst, epc_update, EPCinp, EPC); - -- COUNT & COMPARE ------------------------------ not_stalled = '1' + -- COUNT & COMPARE -- pg 75, 78 ----------------- not_stalled = '1' compare_update <= '0' when (update = '1' and update_reg = cop0reg_COMPARE) else '1'; @@ -2062,10 +2108,13 @@ begin COP0_DISABLE_COUNT: FFD port map (clk,'1',rst,disable_count, count_enable); - -- BadVAddr ------------------------------------ + -- BadVAddr -- pg 74 --------------------------- - BadVAddr_inp <= EX_PC when badVAddr_source = '0' -- instruction fetch - else WB_result; -- load/store + BadVAddr_inp <= v_addr when addrError or tlb_miss_mm else -- D-TLB | misaligned + EX_PC when EX_PC_abort else -- fetch misaligned + PC; -- I-TLB + + BadVAddr_update <= '0' when tlb_exception or addrError else '1'; COP0_BadVAddr: register32 generic map(x"00000000") port map (clk, rst, BadVAddr_update, BadVAddr_inp, BadVAddr); @@ -2110,7 +2159,7 @@ begin else not(tlb_probe); hit_mm_bit <= '0' when (hit_mm = TRUE) else '1'; - + with hit_mm_adr select tlb_adr_mm <= "000" when 0, "001" when 1, "010" when 2, @@ -2159,7 +2208,7 @@ begin -- MMU EntryLo0 -- pg 63 -- cop0_2 ------------ entryLo0_update <= '0' when (update = '1' and update_reg = cop0reg_EntryLo0) - else not(tlb_read); + else not(tlb_read); entryLo0_inp <= cop0_inp when tlb_read = '0' else tlb_entryLo0; @@ -2180,11 +2229,6 @@ begin -- MMU Context -- pg 67 -- cop0_4 ------------ - context_upd_pte <= '0' when (update = '1' and update_reg = cop0reg_Context) - else '1'; - - context_upd_bad <= '0' when (not(hit_mm) or not(hit_pc)) else '1'; - assert true -- DEBUG report "pgSz " & integer'image(PAGE_SZ_BITS) & " va-1 " & integer'image(VABITS-1) & @@ -2192,10 +2236,13 @@ begin " add " & integer'image(VABITS-1 - PAGE_SZ_BITS+1) & " lef " & integer'image( PC(VABITS-1 downto PAGE_SZ_BITS+1)'left )& " rig " & integer'image( PC(VABITS-1 downto PAGE_SZ_BITS+1)'right ); + + context_upd_pte <= '0' when (update = '1' and update_reg = cop0reg_Context) + else '1'; + + context_upd_bad <= '0' when tlb_exception else '1'; - tlb_context_inp <= v_addr(VABITS-1 downto PAGE_SZ_BITS+1) when not(hit_mm) else - PC(VABITS-1 downto PAGE_SZ_BITS+1) when not(hit_pc) else - (others => 'X'); + tlb_context_inp <= tlb_excp_VA; MMU_ContextPTE: registerN generic map(9, b"000000000") port map (clk, rst, context_upd_pte, @@ -2223,69 +2270,47 @@ begin -- MMU EntryHi -- pg 76 -- cop0_10 ----------- -- EntryHi holds the ASID of the current process, to check for a match - - entryHi_update <= '0' when (update = '1' and update_reg = cop0reg_EntryHi) + + entryHi_update <= '0' when ( (update = '1' and update_reg = cop0reg_EntryHi) + or ( tlb_exception ) ) else not(tlb_read); - entryHi_inp <= cop0_inp when tlb_read = '0' else tlb_entryhi; + entryHi_inp <= cop0_inp when tlb_read = '0' else + tlb_excp_VA & EHI_ZEROS & EntryHi(EHI_ASIDHI_BIT downto EHI_ASIDLO_BIT) when tlb_exception else + tlb_entryhi; MMU_EntryHi: register32 generic map(x"00000000") port map (clk, rst, entryHi_update, entryHi_inp, EntryHi); - - MMU_exceptions: process(EX_mem_t, EX_wrmem, hit_mm, hit_pc, -- pg 41 -- + + -- -- pg 41 ---------------------------------- + MMU_exceptions: process(EX_wrmem, tlb_miss, hit_mm_v, hit_mm_d, hit_pc_v, STATUS) - variable i_exception : exception_type; begin - -- check for InstructionFetches; if something happens in MM, that - -- takes priority over IF (i_exception is overwritten later) - - -- now check for events later in the pipeline: LOADS and STORES - - if EX_mem_t /= b"0000" then - - if hit_mm = FALSE then -- miss, check for TLBrefill or TLBdoubleFault - - if STATUS(STATUS_EXL) = '1' then - i_exception := exTLBdblFault; - else - i_exception := exTLBrefill; - end if; - - elsif hit_mm_v = '0' then -- hit; check for TLBinvalid - - i_exception := exTLBinval; - - elsif EX_wrmem = '0' and hit_mm_d = '0' then - - i_exception := exTLBmod; - - else - - i_exception := exNOP; - - end if; - - elsif hit_pc = false then + TLB_excp_type <= exNOP; + -- first check for events later in the pipeline: LOADS and STORES + + if tlb_miss then -- miss, check for TLBrefill or TLBdoubleFault if STATUS(STATUS_EXL) = '1' then - i_exception := exTLBdblFault; + TLB_excp_type <= exTLBdblFault; + elsif EX_wrmem = '0' then + TLB_excp_type <= exTLBrefillWR; else - i_exception := exTLBrefill; + TLB_excp_type <= exTLBrefill; end if; - + elsif hit_mm_v = '0' then -- hit; check for TLBinvalid + TLB_excp_type <= exTLBinval; + elsif EX_wrmem = '0' and hit_mm_d = '0' then -- hit; check for TLBmodified + TLB_excp_type <= exTLBmod; elsif hit_pc_v = '0' then -- hit; check for TLBinvalid - - i_exception := exTLBinval; - + TLB_excp_type <= exTLBinval; else - - i_exception := exNOP; - + TLB_excp_type <= exNOP; end if; - MM_excp_TLB <= i_exception; + tlb_exception <= FALSE ; -- (TLB_excp_type /= exNOP); end process MMU_exceptions; -- ----------------------------------------- @@ -2437,8 +2462,16 @@ begin mm <= entryHi(EHI_AHI_BIT downto EHI_ALO_BIT) when tlb_probe = '1' else v_addr(VA_HI_BIT downto VA_LO_BIT); + tlb_miss_MM <= not(hit_mm) and (EX_mem_t /= b"0000"); + tlb_miss_IF <= not(hit_pc); - -- TLB entry 0 -- initialized to 1st page of ROM + tlb_miss <= tlb_miss_IF or tlb_miss_MM; + + tlb_excp_VA <= v_addr(VA_HI_BIT downto VA_LO_BIT) when tlb_miss_MM else + PC(VA_HI_BIT downto VA_LO_BIT); + + +-- TLB entry 0 -- initialized to 1st page of ROM MMU_TAG0: register32 generic map(MMU_ini_tag_ROM0) port map (clk, rst, tlb_tag0_updt, tlb_tag_inp, tlb_tag0); @@ -2613,7 +2646,8 @@ begin -- end of TLB TAG+DATA ARRAY ---------------------------------------- - -- select mapping for IF + + -- select mapping for IF -------------------------------------------- tlb_a2_pc <= 4 when (hit4_pc or hit5_pc or hit6_pc or hit7_pc) else 0; tlb_a1_pc <= 2 when (hit2_pc or hit3_pc or hit6_pc or hit7_pc) else 0; @@ -2654,14 +2688,15 @@ begin phy_i_addr <= tlb_ppn_pc(PPN_BITS-1 downto 0) & PC(PAGE_SZ_BITS-1 downto 0); - -- select mapping for MM + -- select mapping for MM -------------------------------------------- tlb_a2_mm <= 4 when (hit4_mm or hit5_mm or hit6_mm or hit7_mm) else 0; tlb_a1_mm <= 2 when (hit2_mm or hit3_mm or hit6_mm or hit7_mm) else 0; tlb_a0_mm <= 1 when (hit1_mm or hit3_mm or hit5_mm or hit7_mm) else 0; - hit_mm <= hit0_mm or hit1_mm or hit2_mm or hit3_mm or - hit4_mm or hit5_mm or hit6_mm or hit7_mm; + hit_mm <= (hit0_mm or hit1_mm or hit2_mm or hit3_mm or + hit4_mm or hit5_mm or hit6_mm or hit7_mm); + -- and EX_mem_t /= b"0000"; -- hit AND is load or store hit_mm_adr <= (tlb_a2_mm + tlb_a1_mm + tlb_a0_mm); @@ -2705,34 +2740,16 @@ begin PIPESTAGE_EXCP_EX_MM: reg_excp_EX_MM port map (clk, rst, excp_EX_MM_ld, EX_can_trap,MM_can_trap, EX_excp_type,MM_excp_type_i, EX_PC,MM_PC, - EX_LLbit,MM_LLbit, + EX_LLbit,MM_LLbit, addrError,MM_abort, EX_cop0_a_c,MM_cop0_a_c, EX_cop0_val,MM_cop0_val, EX_trapped, MM_ex_trapped, EX_mfc0,MM_mfc0); - COP0_MM_EXCEPTIONS: process(MM_addr_error, MM_excp_type_i) - begin - - if ( MM_excp_type_i = exNOP and -- nothing bad from EX - MM_addr_error /= exNOP ) then -- something wrong in MM - MM_abort <= '1'; - MM_excp_type <= MM_addr_error; - else - MM_abort <= '0'; - MM_excp_type <= exNOP; - end if; - - end process COP0_MM_EXCEPTIONS; - - -- MM does nothing while we do not have an MMU -------------------------- - - - -- ---------------------------------------------------------------------- PIPESTAGE_EXCP_MM_WB: reg_excp_MM_WB port map (clk, rst, excp_MM_WB_ld, MM_can_trap,WB_can_trap, MM_excp_type, WB_excp_type, MM_PC,WB_PC, - MM_LLbit,WB_LLbit, MM_abort,WB_abort, + MM_LLbit,WB_LLbit, MM_abort,WB_abort, MM_cop0_a_c,WB_cop0_a_c, MM_cop0_val,WB_cop0_val); diff --git a/cMIPS/vhdl/exception.vhd b/cMIPS/vhdl/exception.vhd index e788078aca27524a888369d1bb4fb2cc8f8238a1..e40fd79f2ad420c5c7fb0d3f0db182853fffc146 100644 --- a/cMIPS/vhdl/exception.vhd +++ b/cMIPS/vhdl/exception.vhd @@ -32,6 +32,8 @@ entity reg_excp_IF_RF is port(clk, rst, ld: in std_logic; IF_excp_type: in exception_type; RF_excp_type: out exception_type; + PC_abort: in boolean; + RF_PC_abort: out boolean; IF_PC: in reg32; RF_PC: out reg32); end reg_excp_IF_RF; @@ -43,6 +45,7 @@ begin if rising_edge(clk) then if ld = '0' then RF_excp_type <= IF_excp_type ; + RF_PC_abort <= PC_abort ; RF_PC <= IF_PC ; end if; end if; @@ -72,6 +75,8 @@ entity reg_excp_RF_EX is EX_cop0_sel: out reg3; RF_is_delayslot: in std_logic; EX_is_delayslot: out std_logic; + RF_PC_abort: in boolean; + EX_PC_abort: out boolean; RF_PC: in reg32; EX_PC: out reg32; RF_nmi: in std_logic; @@ -101,6 +106,7 @@ begin EX_cop0_reg <= RF_cop0_reg ; EX_cop0_sel <= RF_cop0_sel ; EX_is_delayslot <= RF_is_delayslot ; + EX_PC_abort <= RF_PC_abort ; EX_PC <= RF_PC ; EX_nmi <= RF_nmi ; EX_interrupt <= RF_interrupt ; @@ -131,6 +137,8 @@ entity reg_excp_EX_MM is MM_PC: out reg32; EX_cop0_LLbit: in std_logic; MM_cop0_LLbit: out std_logic; + addrError: in boolean; + MM_abort: out boolean; EX_cop0_a_c: in reg5; MM_cop0_a_c: out reg5; EX_cop0_val: in reg32; @@ -155,6 +163,7 @@ begin MM_can_trap <= EX_can_trap ; MM_PC <= EX_PC ; MM_cop0_LLbit <= EX_cop0_LLbit ; + MM_abort <= addrError ; MM_cop0_a_c <= EX_cop0_a_c ; MM_cop0_val <= EX_cop0_val ; MM_ex_trapped <= EX_trapped ; @@ -183,8 +192,8 @@ entity reg_excp_MM_WB is WB_PC: out reg32; MM_cop0_LLbit: in std_logic; WB_cop0_LLbit: out std_logic; - MM_abort: in std_logic; - WB_abort: out std_logic; + MM_abort: in boolean; + WB_abort: out boolean; MM_cop0_a_c: in reg5; WB_cop0_a_c: out reg5; MM_cop0_val: in reg32; @@ -198,7 +207,7 @@ begin if rst = '0' then WB_can_trap <= b"00"; WB_cop0_LLbit <= '0'; - WB_abort <= '0'; + WB_abort <= FALSE; elsif rising_edge(clk) then if ld = '0' then WB_excp_type <= MM_excp_type ; diff --git a/cMIPS/vhdl/packageExcp.vhd b/cMIPS/vhdl/packageExcp.vhd index c88504f36b12f5dbc7c00aa005cb76e1bb8cef96..df6a2531723bbf0ce454b9a831ecf99877c6501d 100644 --- a/cMIPS/vhdl/packageExcp.vhd +++ b/cMIPS/vhdl/packageExcp.vhd @@ -29,18 +29,19 @@ package p_EXCEPTION is exBREAK, exTRAP, exSYSCALL, -- 8 exRESV_INSTR, exWAIT, -- 10 IFaddressError, MMaddressErrorLD, MMaddressErrorST, --13 - exTLBrefill, exTLBdblFault, exTLBinval, exTLBmod, -- 17 - exOvfl, -- 18 - exLL,exSC, -- 19,20 these are handled by COP0 - exEHB, -- 21 - exTLBP, exTLBR, exTLBWI, exTLBWR, -- 25 - exDERET, -- 26 + exTLBrefill, exTLBrefillWR, -- 15 + exTLBdblFault, exTLBinval, exTLBmod, -- 18 + exOvfl, -- 19 + exLL,exSC, -- 20,21 these are handled by COP0 + exEHB, -- 22 + exTLBP, exTLBR, exTLBWI, exTLBWR, -- 26 + exDERET, -- 27 invalid_exception); attribute enum_encoding of exception_type : type is - "000000 000001 000010 000011 000100 000101 000110 000111 001000 001001 001010 001011 001100 001101 001110 001111 010000 010001 010010 010011 010100 010101 010110 010111 011000 011001 011010 011011"; + "000000 000001 000010 000011 000100 000101 000110 000111 001000 001001 001010 001011 001100 001101 001110 001111 010000 010001 010010 010011 010100 010101 010110 010111 011000 011001 011010 011011 011100"; --- 011100 011101 011110 011111 100000 100001 100010"; +-- 011101 011110 011111 100000 100001 100010"; diff --git a/cMIPS/vhdl/packageMemory.vhd b/cMIPS/vhdl/packageMemory.vhd index d44c63c9aef1305d07796bd2a27591c4ae0eaaf9..135c8b550b515d197feb4b82ea8585763036214c 100644 --- a/cMIPS/vhdl/packageMemory.vhd +++ b/cMIPS/vhdl/packageMemory.vhd @@ -154,7 +154,7 @@ package p_MEMORY is constant VABITS : natural := 32; constant PABITS : natural := 32; - constant PAGE_SZ : natural := 4096; -- 4k pages + constant PAGE_SZ : natural := 4096; -- 4k pages constant PAGE_SZ_BITS : natural := log2_ceil( PAGE_SZ ); constant PPN_BITS : natural := PABITS - PAGE_SZ_BITS; @@ -168,7 +168,9 @@ package p_MEMORY is constant EHI_ASIDHI_BIT : natural := 7; constant EHI_ALO_BIT : natural := PAGE_SZ_BITS + 1; -- maps 2 phy-pages constant EHI_AHI_BIT : natural := 31; - + constant EHI_ZEROS : std_logic_vector(PAGE_SZ_BITS-EHI_AHI_BIT downto 0) := + (others => '0'); + constant TAG_ASIDLO_BIT : natural := 0; constant TAG_ASIDHI_BIT : natural := 7; constant TAG_G_BIT : natural := 8;