mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-24 22:27:10 -04:00
553 lines
20 KiB
C
553 lines
20 KiB
C
/*
|
|
**
|
|
** Copyright 2020 OpenHW Group
|
|
**
|
|
** Licensed under the Solderpad Hardware Licence, 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
|
|
**
|
|
** https://solderpad.org/licenses/
|
|
**
|
|
** 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.
|
|
**
|
|
*******************************************************************************
|
|
** Basic debugger test. Needs more work and bugs fixed
|
|
** It will launch a debug request and have debugger code execute (debugger.S)
|
|
*******************************************************************************
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include "corev_uvmt.h"
|
|
|
|
volatile int glb_hart_status = 0; // Written by main code only, read by debug code
|
|
volatile int glb_debug_status = 0; // Written by debug code only, read by main code
|
|
volatile int glb_ebreak_status = 0; // Written by ebreak code only, read by main code
|
|
volatile int glb_illegal_insn_status = 0; // Written by illegal instruction code only, read by main code
|
|
volatile int glb_debug_exception_status = 0; // Written by debug code during exception only
|
|
volatile int glb_exception_ebreak_status = 0; // Written by main code, read by exception handler
|
|
|
|
volatile int glb_previous_dpc = 0; // holds last dpc, used for checking correctness of stepping
|
|
volatile int glb_step_info = 0; // info to dbg code about actions to take on stepping
|
|
volatile int glb_step_count = 0; // Written by debug code for each time single step is entered
|
|
// Expectation flags. Raise an error if handler or routine is enterred when not expected,
|
|
volatile int glb_expect_illegal_insn = 0;
|
|
volatile int glb_expect_ebreak_handler = 0;
|
|
volatile int glb_expect_debug_entry = 0;
|
|
volatile int glb_expect_debug_exception = 0;
|
|
volatile int glb_expect_irq_entry = 0;
|
|
volatile int glb_irq_timeout = 0;
|
|
// Counter values
|
|
// Checked at start and end of debug code
|
|
// Only lower 32 bits checked, as simulation cannot overflow on 32 bits
|
|
volatile int glb_mcycle_start = 0;
|
|
volatile int glb_mcycle_end = 0;
|
|
volatile int glb_minstret_start = 0;
|
|
volatile int glb_minstret_end = 0;
|
|
#define TEST_FAILED *(volatile int *)CV_VP_STATUS_FLAGS_BASE = 1
|
|
#define TEST_PASSED *(volatile int *)CV_VP_STATUS_FLAGS_BASE = 123456789
|
|
|
|
extern int __stack_start;
|
|
typedef union {
|
|
struct {
|
|
unsigned int start_delay : 15; // 14: 0
|
|
unsigned int rand_start_delay : 1; // 15
|
|
unsigned int pulse_width : 13; // 28:16
|
|
unsigned int rand_pulse_width : 1; // 29
|
|
unsigned int pulse_mode : 1; // 30 0 = level, 1 = pulse
|
|
unsigned int value : 1; // 31
|
|
} fields;
|
|
unsigned int bits;
|
|
} debug_req_control_t;
|
|
|
|
#define DEBUG_REQ_CONTROL_REG *((volatile uint32_t *) (CV_VP_DEBUG_CONTROL_BASE))
|
|
#define TIMER_REG_ADDR ((volatile uint32_t *) (CV_VP_INTR_TIMER_BASE+0))
|
|
#define TIMER_VAL_ADDR ((volatile uint32_t *) (CV_VP_INTR_TIMER_BASE+4))
|
|
|
|
typedef union {
|
|
struct {
|
|
unsigned int uie : 1; // 0 // Implemented if USER mode enabled
|
|
unsigned int sie : 1; // 1
|
|
unsigned int wpri : 1; // 2
|
|
unsigned int mie : 1; // 3 // Implemented
|
|
unsigned int upie : 1; // 4 // Implemented if USER mode enabled
|
|
unsigned int spie : 1; // 5
|
|
unsigned int wpri0 : 1; // 6
|
|
unsigned int mpie : 1; // 7 // Implemented
|
|
unsigned int spp : 1; // 8
|
|
unsigned int wpri1 : 2; // 10: 9
|
|
unsigned int mpp : 2; // 12:11 // Implemented
|
|
unsigned int fs : 2; // 14:13
|
|
unsigned int xs : 2; // 16:15
|
|
unsigned int mprv : 1; // 17
|
|
unsigned int sum : 1; // 18
|
|
unsigned int mxr : 1; // 19
|
|
unsigned int tvm : 1; // 20
|
|
unsigned int tw : 1; // 21
|
|
unsigned int tsr : 1; // 22
|
|
unsigned int wpri3 : 8; // 30:23
|
|
unsigned int sd : 1; // 31
|
|
} fields;
|
|
unsigned int bits;
|
|
} mstatus_t;
|
|
|
|
extern void _single_step(int d);
|
|
// Tag is simply to help debug and determine where the failure came from
|
|
void check_debug_status(int tag, int value)
|
|
{
|
|
if(glb_debug_status != value){
|
|
printf("ERROR: check_debug_status(%d, %d): Tag=%d status=%d, exp=%d \n\n",
|
|
tag, value, tag, glb_debug_status, value);
|
|
TEST_FAILED;
|
|
}
|
|
}
|
|
void check_debug_exception_status(int tag, int value)
|
|
{
|
|
if(glb_debug_exception_status != value){
|
|
printf("ERROR: check_debug_exception_status(%d, %d): Tag=%d status=%d, exp=%d \n\n",
|
|
tag, value, tag, glb_debug_exception_status, value);
|
|
TEST_FAILED;
|
|
}
|
|
}
|
|
void check_hart_status(int tag, int value)
|
|
{
|
|
if(glb_hart_status != value){
|
|
printf("ERROR: check_hart_status(%d, %d): Tag=%d status=%d, exp=%d \n\n",
|
|
tag, value, tag, glb_hart_status, value);
|
|
TEST_FAILED;
|
|
}
|
|
}
|
|
void check_ebreak_status(int tag, int value)
|
|
{
|
|
if(glb_ebreak_status != value){
|
|
printf("ERROR: check_ebreak_status(%d, %d): Tag=%d status=%d, exp=%d \n\n",
|
|
tag, value, tag, glb_ebreak_status, value);
|
|
TEST_FAILED;
|
|
}
|
|
}
|
|
void check_illegal_insn_status(int tag, int value)
|
|
{
|
|
if(glb_illegal_insn_status != value){
|
|
printf("ERROR: check_illegal_insn_status(%d, %d): Tag=%d status=%d, exp=%d \n\n",
|
|
tag, value, tag, glb_illegal_insn_status, value);
|
|
TEST_FAILED;
|
|
}
|
|
}
|
|
void delay(int count) {
|
|
for (volatile int d = 0; d < count; d++);
|
|
}
|
|
|
|
void mstatus_mie_enable() {
|
|
int mie_bit = 0x1 << 3;
|
|
asm volatile("csrrs x0, mstatus, %0" : : "r" (mie_bit));
|
|
}
|
|
|
|
void mstatus_mie_disable() {
|
|
int mie_bit = 0x1 << 3;
|
|
asm volatile("csrrc x0, mstatus, %0" : : "r" (mie_bit));
|
|
}
|
|
|
|
void mie_enable_all() {
|
|
uint32_t mie_mask = (uint32_t) -1;
|
|
asm volatile("csrrs x0, mie, %0" : : "r" (mie_mask));
|
|
}
|
|
|
|
void mie_disable_all() {
|
|
uint32_t mie_mask = (uint32_t) -1;
|
|
asm volatile("csrrc x0, mie, %0" : : "r" (mie_mask));
|
|
}
|
|
|
|
void mie_enable(uint32_t irq) {
|
|
// Enable the interrupt irq in MIE
|
|
uint32_t mie_bit = 0x1 << irq;
|
|
asm volatile("csrrs x0, mie, %0" : : "r" (mie_bit));
|
|
}
|
|
|
|
void mie_disable(uint32_t irq) {
|
|
// Disable the interrupt irq in MIE
|
|
uint32_t mie_bit = 0x1 << irq;
|
|
asm volatile("csrrc x0, mie, %0" : : "r" (mie_bit));
|
|
}
|
|
|
|
void mm_ram_assert_irq(uint32_t mask, uint32_t cycle_delay) {
|
|
*TIMER_REG_ADDR = mask;
|
|
*TIMER_VAL_ADDR = 1 + cycle_delay;
|
|
}
|
|
|
|
void counters_enable() {
|
|
// Enable counters mcycle (bit0) and minstret (bit2)
|
|
uint32_t mask = 1<<2 | 1<<0;
|
|
asm volatile("csrrc x0, 0x320, %0" : : "r" (mask));
|
|
}
|
|
#define MACHINE 3
|
|
int main(int argc, char *argv[])
|
|
{
|
|
unsigned int temp,temp1,temp2;
|
|
debug_req_control_t debug_req_control;
|
|
mstatus_t mstatus, mstatus_cmp;
|
|
counters_enable();
|
|
printf("\nBasic test checking debug functionality.\n");
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test1: check initialization values\n");
|
|
//check_debug_status(0,0);
|
|
|
|
temp1 = 0xFFFFFFFF;
|
|
/* get relevant CSRs and compare init values*/
|
|
__asm__ volatile("csrr %0, mstatus" : "=r"(temp1));
|
|
__asm__ volatile("csrw mstatus, %0 " : "=r"(temp1));
|
|
__asm__ volatile("csrr %0, mstatus" : "=r"(mstatus.bits));
|
|
__asm__ volatile("csrr %0, mie" : "=r"(temp));
|
|
__asm__ volatile("csrw mie, %0 " : "=r"(temp1));
|
|
__asm__ volatile("csrr %0, mie" : "=r"(temp2));
|
|
printf("\tmstats_rval = 0x%0x 0x%0x 0x%0x 0x%0x\n",temp2,mstatus.bits,temp,temp1);
|
|
|
|
check_debug_status(0,0);
|
|
printf("------------------------\n");
|
|
printf(" Test2.1: check access to Debug and Trigger registers\n");
|
|
// debug specifcation 13.2: 4.8 Core Debug Registers are not accessable unless in debug mode
|
|
|
|
// ----------------------
|
|
// Check Debug Write Access
|
|
temp = 0xFFFFFFFF;
|
|
temp1 = glb_illegal_insn_status+1;
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrw dcsr, %0" : "=r"(temp)); // Debug DCSR
|
|
check_illegal_insn_status(11,temp1++);
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrw dpc, %0" : "=r"(temp)); // Debug DPC
|
|
check_illegal_insn_status(12,temp1++);
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrw dscratch, %0" : "=r"(temp)); // Debug DSCRATCH0
|
|
check_illegal_insn_status(13,temp1++);
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrw 0x7b3, %0" : "=r"(temp)); // Debug DSCRATCH1
|
|
check_illegal_insn_status(14,temp1++);
|
|
|
|
// Check Read Access
|
|
temp1 = glb_illegal_insn_status+1;
|
|
// Allow illegal instruction handler to run
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrr %0, dcsr" : "=r"(temp)); // Debug DCSR
|
|
check_illegal_insn_status(1,temp1++);
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrr %0, dpc" : "=r"(temp)); // Debug DPC
|
|
check_illegal_insn_status(2,temp1++);
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrr %0, dscratch": "=r"(temp)); // Debug DSCRATCH0
|
|
check_illegal_insn_status(3,temp1++);
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("csrr %0, 0x7b3" : "=r"(temp)); // Debug DSCRATCH1
|
|
check_illegal_insn_status(4,temp1++);
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test2.2: check access to Trigger registers\n");
|
|
|
|
// NOTE: As of July 2024, CVA6 does not implement the trigger module.
|
|
// TODO: Consider adding trigger module support in future revisions.
|
|
|
|
// Writes are ignored
|
|
temp = 0xFFFFFFFF; //TODO:MT should these be writes?
|
|
__asm__ volatile("csrw 0x7a0, %0" : "=r"(temp)); // Trigger TSELECT
|
|
__asm__ volatile("csrw 0x7a1, %0" : "=r"(temp)); // Trigger TDATA1
|
|
__asm__ volatile("csrw 0x7a2, %0" : "=r"(temp)); // Trigger TDATA2
|
|
__asm__ volatile("csrw 0x7a3, %0" : "=r"(temp)); // Trigger TDATA3
|
|
__asm__ volatile("csrw 0x7a4, %0" : "=r"(temp)); // Trigger TINFO
|
|
|
|
// Read default value
|
|
__asm__ volatile("csrr %0, 0x7a0" : "=r"(temp)); // Trigger TSELECT
|
|
// CVA6 if(temp != 0x0){printf("ERROR: TSELET Read\n");TEST_FAILED;}
|
|
|
|
__asm__ volatile("csrr %0, 0x7a1" : "=r"(temp)); // Trigger TDATA1
|
|
// CVA6 // 31:28 type = 2
|
|
// CVA6 // 27 dmode = 1
|
|
// CVA6 // 15:12 action = 1
|
|
// CVA6 // 6 m(achine) = 1
|
|
// CVA6 if(temp != (2<<28 | 1<<27 | 1<<12 | 1<<6)){printf("ERROR: TDATA1 Read\n");TEST_FAILED;}
|
|
|
|
__asm__ volatile("csrr %0, 0x7a2" : "=r"(temp)); // Trigger TDATA2
|
|
// CVA6 if(temp != 0x0){printf("ERROR: TDATA2 Read\n");TEST_FAILED;}
|
|
|
|
__asm__ volatile("csrr %0, 0x7a3" : "=r"(temp)); // Trigger TDATA3
|
|
// CVA6 if(temp != 0x0){printf("ERROR: TDATA3 Read\n");TEST_FAILED;}
|
|
|
|
__asm__ volatile("csrr %0, 0x7a4" : "=r"(temp)); // Trigger TINFO
|
|
// CVA6 // tmatch = 1<<2
|
|
// CVA6 if(temp != 1<<2){printf("ERROR: TINFO Read %d \n",temp);TEST_FAILED;}
|
|
|
|
|
|
// Do not expect or allow any more illegal instructions
|
|
|
|
|
|
mstatus_cmp = (mstatus_t) {
|
|
.fields.mpp = MACHINE //
|
|
};
|
|
if(mstatus_cmp.bits != mstatus.bits) {printf("ERROR: init mstatus mismatch exp=%x val=%x\n",
|
|
mstatus_cmp.bits, mstatus.bits); TEST_FAILED;}
|
|
//TODO:MT are these switched up?
|
|
printf("------------------------\n");
|
|
printf(" Test3.1: check hart ebreak executes ebreak handler but does not execute debugger code\n");
|
|
glb_expect_ebreak_handler = 1;
|
|
asm volatile("c.ebreak");
|
|
check_ebreak_status(32,1);
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test3.2: check hart c.ebreak executes ebreak handler but does not execute debugger code\n");
|
|
glb_expect_ebreak_handler = 1;
|
|
asm volatile(".4byte 0x00100073");
|
|
check_ebreak_status(32,2);
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test4: request hardware debugger\n");
|
|
|
|
debug_req_control = (debug_req_control_t) {
|
|
.fields.value = 1,
|
|
.fields.pulse_mode = 1, //PULSE Mode
|
|
.fields.rand_pulse_width = 0,
|
|
.fields.pulse_width = 5,// TODO:MT determine pulse width with non-sticky debug_req
|
|
.fields.rand_start_delay = 0,
|
|
.fields.start_delay = 200
|
|
};
|
|
glb_expect_debug_entry = 1;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
|
|
glb_hart_status = 4; // Basic test
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(41,glb_hart_status);
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test5: have debugger execute ebreak 3 more times\n");
|
|
|
|
glb_hart_status = 5;
|
|
glb_expect_debug_entry = 1;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
while(glb_debug_status != (5+3)){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(51,(5+3));
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test6: Test CSR access and default values in debug mode\n");
|
|
glb_hart_status = 6;
|
|
glb_expect_debug_entry = 1;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(61,glb_hart_status);
|
|
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test10: check hart ebreak executes debugger code\n");
|
|
glb_hart_status = 10;
|
|
glb_expect_debug_entry = 1;
|
|
asm volatile(".4byte 0x00100073");
|
|
check_debug_status(33,glb_hart_status);
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test11: check illegal csr exception during debug launches debugger exception and no csr modified\n");
|
|
glb_hart_status = 11;
|
|
glb_expect_debug_entry = 1;
|
|
glb_expect_debug_exception = 1;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(111,glb_hart_status);
|
|
check_debug_exception_status(111,glb_hart_status);
|
|
//FIXME TBD BUG : need to update test to check actual csrs not modified.
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test12: check ecall exception during debug launches debugger exception and no csr modified\n");
|
|
glb_hart_status = 12;
|
|
glb_expect_debug_entry = 1;
|
|
glb_expect_debug_exception = 1;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(112,glb_hart_status);
|
|
check_debug_exception_status(112,glb_hart_status);
|
|
//FIXME TBD BUG : need to update test to check actual csrs not modified.
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test13: check mret during debug launches debugger exception and no csr modified\n");
|
|
glb_hart_status = 13;
|
|
glb_expect_debug_entry = 1;
|
|
glb_expect_debug_exception = 1;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(113,glb_hart_status);
|
|
check_debug_exception_status(113,glb_hart_status);
|
|
|
|
printf("------------------------\n");
|
|
printf(" Test14: Check exception ebreak enters debug mode\n");
|
|
glb_hart_status = 14;
|
|
glb_expect_illegal_insn = 1;
|
|
glb_exception_ebreak_status = 1;
|
|
glb_expect_debug_entry = 1;
|
|
|
|
// DCSR read will cause illegal instruction.
|
|
// Exception routine reads glb_exception_ebreak_status=1 and executes c.ebreak
|
|
__asm__ volatile("csrr %0, dcsr" : "=r"(temp)); // Debug DCSR
|
|
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
|
|
check_illegal_insn_status(114,temp1++);
|
|
check_debug_status(114, glb_hart_status);
|
|
printf("----------------------\n");
|
|
printf("Test 16: dret in m-mode causes exception\n");
|
|
|
|
glb_expect_illegal_insn = 1;
|
|
__asm__ volatile("dret");
|
|
check_illegal_insn_status(16, temp1++);
|
|
|
|
printf("------------------------\n");
|
|
printf("Test 17: WFI before debug_req_i and WFI in debug mode\n");
|
|
printf("If test hangs, WFI is NOT converted to NOP\n");
|
|
|
|
glb_expect_debug_entry = 1;
|
|
glb_hart_status = 17;
|
|
// start_delay is set to 200, should get the wfi executing before dbg request is asserted
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
|
|
// Execute WFI, when debug is asserted, it will act as NOP and enter debug mode
|
|
// If not, test will hang
|
|
__asm__ volatile("wfi");
|
|
check_debug_status(117, glb_hart_status);
|
|
|
|
printf("----------------------\n");
|
|
printf("Checking interrupt, as this is needed by later tests\n");
|
|
|
|
// Assert and check irq, as this is needed by some tests.
|
|
mstatus_mie_enable();
|
|
mie_enable(30);
|
|
glb_expect_irq_entry = 1;
|
|
mm_ram_assert_irq(0x40000000, 1);
|
|
while(glb_expect_irq_entry == 1);
|
|
mm_ram_assert_irq(0,0);
|
|
printf("Irq check done\n");
|
|
|
|
// Check that stoupcount bit (10) in dcsr has no affect
|
|
printf("-------------------------\n");
|
|
printf("Test 21: Setting stopcount bit=1\n");
|
|
glb_expect_debug_entry = 1;
|
|
glb_hart_status = 21;
|
|
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(121, glb_hart_status);
|
|
|
|
|
|
printf("------------------------\n");
|
|
printf("Test 18: Single stepping\n");
|
|
glb_hart_status = 18;
|
|
|
|
// Run single step code (in single_step.S)
|
|
_single_step(0);
|
|
|
|
// Single step code should generate 2 illegal insn
|
|
temp1++;
|
|
check_illegal_insn_status(118, temp1++);
|
|
check_debug_status(118, glb_hart_status);
|
|
|
|
printf("Stepped %d times\n", glb_step_count);
|
|
|
|
|
|
printf("------------------------\n");
|
|
printf("Test 19: irq in debug\n");
|
|
glb_hart_status = 19;
|
|
glb_expect_debug_entry = 1;
|
|
|
|
// Does not expect irq to be taken while in debug mode
|
|
// but it will be taken when we exit from debug.
|
|
// Timeout added in debug code to check for taken irq or not
|
|
glb_expect_irq_entry = 1;
|
|
DEBUG_REQ_CONTROL_REG=debug_req_control.bits;
|
|
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
|
|
check_debug_status(119, glb_hart_status);
|
|
if(glb_irq_timeout != 0) {
|
|
printf("glb_irq_timeout != 0, interrupt taken in debug.\n");
|
|
TEST_FAILED;
|
|
}
|
|
|
|
// Test debug req vs irq timing
|
|
printf("-----------------------\n");
|
|
printf("Test 20: Asserting debug_req and irq at the same cycle\n");
|
|
glb_expect_debug_entry = 1;
|
|
glb_expect_irq_entry = 1;
|
|
glb_hart_status = 20;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
// 170 halts on first instuction in interrupt handler
|
|
// 175 gives same timing for interrupt and debug_req_i
|
|
mm_ram_assert_irq(0x40000000, 175+20);
|
|
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
check_debug_status(120, glb_hart_status);
|
|
|
|
|
|
// Execute fence instruction in debug
|
|
printf("-----------------------------\n");
|
|
printf("Test 22: Execute fence in debug mode\n");
|
|
glb_expect_debug_entry = 1;
|
|
glb_hart_status = 22;
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
|
|
while(glb_debug_status != glb_hart_status) {
|
|
printf("Wait for debugger\n");
|
|
}
|
|
|
|
check_debug_status(121, glb_hart_status);
|
|
|
|
printf("------------------------\n");
|
|
printf("Test 23: trigger match in debug mode with match disabled\n");
|
|
glb_hart_status = 23;
|
|
glb_expect_debug_entry = 1;
|
|
|
|
// Request debug
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
|
|
check_debug_status(123, glb_hart_status);
|
|
printf("------------------------\n");
|
|
printf("Test 24: trigger register access in D-mode\n");
|
|
glb_hart_status = 24;
|
|
glb_expect_debug_entry = 1;
|
|
|
|
// Request debug
|
|
DEBUG_REQ_CONTROL_REG = debug_req_control.bits;
|
|
|
|
while(glb_debug_status != glb_hart_status){
|
|
printf("Wait for Debugger\n");
|
|
}
|
|
|
|
check_debug_status(124, glb_hart_status);
|
|
|
|
//--------------------------------
|
|
//return EXIT_FAILURE;
|
|
printf("------------------------\n");
|
|
printf("Finished \n");
|
|
return EXIT_SUCCESS;
|
|
}
|