From: ljsebald <ljs...@us...> - 2023-03-31 19:37:43
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 4c7ef784f214b83ef5503fe2a56145e68f93bb75 (commit) via b69def42a7a046e43d4b5d85bf3a8770d67de87f (commit) via f58eaa82c102eae29d64aa1d6ceb296ca948cae9 (commit) via 667764379bd03078847481edc7328955cba65391 (commit) via 6f5ff8997e907aa5a68dedccb02ffbc8e621df12 (commit) via 5b8865f9ab8518366c19eb1ccac2596ef6a6306f (commit) via 810ac57d3c2bfdc05bea12abdb0ec0e12d4fafe6 (commit) from 35364a74b969f71c422a98f214fbf3599a4a914f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 4c7ef784f214b83ef5503fe2a56145e68f93bb75 Merge: 35364a7 b69def4 Author: Lawrence Sebald <ljs...@us...> Date: Fri Mar 31 15:37:07 2023 -0400 Merge pull request #139 from Dreamcast-Projects/master Added timer_ns_gettime64() and performance counters commit b69def42a7a046e43d4b5d85bf3a8770d67de87f Author: Andress Barajas <and...@gm...> Date: Fri Mar 31 08:37:23 2023 -0700 Updated entry position in Changelog. Return a value using micro seconds timer to generate a nanoseconds value instead of returning 0 commit f58eaa82c102eae29d64aa1d6ceb296ca948cae9 Author: Andress Barajas <and...@gm...> Date: Fri Mar 31 01:21:01 2023 -0700 Added inline to speed things up commit 667764379bd03078847481edc7328955cba65391 Author: Andress Barajas <and...@gm...> Date: Fri Mar 31 00:50:38 2023 -0700 Updated Changelog commit 6f5ff8997e907aa5a68dedccb02ffbc8e621df12 Author: Andress Barajas <and...@gm...> Date: Fri Mar 31 00:46:21 2023 -0700 Fix comment typo commit 5b8865f9ab8518366c19eb1ccac2596ef6a6306f Merge: 810ac57 35364a7 Author: Andress Barajas <and...@gm...> Date: Fri Mar 31 00:42:35 2023 -0700 Merge branch 'KallistiOS:master' into master commit 810ac57d3c2bfdc05bea12abdb0ec0e12d4fafe6 Author: Andress Barajas <and...@gm...> Date: Fri Mar 31 00:41:13 2023 -0700 Added timer_ns_gettime64() ----------------------------------------------------------------------- Summary of changes: doc/CHANGELOG | 1 + kernel/arch/dreamcast/include/arch/timer.h | 140 ++++++++++++++++++++++++++++- kernel/arch/dreamcast/kernel/init.c | 1 + kernel/arch/dreamcast/kernel/timer.c | 77 +++++++++++++++- 4 files changed, 216 insertions(+), 3 deletions(-) diff --git a/doc/CHANGELOG b/doc/CHANGELOG index cb6ed7f..8de8b48 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -157,6 +157,7 @@ KallistiOS version 2.1.0 ----------------------------------------------- - DC Removed "navi" subarch, moved code to addons/libnavi [LS] - *** Removed (completely unsupported) support for GCC 3.x and older [LS] - *** Add timespec_get C11 function to koslib's libc [LS] +- DC Added timer_ns_gettime64() and performance counters [AB] KallistiOS version 2.0.0 ----------------------------------------------- - DC Broadband Adapter driver fixes [Dan Potter == DP] diff --git a/kernel/arch/dreamcast/include/arch/timer.h b/kernel/arch/dreamcast/include/arch/timer.h index 82fa661..4286cf1 100644 --- a/kernel/arch/dreamcast/include/arch/timer.h +++ b/kernel/arch/dreamcast/include/arch/timer.h @@ -51,7 +51,7 @@ __BEGIN_DECLS KallistiOS does not currently support using this timer. */ -#define WDT 3 +#define WDT 3 /** \brief Which timer does the thread system use? */ #define TIMER_ID TMU0 @@ -225,6 +225,144 @@ int timer_init(); void timer_shutdown(); /* \endcond */ +/** \brief SH4 Performance Counter. + + This counter is used by the ns_gettime function in this header. +*/ +#define PRFC0 0 + +/** \brief SH4 Performance Counter. + + A counter that is not used by KOS. +*/ +#define PRFC1 1 + +/** \brief CPU Cycles Count Type + + Count cycles. At 5 ns increments, a 48-bit cycle counter can + run continuously for 16.33 days. +*/ +#define PMCR_COUNT_CPU_CYCLES 0 + +/** \brief Ratio Cycles Count Type + + CPU/bus ratio mode where cycles (where T = C x B / 24 and T is time, + C is count, and B is time of one bus cycle). +*/ +#define PMCR_COUNT_RATIO_CYCLES 1 + +/* MODE DEFINITION VALUE MEASURMENT TYPE & NOTES */ +#define PMCR_INIT_NO_MODE 0x00 /* None; Just here to be complete */ +#define PMCR_OPERAND_READ_ACCESS_MODE 0x01 /* Quantity; With cache */ +#define PMCR_OPERAND_WRITE_ACCESS_MODE 0x02 /* Quantity; With cache */ +#define PMCR_UTLB_MISS_MODE 0x03 /* Quantity */ +#define PMCR_OPERAND_CACHE_READ_MISS_MODE 0x04 /* Quantity */ +#define PMCR_OPERAND_CACHE_WRITE_MISS_MODE 0x05 /* Quantity */ +#define PMCR_INSTRUCTION_FETCH_MODE 0x06 /* Quantity; With cache */ +#define PMCR_INSTRUCTION_TLB_MISS_MODE 0x07 /* Quantity */ +#define PMCR_INSTRUCTION_CACHE_MISS_MODE 0x08 /* Quantity */ +#define PMCR_ALL_OPERAND_ACCESS_MODE 0x09 /* Quantity */ +#define PMCR_ALL_INSTRUCTION_FETCH_MODE 0x0a /* Quantity */ +#define PMCR_ON_CHIP_RAM_OPERAND_ACCESS_MODE 0x0b /* Quantity */ +/* No 0x0c */ +#define PMCR_ON_CHIP_IO_ACCESS_MODE 0x0d /* Quantity */ +#define PMCR_OPERAND_ACCESS_MODE 0x0e /* Quantity; With cache, counts both reads and writes */ +#define PMCR_OPERAND_CACHE_MISS_MODE 0x0f /* Quantity */ +#define PMCR_BRANCH_ISSUED_MODE 0x10 /* Quantity; Not the same as branch taken! */ +#define PMCR_BRANCH_TAKEN_MODE 0x11 /* Quantity */ +#define PMCR_SUBROUTINE_ISSUED_MODE 0x12 /* Quantity; Issued a BSR, BSRF, JSR, JSR/N */ +#define PMCR_INSTRUCTION_ISSUED_MODE 0x13 /* Quantity */ +#define PMCR_PARALLEL_INSTRUCTION_ISSUED_MODE 0x14 /* Quantity */ +#define PMCR_FPU_INSTRUCTION_ISSUED_MODE 0x15 /* Quantity */ +#define PMCR_INTERRUPT_COUNTER_MODE 0x16 /* Quantity */ +#define PMCR_NMI_COUNTER_MODE 0x17 /* Quantity */ +#define PMCR_TRAPA_INSTRUCTION_COUNTER_MODE 0x18 /* Quantity */ +#define PMCR_UBC_A_MATCH_MODE 0x19 /* Quantity */ +#define PMCR_UBC_B_MATCH_MODE 0x1a /* Quantity */ +/* No 0x1b-0x20 */ +#define PMCR_INSTRUCTION_CACHE_FILL_MODE 0x21 /* Cycles */ +#define PMCR_OPERAND_CACHE_FILL_MODE 0x22 /* Cycles */ +#define PMCR_ELAPSED_TIME_MODE 0x23 /* Cycles; For 200MHz CPU: 5ns per count in 1 cycle = 1 count mode, or around 417.715ps per count (increments by 12) in CPU/bus ratio mode */ +#define PMCR_PIPELINE_FREEZE_BY_ICACHE_MISS_MODE 0x24 /* Cycles */ +#define PMCR_PIPELINE_FREEZE_BY_DCACHE_MISS_MODE 0x25 /* Cycles */ +/* No 0x26 */ +#define PMCR_PIPELINE_FREEZE_BY_BRANCH_MODE 0x27 /* Cycles */ +#define PMCR_PIPELINE_FREEZE_BY_CPU_REGISTER_MODE 0x28 /* Cycles */ +#define PMCR_PIPELINE_FREEZE_BY_FPU_MODE 0x29 /* Cycles */ + +/** \brief Get a performance counter's settings. + + This function returns a performance counter's settings. + + \param which The performance counter (i.e, \ref PRFC0 or PRFC1). + \retval 0 On success. +*/ +uint16 perf_cntr_get_config(int which); + +/** \brief Start a performance counter. + + This function starts a performance counter + + \param which The counter to start (i.e, \ref PRFC0 or PRFC1). + \param mode Use one of the 33 modes listed above. + \param count_type PMCR_COUNT_CPU_CYCLES or PMCR_COUNT_RATIO_CYCLES. + \retval 0 On success. +*/ +int perf_cntr_start(int which, int mode, int count_type); + +/** \brief Stop a performance counter. + + This function stops a performance counter that was started with perf_cntr_start(). + Stopping a counter retains its count. To clear the count use perf_cntr_clear(). + + \param which The counter to stop (i.e, \ref PRFC0 or PRFC1). + \retval 0 On success. +*/ +int perf_cntr_stop(int which); + +/** \brief Clear a performance counter + + This function clears a performance counter. It resets its value to zero. + You cannot clear a running counter. This function stops the counter before + clearing it because you cant clear a running counter. + + \param which The counter to clear (i.e, \ref PRFC0 or PRFC1). + \retval 0 On success. +*/ +int perf_cntr_clear(int which); + +/** \brief Obtain the count of a performance counter. + + This function simply returns the count of the counter. + + \param which The counter to read (i.e, \ref PRFC0 or PRFC1). + \return The counter's count. +*/ +uint64 perf_cntr_count(int which); + +/** \brief Enable the nanosecond timer. + + This function enables the performance counter used for the timer_ns_gettime64() + function. This is on by default. The function uses \ref PRFC0 to do the work. +*/ +void timer_ns_enable(); + +/** \brief Disable the nanosecond timer. + + This function disables the performance counter used for the timer_ns_gettime64() + function. Generally, you will not want to do this, unless you have some need to use + the counter \ref PRFC0 for something else. +*/ +void timer_ns_disable(); + +/** \brief Get the current uptime of the system (in nanoseconds). + + This function retrieves the number of nanoseconds since KOS was started. + + \return The number of nanoseconds since KOS started. +*/ +uint64 timer_ns_gettime64(); + __END_DECLS #endif /* __ARCH_TIMER_H */ diff --git a/kernel/arch/dreamcast/kernel/init.c b/kernel/arch/dreamcast/kernel/init.c index bb51d60..2b6ab91 100644 --- a/kernel/arch/dreamcast/kernel/init.c +++ b/kernel/arch/dreamcast/kernel/init.c @@ -101,6 +101,7 @@ int __attribute__((weak)) arch_auto_init() { hardware_sys_init(); /* DC low-level hardware init */ /* Initialize our timer */ + timer_ns_enable(); timer_ms_enable(); rtc_init(); diff --git a/kernel/arch/dreamcast/kernel/timer.c b/kernel/arch/dreamcast/kernel/timer.c index bfa52ad..3829781 100644 --- a/kernel/arch/dreamcast/kernel/timer.c +++ b/kernel/arch/dreamcast/kernel/timer.c @@ -120,8 +120,6 @@ void timer_spin_sleep(int ms) { timer_stop(TMU1); } - - /* Enable timer interrupts (high priority); needs to move to irq.c sometime. */ void timer_enable_ints(int which) { @@ -316,5 +314,80 @@ void timer_shutdown() { timer_disable_ints(TMU2); } +/* Quick access macros */ +#define PMCR_CTRL(o) ( *((volatile uint16*)(0xff000084) + (o << 1)) ) +#define PMCTR_HIGH(o) ( *((volatile uint32*)(0xff100004) + (o << 1)) ) +#define PMCTR_LOW(o) ( *((volatile uint32*)(0xff100008) + (o << 1)) ) + +#define PMCR_CLR 0x2000 +#define PMCR_PMST 0x4000 +#define PMCR_PMENABLE 0x8000 +#define PMCR_RUN 0xc000 +#define PMCR_PMM_MASK 0x003f + +#define PMCR_CLOCK_TYPE_SHIFT 8 + +/* 5ns per count in 1 cycle = 1 count mode(PMCR_COUNT_CPU_CYCLES) */ +#define NS_PER_CYCLE 5 + +/* Get a counter's current configuration */ +uint16 perf_cntr_get_config(int which) { + return PMCR_CTRL(which); +} + +/* Start a performance counter */ +int perf_cntr_start(int which, int mode, int count_type) { + perf_cntr_stop(which); + perf_cntr_clear(which); + PMCR_CTRL(which) = PMCR_RUN | mode | (count_type << PMCR_CLOCK_TYPE_SHIFT); + + return 0; +} + +/* Stop a performance counter */ +int perf_cntr_stop(int which) { + PMCR_CTRL(which) &= ~(PMCR_PMM_MASK | PMCR_PMENABLE); + + return 0; +} + +/* Clears a performance counter */ +int perf_cntr_clear(int which) { + PMCR_CTRL(which) |= PMCR_CLR; + return 0; +} + +/* Returns the count value of a counter */ +inline uint64 perf_cntr_count(int which) { + return (uint64)(PMCTR_HIGH(which) & 0xffff) << 32 | PMCTR_LOW(which); +} + +void timer_ns_enable() { + perf_cntr_start(PRFC0, PMCR_ELAPSED_TIME_MODE, PMCR_COUNT_CPU_CYCLES); +} + +void timer_ns_disable() { + uint16 config = PMCR_CTRL(PRFC0); + + /* If timer is running, disable it */ + if((config & PMCR_ELAPSED_TIME_MODE)) { + perf_cntr_stop(PRFC0); + perf_cntr_clear(PRFC0); + } +} + +inline uint64 timer_ns_gettime64() { + uint16 config = PMCR_CTRL(PRFC0); + + /* If timer is running */ + if((config & PMCR_ELAPSED_TIME_MODE)) { + uint64 cycles = perf_cntr_count(PRFC0); + return cycles * NS_PER_CYCLE; + } + else { + uint64 micro_secs = timer_us_gettime64(); + return micro_secs * 1000; + } +} hooks/post-receive -- A pseudo Operating System for the Dreamcast. |