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

Subversion Repositories neorv32

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

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

Rev 63 Rev 64
Line 149... Line 149...
  union {
  union {
    uint64_t uint64;
    uint64_t uint64;
    uint32_t uint32[sizeof(uint64_t)/2];
    uint32_t uint32[sizeof(uint64_t)/2];
  } cycles;
  } cycles;
 
 
  uint32_t tmp1, tmp2, tmp3;
  register uint32_t tmp1, tmp2, tmp3;
  while(1) {
  while(1) {
    tmp1 = neorv32_cpu_csr_read(CSR_CYCLEH);
    tmp1 = neorv32_cpu_csr_read(CSR_CYCLEH);
    tmp2 = neorv32_cpu_csr_read(CSR_CYCLE);
    tmp2 = neorv32_cpu_csr_read(CSR_CYCLE);
    tmp3 = neorv32_cpu_csr_read(CSR_CYCLEH);
    tmp3 = neorv32_cpu_csr_read(CSR_CYCLEH);
    if (tmp1 == tmp3) {
    if (tmp1 == tmp3) {
Line 200... Line 200...
  union {
  union {
    uint64_t uint64;
    uint64_t uint64;
    uint32_t uint32[sizeof(uint64_t)/2];
    uint32_t uint32[sizeof(uint64_t)/2];
  } cycles;
  } cycles;
 
 
  uint32_t tmp1, tmp2, tmp3;
  register uint32_t tmp1, tmp2, tmp3;
  while(1) {
  while(1) {
    tmp1 = neorv32_cpu_csr_read(CSR_INSTRETH);
    tmp1 = neorv32_cpu_csr_read(CSR_INSTRETH);
    tmp2 = neorv32_cpu_csr_read(CSR_INSTRET);
    tmp2 = neorv32_cpu_csr_read(CSR_INSTRET);
    tmp3 = neorv32_cpu_csr_read(CSR_INSTRETH);
    tmp3 = neorv32_cpu_csr_read(CSR_INSTRETH);
    if (tmp1 == tmp3) {
    if (tmp1 == tmp3) {
Line 251... Line 251...
  union {
  union {
    uint64_t uint64;
    uint64_t uint64;
    uint32_t uint32[sizeof(uint64_t)/2];
    uint32_t uint32[sizeof(uint64_t)/2];
  } cycles;
  } cycles;
 
 
  uint32_t tmp1, tmp2, tmp3;
  register uint32_t tmp1, tmp2, tmp3;
  while(1) {
  while(1) {
    tmp1 = neorv32_cpu_csr_read(CSR_TIMEH);
    tmp1 = neorv32_cpu_csr_read(CSR_TIMEH);
    tmp2 = neorv32_cpu_csr_read(CSR_TIME);
    tmp2 = neorv32_cpu_csr_read(CSR_TIME);
    tmp3 = neorv32_cpu_csr_read(CSR_TIMEH);
    tmp3 = neorv32_cpu_csr_read(CSR_TIMEH);
    if (tmp1 == tmp3) {
    if (tmp1 == tmp3) {
Line 269... Line 269...
  return cycles.uint64;
  return cycles.uint64;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Simple delay function using busy wait (simple loop).
 * Delay function using busy wait.
 *
 *
 * @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.
 * @note This function uses the time CSRs (from int./ext. MTIME). A simple ASM loop
 
 * is used as fall back if system timer is not advancing (no MTIME available).
 *
 *
 * @param[in] time_ms Time in ms to wait (max 32767ms).
 * @warning Delay time might be less precise if M extensions is not available
 
 * (especially if MTIME unit is not available).
 
 *
 
 * @param[in] time_ms Time in ms to wait (unsigned 32-bit).
 **************************************************************************/
 **************************************************************************/
void neorv32_cpu_delay_ms(int16_t time_ms) {
void neorv32_cpu_delay_ms(uint32_t time_ms) {
 
 
  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 = NEORV32_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);
  uint32_t ticks = (uint32_t)(wait_cycles / loop_cycles_c);
 
 
  register uint64_t tmp = neorv32_cpu_get_systime();
 
  if (neorv32_cpu_get_systime() > tmp) { // system time advancing (MTIME available and running)?
 
 
 
    // use MTIME machine timer
 
    tmp += wait_cycles;
 
    while(1) {
 
      if (neorv32_cpu_get_systime() >= tmp) {
 
        break;
 
      }
 
    }
 
  }
 
  else {
 
    // use ASM loop
 
    // warning! not really precise (especially if M extensions is not available)!
 
 
 
    const uint32_t loop_cycles_c = 16; // clock cycles per iteration of the ASM loop
 
    uint32_t iterations = (uint32_t)(wait_cycles / loop_cycles_c);
 
 
  asm volatile (" .balign 4                                        \n" // make sure this is 32-bit aligned
  asm volatile (" .balign 4                                        \n" // make sure this is 32-bit aligned
                " __neorv32_cpu_delay_ms_start:                    \n"
                " __neorv32_cpu_delay_ms_start:                    \n"
                " 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 (not taken)
                " beq  %[cnt_r], zero, __neorv32_cpu_delay_ms_end  \n" // 3 cycles (never taken)
                " beq  %[cnt_r], zero, __neorv32_cpu_delay_ms_end  \n" // 3 cycles (never taken)
                " addi %[cnt_w], %[cnt_r], -1                      \n" // 2 cycles
                " addi %[cnt_w], %[cnt_r], -1                      \n" // 2 cycles
                " nop                                              \n" // 2 cycles
                " nop                                              \n" // 2 cycles
                " j    __neorv32_cpu_delay_ms_start                \n" // 6 cycles
                " j    __neorv32_cpu_delay_ms_start                \n" // 6 cycles
                " __neorv32_cpu_delay_ms_end: "
                " __neorv32_cpu_delay_ms_end: "
                : [cnt_w] "=r" (ticks) : [cnt_r] "r" (ticks));
                  : [cnt_w] "=r" (iterations) : [cnt_r] "r" (iterations));
 
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Switch from privilege mode MACHINE to privilege mode USER.
 * Switch from privilege mode MACHINE to privilege mode USER.
Line 330... Line 345...
 * @return Returns number of available PMP regions.
 * @return Returns number of available PMP regions.
 **************************************************************************/
 **************************************************************************/
uint32_t neorv32_cpu_pmp_get_num_regions(void) {
uint32_t neorv32_cpu_pmp_get_num_regions(void) {
 
 
  // PMP implemented at all?
  // PMP implemented at all?
  if ((SYSINFO_CPU & (1<<SYSINFO_CPU_PMP)) == 0) {
  if ((NEORV32_SYSINFO.CPU & (1<<SYSINFO_CPU_PMP)) == 0) {
    return 0;
    return 0;
  }
  }
 
 
  uint32_t i = 0;
  uint32_t i = 0;
 
 
Line 595... Line 610...
 * @return Returns number of available HPM counters (0..29).
 * @return Returns number of available HPM counters (0..29).
 **************************************************************************/
 **************************************************************************/
uint32_t neorv32_cpu_hpm_get_counters(void) {
uint32_t neorv32_cpu_hpm_get_counters(void) {
 
 
  // HPMs implemented at all?
  // HPMs implemented at all?
  if ((SYSINFO_CPU & (1<<SYSINFO_CPU_HPM)) == 0) {
  if ((NEORV32_SYSINFO.CPU & (1<<SYSINFO_CPU_HPM)) == 0) {
    return 0;
    return 0;
  }
  }
 
 
  // inhibit all HPM counters
  // inhibit all HPM counters
  uint32_t tmp = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT);
  uint32_t tmp = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT);
Line 678... Line 693...
 * @return Size of HPM counter bits (1-64, 0 if not implemented at all).
 * @return Size of HPM counter bits (1-64, 0 if not implemented at all).
 **************************************************************************/
 **************************************************************************/
uint32_t neorv32_cpu_hpm_get_size(void) {
uint32_t neorv32_cpu_hpm_get_size(void) {
 
 
  // HPMs implemented at all?
  // HPMs implemented at all?
  if ((SYSINFO_CPU & (1<<SYSINFO_CPU_HPM)) == 0) {
  if ((NEORV32_SYSINFO.CPU & (1<<SYSINFO_CPU_HPM)) == 0) {
    return 0;
    return 0;
  }
  }
 
 
  // inhibt auto-update
  // inhibt auto-update
  asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_HPM3));
  asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_HPM3));

powered by: WebSVN 2.1.0

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