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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_cpu.c] - Diff between revs 55 and 56

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

Rev 55 Rev 56
Line 269... Line 269...
  return cycles.uint64;
  return cycles.uint64;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Simple delay function using busy wait.
 * Simple delay function using busy wait (simple loop).
 *
 *
 * @warning This function requires the cycle CSR(s). Hence, the Zicsr extension is mandatory.
 * @warning This function is not really precise (especially if there is no M extension available)! Use a timer-based approach (using cycle or time CSRs) for precise timings.
 *
 *
 * @param[in] time_ms Time in ms to wait.
 * @param[in] time_ms Time in ms to wait (max 32767ms).
 **************************************************************************/
 **************************************************************************/
void neorv32_cpu_delay_ms(uint32_t time_ms) {
void neorv32_cpu_delay_ms(int16_t time_ms) {
 
 
  uint64_t time_resume = neorv32_cpu_get_cycle();
  const uint32_t loop_cycles_c = 16; // clock cycles per iteration of the ASM loop
 
 
 
  // check input
 
  if (time_ms < 0) {
 
    time_ms = -time_ms;
 
  }
 
 
  uint32_t clock = SYSINFO_CLK; // clock ticks per second
  uint32_t clock = SYSINFO_CLK; // clock ticks per second
  clock = clock / 1000; // clock ticks per ms
  clock = clock / 1000; // clock ticks per ms
 
 
  uint64_t wait_cycles = ((uint64_t)clock) * ((uint64_t)time_ms);
  uint64_t wait_cycles = ((uint64_t)clock) * ((uint64_t)time_ms);
  time_resume += wait_cycles;
  uint32_t ticks = (uint32_t)(wait_cycles / loop_cycles_c);
 
 
  while(1) {
  asm volatile (" .balign 4                                        \n" // make sure this is 32-bit aligned
    if (neorv32_cpu_get_cycle() >= time_resume) {
                " __neorv32_cpu_delay_ms_start:                    \n"
      break;
                " beq  %[cnt_r], zero, __neorv32_cpu_delay_ms_end  \n" // 3 cycles (not taken)
    }
                " beq  %[cnt_r], zero, __neorv32_cpu_delay_ms_end  \n" // 3 cycles (never taken)
  }
                " addi %[cnt_w], %[cnt_r], -1                      \n" // 2 cycles
 
                " nop                                              \n" // 2 cycles
 
                " j    __neorv32_cpu_delay_ms_start                \n" // 6 cycles
 
                " __neorv32_cpu_delay_ms_end: "
 
                : [cnt_w] "=r" (ticks) : [cnt_r] "r" (ticks));
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Switch from privilege mode MACHINE to privilege mode USER.
 * Switch from privilege mode MACHINE to privilege mode USER.
Line 302... Line 311...
 **************************************************************************/
 **************************************************************************/
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) {
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) {
 
 
  // make sure to use NO registers in here! -> naked
  // make sure to use NO registers in here! -> naked
 
 
  asm volatile ("csrw mepc, ra           \n\t" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here
  asm volatile ("csrw mepc, ra           \n" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here
                "li ra, %[input_imm]     \n\t" // bit mask to clear the two MPP bits
                "li ra, %[input_imm]     \n" // bit mask to clear the two MPP bits
                "csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode
                "csrrc zero, mstatus, ra \n" // clear MPP bits -> MPP=u-mode
                "mret                    \n\t" // return and switch to user mode
                "mret                    \n" // return and switch to user mode
                :  : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
                :  : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
Line 619... Line 628...
 *
 *
 * @return Returns number of available HPM counters (..29).
 * @return Returns number of available HPM counters (..29).
 **************************************************************************/
 **************************************************************************/
uint32_t neorv32_cpu_hpm_get_counters(void) {
uint32_t neorv32_cpu_hpm_get_counters(void) {
 
 
 
  // inhibit all HPM counters
 
  uint32_t tmp = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT);
 
  tmp |= 0xfffffff8;
 
  neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, tmp);
 
 
  // try setting all mhpmcounter* CSRs to 1
  // try setting all mhpmcounter* CSRs to 1
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3,  1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3,  1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER4,  1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER4,  1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER5,  1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER5,  1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER6,  1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER6,  1);
Line 648... Line 662...
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER26, 1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER26, 1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER27, 1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER27, 1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER28, 1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER28, 1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER29, 1);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER29, 1);
 
 
  // sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
  // sum up all written ones (only available HPM counter CSRs will return =! 0)
  uint32_t num_hpm_cnts = 0;
  uint32_t num_hpm_cnts = 0;
 
 
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER4);
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER4);
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER5);
  num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER5);
Line 684... Line 698...
  return num_hpm_cnts;
  return num_hpm_cnts;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 
 * Hardware performance monitors (HPM): Get total counter width
 
 *
 
 * @warning This function overrides mhpmcounter3[h] CSRs.
 
 *
 
 * @return Size of HPM counter bits (1-64).
 
 **************************************************************************/
 
uint32_t neorv32_cpu_hpm_get_size(void) {
 
 
 
  // inhibt auto-update
 
  asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTEREN_HPM3));
 
 
 
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3,  0xffffffff);
 
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3H, 0xffffffff);
 
 
 
  uint32_t tmp, size, i;
 
 
 
  if (neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H) == 0) {
 
    size = 0;
 
    tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
 
  }
 
  else {
 
    size = 32;
 
    tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H);
 
  }
 
 
 
  for (i=0; i<32; i++) {
 
    if (tmp & (1<<i)) {
 
      size++;
 
    }
 
  }
 
 
 
  return size;
 
}
 
 
 
 
 
/**********************************************************************//**
 * Check if certain Z* extension is available
 * Check if certain Z* extension is available
 *
 *
 * @param[in] flag Index of the Z-extension to check from #NEORV32_CSR_MZEXT_enum
 * @param[in] flag Index of the Z-extension to check from #NEORV32_CSR_MZEXT_enum
 * @return 0 if extension is NOT available, != 0 if extension is available.
 * @return 0 if extension is NOT available, != 0 if extension is available.
 **************************************************************************/
 **************************************************************************/

powered by: WebSVN 2.1.0

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