#include "nuclei_sdk_soc.h" __STATIC_FORCEINLINE uint64_t get_timer_freq(void) { return (uint64_t)SOC_TIMER_FREQ; } __STATIC_FORCEINLINE uint32_t get_time(void) { #if defined(CPU_SERIES) && CPU_SERIES == 100 // NOTE: when CSR_MIRGB_INFO CSR exist and not zero, it means eclic and systimer present if (__RV_CSR_READ(CSR_MIRGB_INFO) == 0) { return __RV_CSR_READ(CSR_MTIME); } #endif return (uint32_t)SysTimer_GetLoadValue(); } // optimize measure_cpu_freq function with Os/O0 // to get a correct cpu frequency, which // is important for flashxip linker script #if defined ( __GNUC__ ) #pragma GCC push_options #pragma GCC optimize ("Os") #elif defined ( __ICCRISCV__ ) #pragma optimize=medium #endif uint32_t measure_cpu_freq(uint32_t n) { #if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1) uint32_t start_mcycle, delta_mcycle; uint32_t start_mtime, delta_mtime; uint64_t mtime_freq = get_timer_freq(); // Don't start measuruing until we see an mtime tick uint32_t tmp = (uint32_t)get_time(); do { start_mtime = (uint32_t)get_time(); start_mcycle = __RV_CSR_READ(CSR_MCYCLE); } while (start_mtime == tmp); do { delta_mtime = (uint32_t)get_time() - start_mtime; delta_mcycle = __RV_CSR_READ(CSR_MCYCLE) - start_mcycle; } while (delta_mtime < n); return (delta_mcycle / delta_mtime) * mtime_freq + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime; #else // When system timer not exist, just return 1000000Hz #warning "measure_cpu_freq function require system timer present, if you are using this, it will not work" return 1000000; #endif } #if defined ( __GNUC__ ) #pragma GCC pop_options #elif defined ( __ICCRISCV__ ) #endif uint32_t get_cpu_freq(void) { uint32_t cpu_freq; // warm up measure_cpu_freq(1); // measure for real #ifdef CFG_SIMULATION cpu_freq = measure_cpu_freq(5); #else cpu_freq = measure_cpu_freq(100); #endif return cpu_freq; } /** * \brief delay a time in milliseconds * \details * provide API for delay * \param[in] count: count in milliseconds * \remarks */ void delay_1ms(uint32_t count) { uint64_t start_mtime, delta_mtime; uint64_t delay_ticks = (SOC_TIMER_FREQ * (uint64_t)count) / 1000; #if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1) start_mtime = get_time(); do { delta_mtime = get_time() - start_mtime; } while (delta_mtime < delay_ticks); #else #warning "delay_1ms function require system timer present, if you are using this, it will not work" #endif } void simulation_exit(int status) { // Both xlspike and qemu will write RXFIFO to make it works for xlspike even SIMU=qemu // workaround for fix cycle model exit with some message not print for (int i = 0; i < 10; i ++) { // print '\0' instead of '\r' for qemu simulation in ide uart_write(UART0, '\0'); } uart_write(UART0, '\n'); // pass exit status via rxfifo register SIMULATION_EXIT(status); #if defined(SIMULATION_MODE) #if SIMULATION_MODE == SIMULATION_MODE_QEMU #define QEMU_VIRT_TEST_BASE 0x100000 #define QEMU_SIG_EXIT 0x3333 REG32(QEMU_VIRT_TEST_BASE) = (status << 16) | QEMU_SIG_EXIT; #endif #endif }