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

Subversion Repositories neorv32

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

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

Rev 72 Rev 73
Line 311... Line 311...
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Switch from privilege mode MACHINE to privilege mode USER.
 
 *
 
 * @warning This function requires the U extension to be implemented.
 
 **************************************************************************/
 
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) {
 
 
 
  // make sure to use NO registers in here! -> naked
 
 
 
  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" // bit mask to clear the two MPP bits
 
                "csrrc zero, mstatus, ra \n" // clear MPP bits -> MPP=u-mode
 
                "mret                    \n" // return and switch to user mode
 
                :  : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Physical memory protection (PMP): Get number of available regions.
 * Physical memory protection (PMP): Get number of available regions.
 *
 *
 * @warning This function overrides all available PMPCFG* CSRs.
 * @warning This function overrides all available PMPCFG* CSRs!
 * @warning This function requires the PMP CPU extension.
 * @note This function requires the PMP CPU extension.
 *
 *
 * @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 ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_PMP)) == 0) {
  if ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_PMP)) == 0) {
    return 0;
    return 0;
  }
  }
 
 
  uint32_t i = 0;
 
 
 
  // try setting R bit in all PMPCFG CSRs
  // try setting R bit in all PMPCFG CSRs
  const uint32_t mask = 0x01010101;
  const uint32_t mask = 0x01010101;
  for (i=0; i<16; i++) {
  __neorv32_cpu_pmp_cfg_write(0, mask);
    __neorv32_cpu_pmp_cfg_write(i, mask);
  __neorv32_cpu_pmp_cfg_write(1, mask);
  }
  __neorv32_cpu_pmp_cfg_write(2, mask);
 
  __neorv32_cpu_pmp_cfg_write(3, mask);
 
 
  // sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
  // sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
  union {
  union {
    uint32_t uint32;
    uint32_t uint32;
    uint8_t  uint8[sizeof(uint32_t)/sizeof(uint8_t)];
    uint8_t  uint8[sizeof(uint32_t)/sizeof(uint8_t)];
  } cnt;
  } cnt;
 
 
  cnt.uint32 = 0;
  cnt.uint32 = 0;
  for (i=0; i<16; i++) {
  cnt.uint32 += __neorv32_cpu_pmp_cfg_read(0) & mask;
    cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i) & mask;
  cnt.uint32 += __neorv32_cpu_pmp_cfg_read(1) & mask;
  }
  cnt.uint32 += __neorv32_cpu_pmp_cfg_read(2) & mask;
 
  cnt.uint32 += __neorv32_cpu_pmp_cfg_read(3) & mask;
 
 
  // sum up bytes
  // sum up bytes
  uint32_t num_regions = 0;
  uint32_t num_regions = 0;
  num_regions += (uint32_t)cnt.uint8[0];
  num_regions += (uint32_t)cnt.uint8[0];
  num_regions += (uint32_t)cnt.uint8[1];
  num_regions += (uint32_t)cnt.uint8[1];
Line 375... Line 358...
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Physical memory protection (PMP): Get minimal region size (granularity).
 * Physical memory protection (PMP): Get minimal region size (granularity).
 *
 *
 * @warning This function overrides PMPCFG0[0] and PMPADDR0 CSRs.
 * @warning This function overrides PMPCFG0[0] and PMPADDR0 CSRs!
 * @warning This function requires the PMP CPU extension.
 * @note This function requires the PMP CPU extension.
 *
 *
 * @return Returns minimal region size in bytes.
 * @return Returns minimal region size in bytes. Returns zero on error.
 **************************************************************************/
 **************************************************************************/
uint32_t neorv32_cpu_pmp_get_granularity(void) {
uint32_t neorv32_cpu_pmp_get_granularity(void) {
 
 
  // check min granulartiy
  // PMP implemented at all?
  uint32_t tmp = neorv32_cpu_csr_read(CSR_PMPCFG0);
  if ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_PMP)) == 0) {
  tmp &= 0xffffff00; // disable entry 0
    return 0;
  neorv32_cpu_csr_write(CSR_PMPCFG0, tmp);
  }
  neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff);
 
  uint32_t tmp_a = neorv32_cpu_csr_read(CSR_PMPADDR0);
  neorv32_cpu_csr_write(CSR_PMPCFG0, neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xffffff00); // disable entry 0
 
  neorv32_cpu_csr_write(CSR_PMPADDR0, -1UL); // try to set all bits
  uint32_t i;
  uint32_t tmp = neorv32_cpu_csr_read(CSR_PMPADDR0);
 
 
  // find least-significat set bit
  // no bits set at all -> fail
  for (i=31; i!=0; i--) {
  if (tmp == 0) {
    if (((tmp_a >> i) & 1) == 0) {
    return 0;
 
  }
 
 
 
  // count trailing zeros
 
  uint32_t i = 2;
 
  while(1) {
 
    if (tmp & 1) {
      break;
      break;
    }
    }
 
    tmp >>= 1;
 
    i++;
  }
  }
 
 
  return (uint32_t)(1 << (i+1+2));
  return 1<<i;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Physical memory protection (PMP): Configure region.
 * Physical memory protection (PMP): Configure region.
 *
 *
 * @note Using NAPOT mode - page base address has to be naturally aligned.
 * @warning Only TOR mode is supported.
 *
 *
 * @warning This function requires the PMP CPU extension.
 * @note This function requires the PMP CPU extension.
 * @warning Only use available PMP regions. Check before using neorv32_cpu_pmp_get_regions(void).
 * @note Only use available PMP regions. Check before using neorv32_cpu_pmp_get_regions(void).
 *
 *
 * @param[in] index Region number (index, 0..PMP_NUM_REGIONS-1).
 * @param[in] index Region number (index, 0..PMP_NUM_REGIONS-1).
 * @param[in] base Region base address (has to be naturally aligned!).
 * @param[in] base Region base address.
 * @param[in] size Region size, has to be a power of 2 (min 8 bytes or according to HW's PMP.granularity configuration).
 * @param[in] config Region configuration byte (see #NEORV32_PMPCFG_ATTRIBUTES_enum).
 * @param[in] config Region configuration (attributes) byte (for PMPCFGx).
 
 * @return Returns 0 on success, 1 on failure.
 * @return Returns 0 on success, 1 on failure.
 **************************************************************************/
 **************************************************************************/
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config) {
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint8_t config) {
 
 
  if (size < 8) {
  if ((index > 15) || ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_PMP)) == 0)) {
    return 1; // minimal region size is 8 bytes
    return 1;
  }
  }
 
 
  if ((size & (size - 1)) != 0) {
  // set base address
    return 1; // region size is not a power of two
  base = base >> 2;
 
  switch(index & 0xf) {
 
    case 0:  neorv32_cpu_csr_write(CSR_PMPADDR0,  base); break;
 
    case 1:  neorv32_cpu_csr_write(CSR_PMPADDR1,  base); break;
 
    case 2:  neorv32_cpu_csr_write(CSR_PMPADDR2,  base); break;
 
    case 3:  neorv32_cpu_csr_write(CSR_PMPADDR3,  base); break;
 
    case 4:  neorv32_cpu_csr_write(CSR_PMPADDR4,  base); break;
 
    case 5:  neorv32_cpu_csr_write(CSR_PMPADDR5,  base); break;
 
    case 6:  neorv32_cpu_csr_write(CSR_PMPADDR6,  base); break;
 
    case 7:  neorv32_cpu_csr_write(CSR_PMPADDR7,  base); break;
 
    case 8:  neorv32_cpu_csr_write(CSR_PMPADDR8,  base); break;
 
    case 9:  neorv32_cpu_csr_write(CSR_PMPADDR9,  base); break;
 
    case 10: neorv32_cpu_csr_write(CSR_PMPADDR10, base); break;
 
    case 11: neorv32_cpu_csr_write(CSR_PMPADDR11, base); break;
 
    case 12: neorv32_cpu_csr_write(CSR_PMPADDR12, base); break;
 
    case 13: neorv32_cpu_csr_write(CSR_PMPADDR13, base); break;
 
    case 14: neorv32_cpu_csr_write(CSR_PMPADDR14, base); break;
 
    case 15: neorv32_cpu_csr_write(CSR_PMPADDR15, base); break;
 
    default: break;
  }
  }
 
 
  // pmpcfg register index
  // pmpcfg register index
  uint32_t pmpcfg_index = index >> 4; // 4 entries per pmpcfg csr
  uint32_t pmpcfg_index = index >> 4; // 4 entries per pmpcfg csr
 
 
  // setup configuration
  // get current configuration
  uint32_t tmp;
  uint32_t tmp = __neorv32_cpu_pmp_cfg_read(pmpcfg_index);
  uint32_t config_int  = ((uint32_t)config) << ((index%4)*8);
 
  uint32_t config_mask = ((uint32_t)0xFF)   << ((index%4)*8);
 
  config_mask = ~config_mask;
 
 
 
  // clear old configuration
  // clear old configuration
  __neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) & config_mask);
  uint32_t config_mask = (((uint32_t)0xFF) << ((index%4)*8));
 
  tmp = tmp & (~config_mask);
 
 
  // set base address and region size
 
  uint32_t addr_mask = ~((size - 1) >> 2);
 
  uint32_t size_mask = (size - 1) >> 3;
 
 
 
  tmp = base & addr_mask;
 
  tmp = tmp | size_mask;
 
 
 
  switch(index & 63) {
 
    case 0:  neorv32_cpu_csr_write(CSR_PMPADDR0,  tmp); break;
 
    case 1:  neorv32_cpu_csr_write(CSR_PMPADDR1,  tmp); break;
 
    case 2:  neorv32_cpu_csr_write(CSR_PMPADDR2,  tmp); break;
 
    case 3:  neorv32_cpu_csr_write(CSR_PMPADDR3,  tmp); break;
 
    case 4:  neorv32_cpu_csr_write(CSR_PMPADDR4,  tmp); break;
 
    case 5:  neorv32_cpu_csr_write(CSR_PMPADDR5,  tmp); break;
 
    case 6:  neorv32_cpu_csr_write(CSR_PMPADDR6,  tmp); break;
 
    case 7:  neorv32_cpu_csr_write(CSR_PMPADDR7,  tmp); break;
 
    case 8:  neorv32_cpu_csr_write(CSR_PMPADDR8,  tmp); break;
 
    case 9:  neorv32_cpu_csr_write(CSR_PMPADDR9,  tmp); break;
 
    case 10: neorv32_cpu_csr_write(CSR_PMPADDR10, tmp); break;
 
    case 11: neorv32_cpu_csr_write(CSR_PMPADDR11, tmp); break;
 
    case 12: neorv32_cpu_csr_write(CSR_PMPADDR12, tmp); break;
 
    case 13: neorv32_cpu_csr_write(CSR_PMPADDR13, tmp); break;
 
    case 14: neorv32_cpu_csr_write(CSR_PMPADDR14, tmp); break;
 
    case 15: neorv32_cpu_csr_write(CSR_PMPADDR15, tmp); break;
 
    case 16: neorv32_cpu_csr_write(CSR_PMPADDR16, tmp); break;
 
    case 17: neorv32_cpu_csr_write(CSR_PMPADDR17, tmp); break;
 
    case 18: neorv32_cpu_csr_write(CSR_PMPADDR18, tmp); break;
 
    case 19: neorv32_cpu_csr_write(CSR_PMPADDR19, tmp); break;
 
    case 20: neorv32_cpu_csr_write(CSR_PMPADDR20, tmp); break;
 
    case 21: neorv32_cpu_csr_write(CSR_PMPADDR21, tmp); break;
 
    case 22: neorv32_cpu_csr_write(CSR_PMPADDR22, tmp); break;
 
    case 23: neorv32_cpu_csr_write(CSR_PMPADDR23, tmp); break;
 
    case 24: neorv32_cpu_csr_write(CSR_PMPADDR24, tmp); break;
 
    case 25: neorv32_cpu_csr_write(CSR_PMPADDR25, tmp); break;
 
    case 26: neorv32_cpu_csr_write(CSR_PMPADDR26, tmp); break;
 
    case 27: neorv32_cpu_csr_write(CSR_PMPADDR27, tmp); break;
 
    case 28: neorv32_cpu_csr_write(CSR_PMPADDR28, tmp); break;
 
    case 29: neorv32_cpu_csr_write(CSR_PMPADDR29, tmp); break;
 
    case 30: neorv32_cpu_csr_write(CSR_PMPADDR30, tmp); break;
 
    case 31: neorv32_cpu_csr_write(CSR_PMPADDR31, tmp); break;
 
    case 32: neorv32_cpu_csr_write(CSR_PMPADDR32, tmp); break;
 
    case 33: neorv32_cpu_csr_write(CSR_PMPADDR33, tmp); break;
 
    case 34: neorv32_cpu_csr_write(CSR_PMPADDR34, tmp); break;
 
    case 35: neorv32_cpu_csr_write(CSR_PMPADDR35, tmp); break;
 
    case 36: neorv32_cpu_csr_write(CSR_PMPADDR36, tmp); break;
 
    case 37: neorv32_cpu_csr_write(CSR_PMPADDR37, tmp); break;
 
    case 38: neorv32_cpu_csr_write(CSR_PMPADDR38, tmp); break;
 
    case 39: neorv32_cpu_csr_write(CSR_PMPADDR39, tmp); break;
 
    case 40: neorv32_cpu_csr_write(CSR_PMPADDR40, tmp); break;
 
    case 41: neorv32_cpu_csr_write(CSR_PMPADDR41, tmp); break;
 
    case 42: neorv32_cpu_csr_write(CSR_PMPADDR42, tmp); break;
 
    case 43: neorv32_cpu_csr_write(CSR_PMPADDR43, tmp); break;
 
    case 44: neorv32_cpu_csr_write(CSR_PMPADDR44, tmp); break;
 
    case 45: neorv32_cpu_csr_write(CSR_PMPADDR45, tmp); break;
 
    case 46: neorv32_cpu_csr_write(CSR_PMPADDR46, tmp); break;
 
    case 47: neorv32_cpu_csr_write(CSR_PMPADDR47, tmp); break;
 
    case 48: neorv32_cpu_csr_write(CSR_PMPADDR48, tmp); break;
 
    case 49: neorv32_cpu_csr_write(CSR_PMPADDR49, tmp); break;
 
    case 50: neorv32_cpu_csr_write(CSR_PMPADDR50, tmp); break;
 
    case 51: neorv32_cpu_csr_write(CSR_PMPADDR51, tmp); break;
 
    case 52: neorv32_cpu_csr_write(CSR_PMPADDR52, tmp); break;
 
    case 53: neorv32_cpu_csr_write(CSR_PMPADDR53, tmp); break;
 
    case 54: neorv32_cpu_csr_write(CSR_PMPADDR54, tmp); break;
 
    case 55: neorv32_cpu_csr_write(CSR_PMPADDR55, tmp); break;
 
    case 56: neorv32_cpu_csr_write(CSR_PMPADDR56, tmp); break;
 
    case 57: neorv32_cpu_csr_write(CSR_PMPADDR57, tmp); break;
 
    case 58: neorv32_cpu_csr_write(CSR_PMPADDR58, tmp); break;
 
    case 59: neorv32_cpu_csr_write(CSR_PMPADDR59, tmp); break;
 
    case 60: neorv32_cpu_csr_write(CSR_PMPADDR60, tmp); break;
 
    case 61: neorv32_cpu_csr_write(CSR_PMPADDR61, tmp); break;
 
    case 62: neorv32_cpu_csr_write(CSR_PMPADDR62, tmp); break;
 
    case 63: neorv32_cpu_csr_write(CSR_PMPADDR63, tmp); break;
 
    default: break;
 
  }
 
 
 
  // wait for HW to compute PMP-internal stuff (address masks)
  // set configuration
  for (tmp=0; tmp<16; tmp++) {
  uint32_t config_new = ((uint32_t)config) << ((index%4)*8);
    asm volatile ("nop");
  tmp = tmp | config_new;
  }
  __neorv32_cpu_pmp_cfg_write(pmpcfg_index, tmp);
 
 
  // set new configuration
 
  __neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) | config_int);
 
 
 
 
  // check if update was successful
 
  tmp = __neorv32_cpu_pmp_cfg_read(pmpcfg_index);
 
  if ((tmp & config_mask) == config_new) {
  return 0;
  return 0;
 
  } else {
 
    return 2;
 
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Internal helper function: Read PMP configuration register 0..15
 * Internal helper function: Read PMP configuration register 0..15
Line 537... Line 471...
 * @return PMP CFG read data.
 * @return PMP CFG read data.
 **************************************************************************/
 **************************************************************************/
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index) {
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index) {
 
 
  uint32_t tmp = 0;
  uint32_t tmp = 0;
  switch(index & 15) {
  switch(index & 3) {
    case 0:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG0);  break;
    case 0:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG0);  break;
    case 1:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG1);  break;
    case 1:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG1);  break;
    case 2:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG2);  break;
    case 2:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG2);  break;
    case 3:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG3);  break;
    case 3:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG3);  break;
    case 4:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG4);  break;
 
    case 5:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG5);  break;
 
    case 6:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG6);  break;
 
    case 7:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG7);  break;
 
    case 8:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG8);  break;
 
    case 9:  tmp = neorv32_cpu_csr_read(CSR_PMPCFG9);  break;
 
    case 10: tmp = neorv32_cpu_csr_read(CSR_PMPCFG10); break;
 
    case 11: tmp = neorv32_cpu_csr_read(CSR_PMPCFG11); break;
 
    case 12: tmp = neorv32_cpu_csr_read(CSR_PMPCFG12); break;
 
    case 13: tmp = neorv32_cpu_csr_read(CSR_PMPCFG13); break;
 
    case 14: tmp = neorv32_cpu_csr_read(CSR_PMPCFG14); break;
 
    case 15: tmp = neorv32_cpu_csr_read(CSR_PMPCFG15); break;
 
    default: break;
    default: break;
  }
  }
 
 
  return tmp;
  return tmp;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Internal helper function: Write PMP configuration register 0..15
 * Internal helper function: Write PMP configuration register 0..4
 *
 *
 * @warning This function requires the PMP CPU extension.
 * @warning This function requires the PMP CPU extension.
 *
 *
 * @param[in] index PMP CFG configuration register ID (0..15).
 * @param[in] index PMP CFG configuration register ID (0..4).
 * @param[in] data PMP CFG write data.
 * @param[in] data PMP CFG write data.
 **************************************************************************/
 **************************************************************************/
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data) {
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data) {
 
 
  switch(index & 15) {
  switch(index & 3) {
    case 0:  neorv32_cpu_csr_write(CSR_PMPCFG0,  data); break;
    case 0:  neorv32_cpu_csr_write(CSR_PMPCFG0,  data); break;
    case 1:  neorv32_cpu_csr_write(CSR_PMPCFG1,  data); break;
    case 1:  neorv32_cpu_csr_write(CSR_PMPCFG1,  data); break;
    case 2:  neorv32_cpu_csr_write(CSR_PMPCFG2,  data); break;
    case 2:  neorv32_cpu_csr_write(CSR_PMPCFG2,  data); break;
    case 3:  neorv32_cpu_csr_write(CSR_PMPCFG3,  data); break;
    case 3:  neorv32_cpu_csr_write(CSR_PMPCFG3,  data); break;
    case 4:  neorv32_cpu_csr_write(CSR_PMPCFG4,  data); break;
 
    case 5:  neorv32_cpu_csr_write(CSR_PMPCFG5,  data); break;
 
    case 6:  neorv32_cpu_csr_write(CSR_PMPCFG6,  data); break;
 
    case 7:  neorv32_cpu_csr_write(CSR_PMPCFG7,  data); break;
 
    case 8:  neorv32_cpu_csr_write(CSR_PMPCFG8,  data); break;
 
    case 9:  neorv32_cpu_csr_write(CSR_PMPCFG9,  data); break;
 
    case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, data); break;
 
    case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, data); break;
 
    case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, data); break;
 
    case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, data); break;
 
    case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, data); break;
 
    case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, data); break;
 
    default: break;
    default: break;
  }
  }
}
}
 
 
 
 
Line 685... Line 595...
 *
 *
 * @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) {
 
 
 
  uint32_t tmp, size, i;
 
 
  // HPMs implemented at all?
  // HPMs implemented at all?
  if ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_ZIHPM)) == 0) {
  if ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_ZIHPM)) == 0) {
    return 0;
    return 0;
  }
  }
 
 
  // inhibt auto-update
  // inhibit auto-update of HPM counter3
  asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_HPM3));
  tmp = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT);
 
  tmp |= 1 << CSR_MCOUNTINHIBIT_HPM3;
 
  neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, tmp);
 
 
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3,  0xffffffff);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3,  0xffffffff);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3H, 0xffffffff);
  neorv32_cpu_csr_write(CSR_MHPMCOUNTER3H, 0xffffffff);
 
 
  uint32_t tmp, size, i;
 
 
 
  if (neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H) == 0) {
  if (neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H) == 0) {
    size = 0;
    size = 0;
    tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
    tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
  }
  }
  else {
  else {

powered by: WebSVN 2.1.0

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