diff --git a/.github/workflows/interactive-debugging.yml b/.github/workflows/interactive-debugging.yml index 570323a50..8415e094d 100644 --- a/.github/workflows/interactive-debugging.yml +++ b/.github/workflows/interactive-debugging.yml @@ -315,3 +315,19 @@ jobs: ${CALIPTRA_ROOT}/.github/scripts/openocd_test.sh \ -f board/caliptra-verilator-rst.cfg \ -f ${CALIPTRA_ROOT}/src/integration/test_suites/infinite_loop/peripheral_access.tcl + + - name: Build Verilated simulation + run: | + export CALIPTRA_ROOT=$(pwd) + rm -rf run/* + make -C run -f ${CALIPTRA_ROOT}/tools/scripts/Makefile verilator-build TESTNAME=infinite_loop DEBUG_UNLOCKED=1 \ + OBJCACHE="" CC=gcc CXX=g++ LINK=g++ + make -C run -f ${CALIPTRA_ROOT}/tools/scripts/Makefile program.hex TESTNAME=infinite_loop + + - name: Test JTAG access with clock gating + run: | + export CALIPTRA_ROOT=$(pwd) + cd run + ${CALIPTRA_ROOT}/.github/scripts/openocd_test.sh \ + -f board/caliptra-verilator.cfg \ + -f ${CALIPTRA_ROOT}/src/integration/test_suites/infinite_loop/jtag_cg.tcl diff --git a/src/integration/test_suites/infinite_loop/common.tcl b/src/integration/test_suites/infinite_loop/common.tcl new file mode 100644 index 000000000..a95351407 --- /dev/null +++ b/src/integration/test_suites/infinite_loop/common.tcl @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +proc compare {x y} { + puts "'$x' vs. '$y'" + + if {[llength $y] != [llength $y]} { + puts "length mismatch!" + return -1 + } + + for {set i 0} {$i < [llength $x]} {incr i} { + if {[lindex $x $i] != [lindex $y $i]} { + puts "item $i mismatch!" + return -1 + } + } + + return 0 +} + +set STDOUT 0x300300cc + +set mbox_clk_gate_en 0xf2 +set mbox_lock_debug 0xf9 +set mbox_unlock_debug 0xfa + +set mbox_lock_mem_addr 0x30020000 +set mbox_user_mem_addr 0x30020004 +set mbox_cmd_mem_addr 0x30020008 +set mbox_dlen_mem_addr 0x3002000C +set mbox_datain_mem_addr 0x30020010 +set mbox_dataout_mem_addr 0x30020014 +set mbox_execute_mem_addr 0x30020018 +set mbox_status_mem_addr 0x3002001C +set mbox_unlock_mem_addr 0x30020020 + +set mbox_dlen_dmi_addr 0x50 +set mbox_dout_dmi_addr 0x51 +set mbox_status_dmi_addr 0x52 + +set dmstatus_addr 0x11 + diff --git a/src/integration/test_suites/infinite_loop/infinite_loop.s b/src/integration/test_suites/infinite_loop/infinite_loop.s index 4a3753157..fae20f79c 100644 --- a/src/integration/test_suites/infinite_loop/infinite_loop.s +++ b/src/integration/test_suites/infinite_loop/infinite_loop.s @@ -17,6 +17,13 @@ #include "caliptra_defines.h" .set mfdc, 0x7f9 +.set mfdht, 0x7ce +.set mstatus, 0x300 +.set mitcnt0, 0x7d2 +.set mitb0, 0x7d3 +.set mitctl0, 0x7d4 +.set mie, 0x304 +.set mpmc, 0x7c6 // Code to execute .section .text @@ -39,6 +46,7 @@ _start: li x6, 0xA0A0A0A0 li x7, 0x00FF00FF li x8, 0xCC00CC00 + li s1, 0xFEEDABED // Writing 0 to this register initiates CPU halt // Simple infinite loop program with inner and outer loop li t3, 0 @@ -46,9 +54,23 @@ outer: addi t3, t3, 1 li t4, 123 inner: + beq s1, zero, halt_cpu addi t4, t4, -1 bne t4, zero, inner - jal x0, outer + j outer + +halt_cpu: + // Set mit0 and halt core + li t5, 0xf0 + li t6, 0x20000800 + csrwi mitcnt0, 0x00 // Internal timer 0 counter + csrw mitb0, t5 // Internal timer 0 boundary + csrwi mitctl0, 0x01 // Internal timer 0 enable + csrw mie, t6 // Internal timer 0 local interrupt enable + csrwi mstatus, 0x08 // Internal timer 0 global interrupt enable + csrwi mpmc, 0x03 // Initiate core halt with disable on mit0 interrupt + li s1, 0xFEEDABED // Indicate halt init + j outer // Return to infinite loop .section .dccm .global stdout diff --git a/src/integration/test_suites/infinite_loop/jtag_cg.tcl b/src/integration/test_suites/infinite_loop/jtag_cg.tcl new file mode 100644 index 000000000..037e3c178 --- /dev/null +++ b/src/integration/test_suites/infinite_loop/jtag_cg.tcl @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +init + +set script_dir [file dirname [info script]] +source [file join $script_dir common.tcl] + +array set data { + 0 0x12345678 + 1 0xABBACDDC + 2 0xDEADBEEF + 3 0xFEEDBABE + 4 0xBEACCAEB +} +set dlen_words [array size data] +set dlen_bytes [expr {$dlen_words * 4}] + +puts "Read Debug Module Status Register..." +set val [riscv dmi_read $dmstatus_addr] +puts "dmstatus: $val" +if {($val & 0x00000c00) == 0} { + echo "The hart is halted!" + shutdown error +} +puts "" + +riscv set_mem_access sysbus +puts "Enable clock gating..." +write_memory $STDOUT 32 $mbox_clk_gate_en phys + +puts "Set debug security state to locked..." +write_memory $STDOUT 32 $mbox_lock_debug phys +puts "" + +puts "Retrieve mailbox lock..." +set golden {0x0} +set actual [read_memory $mbox_lock_mem_addr 32 1 phys] +if {[compare $actual $golden] != 0} { + shutdown error +} +puts "" + +puts "Write few bytes to mailbox..." +write_memory $mbox_cmd_mem_addr 32 0x12345678 phys +write_memory $mbox_dlen_mem_addr 32 $dlen_bytes phys +for {set i 0} {$i < $dlen_words} {incr i} { + write_memory $mbox_datain_mem_addr 32 $data($i) phys +} +write_memory $mbox_execute_mem_addr 32 1 phys +puts "" + +puts "Read mailbox status..." +set golden {0x100} +set actual [read_memory $mbox_status_mem_addr 32 1 phys] +if {[compare $actual $golden] != 0} { + shutdown error +} +puts "" + +puts "Halt CPU to access its registers..." +halt +puts "Initiate firmware halt (set register s1 to 0)..." +set_reg {s1 0} +puts "Resume CPU..." +resume +puts "" + +puts "Read Debug Module Status Register..." +set val [riscv dmi_read $dmstatus_addr] +puts "dmstatus: $val" +if {($val & 0x00000c00) == 0} { + echo "The hart is halted!" + shutdown error +} +puts "" + +puts "Read mailbox status and dlen..." +set golden $dlen_bytes +set actual [riscv dmi_read $mbox_dlen_dmi_addr] +if {[compare $actual $golden] != 0} { + shutdown error +} +puts "" + +puts "Read mailbox data..." +for {set i 0} {$i < $dlen_words} {incr i} { + set golden $data($i) + set actual [riscv dmi_read $mbox_dout_dmi_addr] + if {[compare $actual $golden] != 0} { + shutdown error + } +} + +# Success +shutdown diff --git a/src/integration/test_suites/infinite_loop/peripheral_access.tcl b/src/integration/test_suites/infinite_loop/peripheral_access.tcl index d6bf70d37..c2dbcbc16 100644 --- a/src/integration/test_suites/infinite_loop/peripheral_access.tcl +++ b/src/integration/test_suites/infinite_loop/peripheral_access.tcl @@ -14,28 +14,13 @@ # init -proc compare {x y} { - puts "'$x' vs. '$y'" - - if {[llength $y] != [llength $y]} { - puts "length mismatch!" - return -1 - } - - for {set i 0} {$i < [llength $x]} {incr i} { - if {[lindex $x $i] != [lindex $y $i]} { - puts "item $i mismatch!" - return -1 - } - } - - return 0 -} +set script_dir [file dirname [info script]] +source [file join $script_dir common.tcl] # Manually read dmstatus and check if the core is actually held in external # reset. In the expected state bits anyunavail allrunning anyrunning allhalted # and anyhalted should be cleared. -set val [riscv dmi_read 0x11] +set val [riscv dmi_read $dmstatus_addr] puts "dmstatus: $val" if { ($val & 0x00000F00) != 0 } { diff --git a/src/integration/test_suites/infinite_loop/regdump_golden.txt b/src/integration/test_suites/infinite_loop/regdump_golden.txt index 27196e7d5..b1913bb9d 100644 --- a/src/integration/test_suites/infinite_loop/regdump_golden.txt +++ b/src/integration/test_suites/infinite_loop/regdump_golden.txt @@ -5,7 +5,7 @@ tp 0xdeadbeef 0xdeadbeef t0 0x5050505 84215045 t1 0xa0a0a0a0 -1600085856 t2 0xff00ff 16711935 -s1 0x0 0 +s1 0xfeedabed -17978387 a0 0x0 0 a1 0x0 0 a2 0x0 0