Line 10... |
Line 10... |
# module ever supports more than one chunk (e.g. DRAM and SRAM as in the DE-1
|
# module ever supports more than one chunk (e.g. DRAM and SRAM as in the DE-1
|
# board) this program will be modified accordingly.
|
# board) this program will be modified accordingly.
|
#
|
#
|
# The program assumes there's no useable r/w memory other than the XRAM so it
|
# The program assumes there's no useable r/w memory other than the XRAM so it
|
# does not use any memory for variables or stack.
|
# does not use any memory for variables or stack.
|
|
#-------------------------------------------------------------------------------
|
|
#
|
#
|
#
|
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
# To be run from reset vector, standalone. Interrupts must be disabled.
|
# To be run from reset vector, standalone. Interrupts must be disabled.
|
#
|
#
|
################################################################################
|
################################################################################
|
|
|
|
#---- Test parameters
|
|
.ifndef XRAM_MAX
|
|
.set XRAM_MAX, 1024 # max. no. of KB to test for
|
|
.endif
|
|
.ifndef XRAM_BASE
|
|
.set XRAM_BASE, 0x00000000 # 1st XRAM address
|
|
.endif
|
|
|
|
|
#---- Set to >0 to enable a few debug messages
|
#---- Set to >0 to enable a few debug messages
|
.set DEBUG, 0
|
.set DEBUG, 0
|
|
|
#----
|
#---- Cache parameters
|
#.set XRAM_BASE, 0x80000000 # 1st XRAM address
|
.set ICACHE_NUM_LINES, 256 # no. of lines in the I-Cache
|
.set XRAM_MAX, 1024 # max. no. of KB to test for
|
.set DCACHE_NUM_LINES, 256 # no. of lines in the D-Cache
|
|
.set DCACHE_LINE_SIZE, 4 # D-Cache line size in words
|
|
|
|
|
|
#---- UART stuff
|
.set UART_BASE, 0x20000000 # UART base address
|
.set UART_BASE, 0x20000000 # UART base address
|
.set UART_TX, 0x0000 # TX reg offset
|
.set UART_TX, 0x0000 # TX reg offset
|
.set UART_STATUS, 0x0020 # status reg offset
|
.set UART_STATUS, 0x0020 # status reg offset
|
|
|
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
Line 41... |
Line 55... |
b start_test
|
b start_test
|
nop
|
nop
|
|
|
.ifgt 0
|
.ifgt 0
|
#--- Trap handler address: we don't expect any traps -----------------------
|
#--- Trap handler address: we don't expect any traps -----------------------
|
#.org 0x3c
|
|
.org 0x0180
|
.org 0x0180
|
interrupt_vector:
|
interrupt_vector:
|
b interrupt_vector
|
b interrupt_vector # just freeze there
|
nop
|
nop
|
.endif
|
.endif
|
|
|
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
|
|
start_test:
|
start_test:
|
mtc0 $0,$12 # disable interrupts
|
mtc0 $0,$12 # disable interrupts
|
|
|
la $a0,msg0
|
.ifdef TEST_CACHE # if we're going to test the I-caches then
|
|
jal init_cache # invalidate all the I-Cache lines now
|
|
nop
|
|
.endif
|
|
|
|
la $a0,msg0
|
jal puts
|
jal puts
|
nop
|
nop
|
li $a0,XRAM_BASE
|
li $a0,XRAM_BASE
|
li $a1,8
|
li $a1,8
|
jal put_hex
|
jal put_hex
|
nop
|
nop
|
la $a0,crlf
|
la $a0,crlf
|
jal puts
|
jal puts
|
nop
|
nop
|
|
|
la $t0,XRAM_BASE+4 # address of memory word being tested
|
la $t0,XRAM_BASE+4 # address of memory word being tested
|
li $t2,XRAM_MAX # max amount of KBs to test for
|
li $t2,XRAM_MAX # max amount of KBs to test for
|
li $t3,1 # (used to decrement $t2)
|
li $t3,1 # (used to decrement $t2)
|
li $t4,0 # no. of KBs found
|
li $t4,0 # no. of KBs found
|
move $t5,$t0 # keep the start addr at hand for comparison
|
move $t5,$t0 # keep the start addr at hand for comparison
|
|
|
sw $zero,0($t0) # clear 1st test word (in case of prev. run)
|
sw $zero,0($t0) # clear 1st test word (in case of prev. run)
|
|
|
test_loop:
|
test_loop:
|
lw $t1,0($t0) # read word contents
|
lw $t1,0($t0) # read word contents
|
beq $t5,$t1,hit_mirror # if it's the start address, we hit a mirror
|
beq $t5,$t1,hit_mirror # if it's the start address, we hit a mirror
|
nop # we rolled off the end of the RAM back here
|
nop # we rolled off the end of the RAM back here
|
sw $t0,0($t0) # word = word address
|
sw $t0,0($t0) # word = word address
|
lw $t1,0($t0) # read word back...
|
lw $t1,0($t0) # read word back...
|
bne $t1,$t0,bad_word # ...and if no match, we run off the RAM
|
bne $t1,$t0,bad_word # ...and if no match, we run off the RAM
|
nop #
|
nop #
|
sub $t2,$t2,$t3 # decrement loop counter...
|
sub $t2,$t2,$t3 # decrement loop counter...
|
bnez $t2,test_loop # ...and go back if there's more to go
|
bnez $t2,test_loop # ...and go back if there's more to go
|
addiu $t0,0x400 # in any case, increment test address by 1KB
|
addiu $t0,0x400 # in any case, increment test address by 1KB
|
|
|
b end_test # end of memory found, result is in $t4
|
b end_test # end of memory found, result is in $t4
|
nop
|
nop
|
|
|
hit_mirror: # memory mirror detected
|
hit_mirror: # memory mirror detected
|
.ifgt DEBUG
|
.ifgt DEBUG
|
la $a0,msg_mirror
|
la $a0,msg_mirror
|
jal puts
|
jal puts
|
nop
|
nop
|
.endif
|
.endif
|
b end_test
|
b end_test
|
nop
|
nop
|
|
|
bad_word: # readback error detected (maybe r/o area?)
|
bad_word: # readback error detected (maybe r/o area?)
|
.ifgt DEBUG
|
.ifgt DEBUG
|
la $a0,msg_bad
|
la $a0,msg_bad
|
jal puts
|
jal puts
|
nop
|
nop
|
.endif
|
.endif
|
b end_test
|
b end_test
|
nop
|
nop
|
|
|
end_test: # test done, ramtop+4 in $t0, #KB in $t4
|
end_test: # test done, ramtop+4 in $t0, #KB in $t4
|
|
|
|
|
la $a0,msg1 # Print ramtop message...
|
la $a0,msg1 # Print ramtop message...
|
jal puts
|
jal puts
|
nop
|
nop
|
addi $a0,$t0,-4 # substract the +4 offset we added before
|
|
move $sp,$t0 # init SP at the top of RAM space
|
addi $a0,$t0,-4 # substract the +4 offset we added before
|
addi $sp,$sp,-16
|
move $sp,$t0 # init SP at the top of RAM space
|
li $a1,8
|
addi $sp,$sp,-16
|
|
li $a1,8
|
jal put_hex
|
jal put_hex
|
nop
|
nop
|
la $a0,crlf
|
la $a0,crlf
|
jal puts
|
jal puts
|
nop
|
nop
|
|
|
# Test code execution from SRAM. We copy the test_exec_sram routine to
|
|
# the base of the SRAM and then jal to it
|
|
li $a1,64
|
|
li $a0,XRAM_BASE
|
|
la $a3,test_exec_sram
|
|
copy_to_sram:
|
|
lw $a2,0($a3)
|
|
nop
|
|
sw $a2,0($a0)
|
|
addi $a1,$a1,-4
|
|
addi $a3,$a3,4
|
|
bnez $a1,copy_to_sram
|
|
addi $a0,$a0,4
|
|
|
|
.ifgt 0
|
# Clear RAM (only first words, so that simulation is not eternal)
|
li $a0,0
|
.ifgt 1
|
|
li $a0,XRAM_BASE
|
|
addi $a1,$a0,80*4
|
|
clear_xram_loop:
|
|
sw $zero,0($a0)
|
|
blt $a0,$a1,clear_xram_loop
|
|
addi $a0,$a0,4
|
|
.endif
|
|
|
|
# Test code execution from SRAM. We copy the test_exec_sram routine to
|
|
# the base of the SRAM and then jal to it
|
|
li $a1,64
|
|
li $a0,XRAM_BASE
|
|
la $a3,test_exec_sram
|
|
copy_to_sram:
|
|
lw $a2,0($a3)
|
|
nop
|
|
sw $a2,0($a0)
|
|
addi $a1,$a1,-4
|
|
addi $a3,$a3,4
|
|
bnez $a1,copy_to_sram
|
|
addi $a0,$a0,4
|
|
|
|
# Optionally dump first few words of XRAM and jump onto XRAM
|
|
.ifgt 1
|
|
la $a0,msg5
|
|
jal puts
|
|
nop
|
|
li $a0,XRAM_BASE
|
jal dump_hex
|
jal dump_hex
|
ori $a1,$zero,16
|
ori $a1,$zero,20
|
.endif
|
.endif
|
|
|
li $a0,XRAM_BASE
|
.ifgt 1
|
|
li $a0,XRAM_BASE
|
|
nop
|
jalr $a0
|
jalr $a0
|
nop
|
nop
|
|
.endif
|
|
|
|
# If all went well in the SRAM we'll have returned here
|
.ifgt 0
|
.ifgt 0
|
# If all went well in the SRAM we'll have returned here
|
# FIXME now we should do some strong test on the RAM to see if it's wired
|
|
# correctly, using the right timing, etc.
|
|
|
# FIXME now we should so some strong test on the RAM to see if it's wired
|
# Ok, now we know we have some RAM and stack space we can do some further
|
# correctly, using the right timing, etc.
|
# testing.
|
|
|
# Ok, now we know we have some RAM and stack space we can do some further
|
|
# testing.
|
|
# dump the first few words of FLASH
|
# dump the first few words of FLASH
|
|
|
la $a0,msg2
|
la $a0,msg2
|
jal puts
|
jal puts
|
nop
|
nop
|
|
|
# FIXME flash base address is hardcoded
|
# FIXME flash base address is hardcoded
|
li $a0,0xb0000000
|
li $a0,0xb0000000
|
jal put_hex
|
jal put_hex
|
ori $a1,$zero,8
|
ori $a1,$zero,8
|
|
|
la $a0,crlf
|
la $a0,crlf
|
jal puts
|
jal puts
|
nop
|
nop
|
|
|
la $a0,crlf
|
la $a0,crlf
|
jal puts
|
jal puts
|
nop
|
nop
|
|
|
li $a0,0xb0000000
|
li $a0,0xb0000000
|
jal dump_hex
|
jal dump_hex
|
ori $a1,$zero,24
|
ori $a1,$zero,6
|
.endif
|
.endif
|
|
|
$DONE:
|
|
j $DONE # ...and freeze here
|
|
nop
|
|
|
|
|
# Optionally jump to FLASH. This is only useful in simulation.
|
|
.ifgt 1
|
|
.ifdef EXEC_FLASH
|
|
la $a0,msg8
|
|
jal puts
|
|
nop
|
|
li $a0,0xb0000000
|
|
nop
|
|
jalr $a0
|
|
nop
|
|
.endif
|
|
.endif
|
|
|
|
la $a0,msg4
|
|
jal puts
|
|
nop
|
|
|
|
|
|
$DONE:
|
|
j $DONE # ...and freeze here
|
|
nop
|
|
|
test_exec_sram:
|
|
|
# This short routine will be copied to RAM and then executed there. This
|
|
# will test the behavior of the I-Cache.
|
|
test_exec_sram:
|
#jr $ra
|
#jr $ra
|
#nop
|
#nop
|
sw $ra,0($sp)
|
sw $ra,0($sp)
|
addi $sp,$sp,-4
|
addi $sp,$sp,-4
|
la $a0,msg3
|
la $a0,msg3
|
la $a1,puts
|
la $a1,puts
|
jalr $a1
|
jalr $a1
|
nop
|
nop
|
lw $ra,4($sp)
|
lw $ra,4($sp)
|
jr $ra
|
jr $ra
|
addi $sp,$sp,4
|
addi $sp,$sp,4
|
test_exec_sram_end:
|
test_exec_sram_end:
|
|
nop
|
|
|
|
|
|
|
#---- Functions ----------------------------------------------------------------
|
#---- Functions ----------------------------------------------------------------
|
|
|
# void dump_hex(int *address, int len)
|
# void dump_hex(int *address {a0}, int len {a1})
|
dump_hex:
|
dump_hex:
|
move $t7,$a0
|
move $t7,$a0
|
move $t8,$a1
|
move $t6,$a1
|
sw $ra,0($sp)
|
sw $ra,0($sp)
|
addi $sp,$sp,-4
|
addi $sp,$sp,-4
|
|
|
|
dump_hex_loop_lines:
|
|
move $a0,$t7
|
|
li $a1,8
|
|
jal put_hex
|
|
nop
|
|
la $a0,msg6
|
|
jal puts
|
|
nop
|
|
li $t9,4
|
|
|
dump_hex_loop:
|
dump_hex_loop_words:
|
lw $a0,0($t7)
|
lw $a0,0($t7)
|
jal put_hex
|
jal put_hex
|
li $a1,8
|
li $a1,8
|
|
|
la $a0,space
|
la $a0,space
|
jal puts
|
jal puts
|
addi $t7,4
|
addi $t7,4
|
|
|
addi $t8,$t8,-1
|
addi $t9,$t9,-1
|
bnez $t8,dump_hex_loop
|
bnez $t9,dump_hex_loop_words
|
nop
|
nop
|
|
|
lw $ra,4($sp)
|
la $a0,crlf
|
jr $ra
|
jal puts
|
addi $sp,$sp,4
|
nop
|
|
|
|
addi $t6,$t6,-1
|
|
bnez $t6,dump_hex_loop_lines
|
|
nop
|
|
|
|
la $a0,msg7
|
|
jal puts
|
|
addi $t7,4
|
|
|
|
.ifgt 0
|
|
lw $ra,4($sp)
|
|
move $a0,$ra
|
|
li $a1,8
|
|
jal put_hex
|
|
nop
|
|
qqqq:
|
|
j qqqq
|
|
nop
|
|
.endif
|
|
|
#--- Special functions that do not use any RAM ---------------------------------
|
|
# WARNING: Not for general use!
|
|
# All parameters in $a0..$a4, stack unused. No attempt to comply with any ABI
|
|
# has been made.
|
|
# Since we can't use any RAM, register have been used liberally with no regard
|
|
# for intended usage -- have to share reg bank with calling function.
|
|
|
|
# void puts(char *s) -- print zero-terminated string
|
|
puts:
|
|
la $a2,UART_BASE # UART base address
|
|
puts_loop:
|
|
lb $v0,0($a0)
|
|
beqz $v0,puts_end
|
|
addiu $a0,1
|
|
puts_wait_tx_rdy:
|
|
lw $v1,UART_STATUS($a2)
|
|
andi $v1,$v1,0x02
|
|
beqz $v1,puts_wait_tx_rdy
|
|
nop
|
nop
|
sw $v0,UART_TX($a2)
|
lw $ra,4($sp)
|
|
jr $ra
|
|
addi $sp,$sp,4
|
|
|
|
|
|
#---- Cache-related functions --------------------------------------------------
|
|
|
|
# void init_cache(void) -- invalidates all I-Cache lines (uses no RAM)
|
|
init_cache:
|
|
li $a0,0x00010000 # Disable cache, enable I-cache line invalidation
|
|
mtc0 $a0,$12
|
|
|
|
# In order to invalidate a I-Cache line we have to write its tag number to
|
|
# any address while bits CP0[12].17:16=01. The write will be executed as a
|
|
# regular write too, as a side effect, so we need to choose a harmless
|
|
# target address.
|
|
|
|
li $a0,XRAM_BASE
|
|
li $a2,0
|
|
li $a1,ICACHE_NUM_LINES-1
|
|
|
|
inv_i_cache_loop:
|
|
sw $a2,0($a0)
|
|
blt $a2,$a1,inv_i_cache_loop
|
|
addi $a2,1
|
|
|
|
mfc0 $a0,$12
|
|
li $a1,0x00020000 # Leave cache enabled
|
|
or $a0,$a1,$a1
|
|
jr $ra
|
|
mtc0 $a0,$12
|
|
|
|
|
|
|
|
#--- Special functions that do not use any RAM ---------------------------------
|
|
# WARNING: Not for general use!
|
|
# All parameters in $a0..$a4, stack unused. No attempt to comply with any ABI
|
|
# has been made.
|
|
# Since we can't use any RAM, registers have been used with no regard for
|
|
# intended usage -- have to share reg bank with calling function.
|
|
|
|
# void puts(char *s) -- print zero-terminated string
|
|
puts:
|
|
la $a2,UART_BASE # UART base address
|
|
puts_loop:
|
|
lb $v0,0($a0)
|
|
beqz $v0,puts_end
|
|
addiu $a0,1
|
|
puts_wait_tx_rdy:
|
|
lw $v1,UART_STATUS($a2)
|
|
andi $v1,$v1,0x02
|
|
beqz $v1,puts_wait_tx_rdy
|
|
nop
|
|
sw $v0,UART_TX($a2)
|
b puts_loop
|
b puts_loop
|
nop
|
nop
|
|
|
puts_end:
|
puts_end:
|
jr $ra
|
jr $ra
|
nop
|
nop
|
|
|
# void put_hex(int n, int d) -- print integer as d-digit hex
|
# void put_hex(int n, int d) -- print integer as d-digit hex
|
put_hex:
|
put_hex:
|
la $a2,UART_BASE
|
la $a2,UART_BASE
|
la $a3,put_hex_table
|
la $a3,put_hex_table
|
addi $a1,-1
|
addi $a1,-1
|
add $a1,$a1,$a1
|
add $a1,$a1,$a1
|
add $a1,$a1,$a1
|
add $a1,$a1,$a1
|
|
|
put_hex_loop:
|
put_hex_loop:
|
srlv $v0,$a0,$a1
|
srlv $v0,$a0,$a1
|
andi $v0,$v0,0x0f
|
andi $v0,$v0,0x0f
|
addu $s2,$a3,$v0
|
addu $s2,$a3,$v0
|
lb $v0,0($s2)
|
lb $v0,0($s2)
|
put_hex_wait_tx_rdy:
|
put_hex_wait_tx_rdy:
|
lw $v1,UART_STATUS($a2)
|
lw $v1,UART_STATUS($a2)
|
andi $v1,$v1,0x02
|
andi $v1,$v1,0x02
|
beqz $v1,put_hex_wait_tx_rdy
|
beqz $v1,put_hex_wait_tx_rdy
|
nop
|
nop
|
sw $v0,UART_TX($a2)
|
sw $v0,UART_TX($a2)
|
|
|
bnez $a1,put_hex_loop
|
bnez $a1,put_hex_loop
|
addi $a1,-4
|
addi $a1,-4
|
|
|
jr $ra
|
jr $ra
|
nop
|
nop
|
|
|
|
|
|
#---- Constant data (note we keep it in the text section) ----------------------
|
|
|
#---- Constant data (note we keep it in the text section) ----------------------
|
put_hex_table:
|
|
.ascii "0123456789abcdef"
|
|
|
put_hex_table:
|
msg0:
|
.ascii "0123456789abcdef"
|
.ascii "\n\r"
|
|
.asciz "Scanning external memory at 0x"
|
|
msg1:
|
|
.asciz "Found XRAM top at 0x"
|
|
crlf:
|
|
.asciz "\n\r"
|
|
space:
|
|
.asciz " "
|
|
msg_mirror:
|
|
.asciz "hit mirror!\n\r"
|
|
msg_bad:
|
|
.asciz "bad readback!\n\r"
|
|
msg2:
|
|
.asciz "\n\rDumping the first few words of FLASH at address 0x"
|
|
msg3:
|
|
.ascii "\n\rTesting code execution from SRAM... "
|
|
.asciz "if you see this, it worked\n\r"
|
|
msg4:
|
|
.ascii "\n\r\n\r"
|
|
.asciz "End of test.\n\r\n\r"
|
|
msg5:
|
|
.asciz "Dump of first few words of XRAM after initialization:\n\r"
|
|
msg6:
|
|
.asciiz ": "
|
|
msg7:
|
|
.asciiz "<end of dump>"
|
|
msg8:
|
|
.ascii "\n\r"
|
|
.asciiz "Testing execution from 8-bit static memory (FLASH)\n\r"
|
|
|
msg0:
|
.set reorder
|
.ascii "\n\r"
|
.end entry
|
.asciz "Scanning external memory at 0x"
|
|
msg1:
|
|
.asciz "Found XRAM top at 0x"
|
|
crlf:
|
|
.asciz "\n\r"
|
|
space:
|
|
.asciz " "
|
|
msg_mirror:
|
|
.asciz "hit mirror!\n\r"
|
|
msg_bad:
|
|
.asciz "bad readback!\n\r"
|
|
msg2:
|
|
.asciz "\n\rDumping the first few words of FLASH at address 0x"
|
|
msg3:
|
|
.ascii "\n\rTesting code execution from SRAM... "
|
|
.asciz "if you see this, it worked\n\r"
|
|
|
|
.set reorder
|
|
.end entry
|
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|