diff --git a/cMIPS/bin/assemble.sh b/cMIPS/bin/assemble.sh index f41a4b047f13e8589a4d38271092a273bf25730e..5fa45a869aafe98d10fbbc590e529299abf403bf 100755 --- a/cMIPS/bin/assemble.sh +++ b/cMIPS/bin/assemble.sh @@ -32,6 +32,7 @@ OPTIONS: -h Show this message -O n Optimization level, defaults to n=0 {0,1,2,3} -v Verbose, creates memory map: SOURCE.map + -n when verbose, display register names instead of numbers -mif Generate output file ROM.mif for Altera's FPGAs EOF } @@ -54,6 +55,7 @@ if [ $# = 0 ] ; then usage ; exit 1 ; fi miffile=false verbose=false +names=false unset mem_map level=0 @@ -82,6 +84,8 @@ while true ; do ;; -v) verbose=true ;; + -n) names=true + ;; -mif|-m) miffile=true ;; -x) set -x @@ -105,6 +109,12 @@ fi if [ $verbose = true ] ; then mem_map="-Map ${inp}.map" ; fi +if [ $names = true ] ; then + reg_names="-M reg-names=mips2r2 -M cp0-names=mips2r2" +else + reg_names="-M reg-names=numeric -M cp0-names=numeric" +fi + asm=${inp}.s obj=${inp}.o elf=${inp}.elf @@ -114,18 +124,15 @@ dat=data.bin (mips-as -O${level} -EL -mips32r2 -I "${include}" -o $obj $asm || exit 1) &&\ mips-ld -EL ${mem_map} -I "${include}" --script $c_ld -o $elf $obj &&\ mips-objcopy -S -j .text -O binary $elf $bin &&\ - mips-objcopy -S -j .data -j .rodata -O binary $elf $dat &&\ + mips-objcopy -S -j .data -j .rodata -j .PT -O binary $elf $dat &&\ chmod a-x $bin $dat &&\ if [ $verbose = true ] ; then - mips-objdump -z -D -EL -M reg-names=numeric -M cp0-names=mips2r2 \ - --show-raw-insn \ + mips-objdump -z -D -EL $reg_names --show-raw-insn \ --section .text --section .data --section .rodata --section .bss $elf fi &&\ if [ $miffile = true ] ; then elf2mif.sh "$elf" || exit 1 - fi -# -M reg-names=mips2r2 -M cp0-names=mips2r2 reg-names=numeric \ # --section .reginfo diff --git a/cMIPS/bin/compile.sh b/cMIPS/bin/compile.sh index afe7779c80977944f2d9861df5a569a1337e0c6d..a1e8d9f9541d245e593158248a2aa88317de1f3c 100755 --- a/cMIPS/bin/compile.sh +++ b/cMIPS/bin/compile.sh @@ -33,6 +33,7 @@ OPTIONS: -h Show this message -O n Optimization level, defaults to n=1 {0,1,2,3} -v Verbose, creates memory map: source.map + -n when verbose, display register numbers instead of names -W Pass -Wall on to GCC -mif Generate output file ROM.mif for Altera's FPGAs -syn Compile for synthesis, else for simulation @@ -57,6 +58,7 @@ if [ $# = 0 ] ; then usage ; exit 1 ; fi miffile=false synth=false verbose=false +names=true unset memory_map level=1 @@ -80,6 +82,8 @@ while true ; do ;; -v) verbose=true ;; + -n) names=false + ;; -mif) miffile=true ;; -syn) synth=true @@ -146,15 +150,20 @@ mips-ld -EL -e _start ${memory_map} -I "${include}" --script $c_ld \ mips-objcopy -S -j .text -O binary $elf $bin && \ mips-objcopy -S -j .data -j .rodata -j .rodata1 -j .data1 \ - -j .sdata -j .lit8 -j .lit4 -j .sbss -j .bss \ + -j .sdata -j .lit8 -j .lit4 -j .sbss -j .bss -j .PT \ -O binary $elf $dat || exit 1 +if [ $names = true ] ; then + reg_names="-M reg-names=mips2r2 -M cp0-names=mips2r2" +else + reg_names="-M reg-names=numeric -M cp0-names=numeric" +fi + if [ $? == 0 -a $verbose = true ]; then - mips-objdump -z -D -EL -M reg-names=mips2r2 -M cp0-names=mips2r2 \ - --show-raw-insn \ + mips-objdump -z -D -EL $reg_names --show-raw-insn \ --section .text --section .data \ --section .rodata --section .sdata --section .sbss \ - --section .bss $elf + --section .bss --section .PT $elf fi if [ $? == 0 -a $miffile = true ] ; then diff --git a/cMIPS/docs/cMIPS.pdf b/cMIPS/docs/cMIPS.pdf index 132dcc6716f71839a57c6520fa453512337bedb6..618b22b3bf03a1be1beb0ddfbf230e4f0284cd0b 100644 Binary files a/cMIPS/docs/cMIPS.pdf and b/cMIPS/docs/cMIPS.pdf differ diff --git a/cMIPS/include/cMIPS.h b/cMIPS/include/cMIPS.h index d718c68f882fa6720170270cb2988e5a3cc55d76..ea9ad50cbe8c61251abb2af4bc67848281483ba3 100644 --- a/cMIPS/include/cMIPS.h +++ b/cMIPS/include/cMIPS.h @@ -1,6 +1,7 @@ #define x_INST_BASE_ADDR 0x00000000 -#define x_DATA_BASE_ADDR 0x00010000 +#define x_DATA_BASE_ADDR 0x00040000 +#define x_DATA_MEM_SZ 0x00020000 #define x_SDRAM_BASE_ADDR 0x04000000 #define x_SDRAM_MEM_SZ 0x02000000 #define x_IO_BASE_ADDR 0x3c000000 diff --git a/cMIPS/include/cMIPS.ld b/cMIPS/include/cMIPS.ld index 9f4bd2cc4fad09fae1c042d7c37c8602c216e6bd..fa13f2198607ac5fec345fdb95ee5b247207b658 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 = 0x00008000, /* x_DATA_MEM_SZ */ + ram (!rx) : ORIGIN = 0x00040000, /* x_DATA_BASE_ADDR */ + LENGTH = 0x00020000, /* x_DATA_MEM_SZ */ sdram (!rx) : ORIGIN = 0x04000000, /* x_SDRAM_BASE_ADDR */ LENGTH = 0x02000000, /* x_SDRAM_MEM_SZ */ io (!rx) : ORIGIN = 0x3c000000, /* not used, do not remove */ @@ -40,8 +40,9 @@ SECTIONS _end = . ; /* end of image constant (from Xinu) */ } > ram - end_RAM = 0x00008000; /* x_DATA_MEM_SZ */ + end_RAM = 0x00020000; /* x_DATA_MEM_SZ */ half_RAM = (end_RAM / 2); - base_TP = ( _bdata + half_RAM ); - .TP base_TP : { *(.TP) } > ram + base_PT = ( _bdata + half_RAM ); + .PT base_PT : { *(.PT) } > ram } + diff --git a/cMIPS/include/cMIPS.s b/cMIPS/include/cMIPS.s index d6636a560114ca566e352eeb84910eadebd6ce6f..67514d9c36994145484ce1f4e95602bb3450015a 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,0x00010000 - .set x_DATA_MEM_SZ,0x00008000 + .set x_DATA_BASE_ADDR,0x00040000 + .set x_DATA_MEM_SZ,0x00020000 .set x_IO_BASE_ADDR,0x3c000000 .set x_IO_MEM_SZ,0x00002000 @@ -71,8 +71,9 @@ # reset: COP0 present, at exception level, all else disabled .set cop0_STATUS_reset,0x10000002 - .set c0_status_reset, cop0_STATUS_reset + + # normal state: COP0 present, user mode, all IRQs enabled + .set cop0_STATUS_normal,0x1000ff11 # reset: COUNTER stopped, use special interrVector, no interrupts .set cop0_CAUSE_reset, 0x0880007c - .set c0_cause_reset, cop0_CAUSE_reset diff --git a/cMIPS/include/cMIPSio.c b/cMIPS/include/cMIPSio.c index b00322f357ce83c2a72f11306125077126e915a9..d8f781bd6e82d0c9fd08e84b8f6acab6bf8afd27 100644 --- a/cMIPS/include/cMIPSio.c +++ b/cMIPS/include/cMIPSio.c @@ -348,10 +348,10 @@ void DSP7SEGput(int MSD, int MSdot, int lsd, int lsdot) { //======================================================================= -// external counter -- counts down to zero and stops or interrupts +// external counter -- counts up to limit, then stops or interrupts //======================================================================= // write an integer with number of pulses to count and start counter -// if interr is not 0, then will interrupt when count reaches zero +// if interr is not 0, then raise an interrupt when count reaches 'n' void startCounter(int n, int interr) { int *IO = (int *)IO_COUNT_ADDR; int interrupt; diff --git a/cMIPS/include/handlers.s b/cMIPS/include/handlers.s index 1889009961f6a5f6a8ae4141590338af4a53cdbe..ebb702a1cd4f10fb413507147a97da07a11324ad 100644 --- a/cMIPS/include/handlers.s +++ b/cMIPS/include/handlers.s @@ -4,7 +4,7 @@ .set noreorder .align 2 - .set M_StatusIEn,0x0000ff09 # STATUS.intEn=1, user mode + .set M_StatusIEn,0x0000ff11 # STATUS.intEn=1, user mode #---------------------------------------------------------------- # interrupt handler for external counter attached to IP5=HW3 @@ -57,11 +57,11 @@ extCounter: # lw $a1, 1*4($k1) #---------------------------------- - mfc0 $k0, cop0_STATUS # Read STATUS register + mfc0 $k0, c0_status # Read STATUS register ori $k0, $k0, M_StatusIEn # but do not modify its contents addiu $k1, $zero, -7 # except for re-enabling interrupts and $k0, $k1, $k0 # -7 = 0xffff.fff9 - mtc0 $k0, cop0_STATUS + mtc0 $k0, c0_status eret # Return from interrupt .end extCounter #---------------------------------------------------------------- @@ -102,10 +102,10 @@ UARTinterr: lui $k0, %hi(_uart_buff) ori $k0, $k0, %lo(_uart_buff) - sw $k1, 0($k0) # and save UART status to memory + sw $k1, 0*4($k0) # and save UART status to memory - sw $a0, 12($k0) # save registers $a0,$a1, others? - sw $a1, 16($k0) + sw $a0, 5*4($k0) # save registers $a0,$a1, others? + sw $a1, 6*4($k0) #---------------------------------- # while you are developing the complete handler, @@ -115,7 +115,7 @@ UARTinterr: andi $a0, $k1, UART_rx_irq # Is this reception? beq $a0, $zero, UARTret # no, ignore it and return - + lui $a0, %hi(HW_uart_addr) ori $a0, $a0, %lo(HW_uart_addr) lw $a1, 4($a0) # Read data @@ -125,14 +125,14 @@ UARTinterr: sw $a1, 8($k0) # Signal new arrival UARTret: - lw $a1, 16($k0) # restore registers $a0,$a1, others? - lw $a0, 12($k0) + lw $a1, 6*4($k0) # restore registers $a0,$a1, others? + lw $a0, 5*4($k0) - mfc0 $k0, cop0_STATUS # Read STATUS register + mfc0 $k0, c0_status # Read STATUS register ori $k0, $k0, M_StatusIEn # but do not modify its contents addiu $k1, $zero, -7 # except for re-enabling interrupts and $k0, $k1, $k0 # -7 = 0xffff.fff9 = user mode - mtc0 $k0, cop0_STATUS + mtc0 $k0, c0_status eret # Return from interrupt .end UARTinterr #---------------------------------------------------------------- @@ -145,16 +145,16 @@ UARTret: .global countCompare .ent countCompare countCompare: - mfc0 $k1,cop0_COUNT # read COMPARE and clear IRQ + mfc0 $k1,c0_count # read COMPARE and clear IRQ addiu $k1,$k1,64 # set next interrupt in 64 ticks - mtc0 $k1,cop0_COMPARE + mtc0 $k1,c0_compare - mfc0 $k0, cop0_STATUS # Read STATUS register + mfc0 $k0, c0_status # Read STATUS register ori $k0, $k0, M_StatusIEn # but do not modify its contents lui $k1, 0xffff # except for re-enabling interrupts ori $k1, $k1, 0xfff9 # and going into user mode and $k0, $k1, $k0 - mtc0 $k0, cop0_STATUS + mtc0 $k0, c0_status eret # Return from interrupt .end countCompare #---------------------------------------------------------------- diff --git a/cMIPS/include/start.s b/cMIPS/include/start.s index f32602b706a0e023ed186d519aeffe3a0e425688..9652e4e38efce0ce15d93c5068ff19bb0cf4117c 100644 --- a/cMIPS/include/start.s +++ b/cMIPS/include/start.s @@ -21,67 +21,113 @@ _start: # needed so simulations without a page table will not break # read TLB[4] and write it to TLB[2] li $k0, 4 - mtc0 $k0, cop0_Index + mtc0 $k0, c0_index ehb tlbr li $k1, 2 - mtc0 $k1, cop0_Index + mtc0 $k1, c0_index ehb tlbwi + +#### this is not needed when simulating with a PageTable +# +# # then set another mapping onto TLB[4] to avoid replicated entries +# li $a0, ( (x_DATA_BASE_ADDR + 8*4096) >>13 )<<13 +# mtc0 $a0, c0_entryhi # tag for RAM[8,9] double-page +# +# li $a0, ((x_DATA_BASE_ADDR + 8*4096) >>12)<<6 # RAM[8] (even) +# ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 +# mtc0 $a1, c0_entrylo0 +# +# li $a0, ((x_DATA_BASE_ADDR + 9*4096) >>12)<<6 # RAM[9] (odd) +# ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 +# mtc0 $a1, c0_entrylo1 +# +# # and write it to TLB[4] +# li $k0, 4 +# mtc0 $k0, c0_index +# tlbwi +#### + # + # the page table is located at the middle of the RAM + # bottom half is reserved for "RAM memory", top for page table + # + .set TOP_OF_RAM, (x_DATA_BASE_ADDR + x_DATA_MEM_SZ) + .set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2)) - # then set another mapping onto TLB[4], to avoid replicated entries - li $a0, ( (x_DATA_BASE_ADDR + 8*4096) >>12 ) - sll $a2, $a0, 12 # tag for RAM[8,9] double-page - mtc0 $a2, cop0_EntryHi + # get physical page number for two pages at the top of RAM, for stack + la $a0, ( (MIDDLE_RAM - 2*4096) >>13 )<<13 + mtc0 $a0, c0_entryhi # tag for top double-page - li $a0, ((x_DATA_BASE_ADDR + 8*4096) >>12 ) - sll $a1, $a0, 6 # RAM[8] (even) - ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 - mtc0 $a1, cop0_EntryLo0 + la $a0, ( (MIDDLE_RAM - 2*4096) >>12 )<<6 + ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 + mtc0 $a1, c0_entrylo0 # top page - 2 (even) - li $a0, ( (x_DATA_BASE_ADDR + 9*4096) >>12 ) - sll $a1, $a0, 6 # RAM[9] (odd) - ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 - mtc0 $a1, cop0_EntryLo1 + la $a0, ( (MIDDLE_RAM - 1*4096) >>12 )<<6 + ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 + mtc0 $a1, c0_entrylo1 # top page - 1 (odd) - # and write it to TLB[4] - li $k0, 4 - mtc0 $k0, cop0_Index + # and write it to TLB[3] + li $k0, 3 + mtc0 $k0, c0_index tlbwi - - # get physical page number for two pages at the top of RAM, for stack - li $a0, ( (x_DATA_BASE_ADDR+x_DATA_MEM_SZ - 2*4096) >>12 ) - sll $a2, $a0, 12 # tag for top double-page - mtc0 $a2, cop0_EntryHi + # then set another mapping onto TLB[7], to avoid replicated entries + li $a0, ( (x_DATA_BASE_ADDR + 10*4096) >>13 )<<13 + mtc0 $a0, c0_entryhi # tag for RAM[10,11] double-page - li $a0, ( (x_DATA_BASE_ADDR+x_DATA_MEM_SZ - 2*4096) >>12 ) - sll $a1, $a0, 6 # top page - 2 (even) - ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 - mtc0 $a1, cop0_EntryLo0 + li $a0, ((x_DATA_BASE_ADDR + 10*4096) >>12)<<6 # RAM[10] (even) + ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 + mtc0 $a1, c0_entrylo0 - li $a0, ( (x_DATA_BASE_ADDR+x_DATA_MEM_SZ - 1*4096) >>12 ) - sll $a1, $a0, 6 # top page - 1 (odd) - ori $a1, $a1, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 - mtc0 $a1, cop0_EntryLo1 + li $a0, ((x_DATA_BASE_ADDR + 11*4096) >>12)<<6 # RAM[11] (odd) + ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 + mtc0 $a1, c0_entrylo1 - # and write it to TLB[3] - li $k0, 3 - mtc0 $k0, cop0_Index + # and write it to TLB[7] + li $k0, 7 + mtc0 $k0, c0_index + tlbwi + + + # get physical page number for two pages at the bottom of PageTable + la $a0, ( MIDDLE_RAM >>13 )<<13 + mtc0 $a0, c0_entryhi # tag for bottom double-page + + la $a0, ( (MIDDLE_RAM + 0*4096) >>12 )<<6 + ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 + mtc0 $a1, c0_entrylo0 # bottom page (even) + + la $a0, ( (MIDDLE_RAM + 1*4096) >>12 )<<6 + ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1 + mtc0 $a1, c0_entrylo1 # bottom page + 1 (odd) + + # and write it to TLB[4] + li $k0, 4 + mtc0 $k0, c0_index tlbwi - # pin down first four TLB entries: ROM[0], RAM[0], stack and I/O - li $k0, 4 - mtc0 $k0, cop0_Wired + + # pin down first five TLB entries: ROM[0], I/O, RAM[0], stack, PgTbl + li $k0, 5 + mtc0 $k0, c0_wired + + + # write PageTable base address to Context + la $k0, MIDDLE_RAM + mtc0 $k0, c0_context - # initialize SP at top of RAM: ramTop - 16 - li $sp, ((x_DATA_BASE_ADDR+x_DATA_MEM_SZ) - 16) - # set STATUS, cop0, hw interrupt IRQ7,IRQ6,IRQ5 enabled, user mode - li $k0, 0x1000e011 - mtc0 $k0, cop0_STATUS + # initialize SP at top of usable RAM: (middle of ram) - 16 + la $sp, (MIDDLE_RAM - 16) + + # set STATUS, cop0, hw interrupts IRQ7,IRQ6,IRQ5 enabled, user mode + li $k0, cop0_STATUS_normal + mtc0 $k0, c0_status + + jal main # on returning from main(), MUST go into exit() nop # to stop the simulation. exit: @@ -108,11 +154,11 @@ _excp_0000: .set noreorder .set noat - mfc0 $k1, cop0_Context - lw $k0, 0($k1) # k0 <- TP[Context.lo] - lw $k1, 8($k1) # k1 <- TP[Context.hi] - mtc0 $k0, cop0_EntryLo0 # EntryLo0 <- k0 = even element - mtc0 $k1, cop0_EntryLo1 # EntryLo1 <- k1 = odd element + mfc0 $k1, c0_context + lw $k0, 0($k1) # k0 <- TP[context.lo] + lw $k1, 8($k1) # k1 <- TP[context.hi] + mtc0 $k0, c0_entrylo0 # EntryLo0 <- k0 = even element + mtc0 $k1, c0_entrylo1 # EntryLo1 <- k1 = odd element ehb tlbwr # update TLB eret @@ -131,8 +177,8 @@ _excp_0100: .set noat la $k0, x_IO_BASE_ADDR # PANIC: SHOULD NEVER GET HERE - mfc0 $k1, cop0_CAUSE - sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation + mfc0 $k1, c0_cause + sw $k1, 0($k0) # print CAUSE, flush pipe and kill simulation nop nop nop @@ -158,11 +204,11 @@ _excp_0100: .org x_EXCEPTION_0180,0 # exception vector_180 .ent _excp_0180 _excp_0180: - mfc0 $k0, cop0_STATUS + mfc0 $k0, c0_status lui $k1, %hi(_excp_saves) ori $k1, $k1, %lo(_excp_saves) sw $k0, 1*4($k1) - mfc0 $k0, cop0_CAUSE + mfc0 $k0, c0_cause sw $k0, 0*4($k1) andi $k0, $k0, 0x3f # keep only the first 16 ExceptionCodes & b"00" @@ -174,7 +220,7 @@ _excp_0180: nop excp_tbl: # see Table 8-25, pg 95,96 - wait 0x02 # interrupt, should never arrive here, abort simulation + wait 0x02 # interrupt, should never get here, abort simulation nop j h_Mod # 1 @@ -219,7 +265,7 @@ excp_tbl: # see Table 8-25, pg 95,96 wait 0x0f # FP exception, should never get here -- abort simulation nop - + h_Mod: h_TLBL: h_TLBS: @@ -233,13 +279,12 @@ excp_0180ret: lui $k1, %hi(_excp_saves) # Read previous contents of STATUS ori $k1, $k1, %lo(_excp_saves) lw $k0, 1*4($k1) - # mfc0 $k0, cop0_STATUS - - lui $k1, 0xffff # and do not modify its contents - ori $k1, $k1, 0xfff1 # except for re-enabling interrupts + # mfc0 $k0, c0_status + # and do not modify its contents + addi $k1, $zero, -15 # except for re-enabling interrupts ori $k0, $k0, M_StatusIEn # and keeping user/kernel mode and $k0, $k1, $k0 # as it was on exception entry - mtc0 $k0, cop0_STATUS + mtc0 $k0, c0_status # -15 = 0xffff.fff1 eret # Return from exception .end _excp_0180 @@ -255,7 +300,7 @@ excp_0180ret: .extern extCounter # IRQ5 - hwIRQ3, see vhdl/tb_cMIPS.vhd .set M_CauseIM,0x0000ff00 # keep bits 15..8 -> IM = IP - .set M_StatusIEn,0x0000ff01 # user mode, enable all interrupts + .set M_StatusIEn,0xff11 # user mode, enable all interrupts .set noreorder @@ -263,9 +308,9 @@ excp_0180ret: .ent _excp_0200 excp_0200: _excp_0200: - mfc0 $k0, cop0_CAUSE + mfc0 $k0, c0_cause andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause - mfc0 $k1, cop0_STATUS + mfc0 $k1, c0_status and $k0, $k0, $k1 # and mask with IM bits srl $k0, $k0, 10 # keep only 3 MS bits of IP (irq7..5) @@ -304,11 +349,11 @@ dismiss: # No pending request, must have been noise # do nothing and return excp_0200ret: - mfc0 $k0, cop0_STATUS # Read STATUS register + mfc0 $k0, c0_status # Read STATUS register addi $k1, $zero, -15 # and do not modify its contents -15=fff1 ori $k0, $k0, M_StatusIEn # except for re-enabling interrupts and $k0, $k1, $k0 # and keeping user/kernel mode - mtc0 $k0, cop0_STATUS # as it was on interrupt entry + mtc0 $k0, c0_status # as it was on interrupt entry eret # Return from interrupt nop @@ -327,7 +372,7 @@ _excp_BFC0: .set noat la $k0, x_IO_BASE_ADDR # PANIC: SHOULD NEVER GET HERE - mfc0 $k1, cop0_CAUSE + mfc0 $k1, c0_cause sw $k1, 0($k0) # print CAUSE, flush pipe and stop simulation nop nop @@ -342,16 +387,133 @@ _excp_BFC0: ##=============================================================== ## main(), normal code starts below -- do not edit next line .org x_ENTRY_POINT,0 - + ##--------------------------------------------------------------- + ## ##=============================================================== - ## reserve first two pages for the Page Table + ## Page Table + ## + ## See EntryLo, pg 63 + ## + .section .PT,"aw",@progbits + + ## ( ( (x_INST_BASE_ADDR + n*4096) >>12 )<<6 ) || 0b000011 d,v,g + +_PT: + ## + ## ROM mappings ## - .section .TP,"aw",@progbits -_TP: .skip (2*4096), 0 -_endTP: + .org (_PT + (x_INST_BASE_ADDR >>13)*16) + + # PT[0], ROM + .word ( (x_INST_BASE_ADDR + 0*4096) >>6) | 0b000011 + .word 0 + .word ( (x_INST_BASE_ADDR + 1*4096) >>6) | 0b000011 + .word 0 + + # PT[1] + .word ( (x_INST_BASE_ADDR + 2*4096) >>6) | 0b000011 + .word 0 + .word ( (x_INST_BASE_ADDR + 3*4096) >>6) | 0b000011 + .word 0 + # PT[2] + .word ( (x_INST_BASE_ADDR + 4*4096) >>6) | 0b000011 + .word 0 + .word ( (x_INST_BASE_ADDR + 5*4096) >>6) | 0b000011 + .word 0 + + # PT[3] + .word ( (x_INST_BASE_ADDR + 6*4096) >>6) | 0b000011 + .word 0 + .word ( (x_INST_BASE_ADDR + 7*4096) >>6) | 0b000011 + .word 0 + + # PT[4] -- not mapped for simulation + .word ( (x_INST_BASE_ADDR + 8*4096) >>6) | 0b000001 + .word 0 + .word ( (x_INST_BASE_ADDR + 9*4096) >>6) | 0b000001 + .word 0 + + # PT[5] -- not mapped for simulation + .word ( (x_INST_BASE_ADDR + 10*4096) >>6) | 0b000001 + .word 0 + .word ( (x_INST_BASE_ADDR + 11*4096) >>6) | 0b000001 + .word 0 + + # PT[6] -- not mapped for simulation + .word ( (x_INST_BASE_ADDR + 12*4096) >>6) | 0b000001 + .word 0 + .word ( (x_INST_BASE_ADDR + 13*4096) >>6) | 0b000001 + .word 0 + + # PT[7] -- not mapped for simulation + .word ( (x_INST_BASE_ADDR + 14*4096) >>6) | 0b000001 + .word 0 + .word ( (x_INST_BASE_ADDR + 15*4096) >>6) | 0b000001 + .word 0 + + ## all remaining ROM entries are invalid + + + ## + ## RAM mappings + ## + .org (_PT + (x_DATA_BASE_ADDR >>13)*16) + ## ( ( (x_DATA_BASE_ADDR + n*4096) >>12 )<<6 ) || 0b000111 d,v,g + + # PT[ram+0], RAM + .word ( (x_DATA_BASE_ADDR + 0*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 1*4096) >>6) | 0b000111 + .word 0 + + # PT[ram+1] + .word ( (x_DATA_BASE_ADDR + 2*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 3*4096) >>6) | 0b000111 + .word 0 + + # PT[ram+2] + .word ( (x_DATA_BASE_ADDR + 4*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 5*4096) >>6) | 0b000111 + .word 0 + + # PT[ram+3] + .word ( (x_DATA_BASE_ADDR + 6*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 7*4096) >>6) | 0b000111 + .word 0 + + # PT[ram+4] + .word ( (x_DATA_BASE_ADDR + 8*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 9*4096) >>6) | 0b000111 + .word 0 + + # PT[ram+5] + .word ( (x_DATA_BASE_ADDR + 10*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 11*4096) >>6) | 0b000111 + .word 0 + + # PT[ram+6] + .word ( (x_DATA_BASE_ADDR + 12*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 13*4096) >>6) | 0b000111 + .word 0 + + # PT[ram+7] + .word ( (x_DATA_BASE_ADDR + 14*4096) >>6) | 0b000111 + .word 0 + .word ( (x_DATA_BASE_ADDR + 15*4096) >>6) | 0b000111 + .word 0 + + ## all remaining RAM entries are invalid + +_endPT: diff --git a/cMIPS/tests/divmul.c b/cMIPS/tests/divmul.c index ce95b50cd9e81ae91783a01aab0642fb9558ea1c..8cf94132aab41973072c7cc6c2e50797fca0b618 100644 --- a/cMIPS/tests/divmul.c +++ b/cMIPS/tests/divmul.c @@ -13,7 +13,7 @@ extern void exit(int); extern void print(int); -extern int readInt(int *); +extern int readInt(int *); extern void writeInt(int); #else diff --git a/cMIPS/tests/extCounter.c b/cMIPS/tests/extCounter.c index 4fc8f16796624ef37405b9d397ba4d1b7f738e3c..6afff827838e52ab26d99fe19d6290f42092d262 100644 --- a/cMIPS/tests/extCounter.c +++ b/cMIPS/tests/extCounter.c @@ -5,7 +5,7 @@ #include "cMIPS.h" #define FALSE (0==1) -#define TRUE ~(FALSE) +#define TRUE !(FALSE) #define N 4 #define CNT_VALUE 0x40000040 // set count to 64 cycles diff --git a/cMIPS/tests/extCounterInt.c b/cMIPS/tests/extCounterInt.c index f9c08e255173d819692c13b4e36876e04f43f3cf..b3f3856380a961924e74128a4843453a17dedf73 100644 --- a/cMIPS/tests/extCounterInt.c +++ b/cMIPS/tests/extCounterInt.c @@ -5,7 +5,7 @@ #define MAX 100 #define FALSE (0==1) -#define TRUE ~FALSE +#define TRUE !FALSE extern int _counter_val; diff --git a/cMIPS/tests/interrJR_dlySlot.s b/cMIPS/tests/interrJR_dlySlot.s index ab152fa3ff28f89854125bb0f9bc7bade0e9bc41..0351ea963f81ef109e9c19a9fa89a62014e14018 100644 --- a/cMIPS/tests/interrJR_dlySlot.s +++ b/cMIPS/tests/interrJR_dlySlot.s @@ -11,15 +11,13 @@ .global _start .global _exit - .set c0_cause_rst, 0x0880007c # disable counter, separate IntVector - _start: nop - li $k0, c0_status_reset # RESET, kernel mode, all else disabled + li $k0, cop0_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, 0x1000ff01 # RESET_STATUS, kernel mode, interr enabled mtc0 $k0, c0_status - li $k0, c0_cause_rst # RESET, disable counter + li $k0, cop0_CAUSE_reset # RESET, disable counter mtc0 $k0, c0_cause la $15,x_IO_BASE_ADDR diff --git a/cMIPS/tests/interr_x2.s b/cMIPS/tests/interr_x2.s index 7a25d7469f0d4986e5f707254333d2d62408a738..5d2e50fccf1a38c81419b2228f1b0f0eab3e9207 100644 --- a/cMIPS/tests/interr_x2.s +++ b/cMIPS/tests/interr_x2.s @@ -5,9 +5,10 @@ # 2nd test: lo priority (external cntr) arrives first # then the two alternate -# Testing the internal counter is difficult because it counts clock cycles +# Testing the counters is difficult because they count clock cycles # rather than instructions -- if the I/O or memory latencies change then -# the simulation output also changes and comparisons may be impossible. +# the simulation output also changes and comparisons to the expected values +# may/will fail. .include "cMIPS.s" @@ -19,16 +20,15 @@ .global _start .global _exit - .set c0_cause_rst, 0x0880007c # disable counter, separate IntVector .set ext_restart, 0xc0000000 # start ext_counter, intrr enable _start: nop - li $k0, c0_status_reset # RESET, kernel mode, all else disabled + li $k0, cop0_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, 0x1000ff01 # RESET_STATUS, kernel mode, interr enabled + li $k0, 0x1000ff01 # RESET_STATUS, kernel mode, interr enabled mtc0 $k0, c0_status - li $k0, c0_cause_rst # RESET, disable counter + li $k0, cop0_CAUSE_reset # RESET, disable counter mtc0 $k0, c0_cause la $15,x_IO_BASE_ADDR diff --git a/cMIPS/tests/pt_walk.c b/cMIPS/tests/pt_walk.c new file mode 100644 index 0000000000000000000000000000000000000000..3a24e13fc811888f127dbfa515703dba0c222fe6 --- /dev/null +++ b/cMIPS/tests/pt_walk.c @@ -0,0 +1,54 @@ +// +// This program references a wide range of addresses to do a walk over +// several entries of the Page Table (PT). +// As the pages are referenced, the TLB must be refilled with entries from +// the PT. +// +// This program needs a large (simulated) RAM. RAM must be allocated +// so that the bottom half is "usable memory" and the top half is +// allocated to the Page Table. The base address and RAM size must +// be set on file vhdl/packageMemory.vhd. +// +// x_DATA_BASE_ADDR : reg32 := x"00040000"; +// x_DATA_MEM_SZ : reg32 := x"00020000"; +// +// With this much memory, simulations run slowly. No free lunch. + + +#include "cMIPS.h" + +#define FALSE (0==1) +#define TRUE !FALSE + +#define MAX_RAM ( x_DATA_BASE_ADDR + (x_DATA_MEM_SZ / 2) ) + +#define NUM_RAM_PAGES ( (x_DATA_MEM_SZ / 2) / 4096 ) + + +void main(void) { + int i; + int *walker; + + // write to the middle of all pages + walker = (int *)(x_DATA_BASE_ADDR + 1024); + + for( i = 0 ; i < NUM_RAM_PAGES; i++){ + *walker = i; + walker = (int *)((int)walker + 4096); + } + + // and now read what was written + walker = (int *)(x_DATA_BASE_ADDR + 1024); + + for( i = 0 ; i < NUM_RAM_PAGES; i++){ + print( *walker ); + walker = (int *)((int)walker + 4096); + } + + to_stdout('\n'); + to_stdout('o'); + to_stdout('k'); + to_stdout('\n'); + +} + diff --git a/cMIPS/tests/pt_walk.expected b/cMIPS/tests/pt_walk.expected new file mode 100644 index 0000000000000000000000000000000000000000..06ddebbb41429b5fcbfa84f72629534a23a0e05e --- /dev/null +++ b/cMIPS/tests/pt_walk.expected @@ -0,0 +1,18 @@ +00000000 +00000001 +00000002 +00000003 +00000004 +00000005 +00000006 +00000007 +00000008 +00000009 +0000000a +0000000b +0000000c +0000000d +0000000e +0000000f + +ok diff --git a/cMIPS/tests/sieve.c b/cMIPS/tests/sieve.c index 65e8f71d1539f088bec765e2c3439a405d16e40d..b295816bcbb156da3385a474250285f41cb502ac 100644 --- a/cMIPS/tests/sieve.c +++ b/cMIPS/tests/sieve.c @@ -8,8 +8,8 @@ #endif #define MAX 100 -#define FALSE 0 -#define TRUE 1 +#define FALSE (0==1) +#define TRUE !FALSE int p[MAX] = {0}; diff --git a/cMIPS/tests/testAllLatencies.sh b/cMIPS/tests/testAllLatencies.sh deleted file mode 100755 index f66a38116effb1e0e82b88f10874f51d2b07bd42..0000000000000000000000000000000000000000 --- a/cMIPS/tests/testAllLatencies.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# set -x - -if [ ! -v tree ] ; then - # you must set the location of the cMIPS root directory in the variable tree - # tree=${HOME}/cmips-code/cMIPS - export tree="$(echo $PWD | sed -e 's:^\(/.*/cMIPS\)/.*:\1:')" -fi - -srcVHDL=${tree}/vhdl - -pack=$srcVHDL/packageWires.vhd - -# for ROM in 0 1 2 3 5 10 13 14; do - -for ROM in 0 1 ; do - sed -i -e "/ROM_WAIT_STATES/s/ := \([0-9][0-9]*\);/ := ${ROM};/" $pack - echo -n "rom=$ROM" - # for RAM in 0 1 15 11 10 5 4 3 2; do - for RAM in 0 1 ; do - sed -i -e "/RAM_WAIT_STATES/s/ := \([0-9][0-9]*\);/ := ${RAM};/" $pack - echo " ram=$RAM" - ./doTests.sh || exit 1 - done -done - -sed -i -e "/ROM_WAIT_STATES/s/ := \([0-9][0-9]*\);/ := 0;/" \ - -e "/RAM_WAIT_STATES/s/ := \([0-9][0-9]*\);/ := 0;/" $pack - diff --git a/cMIPS/tests/uart_irx.c b/cMIPS/tests/uart_irx.c index fa7976998f946de7392f77fa6abccc54be86788c..2f6139c40fc4f819df396c9ab61e01549a4ec3f5 100644 --- a/cMIPS/tests/uart_irx.c +++ b/cMIPS/tests/uart_irx.c @@ -1,3 +1,14 @@ +// +// Test interrupts caused by UART's reception circuit. +// +// Remote unit reads string from serial.inp and sends it over the +// serial line. +// +// UARTinterr, in include/handlers.s, reads newly arrived character, +// sets a flag and puts character in a buffer. main() reads from the +// buffer and prints it to the simulator's standard output. + + #include "cMIPS.h" typedef struct control { // control register fields (uses only ls byte) @@ -38,7 +49,7 @@ typedef struct serial { } Tserial; -extern int _uart_buff[16]; +extern int _uart_buff[16]; // declared in include/handlers.s int main(void) { // receive a string through the UART serial interface diff --git a/cMIPS/vhdl/core.vhd b/cMIPS/vhdl/core.vhd index 20cfcf1fd9cf1caed41b02747b9c7ec52ebc191a..6e9164fcd67e48a5880040e1582561ffddf09d74 100644 --- a/cMIPS/vhdl/core.vhd +++ b/cMIPS/vhdl/core.vhd @@ -1977,7 +1977,7 @@ begin end if; newSTATUS(STATUS_EXL) := '1'; -- at exception level newSTATUS(STATUS_UM) := '0'; -- enter kernel mode - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + -- newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_stall := '0'; -- do not stall @@ -1996,7 +1996,7 @@ begin ExcCode <= cop0code_Tr; newSTATUS(STATUS_EXL) := '1'; -- at exception level newSTATUS(STATUS_UM) := '0'; -- enter kernel mode - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + -- newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_stall := '0'; @@ -2026,7 +2026,7 @@ begin when exOvfl => -- OVERFLOW happened one cycle earlier newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + -- newSTATUS(STATUS_IE) := '0'; -- disable interrupts exception_taken <= '1'; i_update := '1'; i_update_r := cop0reg_STATUS; @@ -2042,8 +2042,7 @@ begin end if; - when IFaddressError => - -- fetch from UNALIGNED ADDRESS + when IFaddressError => -- fetch from UNALIGNED ADDRESS newSTATUS(STATUS_EXL) := '1'; -- at exception level newSTATUS(STATUS_IE) := '0'; -- disable interrupts exception_taken <= '1'; @@ -2097,7 +2096,7 @@ begin is_delayslot <= '0'; end if; newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + -- newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; @@ -2120,7 +2119,7 @@ begin is_delayslot <= MM_is_delayslot; end if; newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + -- newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; @@ -2136,7 +2135,7 @@ begin is_delayslot <= '0'; end if; newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + -- newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; @@ -2162,7 +2161,7 @@ begin is_delayslot <= MM_is_delayslot; end if; newSTATUS(STATUS_EXL) := '1'; -- at exception level - newSTATUS(STATUS_IE) := '0'; -- disable interrupts + -- newSTATUS(STATUS_IE) := '0'; -- disable interrupts i_update := '1'; i_update_r := cop0reg_STATUS; i_epc_update := '0'; @@ -3011,7 +3010,7 @@ begin - -- TLB entry 6 -- initialized to 1st,2nd pages of SDRAM + -- TLB entry 6 -- initialized to RAM 5th, 6th (1st,2nd pages of SDRAM) MMU_TAG6: register32 generic map(MMU_ini_tag_RAM4) port map (clk, rst, tlb_tag6_updt, tlb_tag_inp, tlb_tag6); diff --git a/cMIPS/vhdl/packageMemory.vhd b/cMIPS/vhdl/packageMemory.vhd index e8e4f3c4c215ed820a2ae1d85f3630d948bc17ff..03f894c68e2cb3f42216252a0cfe5c509c958d50 100644 --- a/cMIPS/vhdl/packageMemory.vhd +++ b/cMIPS/vhdl/packageMemory.vhd @@ -42,8 +42,8 @@ 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_MEM_SZ : reg32 := x"00008000"; + constant x_DATA_BASE_ADDR : reg32 := x"00040000"; + constant x_DATA_MEM_SZ : reg32 := x"00020000"; constant x_IO_BASE_ADDR : reg32 := x"3c000000"; constant x_IO_MEM_SZ : reg32 := x"00002000"; constant x_IO_ADDR_RANGE : reg32 := x"00000020"; diff --git a/cMIPS/vhdl/uart.vhd b/cMIPS/vhdl/uart.vhd index 8a4bc38d6defccc8945492eb5894ddfebb0fbb2d..a25b953e90bc9f534915ff43c9004ecfd3df34a6 100644 --- a/cMIPS/vhdl/uart.vhd +++ b/cMIPS/vhdl/uart.vhd @@ -856,7 +856,7 @@ begin end if; when st_init => -- 0 outDat <= '1'; - tx_run <= '1'; -- start TX clock + tx_run <= '1'; -- start TX clock tx_next_st <= st_idle; when st_idle => -- 1 if not endfile(input_stream) then @@ -866,7 +866,7 @@ begin bfr := x"0a"; -- new line j := 0; elsif sentence'length = 0 then - bfr := x"0a"; -- send new line for empty line + bfr := x"0a"; -- send new line for empty line -- assert false report "empty line: " & integer'image(j)&" " & LF; else read (sentence, char, good); @@ -910,7 +910,7 @@ begin tx_next_st <= st_idle; when st_done => -- 13 wait forever if send_null = FALSE then - bfr := x"00"; -- send out a NULL character + bfr := x"00"; -- send out a NULL character send_null := TRUE; tx_next_st <= st_start; else