diff --git a/sw/applications/example_timer_sdk/main.c b/sw/applications/example_timer_sdk/main.c new file mode 100644 index 000000000..8e6c6c2c5 --- /dev/null +++ b/sw/applications/example_timer_sdk/main.c @@ -0,0 +1,56 @@ +// Copyright 2024 EPFL +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: example_timer_sdk.c +// Author: Juan Sapriza +// Date: 15/07/2024 +// Description: Example application to test the Timer SDK. Will count the time to execute a few short tasks. + +#include +#include +#include "core_v_mini_mcu.h" +#include "timer_sdk.h" +#include "x-heep.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif PRINTF_IN_FPGA && !TARGET_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +int main(){ + uint8_t i = 0; + uint32_t cpu_cycles; + + timer_init(); // Init the timer SDK + timer_start(); // Start counting the time + cpu_cycles = timer_stop(); // Stop counting the time + PRINTF("0 NOPs:\t%d cc\n\r", cpu_cycles ); + + timer_start(); + asm volatile ("nop"); + cpu_cycles = timer_stop(); + PRINTF("1 NOP:\t%d cc\n\r", cpu_cycles ); + + timer_start(); + asm volatile ("nop"); + asm volatile ("nop"); + cpu_cycles = timer_stop(); + PRINTF("2 NOPs:\t%d cc\n\r", cpu_cycles ); + + timer_start(); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + cpu_cycles = timer_stop(); + PRINTF("3 NOPs:\t%d cc\n\r", cpu_cycles ); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/sw/device/lib/sdk/timer/timer_sdk.c b/sw/device/lib/sdk/timer/timer_sdk.c new file mode 100644 index 000000000..acfed2869 --- /dev/null +++ b/sw/device/lib/sdk/timer/timer_sdk.c @@ -0,0 +1,73 @@ +// Copyright 2023 EPFL and Politecnico di Torino. +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: timer_sdk.c +// Author: Michele Caon +// Date: 31/07/2023 +// Description: Timer functions + +#include + +#include "timer_sdk.h" +#include "csr.h" + +/******************************/ +/* ---- GLOBAL VARIABLES ---- */ +/******************************/ + +// Timer value +uint32_t timer_value = 0; +uint32_t hw_timer_value = 0; + +rv_timer_t timer; + +rv_timer_config_t timer_cfg = { + .hart_count = RV_TIMER_PARAM_N_HARTS, + .comparator_count = RV_TIMER_PARAM_N_TIMERS, +}; + +mmio_region_t timer_base = { + .base = (void *)RV_TIMER_AO_START_ADDRESS, +}; + +rv_timer_tick_params_t tick_params; + +/*************************************/ +/* ---- FUNCTION IMPLEMENTATION ---- */ +/*************************************/ + +// Initialize the hardware timer +void hw_timer_init() +{ + // Initialize the timer + rv_timer_init(timer_base, timer_cfg, &timer); + rv_timer_approximate_tick_params(REFERENCE_CLOCK_Hz, REFERENCE_CLOCK_Hz, &tick_params); + rv_timer_set_tick_params(&timer, 0, tick_params); + rv_timer_counter_set_enabled(&timer, 0, true); +} + +uint32_t hw_timer_get_cycles() +{ + uint64_t cycle_count; + rv_timer_counter_read(&timer, 0, &cycle_count); + return (uint32_t)cycle_count; +} + +void hw_timer_start() +{ + hw_timer_value = -hw_timer_get_cycles(); +} + +uint32_t hw_timer_stop() +{ + hw_timer_value += hw_timer_get_cycles(); + return hw_timer_value; +} + +// Initialize the timer +void timer_init() +{ + // Enable MCYCLE counter + CSR_CLEAR_BITS(CSR_REG_MCOUNTINHIBIT, 0x1); +} diff --git a/sw/device/lib/sdk/timer/timer_sdk.h b/sw/device/lib/sdk/timer/timer_sdk.h new file mode 100644 index 000000000..1f16df64f --- /dev/null +++ b/sw/device/lib/sdk/timer/timer_sdk.h @@ -0,0 +1,100 @@ +// Copyright 2023 EPFL and Politecnico di Torino. +// Solderpad Hardware License, Version 2.1, see LICENSE.md for details. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// File: timer_sdk.h +// Authors: Michele Caon, Luigi Giuffrida +// Date: 31/07/2023 +// Description: Execution time measurements utilities + +#ifndef TIMER_SDK_H_ +#define TIMER_SDK_H_ + +#include + +#include "csr.h" +#include "gpio.h" +#include "rv_timer.h" +#include "rv_timer_regs.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" + +#define TICK_FREQ 1000000 + +/******************************/ +/* ---- GLOBAL VARIABLES ---- */ +/******************************/ + +// Timer value +extern uint32_t timer_value; +extern uint32_t hw_timer_value; + +extern rv_timer_t timer; + +/********************************/ +/* ---- EXPORTED FUNCTIONS ---- */ +/********************************/ + +/** + * @brief Initialize the hardware timer + * + */ +void hw_timer_init(); + +/** + * @brief Get the current value of the HW timer + * +* @return int64_t Current value of the HW timer + */ +uint32_t hw_timer_get_cycles(); + +/** + * @brief Start the HW timer + * + */ +void hw_timer_start(); + +/** + * @brief Stop the HW timer + * + * @return int64_t Elapsed time in clock cycles + */ +uint32_t hw_timer_stop(); + + +/** + * @brief Initialize the timer + * + */ +void timer_init(); + +/** + * @brief Get the current value of the MCYCLE CSR + * + * @return int64_t Current value of the MCYCLE CSR + */ +inline uint32_t timer_get_cycles() { + uint32_t cycle_count; + CSR_READ(CSR_REG_MCYCLE, &cycle_count); + return cycle_count; +} + +/** + * @brief Start the timer + * + */ +inline void timer_start() { + timer_value = -timer_get_cycles(); +} + +/** + * @brief Stop the timer + * + * @return int64_t Elapsed time in clock cycles + */ +inline uint32_t timer_stop() { + timer_value += timer_get_cycles(); + return timer_value; +} + +#endif /* TIMER_SDK_H_ */