diff --git a/cMIPS/include/cMIPS.h b/cMIPS/include/cMIPS.h index 690735c1c45f866b4bc05345c7fa2e030e8d67f8..f6791e202f0eefed026c2809912119f8951c4dcd 100644 --- a/cMIPS/include/cMIPS.h +++ b/cMIPS/include/cMIPS.h @@ -1,6 +1,6 @@ #define x_INST_BASE_ADDR 0x00000000 -#define x_DATA_BASE_ADDR 0x00040000 +#define x_DATA_BASE_ADDR 0x00020000 #define x_IO_BASE_ADDR 0x0F000000 #define x_IO_MEM_SZ 0x00002000 #define x_IO_ADDR_RANGE 0x00000020 diff --git a/cMIPS/include/cMIPS.ld b/cMIPS/include/cMIPS.ld index 0163f3d88dfd41689bcdf400b7c88f73186801f6..9a67592a9536ef51397c4618a8183f496d5e05c3 100644 --- a/cMIPS/include/cMIPS.ld +++ b/cMIPS/include/cMIPS.ld @@ -5,8 +5,8 @@ MEMORY { rom (rx) : ORIGIN = 0x00000000, /* x_INST_BASE_ADDR */ LENGTH = 0x00004000, /* x_INST_MEM_SZ */ - ram (!rx) : ORIGIN = 0x00010000, /* x_DATA_BASE_ADDR */ - LENGTH = 0x00020000, /* x_DATA_MEM_SZ */ + ram (!rx) : ORIGIN = 0x00020000, /* x_DATA_BASE_ADDR */ + LENGTH = 0x00008000, /* x_DATA_MEM_SZ */ io (!rx) : ORIGIN = 0x0f000000, /* not used, do not remove */ LENGTH = 0x00020000 /* edMemory.sh needs thess lines */ } @@ -38,7 +38,7 @@ SECTIONS _end = . ; /* end of image constant (from Xinu) */ } > ram - end_RAM = 0x00020000; /* x_DATA_MEM_SZ */ + end_RAM = 0x00008000; /* x_DATA_MEM_SZ */ half_RAM = (end_RAM / 2); base_TP = ( _bdata + half_RAM ); .TP base_TP : { *(.TP) } > ram diff --git a/cMIPS/include/cMIPS.s b/cMIPS/include/cMIPS.s index c21398cdfc9037fbdb5bf66ba38d7cc029dc76d9..21de4c66c27ca89cd5feb84e5d13372a7f649043 100644 --- a/cMIPS/include/cMIPS.s +++ b/cMIPS/include/cMIPS.s @@ -3,8 +3,8 @@ .set x_INST_BASE_ADDR,0x00000000 .set x_INST_MEM_SZ,0x00004000 - .set x_DATA_BASE_ADDR,0x00040000 - .set x_DATA_MEM_SZ,0x00004000 + .set x_DATA_BASE_ADDR,0x00020000 + .set x_DATA_MEM_SZ,0x00008000 .set x_IO_BASE_ADDR,0x0F000000 .set x_IO_MEM_SZ,0x00002000 diff --git a/cMIPS/include/start.s b/cMIPS/include/start.s index 6ef659a47690194de8269db2493219542e9a279e..747e661f95412a563e955a050a39a12db2e56764 100644 --- a/cMIPS/include/start.s +++ b/cMIPS/include/start.s @@ -228,7 +228,7 @@ h_breakpoint: h_RI: h_CpU: h_Ov: - + excp_0180ret: lui $k1, %hi(_excp_saves) # Read previous contents of STATUS ori $k1, $k1, %lo(_excp_saves) @@ -345,7 +345,6 @@ _excp_BFC0: ##=============================================================== ## reserve first two pages for the Page Table ## - .section .TP,"aw",@progbits _TP: .skip (2*4096), 0 _endTP: diff --git a/cMIPS/tests/FPU_m.c b/cMIPS/tests/FPU_m.c index 45a5c961c6c89562cb0a5354c080214fe003415f..55dfb3aed2754dc6f4c5d03f9fef01d6083a8ceb 100644 --- a/cMIPS/tests/FPU_m.c +++ b/cMIPS/tests/FPU_m.c @@ -1,23 +1,5 @@ #include "cMIPS.h" -// ALL NaN cases : set i < 11 stop case -// int A[] = {(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7f800000,(int)0x7f800000,(int)0xff800000,(int)0xff800000}; -// int B[] = {(int)0x7fffffff,(int)0x7f800000,(int)0xff800000,(int)0x00000000,(int)0x80000000,(int)0x1c038000,(int)0x9c038000,(int)0x00000000,(int)0x80000000,(int)0x00000000,(int)0x80000000}; -// int C[] = {(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff,(int)0x7fffffff}; -// ALL inf cases : set i < 12 stop case -// int A[] = {(int)0x7f800000,(int)0xff800000,(int)0x7f800000,(int)0xff800000,(int)0x7f000000,(int)0xff000000,(int)0xff800000,(int)0xff800000,(int)0x7f800000,(int)0xff800000,(int)0x7f000000,(int)0xff000000}; -// int B[] = {(int)0x7f800000,(int)0xff800000,(int)0x1c038000,(int)0x9c038000,(int)0x7f000000,(int)0xff000000,(int)0x7f800000,(int)0x1c038000,(int)0x9c038000,(int)0x1c038000,(int)0xff000000,(int)0x7f000000}; -// int C[] = {(int)0x7f800000,(int)0x7f800000,(int)0x7f800000,(int)0x7f800000,(int)0x7f800000,(int)0x7f800000,(int)0xff800000,(int)0xff800000,(int)0xff800000,(int)0xff800000,(int)0xff800000,(int)0xff800000}; -// ALL 0 cases : set i < 12 stop case -// int A[] = {(int)0x00000000,(int)0x80000000,(int)0x00000000,(int)0x80000000,(int)0x00800000,(int)0x80800000,(int)0x00000000,(int)0x00000000,(int)0x80000000,(int)0x80000000,(int)0x00800000,(int)0x80800000}; -// int B[] = {(int)0x00000000,(int)0x80000000,(int)0x1c038000,(int)0x9c038000,(int)0x00800000,(int)0x80800000,(int)0x9c038000,(int)0x80000000,(int)0x00000000,(int)0x1c038000,(int)0x80800000,(int)0x00800000}; -// int C[] = {(int)0x00000000,(int)0x00000000,(int)0x00000000,(int)0x00000000,(int)0x00000000,(int)0x00000000,(int)0x80800000,(int)0x80800000,(int)0x80800000,(int)0x80800000,(int)0x80800000,(int)0x80800000}; -// denorm cases : set i < 3 stop case -// int A[] = {(int)0x3c000000,(int)0x3c000000,(int)0x3f800000}; -// int B[] = {(int)0x03800000,(int)0x03000000,(int)0x00200000}; -// int C[] = {(int)0x00400000,(int)0x00200000,(int)0x00200000}; - - int A[] = { // normal numbers (int)0x9c038000,(int)0x9c038000,(int)0x9c038000,(int)0x9c038000, @@ -57,14 +39,14 @@ }; int C[] = { - // normal numbers + // normalized, ordinary numbers (int)0x9c038000,(int)0x9c038000,(int)0x9c038000,(int)0x9c038000, // denorm (int)0x00400000,(int)0x00200000,(int)0x00200000, - // all 0 cases + // all zero cases (int)0x00000000,(int)0x00000000,(int)0x00000000,(int)0x00000000, - (int)0x00000000,(int)0x00000000,(int)0x80800000,(int)0x80800000, - (int)0x80800000,(int)0x80800000,(int)0x80800000,(int)0x80800000, + (int)0x00000000,(int)0x00000000,(int)0x80000000,(int)0x80000000, + (int)0x80000000,(int)0x80000000,(int)0x80000000,(int)0x80000000, // all inf cases (int)0x7f800000,(int)0x7f800000,(int)0x7f800000,(int)0x7f800000, (int)0x7f800000,(int)0x7f800000,(int)0xff800000,(int)0xff800000, @@ -85,7 +67,7 @@ void main(void) { // fpu = (int *)IO_FPU_ADDR + 8; // 0x0f0000cc; // DIV acc = 0; - for (i = 0; i < 4; i++) { // ordinary cases + for (i = 0; i < 4; i++) { // normalized, ordinary numbers *fpu = A[i]; *(fpu+1) = B[i]; asm("nop"); @@ -94,7 +76,7 @@ void main(void) { acc = 1; } if (acc == 0) { - to_stdout('o'); to_stdout('r'); to_stdout('d'); to_stdout('\n'); + to_stdout('n'); to_stdout('o'); to_stdout('r'); to_stdout('\n'); } else { to_stdout('E'); to_stdout('R'); to_stdout('R'); to_stdout('\n'); } diff --git a/cMIPS/tests/busError_d.expected b/cMIPS/tests/busError_d.expected new file mode 100644 index 0000000000000000000000000000000000000000..b502b312350298037dcf1193670f98e0c255d0d1 --- /dev/null +++ b/cMIPS/tests/busError_d.expected @@ -0,0 +1,5 @@ + +0880001c + +bus error + diff --git a/cMIPS/tests/busError_d.s b/cMIPS/tests/busError_d.s new file mode 100644 index 0000000000000000000000000000000000000000..0bfcfaa45b55a92e320a0b7e38ca0297baf1f01b --- /dev/null +++ b/cMIPS/tests/busError_d.s @@ -0,0 +1,187 @@ + ## + ## generate and handle (??) a data reference bus error + ## the error occurs on an attempt to load from non-exixting RAM + ## + .include "cMIPS.s" + .text + .align 2 + .set noreorder + .global _start, _exit + .ent _start +_start: nop + li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 + + ## set STATUS, cop0, no interrupts enabled, user mode + li $k0, 0x10000010 + mtc0 $k0, cop0_STATUS + + j main + nop + +exit: +_exit: nop # flush pipeline + nop + nop + nop + nop + wait # then stop VHDL simulation + nop + nop + nop + nop + .end _start + + .set noreorder + .set noat + + .org x_EXCEPTION_0000,0 +_excp_0000: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, cop0_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, cop0_CAUSE + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x02 + nop + + ## + ## handle bus error exception + ## + .org x_EXCEPTION_0180,0 # exception vector_180 + .global excp_180 + .ent excp_180 +excp_180: + li $k0, '\n' + sw $k0, x_IO_ADDR_RANGE($14) + mfc0 $k0, cop0_CAUSE + # andi $k0, $k0, 0x003f # mask off cause of exception + sw $k0, 0($14) # print CAUSE + li $k0, '\n' + sw $k0, x_IO_ADDR_RANGE($14) + + li $k0, 0x10000010 # clear status of exception + mtc0 $k0, cop0_STATUS + + j apocalipse # and print a message + nop + + wait # ought not to be executed, never + # stop simulation if get to here + .end excp_180 + + .org x_EXCEPTION_0200,0 +_excp_0200: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, cop0_CAUSE + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x03 + nop + + .org x_EXCEPTION_BFC0,0 +_excp_BFC0: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, cop0_CAUSE + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x04 + nop + + + + ## + ## + ## +main: la $14, x_IO_BASE_ADDR # used by handler + + ## to cause a bus error, the faulting page MUST be mapped on the TLB + ## else, there will be a TLB miss at stage EXEC, before the + ## busError, which is detected at the MEM stage. + + # set mapping two pages beyond the top of existing RAM + .set ram_displ,(x_DATA_BASE_ADDR + x_DATA_MEM_SZ + 2*4096) + # la $2, ram_displ + # sw $2, 0($14) + + li $8, (ram_displ & 0xfffff000) # keep VPN2 + mtc0 $8, cop0_EntryHi + # sw $8, 0($14) + + li $6, ( ((ram_displ >>12) <<6) | 0b000111 ) # PPN0 + mtc0 $6, cop0_EntryLo0 + # sw $6, 0($14) + + li $7, ( (((ram_displ+4096) >>12) <<6) | 0b000111 ) # PPN1 + mtc0 $7, cop0_EntryLo1 + # sw $7, 0($14) + + li $5, 7 # read TLB(7) + mtc0 $5, cop0_Index + ehb + tlbwi + + ## address above valid instruction addresses + la $15, ram_displ + nop + lw $16, 4($15) # reference the invalid address + nop + + ## program ought to die at this point, and DO NOT print msg below +zombie: la $19, x_IO_BASE_ADDR + li $20, '\n' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'z' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'o' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'm' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'b' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'i' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'e' + sw $20, x_IO_ADDR_RANGE($19) + li $20, '\n' + j _exit + sw $20, x_IO_ADDR_RANGE($19) + + ## this message should be printed +apocalipse: + la $19, x_IO_BASE_ADDR + li $20, 'b' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'u' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 's' + sw $20, x_IO_ADDR_RANGE($19) + li $20, ' ' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'e' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'r' + sw $20, x_IO_ADDR_RANGE($19) + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'o' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'r' + sw $20, x_IO_ADDR_RANGE($19) + li $20, '\n' + sw $20, x_IO_ADDR_RANGE($19) + j _exit + sw $20, x_IO_ADDR_RANGE($19) diff --git a/cMIPS/tests/busError_i.expected b/cMIPS/tests/busError_i.expected new file mode 100644 index 0000000000000000000000000000000000000000..c74c31041a282d82acef0a53d4e5a51c62f88972 --- /dev/null +++ b/cMIPS/tests/busError_i.expected @@ -0,0 +1,5 @@ + +08800018 + +bus error + diff --git a/cMIPS/tests/busError_i.s b/cMIPS/tests/busError_i.s new file mode 100644 index 0000000000000000000000000000000000000000..4cc0b54cebbf78906b543a856bd68657d4c6f8e6 --- /dev/null +++ b/cMIPS/tests/busError_i.s @@ -0,0 +1,161 @@ + ## + ## generate and handle (??) a instruction fetch bus error + ## the error occurs on an attempt to fetch from non-exixting ROM + ## + + .include "cMIPS.s" + .text + .align 2 + .set noreorder + .global _start, _exit + .ent _start +_start: nop + li $sp,(x_DATA_BASE_ADDR+x_DATA_MEM_SZ-8) # initialize SP: ramTop-8 + + ## set STATUS, cop0, no interrupts enabled, user mode + li $k0, 0x10000010 + mtc0 $k0, cop0_STATUS + + j main + nop + +exit: +_exit: nop # flush pipeline + nop + nop + nop + nop + wait # then stop VHDL simulation + nop + nop + nop + nop + .end _start + + .set noreorder + .set noat + + .org x_EXCEPTION_0000,0 +_excp_0000: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, cop0_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, cop0_CAUSE + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x02 + nop + + ## + ## handle the bus error exception + ## + .org x_EXCEPTION_0180,0 # exception vector_180 + .global excp_180 + .ent excp_180 +excp_180: + li $k0, '\n' + sw $k0, x_IO_ADDR_RANGE($14) + mfc0 $k0, cop0_CAUSE + sw $k0, 0($14) # print CAUSE + li $k0, '\n' + sw $k0, x_IO_ADDR_RANGE($14) + + li $k0, 0x10000010 # clear status of exception + mtc0 $k0, cop0_STATUS + + j apocalipse # and print a message + nop + + eret # ought not to be executed, never + .end excp_180 + + .org x_EXCEPTION_0200,0 +_excp_0200: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, cop0_CAUSE + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x03 + nop + + .org x_EXCEPTION_BFC0,0 +_excp_BFC0: + la $k0, x_IO_BASE_ADDR + mfc0 $k1, cop0_CAUSE + sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + nop + nop + nop + wait 0x04 + nop + + + + ## + ## + ## +main: la $14, x_IO_BASE_ADDR # used by handler + + ## address above valid instruction addresses + la $15, (x_INST_BASE_ADDR + x_INST_MEM_SZ + 4) + nop + jr $15 # jump to the invalid address + nop + + ## program ought to die at this point, and DO NOT print msg below + + la $19, x_IO_BASE_ADDR + li $20, '\n' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'z' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'o' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'm' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'b' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'i' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'e' + sw $20, x_IO_ADDR_RANGE($19) + li $20, '\n' + j _exit + sw $20, x_IO_ADDR_RANGE($19) + + +apocalipse: + la $19, x_IO_BASE_ADDR + li $20, 'b' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'u' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 's' + sw $20, x_IO_ADDR_RANGE($19) + li $20, ' ' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'e' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'r' + sw $20, x_IO_ADDR_RANGE($19) + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'o' + sw $20, x_IO_ADDR_RANGE($19) + li $20, 'r' + sw $20, x_IO_ADDR_RANGE($19) + li $20, '\n' + sw $20, x_IO_ADDR_RANGE($19) + j _exit + sw $20, x_IO_ADDR_RANGE($19) diff --git a/cMIPS/tests/doTests.sh b/cMIPS/tests/doTests.sh index 5173ef8bf640bd83ea99f3dce9270b66378bbcf8..8b7c9d8706be3b9b647d2838e5bc983d0897b34a 100755 --- a/cMIPS/tests/doTests.sh +++ b/cMIPS/tests/doTests.sh @@ -73,9 +73,7 @@ a_MEM="lwSweepRAM" a_CTR="teq_tne teq_jal teq_lw tlt_tlti tltu_tgeu eiDI ll_sc overflow counter" a_COP="mtc0CAUSE2 mtc0EPC syscall break mfc0CONFIG badVAddr badVAddrMM" a_MMU="mmu_index mmu_tlbwi mmu_tlbp mmu_tlbwr mmu_context" -a_EXC="mmu_refill mmu_refill2 mmu_refill3 mmu_inval mmu_inval2 mmu_mod mmu_mod2 mmu_double mmu_double2" - - +a_EXC="mmu_refill mmu_refill2 mmu_refill3 mmu_inval mmu_inval2 mmu_mod mmu_mod2 mmu_double mmu_double2 busError_d busError_i" ## force an update of all include files with edMemory.sh diff --git a/cMIPS/tests/mmu_context.s b/cMIPS/tests/mmu_context.s index 327df17ab4f6a704e0f34591517c0931c7699305..90e4d09c0fd7ee2e959f1a201e9de8047f4257d3 100644 --- a/cMIPS/tests/mmu_context.s +++ b/cMIPS/tests/mmu_context.s @@ -19,8 +19,9 @@ # New entries cannot overwrite tlb[0,1] that map base of ROM + I/O # EntryHi cannot have an ASID different from zero, otw TLB misses - .set entryHi_1, 0x00012000 # pfn0 zzcc cdvg - .set entryLo0_1, 0x0000091b # x0 x0 x0 x0 x0 1001 0001 1011 x91b + .set entryHi_1, 0x00012000 # VPN2 (31..13) 0000 0000 0000 asid + # pfn0 zzcc cdvg + .set entryLo0_1, 0x0000091b # PPN (31..9)=9 1001 0001 1011 x91b .set entryLo1_1, 0x00000c1b # x0 x0 x0 x0 x0 1100 0001 1011 xc1b .set entryHi_2, 0x00014000 # pfn0 zzcc cdvg @@ -31,7 +32,7 @@ .set entryLo0_3, 0x0000191f # x0 x0 x0 x0 x1 1001 0001 1111 x191f .set entryLo1_3, 0x00001d3f # x0 x0 x0 x0 x1 1101 0011 1111 x1d3f - .set entryHi_4, 0x00018000 # pfn0 zzcc cdvg + .set entryHi_4, 0x00018000 # VPN2=30,31 pfn0 zzcc cdvg .set entryLo0_4, 0x00000012 # x0 x0 x0 x0 x0 0000 0001 0010 x12 .set entryLo1_4, 0x00000412 # x0 x0 x0 x0 x0 0100 0001 0010 x412 @@ -105,6 +106,7 @@ main: la $31, x_IO_BASE_ADDR la $29, 0xaaaf0000 # 16 MS bits mtc0 $29, cop0_Context + ehb # clear hazards ehb # clear hazards mfc0 $28, cop0_Context @@ -137,6 +139,7 @@ next1: li $30, '\n' la $29, 0x555f0000 # can write only 16 MS bits mtc0 $29, cop0_Context # must read back 0x555f0000 + ehb # clear hazards ehb # clear hazards mfc0 $28, cop0_Context @@ -163,29 +166,28 @@ next2: li $30, '\n' ## - ## cause a TLB exception and check only bottom 18 bits are written + ## cause a TLB exception and check only bottom 16 bits are written ## mark first RAM VPN2 as invalid ## li $5, 4 # tlb[4] maps first RAM entry mtc0 $5, cop0_Index - la $5, MMU_ini_tag_RAM0 - mtc0 $5, cop0_EntryHi - - la $5, MMU_ini_dat_RAM0 # set mapping invalid: d,v,g=101 + tlbr + ehb + + mfc0 $6, cop0_EntryLo0 + li $7, -3 # clear valid bit: -3 =0xffff.fffd + and $5, $6, $7 mtc0 $5, cop0_EntryLo0 - la $5, MMU_ini_dat_RAM1 - mtc0 $5, cop0_EntryLo1 - + ehb tlbwi # change mapping la $29, 0xffff0000 # can write only 16 MS bits mtc0 $29, cop0_Context ehb # clear hazards - nop nop diff --git a/cMIPS/tests/mmu_refill.s b/cMIPS/tests/mmu_refill.s index 55c5bf88dfd1e684839e8cfa33ca5b15fb8928d6..9958c118ac323f257e1aad49715a164205f0920b 100644 --- a/cMIPS/tests/mmu_refill.s +++ b/cMIPS/tests/mmu_refill.s @@ -1,8 +1,10 @@ ## ## Cause a TLB miss on a fetch, then copy a mapping from page table ## + ## ## This test breaks if the base of RAM is below 0x0001.0000 since - ## cop0_Context maps only addresses ABOVE 0x0001.xxxx + ## cop0_Context maps only addresses ABOVE 0x0000.ffff + ## ## ## EntryHi : EntryLo0 : EntryLo1 ## VPN2 g ASID : PPN0 ccc0 d0 v0 g0 : PPN1 ccc1 d1 v1 g1 diff --git a/cMIPS/tests/mmu_refill2.s b/cMIPS/tests/mmu_refill2.s index 38ad4883a953f7f1ca858c3f30db6fed407b639e..e95bd7e616cd4c5bfe7315d6b0a73d89be737103 100644 --- a/cMIPS/tests/mmu_refill2.s +++ b/cMIPS/tests/mmu_refill2.s @@ -11,23 +11,6 @@ # New entries cannot overwrite tlb[0,1] which map base of ROM, I/O - # EntryHi cannot have an ASID different from zero, otw TLB misses - .set entryHi_1, 0x00012000 # pfn0 zzcc cdvg - .set entryLo0_1, 0x0000091b # x0 x0 x0 x0 x0 1001 0001 1011 x91b - .set entryLo1_1, 0x00000c1b # x0 x0 x0 x0 x0 1100 0001 1011 xc1b - - .set entryHi_2, 0x00014000 # pfn0 zzcc cdvg - .set entryLo0_2, 0x00001016 # x0 x0 x0 x0 x1 0000 0001 0110 x1016 - .set entryLo1_2, 0x0000141e # x0 x0 x0 x0 x1 0100 0001 1110 x141e - - .set entryHi_3, 0x00016000 # pfn0 zzcc cdvg - .set entryLo0_3, 0x0000191f # x0 x0 x0 x0 x1 1001 0001 1111 x191f - .set entryLo1_3, 0x00001d3f # x0 x0 x0 x0 x1 1101 0011 1111 x1d3f - - .set entryHi_4, 0x00018000 # pfn0 zzcc cdvg - .set entryLo0_4, 0x00000012 # x0 x0 x0 x0 x0 0000 0001 0010 x12 - .set entryLo1_4, 0x00000412 # x0 x0 x0 x0 x0 0100 0001 0010 x412 - .set MMU_WIRED, 2 ### do not change mapping for ROM-0, I/O .text @@ -222,7 +205,7 @@ chnge3: li $5, 7 # 3rd RAM mapping mfc0 $8, cop0_EntryHi add $8, $9, $8 # change tag mtc0 $8, cop0_EntryHi - + ehb tlbwi # and write it back to TLB (Index = 6) nop diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 18fe79a8f170e2b454b94027cf665bec81fb53da..1650a7050f351cfa620a75384069e3baace4f9b9 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -45,7 +45,9 @@ entity core is wr : out std_logic; b_sel : out std_logic_vector; nmi : in std_logic; - irq : in std_logic_vector); + irq : in std_logic_vector; + i_busErr : in std_logic; + d_busErr : in std_logic); end core; architecture rtl of core is @@ -99,26 +101,16 @@ architecture rtl of core is MM_addrError: out boolean; addrErr_stage_mm: in boolean; MM_addrErr_stage_mm: out boolean; - mem_excp_type: in exception_type; - MM_mem_excp_type: out exception_type; EX_is_delayslot: in std_logic; MM_is_delayslot: out std_logic; - EX_ovfl: in boolean; - MM_ex_ovfl: out boolean; EX_trapped: in boolean; MM_trapped: out boolean; - EX_pc_abort: in boolean; - MM_pc_abort: out boolean; EX_ll_sc_abort: in boolean; MM_ll_sc_abort: out boolean; - EX_exception: in exception_type; - MM_exception: out exception_type; TLB_exception: in boolean; MM_tlb_exception: out boolean; tlb_stage_MM: in boolean; MM_tlb_stage_MM: out boolean; - TLB_excp_type: in exception_type; - MM_TLB_excp_type: out exception_type; EX_nmi: in std_logic; MM_nmi: out std_logic; EX_interrupt: in std_logic; @@ -128,7 +120,9 @@ architecture rtl of core is EX_is_SC: in boolean; MM_is_SC: out boolean; EX_is_MFC0: in boolean; - MM_is_MFC0: out boolean); + MM_is_MFC0: out boolean; + EX_is_exception: in exception_type; + MM_is_exception: out exception_type); end component reg_excp_EX_MM; component reg_excp_MM_WB is @@ -148,15 +142,14 @@ architecture rtl of core is signal exception_taken, interrupt_taken : std_logic; signal nullify_fetch, nullify, MM_nullify : boolean; signal addrError, MM_addrError, abort_ref, MM_ll_sc_abort : boolean; - signal PC_abort, RF_PC_abort, EX_PC_abort, MM_PC_abort : boolean; + signal PC_abort, RF_PC_abort, EX_PC_abort : boolean; signal IF_excp_type,RF_excp_type: exception_type; - signal mem_excp_type, MM_mem_excp_type : exception_type; - signal TLB_excp_type, MM_TLB_excp_type : exception_type; + signal mem_excp_type, 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 ll_sc_bit, MM_LLbit,WB_LLbit: std_logic; signal LL_update, LL_SC_abort, LL_SC_differ: std_logic; - signal EX_trapped, MM_trapped, EX_ovfl,MM_ex_ovfl, trap_taken: boolean; + signal EX_trapped, MM_trapped, EX_ovfl, trap_taken: boolean; signal int_req, MM_int_req: reg8; signal EX_nmi,MM_nmi : std_logic; signal can_trap,EX_can_trap : reg2; @@ -171,9 +164,9 @@ architecture rtl of core is signal STATUSinp,STATUS, CAUSEinp,CAUSE, EPCinp,EPC : reg32; signal COUNT, COMPARE : reg32; signal count_eq_compare,count_update,count_enable : std_logic; - signal exception,EX_exception,MM_exception, is_exception : exception_type; + signal exception,EX_exception, is_exception, MM_is_exception : exception_type; signal ExcCode : reg5 := cop0code_NULL; - signal exception_num,exception_dec,TLB_excp_num,trap_dec: integer; -- debugging + signal 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, MM_cop0_sel, epc_source : reg3; signal cop0_reg,EX_cop0_reg,MM_cop0_reg : reg5; @@ -182,6 +175,9 @@ architecture rtl of core is signal BadVAddr_update : std_logic; signal is_SC, MM_is_SC, is_MFC0, MM_is_MFC0 : boolean; + signal busError : boolean; + signal busError_type : exception_type; + -- MMU signals -- signal INDEX, index_inp, RANDOM, WIRED, wired_inp : reg32; signal index_update, wired_update : std_logic; @@ -1097,7 +1093,7 @@ begin RF_DECODE_FUNCT: process (opcode,IF_RF_ld,ctrl_word,funct_word,rimm_word, func,shamt, a_rs,a_rd, STATUS, - RF_excp_type,RF_instruction,mem_excp_type) + RF_excp_type,RF_instruction) -- mem_excp_type) variable i_wreg : std_logic; variable i_csel : reg2; variable i_oper : t_alu_fun := opNOP; @@ -1303,7 +1299,7 @@ begin -- EXECUTION --------------------------------------------- EX_FORWARDING_ALU: process (EX_a_rs,EX_a_rt,EX_a_c, EX_A,EX_B, - is_exception, MM_ll_sc_abort, MM_is_SC, + MM_ll_sc_abort, MM_is_SC, MM_a_c,MM_wreg,WB_a_c,WB_wreg, MM_is_MFC0,MM_cop0_val, MM_result,WB_C) variable i_A,i_B : reg32; @@ -1798,36 +1794,40 @@ begin is_SC <= (EX_exception = exSC); -- is StoreConditional? (alu_fwd) is_mfc0 <= (EX_exception = exMFC0); -- is MFC0? (alu_fwd) + + -- priority is given to events later in the pipeline + busError_type <= exDBE when d_busErr = '0' else + exIBE when i_busErr = '0' else + exNOP; + busError <= (i_busErr = '0') or (d_busErr = '0'); + + is_exception <= busError_type when busError else + TLB_excp_type when tlb_exception else + mem_excp_type when addrError else + exTrap when EX_trapped else + exOvfl when EX_ovfl else + IFaddressError when EX_PC_abort else + EX_exception; -- ---------------------------------------------------------------------- PIPESTAGE_EXCP_EX_MM: reg_excp_EX_MM port map (clk, rst, excp_EX_MM_ld, EX_cop0_reg, MM_cop0_reg, EX_cop0_sel, MM_cop0_sel, EX_PC,MM_PC, v_addr,MM_v_addr, nullify,MM_nullify, - addrError,MM_addrError, addrErr_stage_mm,MM_addrErr_stage_mm, - mem_excp_type,MM_mem_excp_type, EX_is_delayslot,MM_is_delayslot, - EX_ovfl,MM_ex_ovfl, EX_trapped,MM_trapped, - EX_PC_abort,MM_PC_abort, SL2BOOL(LL_SC_abort), MM_ll_sc_abort, - EX_exception,MM_exception, tlb_exception,MM_tlb_exception, - tlb_stage_mm,MM_tlb_stage_mm, TLB_excp_type,MM_TLB_excp_type, + addrError,MM_addrError, + addrErr_stage_mm,MM_addrErr_stage_mm, + EX_is_delayslot,MM_is_delayslot, + EX_trapped,MM_trapped, + SL2BOOL(LL_SC_abort), MM_ll_sc_abort, + tlb_exception,MM_tlb_exception, tlb_stage_mm,MM_tlb_stage_mm, EX_nmi,MM_nmi, interrupt,MM_interrupt, int_req,MM_int_req, - is_SC, MM_is_SC, is_MFC0, MM_is_MFC0); - - - - is_exception <= MM_TLB_excp_type when MM_tlb_exception else - MM_mem_excp_type when MM_addrError else - exTrap when MM_trapped else - exOvfl when MM_ex_ovfl else - IFaddressError when MM_PC_abort else - MM_exception; - - exception_num <= exception_type'pos(is_exception); -- for debugging only + is_SC, MM_is_SC, is_MFC0, MM_is_MFC0, + is_exception,MM_is_exception); -- STATUS -- pg 79 -- cop0_12 -------------------- COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS: - process (MM_a_rt, is_exception, cop0_inp, + process (MM_a_rt, MM_is_exception, cop0_inp, MM_cop0_reg, MM_cop0_sel, MM_nmi, MM_interrupt,MM_int_req, RF_is_delayslot, EX_is_delayslot, MM_is_delayslot, WB_is_delayslot, rom_stall,ram_stall, MM_is_mfc0, @@ -1863,7 +1863,7 @@ begin newSTATUS(STATUS_CU1) := '0'; -- COP-1 absent (always) newSTATUS(STATUS_CU0) := '1'; -- COP-0 present=1 (always) - case is_exception is + case MM_is_exception is when exMTC0 => -- move to COP-0 i_update_r := MM_cop0_reg; @@ -1938,7 +1938,7 @@ begin when exSYSCALL | exBREAK => -- SYSCALL, BREAK i_stall := '0'; - if is_exception = exSYSCALL then + if MM_is_exception = exSYSCALL then ExcCode <= cop0code_Sys; else ExcCode <= cop0code_Bp; @@ -2033,7 +2033,7 @@ begin i_update_r := cop0reg_STATUS; i_epc_update := '0'; i_nullify := TRUE; -- nullify instructions in IF,RF,EX - if is_exception = MMaddressErrorST then + if MM_is_exception = MMaddressErrorST then ExcCode <= cop0code_AdES; else ExcCode <= cop0code_AdEL; @@ -2073,7 +2073,7 @@ begin when exTLBrefillRD | exTLBrefillWR => - case is_exception is + case MM_is_exception is when exTLBrefillRD => ExcCode <= cop0code_TLBL; when exTLBrefillWR => @@ -2103,17 +2103,17 @@ begin i_epc_source := EPC_src_PC; -- PC is_delayslot <= '0'; end if; - newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + newSTATUS(STATUS_EXL) := '1'; -- at exception level + newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; - i_nullify := TRUE; -- nullify instructions in IF,RF,EX + i_nullify := TRUE; -- nullify instructions in IF,RF,EX when exTLBdblFaultRD | exTLBdblFaultWR | exTLBinvalRD | exTLBinvalWR | exTLBmod => - case is_exception is + case MM_is_exception is when exTLBinvalRD | exTLBdblFaultRD => ExcCode <= cop0code_TLBL; when exTLBinvalWR | exTLBdblFaultWR => @@ -2129,13 +2129,26 @@ begin i_epc_source := EPC_src_MM; -- EX_PC is_delayslot <= MM_is_delayslot; end if; - newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + newSTATUS(STATUS_EXL) := '1'; -- at exception level + newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; - i_epc_update := '0'; - i_nullify := TRUE; -- nullify instructions in IF,RF,EX + i_epc_update := '0'; + i_nullify := TRUE; -- nullify instructions in IF,RF,EX + + when exIBE | exDBE => -- BUS ERROR + if MM_is_exception = exIBE then + ExcCode <= cop0code_IBE; + else + ExcCode <= cop0code_DBE; + end if; + newSTATUS(STATUS_EXL) := '1'; -- at exception level + newSTATUS(STATUS_IE) := '0'; -- disable interrupts + i_update := '1'; + i_update_r := cop0reg_STATUS; + i_nullify := TRUE; -- nullify instructions in IF,RF,EX + when others => -- interrupt pending? @@ -2193,7 +2206,7 @@ begin update <= i_update; update_reg <= i_update_r; - if is_exception = exMTC0 and MM_cop0_reg = cop0reg_EPC then + if MM_is_exception = exMTC0 and MM_cop0_reg = cop0reg_EPC then epc_update <= i_epc_update; else epc_update <= i_epc_update OR STATUS(STATUS_EXL); @@ -2207,12 +2220,12 @@ begin -- Select input to PC on an exception -------------------- - COP0_SEL_EPC: process (is_exception, MM_nmi, MM_interrupt, STATUS, CAUSE, + COP0_SEL_EPC: process (MM_is_exception, MM_nmi, MM_interrupt, STATUS, CAUSE, MM_trapped, rom_stall, ram_stall) variable i_excp_PCsel : reg3; begin - case is_exception is + case MM_is_exception is when exERET => -- exception return i_excp_PCsel := PCsel_EXC_EPC; -- PC <= EPC @@ -2220,7 +2233,8 @@ begin when exSYSCALL | exBREAK | exRESV_INSTR | exOvfl | IFaddressError | MMaddressErrorLD | MMaddressErrorST | exTLBdblFaultIF | exTLBdblFaultRD | exTLBdblFaultWR - | exTLBinvalIF | exTLBinvalRD | exTLBinvalWR | exTLBmod => + | exTLBinvalIF | exTLBinvalRD | exTLBinvalWR | exTLBmod + | exIBE | exDBE => i_excp_PCsel := PCsel_EXC_0180; -- PC <= exception_180 when exTRAP => @@ -2327,14 +2341,15 @@ begin end if; end process COP0_COMPUTE_CAUSE; - COP0_CAUSE_HOLD: process(rst,clk, ExcCode,is_exception,MM_cop0_reg,not_stalled) + COP0_CAUSE_HOLD: process(rst,clk, ExcCode,MM_is_exception, + MM_cop0_reg,not_stalled) variable state: reg32; begin if rst = '0' then -- hold CAUSE until it is read cause_update <= '0'; elsif ( rising_edge(clk) and (ExcCode /= cop0code_NULL) ) then cause_update <= '1'; -- syscall/trap/interrupt/exception - elsif ( rising_edge(clk) and (is_exception = exMFC0) and + elsif ( rising_edge(clk) and (MM_is_exception = exMFC0) and MM_cop0_reg = cop0reg_CAUSE and (not_stalled = '1') ) then cause_update <= '0'; -- CAUSE is being read end if; @@ -2387,11 +2402,11 @@ begin -- BadVAddr -- pg 74 --------------------------- - U_BadVAddr_UPDATE: process(is_exception, RF_is_delayslot, RF_PC, EX_PC, + U_BadVAddr_UPDATE: process(MM_is_exception, RF_is_delayslot, RF_PC, EX_PC, MM_v_addr) variable i_update : std_logic; begin - case is_exception is + case MM_is_exception is when IFaddressError | exTLBrefillIF | exTLBdblFaultIF | exTLBinvalIF => if RF_is_delayslot = '1' then -- instr is in delay slot BadVAddr_inp <= EX_PC; @@ -2437,7 +2452,7 @@ begin if rst = '0' then ll_sc_bit <= '0'; elsif rising_edge(clk) then - case is_exception is + case MM_is_exception is when exERET => ll_sc_bit <= '0'; -- break SC -> LL when exLL => @@ -2685,7 +2700,7 @@ begin -- TLB_tag: 31..13 = VPN, 12..9 = 0, 8 = G, 7..0 = ASID -- TLB_dat: 29..6 = PPN, 5..3 = C, 2 = D, 1 = V, 0 = G - MMU_CONTROL: process(is_exception, INDEX, RANDOM) + MMU_CONTROL: process(MM_is_exception, INDEX, RANDOM) variable i_tlb_adr : integer range MMU_CAPACITY-1 downto 0; begin @@ -2707,7 +2722,7 @@ begin tlb_dat6_updt <= '1'; tlb_dat7_updt <= '1'; - case is_exception is + case MM_is_exception is when exTLBP => tlb_probe <= '1'; @@ -2724,7 +2739,7 @@ begin tlb_probe <= '0'; tlb_read <= '0'; - if is_exception = exTLBWI then + if MM_is_exception = exTLBWI then i_tlb_adr := to_integer(unsigned(INDEX(MMU_CAPACITY-1 downto 0))); else i_tlb_adr := to_integer(unsigned(RANDOM)); diff --git a/cMIPS/vhdl/exception.vhd b/cMIPS/vhdl/exception.vhd index bc11588588b42fd23485fc4c769c5b7dded6502c..193176046b8a62ca33bf4c84696511d2f0a11a0b 100644 --- a/cMIPS/vhdl/exception.vhd +++ b/cMIPS/vhdl/exception.vhd @@ -132,28 +132,18 @@ entity reg_excp_EX_MM is MM_addrError: out boolean; addrErr_stage_mm: in boolean; MM_addrErr_stage_mm: out boolean; - mem_excp_type: in exception_type; - MM_mem_excp_type: out exception_type; EX_is_delayslot: in std_logic; MM_is_delayslot: out std_logic; - EX_ovfl: in boolean; - MM_ex_ovfl: out boolean; EX_trapped: in boolean; MM_trapped: out boolean; - EX_pc_abort: in boolean; - MM_pc_abort: out boolean; EX_ll_sc_abort: in boolean; MM_ll_sc_abort: out boolean; - EX_exception: in exception_type; - MM_exception: out exception_type; tlb_exception: in boolean; MM_tlb_exception: out boolean; tlb_stage_mm: in boolean; MM_tlb_stage_mm: out boolean; - TLB_excp_type: in exception_type; - MM_TLB_excp_type: out exception_type; EX_nmi: in std_logic; - MM_nmi: out std_logic; + MM_nmi: out std_logic; EX_interrupt: in std_logic; MM_interrupt: out std_logic; EX_int_req: in reg8; @@ -161,8 +151,11 @@ entity reg_excp_EX_MM is EX_is_SC: in boolean; MM_is_SC: out boolean; EX_is_MFC0: in boolean; - MM_is_MFC0: out boolean); - end reg_excp_EX_MM; + MM_is_MFC0: out boolean; + EX_is_exception: in exception_type; + MM_is_exception: out exception_type + ); +end reg_excp_EX_MM; architecture funcional of reg_excp_EX_MM is begin @@ -170,12 +163,10 @@ begin begin if rst = '0' then MM_trapped <= FALSE; - MM_pc_abort <= FALSE; MM_nullify <= FALSE; MM_addrError <= FALSE; - MM_ex_ovfl <= FALSE; MM_tlb_exception <= FALSE; - MM_exception <= exNOP; + MM_is_exception <= exNOP; elsif rising_edge(clk) then if ld = '0' then MM_cop0_reg <= EX_cop0_reg ; @@ -185,21 +176,17 @@ begin MM_nullify <= nullify ; MM_addrError <= addrError ; MM_addrErr_stage_mm <= addrErr_stage_mm; - MM_mem_excp_type <= mem_excp_type ; MM_is_delayslot <= EX_is_delayslot; - MM_ex_ovfl <= EX_ovfl ; MM_trapped <= EX_trapped ; - MM_pc_abort <= EX_pc_abort ; MM_ll_sc_abort <= EX_ll_sc_abort ; - MM_exception <= EX_exception ; MM_tlb_exception <= TLB_exception ; MM_tlb_stage_MM <= tlb_stage_MM ; - MM_TLB_excp_type <= TLB_excp_type ; MM_nmi <= EX_nmi ; MM_interrupt <= EX_interrupt ; MM_int_req <= EX_int_req ; MM_is_SC <= EX_is_SC ; MM_is_MFC0 <= EX_is_MFC0 ; + MM_is_exception <= EX_is_exception; end if; end if; end process; diff --git a/cMIPS/vhdl/io.vhd b/cMIPS/vhdl/io.vhd index cc5244a50f0ba779818af7b13ff2eab85b263a00..08946e906ac39b7982bf1ba62a2e302dffc520c1 100644 --- a/cMIPS/vhdl/io.vhd +++ b/cMIPS/vhdl/io.vhd @@ -32,7 +32,6 @@ entity print_data is clk : in std_logic; sel : in std_logic; wr : in std_logic; - addr : in reg32; data : in reg32); end print_data; @@ -70,7 +69,6 @@ entity to_stdout is clk : in std_logic; sel : in std_logic; wr : in std_logic; - addr : in std_logic_vector; data : in std_logic_vector); end to_stdout; @@ -245,7 +243,6 @@ entity do_interrupt is clk : in std_logic; -- clock pulses counted sel : in std_logic; wr : in std_logic; - addr : in std_logic_vector; data_inp : in std_logic_vector; data_out : out std_logic_vector; irq : out std_logic); diff --git a/cMIPS/vhdl/packageExcp.vhd b/cMIPS/vhdl/packageExcp.vhd index f0cb26c593304abeb7ad0c65b5223da42a9021f2..0b6e556a2e24818bbb1563a6868f9f47ba6f39ad 100644 --- a/cMIPS/vhdl/packageExcp.vhd +++ b/cMIPS/vhdl/packageExcp.vhd @@ -28,15 +28,16 @@ package p_EXCEPTION is exEI,exDI, -- 5 exBREAK, exTRAP, exSYSCALL, -- 8 exRESV_INSTR, exWAIT, -- 10 - IFaddressError, MMaddressErrorLD, MMaddressErrorST, --13 + IFaddressError,MMaddressErrorLD,MMaddressErrorST,--13 exTLBrefillIF, exTLBrefillRD, exTLBrefillWR, -- 16 - exTLBdblFaultIF, exTLBdblFaultRD, exTLBdblFaultWR, -- 19 + exTLBdblFaultIF,exTLBdblFaultRD,exTLBdblFaultWR,-- 19 exTLBinvalIF, exTLBinvalRD, exTLBinvalWR, -- 22 exTLBmod, exOvfl, -- 24 - exLL,exSC, -- 25,26 these are handled by COP0 + exLL,exSC, -- 25,26 instrns handled by COP0 exEHB, -- 27 exTLBP, exTLBR, exTLBWI, exTLBWR, -- 31 exDERET, -- 32 + exIBE, exDBE, -- 34 invalid_exception); attribute enum_encoding of exception_type : type is @@ -69,9 +70,9 @@ package p_EXCEPTION is -- Table 8-25 Cause Register ExcCode Field, pg 95 constant cop0code_Int : reg5 := b"00000"; -- 0, interrupt=00 (CAUSE lsB) - constant cop0code_Mod : reg5 := b"00001"; -- 1, AddrError if/ld=x04 - constant cop0code_TLBL : reg5 := b"00010"; -- 2, AddrError if/ld=x08 - constant cop0code_TLBS : reg5 := b"00011"; -- 3, AddrError if/ld=x0c + constant cop0code_Mod : reg5 := b"00001"; -- 1, TLBmodified=x04 + constant cop0code_TLBL : reg5 := b"00010"; -- 2, TLBload if/ld=x08 + constant cop0code_TLBS : reg5 := b"00011"; -- 3, TLBstore if/ld=x0c constant cop0code_AdEL : reg5 := b"00100"; -- 4, AddrError if/ld=x10 constant cop0code_AdES : reg5 := b"00101"; -- 5, AddrError store=x14 constant cop0code_IBE : reg5 := b"00110"; -- 6, BusErrorExcp if=x18 @@ -79,6 +80,7 @@ package p_EXCEPTION is constant cop0code_Sys : reg5 := b"01000"; -- 8, syscall=x20 constant cop0code_Bp : reg5 := b"01001"; -- 9, breakpoint=x24 constant cop0code_RI : reg5 := b"01010"; -- 10, reserved instruction=x28 + constant cop0code_CpU : reg5 := b"01011"; -- 11, CopUnusable excp=x2c constant cop0code_Ov : reg5 := b"01100"; -- 12, arithmetic overflow=x30 constant cop0code_Tr : reg5 := b"01101"; -- 13, trap=x34 constant cop0code_NULL : reg5 := b"11111"; -- 1f, (no exception)=x3c diff --git a/cMIPS/vhdl/packageMemory.vhd b/cMIPS/vhdl/packageMemory.vhd index 8edf7bcc3d775edf7bb1ff433ecf95cc6b611cb2..3e0e7994a91947ccff9c27e6878a64f7c3b6e794 100644 --- a/cMIPS/vhdl/packageMemory.vhd +++ b/cMIPS/vhdl/packageMemory.vhd @@ -42,7 +42,7 @@ package p_MEMORY is -- you may change the values, not names neither formatting -- constant x_INST_BASE_ADDR : reg32 := x"00000000"; constant x_INST_MEM_SZ : reg32 := x"00004000"; - constant x_DATA_BASE_ADDR : reg32 := x"00010000"; + constant x_DATA_BASE_ADDR : reg32 := x"00020000"; constant x_DATA_MEM_SZ : reg32 := x"00008000"; constant x_IO_BASE_ADDR : reg32 := x"0F000000"; constant x_IO_MEM_SZ : reg32 := x"00002000"; diff --git a/cMIPS/vhdl/tb_cMIPS.vhd b/cMIPS/vhdl/tb_cMIPS.vhd index f54e3cf03898c1ebca637f68803b7e24eab7f21e..2ad57d84fd65fc4c0ac6774e2f9a1c1f8c472d82 100644 --- a/cMIPS/vhdl/tb_cMIPS.vhd +++ b/cMIPS/vhdl/tb_cMIPS.vhd @@ -76,7 +76,6 @@ architecture TB of tb_cMIPS is clk : in std_logic; sel : in std_logic; wr : in std_logic; - addr : in std_logic_vector; data : in std_logic_vector); end component print_data; @@ -85,7 +84,6 @@ architecture TB of tb_cMIPS is clk : in std_logic; sel : in std_logic; wr : in std_logic; - addr : in std_logic_vector; data : in std_logic_vector); end component to_stdout; @@ -117,7 +115,6 @@ architecture TB of tb_cMIPS is clk : in std_logic; sel : in std_logic; wr : in std_logic; - addr : in std_logic_vector; data_inp : in std_logic_vector; data_out : out std_logic_vector; irq : out std_logic); @@ -215,11 +212,19 @@ architecture TB of tb_cMIPS is not_waiting : in std_logic); end component io_addr_decode; + component busError_addr_decode is + port (rst : in std_logic; + cpu_d_aVal : in std_logic; + addr : in reg32; + d_busError : out std_logic); -- decoded address not in range (act=0) + end component busError_addr_decode; + component inst_addr_decode is port (rst : in std_logic; cpu_i_aVal : in std_logic; addr : in std_logic_vector; - aVal : out std_logic); + aVal : out std_logic; + i_busError : out std_logic); end component inst_addr_decode; component simul_ROM is @@ -386,7 +391,9 @@ architecture TB of tb_cMIPS is wr : out std_logic; b_sel : out std_logic_vector; nmi : in std_logic; - irq : in std_logic_vector); + irq : in std_logic_vector; + i_busErr : in std_logic; + d_busErr : in std_logic); end component core; component mf_altpll port ( @@ -418,7 +425,7 @@ architecture TB of tb_cMIPS is 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 nmi, i_busError, d_busError : std_logic; signal irq : reg6; signal inst_aVal, inst_wait, rom_rdy : std_logic := '1'; signal data_aVal, data_wait, ram_rdy, mem_wr : std_logic; @@ -509,14 +516,13 @@ begin -- TB -- irq <= counter_irq & b"00000"; -- counter interrupts nmi <= '0'; -- input port to TB - 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); + wr, cpu_xfer, nmi, irq, i_busError, d_busError); U_INST_ADDR_DEC: inst_addr_decode - port map (rst, cpu_i_aVal, i_addr, inst_aVal); + port map (rst, cpu_i_aVal, i_addr, inst_aVal, i_busError); U_I_CACHE: fake_i_cache -- or i_cache -- U_I_CACHE: i_cache -- or fake_i_cache @@ -529,6 +535,9 @@ begin -- TB -- U_ROM: fpga_ROM generic map ("prog.bin") port map (rst, clk, mem_i_sel,rom_rdy, phi3, mem_i_addr,datrom); + U_DATA_BUS_ERROR_DEC: busError_addr_decode + port map (rst, cpu_d_aVal, d_addr, d_busError); + U_IO_ADDR_DEC: io_addr_decode port map (phi0, rst, cpu_d_aVal, d_addr, dev_select_io, io_print_sel, io_stdout_sel, io_stdin_sel,io_read_sel, @@ -537,7 +546,7 @@ begin -- TB not_waiting); U_DATA_ADDR_DEC: ram_addr_decode - port map (rst, cpu_d_aVal, d_addr, data_aVal, dev_select_ram); + port map (rst, cpu_d_aVal, d_addr,data_aVal, dev_select_ram); dev_select <= dev_select_io or dev_select_ram; @@ -575,13 +584,13 @@ begin -- TB port map (rst,clk, io_write_sel, wr, d_addr,cpu_data, cpu_xfer, dump_ram); U_print_data: print_data - port map (rst,clk, io_print_sel, wr, d_addr, cpu_data); + port map (rst,clk, io_print_sel, wr, cpu_data); U_to_stdout: to_stdout - port map (rst,clk, io_stdout_sel, wr, d_addr, cpu_data); + port map (rst,clk, io_stdout_sel, wr, cpu_data); U_interrupt_counter: do_interrupt -- external counter+interrupt - port map (rst,clk, io_counter_sel, wr, d_addr, cpu_data, + port map (rst,clk, io_counter_sel, wr, cpu_data, counter_d_out, counter_irq); U_to_7seg: to_7seg @@ -655,7 +664,8 @@ entity inst_addr_decode is -- CPU side triggers access port (rst : in std_logic; cpu_i_aVal : in std_logic; -- CPU instr addr valid (act=0) addr : in reg32; -- CPU address - aVal : out std_logic); -- decoded address in range (act=0) + aVal : out std_logic; -- decoded address in range (act=0) + i_busError : out std_logic); -- decoded address not in range (act=0) end entity inst_addr_decode; architecture behavioral of inst_addr_decode is @@ -667,6 +677,10 @@ begin aVal <= '0' when ( cpu_i_aVal = '0' and rst = '1' and (addr(HI_ADDR downto LO_ADDR) = PREFIX) ) else '1'; + + i_busError <= '0' when ( cpu_i_aVal = '0' and rst = '1' + and (addr(HI_ADDR downto LO_ADDR) /= PREFIX) ) + else '1'; end architecture behavioral; --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -681,7 +695,7 @@ use IEEE.numeric_std.all; use work.p_wires.all; use work.p_memory.all; -entity ram_addr_decode is -- CPU side triggers access +entity ram_addr_decode is -- CPU side triggers access port (rst : in std_logic; cpu_d_aVal : in std_logic; -- CPU data addr valid (active=0) addr : in reg32; -- CPU address @@ -690,27 +704,139 @@ entity ram_addr_decode is -- CPU side triggers access end entity ram_addr_decode; architecture behavioral of ram_addr_decode is - constant LO_ADDR : integer := log2_ceil(DATA_BASE_ADDR); - constant HI_ADDR : integer := log2_ceil(DATA_BASE_ADDR + DATA_MEM_SZ - 1); - constant in_r : std_logic_vector(HI_ADDR downto LO_ADDR) := (others => '1'); - constant ng_r : std_logic_vector(HI_ADDR downto LO_ADDR) := (others => '0'); - constant oth : std_logic_vector(HI_SEL_BITS downto HI_ADDR+1):=(others=>'1'); - constant ng_o : std_logic_vector(HI_SEL_BITS downto HI_ADDR+1):=(others=>'0'); + constant LO_ADDR : natural := log2_ceil(DATA_BASE_ADDR); + constant HI_ADDR : natural := log2_ceil(DATA_BASE_ADDR + DATA_MEM_SZ - 1); + + constant all_0 : std_logic_vector(31 downto 0) := (others=>'0'); + + constant a_hi : std_logic_vector(31 downto HI_ADDR+1) := (others=>'0'); + constant a_lo : std_logic_vector(LO_ADDR-1 downto 0) := (others=>'0'); + constant a_bits : std_logic_vector(HI_ADDR downto LO_ADDR) := (others=>'1'); + constant a_mask : std_logic_vector := a_hi & a_bits & a_lo; + + constant LO_RAM : natural := 0; + constant HI_RAM : natural := log2_ceil(DATA_MEM_SZ-1); + constant r_hi : std_logic_vector(31 downto HI_RAM+1) := (others=>'1'); + constant r_lo : std_logic_vector(HI_RAM downto LO_RAM) := (others=>'0'); + constant r_mask : std_logic_vector := r_hi & r_lo; + + signal in_range : boolean; + begin - aVal <= '0' when ( cpu_d_aVal = '0' and rst = '1' and - ((addr(HI_ADDR downto LO_ADDR) and in_r) /= ng_r) and - ((addr(HI_SEL_BITS downto HI_ADDR+1) and oth) = ng_o) - ) else - '1'; + in_range <= ( rst = '1' + and ((addr and a_mask) = x_DATA_BASE_ADDR) + and ((addr and r_mask) = x_DATA_BASE_ADDR) ); + + aVal <= '0' when (cpu_d_aVal = '0' and in_range) else '1'; + + dev_select <= b"0001" when (cpu_d_aVal = '0' and in_range) else b"0000"; + + assert true -- cpu_d_aVal = '1' + report "e " & SLV32HEX(addr) & + " addr " & SLV2str(addr(15 downto 0)) & LF & + " LO_AD " & integer'image(LO_ADDR) & + " HI_AD " & integer'image(HI_ADDR) & + " a_hi " & SLV2STR(a_hi) & + " a_lo " & SLV2STR(a_lo) & + " a_bits " & SLV2STR(a_bits) & + " a_mask " & SLV32HEX(a_mask) & LF & + " LO_RAM " & integer'image(LO_RAM) & + " HI_RAM " & integer'image(HI_RAM) & + " r_hi " & SLV2STR(r_hi) & + " r_lo " & SLV2STR(r_lo) & + " r_mask " & SLV32HEX(r_mask) + severity NOTE; + +end architecture behavioral; +--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - dev_select <= b"0001" when - ( cpu_d_aVal = '0' and rst = '1' and - ((addr(HI_ADDR downto LO_ADDR) and in_r) /= ng_r) and - ((addr(HI_SEL_BITS downto HI_ADDR+1) and oth) = ng_o) - ) else - b"0000"; - + +--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +-- busError address decoding +--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.p_wires.all; +use work.p_memory.all; + +entity busError_addr_decode is -- CPU side triggers access + port (rst : in std_logic; + cpu_d_aVal : in std_logic; -- CPU data addr valid (active=0) + addr : in reg32; -- CPU address + d_busError : out std_logic); -- decoded address not in range (act=0) +end entity busError_addr_decode; + +architecture behavioral of busError_addr_decode is + + constant all_0 : std_logic_vector(31 downto 0) := (others=>'0'); + + -- I/O constants + constant IO_RANGE : integer := IO_ADDR_RANGE * IO_MAX_NUM_DEVS; + constant LO_DEV : natural := 0; + constant HI_DEV : natural := log2_ceil(IO_RANGE-1); + + constant x_hi : std_logic_vector(31 downto HI_DEV) := (others=>'1'); + constant x_lo : std_logic_vector(HI_DEV-1 downto 0) := (others=>'0'); + constant x_mask : std_logic_vector := x_hi & x_lo; -- 1..10..0 + + -- RAM constants + constant LO_ADDR : natural := log2_ceil(DATA_BASE_ADDR); + constant HI_ADDR : natural := log2_ceil(DATA_BASE_ADDR + DATA_MEM_SZ - 1); + + constant a_hi : std_logic_vector(31 downto HI_ADDR+1) := (others=>'0'); + constant a_lo : std_logic_vector(LO_ADDR-1 downto 0) := (others=>'0'); + constant a_bits : std_logic_vector(HI_ADDR downto LO_ADDR) := (others=>'1'); + constant a_mask : std_logic_vector := a_hi & a_bits & a_lo; -- 0..0110..0 + + constant LO_RAM : natural := 0; + constant HI_RAM : natural := log2_ceil(DATA_MEM_SZ-1); + constant r_hi : std_logic_vector(31 downto HI_RAM+1) := (others=>'1'); + constant r_lo : std_logic_vector(HI_RAM downto LO_RAM) := (others=>'0'); + constant r_mask : std_logic_vector := r_hi & r_lo; -- 1..10..0 + + signal in_range, io_in_range : boolean; + +begin + + in_range <= ( rst = '1' and + ((addr and a_mask) = x_DATA_BASE_ADDR) and + ((addr and r_mask) = x_DATA_BASE_ADDR) ); + + io_in_range <= ( (rst = '1') and ((addr and x_mask) = x_IO_BASE_ADDR) ); + + + d_busError <= '0' when ( (rst = '1') and (cpu_d_aVal = '0') and + (not(in_range) and not(io_in_range)) ) else '1'; + + + assert true -- cpu_d_aVal = '1' + report "e " & SLV32HEX(addr) & + " addr " & SLV2str(addr(15 downto 0)) & LF & + " LO_AD " & integer'image(LO_ADDR) & + " HI_AD " & integer'image(HI_ADDR) & + " a_hi " & SLV2STR(a_hi) & + " a_lo " & SLV2STR(a_lo) & + " a_bits " & SLV2STR(a_bits) & + " a_mask " & SLV32HEX(a_mask) & LF & + " LO_RAM " & integer'image(LO_RAM) & + " HI_RAM " & integer'image(HI_RAM) & + " r_hi " & SLV2STR(r_hi) & + " r_lo " & SLV2STR(r_lo) & + " r_mask " & SLV32HEX(r_mask) + severity NOTE; + + assert true -- cpu_d_aVal = '1' and io_busError + report "e " & SLV32HEX(addr) & + " addr " & SLV2str(addr(15 downto 0)) & LF & + " x_hi " & SLV2STR(x_hi) & + " x_lo " & SLV2STR(x_lo) & + " x_mask " & SLV32HEX(x_mask) & LF & + " LO_DEV " & integer'image(LO_DEV) & + " HI_DEV " & integer'image(HI_DEV) + severity NOTE; + end architecture behavioral; --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -748,25 +874,25 @@ architecture behavioral of io_addr_decode is constant LO_SEL_ADDR : integer := log2_ceil(IO_ADDR_RANGE); constant HI_SEL_ADDR : integer := LO_SEL_ADDR + (IO_MAX_NUM_DEVS - 1); + constant all_0 : std_logic_vector(31 downto 0) := (others=>'0'); + + -- I/O constants constant IO_RANGE : integer := IO_ADDR_RANGE * IO_MAX_NUM_DEVS; - constant LO_ADDR : integer := log2_ceil(IO_BASE_ADDR); - constant HI_ADDR : integer := log2_ceil(IO_BASE_ADDR + IO_RANGE - 1); - constant in_r : std_logic_vector(HI_ADDR downto LO_ADDR) := (others => '1'); - constant ng_r : std_logic_vector(HI_ADDR downto LO_ADDR) := (others => '0'); - constant oth : std_logic_vector(HI_SEL_BITS downto HI_ADDR+1):=(others=>'1'); - constant ng_o : std_logic_vector(HI_SEL_BITS downto HI_ADDR+1):=(others=>'0'); + constant LO_DEV : natural := 0; + constant HI_DEV : natural := log2_ceil(IO_RANGE-1); + constant x_hi : std_logic_vector(31 downto HI_DEV) := (others=>'1'); + constant x_lo : std_logic_vector(HI_DEV-1 downto 0) := (others=>'0'); + constant x_mask : std_logic_vector := x_hi & x_lo; -- 1..10..0 + signal aVal : std_logic; signal dev : integer; -- DEBUGGING only begin aVal <= '0' when ( cpu_d_aVal = '0' and rst = '1' and not_waiting = '1' and - ((addr(HI_ADDR downto LO_ADDR) and in_r) /= ng_r) and - ((addr(HI_SEL_BITS downto HI_ADDR+1) and oth) = ng_o) - ) else + ((addr and x_mask) = x_IO_BASE_ADDR) ) else '1'; - - + dev <= to_integer(signed(addr(HI_SEL_ADDR downto LO_SEL_ADDR))); U_decode: process(clk, aVal, addr, dev) diff --git a/cMIPS/vhdl/units.vhd b/cMIPS/vhdl/units.vhd index 818573eb236d15206890712b6f69ea50c9064c12..dff8a7d38e1a13b8912b34a60277d6608bf50282 100644 --- a/cMIPS/vhdl/units.vhd +++ b/cMIPS/vhdl/units.vhd @@ -669,9 +669,7 @@ begin w_d <= this xor cycle; -- active for ONE cycle only - w <= w_d and sel; - - waiting <= w and will_wait; + waiting <= not(w_d) and n_sel and will_wait; end; -- ++ wait_states +++++++++++++++++++++++++++++++++++++++++++++++++++++