OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_rte.c] - Diff between revs 32 and 33

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 32 Rev 33
Line 49... Line 49...
 
 
// private functions
// private functions
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16))) __attribute__((unused));
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16))) __attribute__((unused));
static void __neorv32_rte_debug_exc_handler(void)     __attribute__((unused));
static void __neorv32_rte_debug_exc_handler(void)     __attribute__((unused));
static void __neorv32_rte_print_true_false(int state) __attribute__((unused));
static void __neorv32_rte_print_true_false(int state) __attribute__((unused));
 
static void __neorv32_rte_print_hex_word(uint32_t num);
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Setup NEORV32 runtime environment.
 * Setup NEORV32 runtime environment.
 *
 *
Line 62... Line 63...
 **************************************************************************/
 **************************************************************************/
void neorv32_rte_setup(void) {
void neorv32_rte_setup(void) {
 
 
  // check if CSR system is available at all
  // check if CSR system is available at all
  if (neorv32_cpu_csr_read(CSR_MISA) == 0) {
  if (neorv32_cpu_csr_read(CSR_MISA) == 0) {
    neorv32_uart_printf("<RTE> WARNING! CPU CSR system not available! </RTE>");
    neorv32_uart_print("<RTE> WARNING! CPU CSR system not available! </RTE>");
  }
  }
 
 
  // configure trap handler base address
  // configure trap handler base address
  uint32_t mtvec_base = (uint32_t)(&__neorv32_rte_core);
  uint32_t mtvec_base = (uint32_t)(&__neorv32_rte_core);
  neorv32_cpu_csr_write(CSR_MTVEC, mtvec_base);
  neorv32_cpu_csr_write(CSR_MTVEC, mtvec_base);
Line 135... Line 136...
 
 
/**********************************************************************//**
/**********************************************************************//**
 * This is the core of the NEORV32 RTE.
 * This is the core of the NEORV32 RTE.
 *
 *
 * @note This function must no be explicitly used by the user.
 * @note This function must no be explicitly used by the user.
 
 * @note The RTE core uses mscratch CSR to store the trap-causing mepc for further (user-defined) processing.
 
 *
 * @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
 * @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
 **************************************************************************/
 **************************************************************************/
static void __attribute__((__interrupt__)) __attribute__((aligned(16)))  __neorv32_rte_core(void) {
static void __attribute__((__interrupt__)) __attribute__((aligned(16)))  __neorv32_rte_core(void) {
 
 
  register uint32_t rte_mepc   = neorv32_cpu_csr_read(CSR_MEPC);
  register uint32_t rte_mepc   = neorv32_cpu_csr_read(CSR_MEPC);
 
  neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // store for later
  register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
  register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
 
 
  // compute return address
  // compute return address
  if ((rte_mcause & 0x80000000) == 0) { // modify pc only if exception
  if ((rte_mcause & 0x80000000) == 0) { // modify pc only if exception
 
 
Line 196... Line 200...
 * @note This function is used by neorv32_rte_exception_uninstall(void) only.
 * @note This function is used by neorv32_rte_exception_uninstall(void) only.
 **************************************************************************/
 **************************************************************************/
static void __neorv32_rte_debug_exc_handler(void) {
static void __neorv32_rte_debug_exc_handler(void) {
 
 
  // intro
  // intro
  neorv32_uart_printf("<RTE> ");
  neorv32_uart_print("<RTE> ");
 
 
  // cause
  // cause
  register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
  register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
  switch (trap_cause) {
  switch (trap_cause) {
    case TRAP_CODE_I_MISALIGNED: neorv32_uart_printf("Instruction address misaligned"); break;
    case TRAP_CODE_I_MISALIGNED: neorv32_uart_print("Instruction address misaligned"); break;
    case TRAP_CODE_I_ACCESS:     neorv32_uart_printf("Instruction access fault"); break;
    case TRAP_CODE_I_ACCESS:     neorv32_uart_print("Instruction access fault"); break;
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart_printf("Illegal instruction"); break;
    case TRAP_CODE_I_ILLEGAL:    neorv32_uart_print("Illegal instruction"); break;
    case TRAP_CODE_BREAKPOINT:   neorv32_uart_printf("Breakpoint"); break;
    case TRAP_CODE_BREAKPOINT:   neorv32_uart_print("Breakpoint"); break;
    case TRAP_CODE_L_MISALIGNED: neorv32_uart_printf("Load address misaligned"); break;
    case TRAP_CODE_L_MISALIGNED: neorv32_uart_print("Load address misaligned"); break;
    case TRAP_CODE_L_ACCESS:     neorv32_uart_printf("Load access fault"); break;
    case TRAP_CODE_L_ACCESS:     neorv32_uart_print("Load access fault"); break;
    case TRAP_CODE_S_MISALIGNED: neorv32_uart_printf("Store address misaligned"); break;
    case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break;
    case TRAP_CODE_S_ACCESS:     neorv32_uart_printf("Store access fault"); break;
    case TRAP_CODE_S_ACCESS:     neorv32_uart_print("Store access fault"); break;
    case TRAP_CODE_MENV_CALL:    neorv32_uart_printf("Environment call"); break;
    case TRAP_CODE_MENV_CALL:    neorv32_uart_print("Environment call"); break;
    case TRAP_CODE_MSI:          neorv32_uart_printf("Machine software interrupt"); break;
    case TRAP_CODE_MSI:          neorv32_uart_print("Machine software interrupt"); break;
    case TRAP_CODE_MTI:          neorv32_uart_printf("Machine timer interrupt"); break;
    case TRAP_CODE_MTI:          neorv32_uart_print("Machine timer interrupt"); break;
    case TRAP_CODE_MEI:          neorv32_uart_printf("Machine external interrupt"); break;
    case TRAP_CODE_MEI:          neorv32_uart_print("Machine external interrupt"); break;
    case TRAP_CODE_FIRQ_0:       neorv32_uart_printf("Fast interrupt 0"); break;
    case TRAP_CODE_FIRQ_0:       neorv32_uart_print("Fast interrupt 0"); break;
    case TRAP_CODE_FIRQ_1:       neorv32_uart_printf("Fast interrupt 1"); break;
    case TRAP_CODE_FIRQ_1:       neorv32_uart_print("Fast interrupt 1"); break;
    case TRAP_CODE_FIRQ_2:       neorv32_uart_printf("Fast interrupt 2"); break;
    case TRAP_CODE_FIRQ_2:       neorv32_uart_print("Fast interrupt 2"); break;
    case TRAP_CODE_FIRQ_3:       neorv32_uart_printf("Fast interrupt 3"); break;
    case TRAP_CODE_FIRQ_3:       neorv32_uart_print("Fast interrupt 3"); break;
    default:                     neorv32_uart_printf("Unknown (0x%x)", trap_cause); break;
    default:                     neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
  }
  }
 
 
  // address
  // instruction address
  register uint32_t trap_addr = neorv32_cpu_csr_read(CSR_MEPC);
  neorv32_uart_print(" @ ");
  register uint32_t trap_inst;
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch
  asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (trap_inst) : [input_i] "r" (trap_addr));
 
 
  // additional info
  // modify return address only if exception (NOT for interrupts)
  neorv32_uart_print(", MTVAL=");
  if ((trap_cause & 0x80000000) == 0) { // is exception?
  __neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
    if ((trap_inst & 3) == 3) { // is uncompressed instruction?
  neorv32_uart_print(" </RTE>");
      trap_addr -= 4;
 
    }
 
    else {
 
      trap_addr -= 2;
 
    }
 
  }
 
  neorv32_uart_printf(" @ 0x%x, MTVAL=0x%x </RTE>", trap_addr, neorv32_cpu_csr_read(CSR_MTVAL));
 
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * NEORV32 runtime environment: Print hardware configuration information via UART
 * NEORV32 runtime environment: Print hardware configuration information via UART
Line 298... Line 295...
    }
    }
  }
  }
 
 
  // Z* CPU extensions (from custom CSR "mzext")
  // Z* CPU extensions (from custom CSR "mzext")
  tmp = neorv32_cpu_csr_read(CSR_MZEXT);
  tmp = neorv32_cpu_csr_read(CSR_MZEXT);
  if (tmp & (1<<0)) {
  if (tmp & (1<<CPU_MZEXT_ZICSR)) {
    neorv32_uart_printf("Zicsr ");
    neorv32_uart_printf("Zicsr ");
  }
  }
  if (tmp & (1<<1)) {
  if (tmp & (1<<CPU_MZEXT_ZIFENCEI)) {
    neorv32_uart_printf("Zifencei ");
    neorv32_uart_printf("Zifencei ");
  }
  }
 
  if (tmp & (1<<CPU_MZEXT_PMP)) {
 
    neorv32_uart_printf("PMP ");
 
  }
 
 
 
 
  // Misc
  // Misc
  neorv32_uart_printf("\n\n\n-- Processor --\n");
  neorv32_uart_printf("\n\n\n-- Processor --\n");
  neorv32_uart_printf("Clock:   %u Hz\n", SYSINFO_CLK);
  neorv32_uart_printf("Clock:   %u Hz\n", SYSINFO_CLK);
Line 376... Line 376...
 * @param[in] state Print TRUE when !=0, print FALSE when 0
 * @param[in] state Print TRUE when !=0, print FALSE when 0
 **************************************************************************/
 **************************************************************************/
static void __neorv32_rte_print_true_false(int state) {
static void __neorv32_rte_print_true_false(int state) {
 
 
  if (state) {
  if (state) {
    neorv32_uart_printf("True\n");
    neorv32_uart_print("True\n");
  }
  }
  else {
  else {
    neorv32_uart_printf("False\n");
    neorv32_uart_print("False\n");
 
  }
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * NEORV32 runtime environment: Private function to print 32-bit number
 
 * as 8-digit hexadecimal value (with "0x" suffix).
 
 *
 
 * @param[in] num Number to print as hexadecimal.
 
 **************************************************************************/
 
void __neorv32_rte_print_hex_word(uint32_t num) {
 
 
 
  static const char hex_symbols[16] = "0123456789ABCDEF";
 
 
 
  neorv32_uart_print("0x");
 
 
 
  int i;
 
  for (i=0; i<8; i++) {
 
    uint32_t index = (num >> (28 - 4*i)) & 0xF;
 
    neorv32_uart_putc(hex_symbols[index]);
  }
  }
}
}
 
 
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * NEORV32 runtime environment: Function to show the processor version in human-readable format.
 * NEORV32 runtime environment: Function to show the processor version in human-readable format.
 **************************************************************************/
 **************************************************************************/
void neorv32_rte_print_hw_version(void) {
void neorv32_rte_print_hw_version(void) {
 
 
  uint32_t i;
  uint32_t i;
  char tmp, cnt;
  char tmp, cnt;
  uint32_t version = neorv32_cpu_csr_read(CSR_MIMPID);
 
 
 
  for (i=0; i<4; i++) {
  for (i=0; i<4; i++) {
 
 
    tmp = (char)(version >> (24 - 8*i));
    tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
 
 
    // serial division
    // serial division
    cnt = 0;
    cnt = 0;
    while (tmp >= 10) {
    while (tmp >= 10) {
      tmp = tmp - 10;
      tmp = tmp - 10;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.