arch/risc-v/common: provide architecture specific perfmon bindings.

Provides two implementations:
 - CSR_CYCLE: Cores which implement hardware performance monitoring.
 - CSR_TIME: Uses the machine time registers.

Using the up_perf_xx bindings directory is more efficient than performing a nanosecond conversion on every gettime event.
This commit is contained in:
Stuart Ianna 2024-05-15 14:40:22 +10:00 committed by Xiang Xiao
parent fe4526c7f9
commit 29ee9aacb3
6 changed files with 177 additions and 0 deletions

View File

@ -668,6 +668,7 @@ config LITEX_CORE_VEXRISCV_SMP
select ARCH_NEED_ADDRENV_MAPPING
select ARCH_HAVE_S_MODE
select ARCH_HAVE_ELF_EXECUTABLE
select ARCH_HAVE_PERF_EVENTS
endchoice # LITEX Core Selection

View File

@ -0,0 +1,84 @@
/****************************************************************************
* arch/risc-v/src/common/riscv_perf_cycle.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this args for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/clock.h>
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include "riscv_internal.h"
#ifdef CONFIG_ARCH_PERF_EVENTS
/****************************************************************************
* Private Data
****************************************************************************/
static unsigned long g_cycle_frequency = ULONG_MAX;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_perf_init
****************************************************************************/
void up_perf_init(void *arg)
{
g_cycle_frequency = (unsigned long)(uintptr_t)arg;
}
/****************************************************************************
* Name: up_perf_gettime
****************************************************************************/
unsigned long up_perf_gettime(void)
{
return READ_CSR(CSR_CYCLE);
}
/****************************************************************************
* Name: up_perf_getfreq
****************************************************************************/
unsigned long up_perf_getfreq(void)
{
return g_cycle_frequency;
}
/****************************************************************************
* Name: up_perf_convert
****************************************************************************/
void up_perf_convert(unsigned long elapsed, struct timespec *ts)
{
DEBUGASSERT(g_cycle_frequency && (g_cycle_frequency != ULONG_MAX));
ts->tv_sec = elapsed / g_cycle_frequency;
elapsed -= ts->tv_sec * g_cycle_frequency;
ts->tv_nsec = elapsed * (NSEC_PER_SEC / g_cycle_frequency);
}
#endif

View File

@ -0,0 +1,84 @@
/****************************************************************************
* arch/risc-v/src/common/riscv_perf_time.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this args for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/clock.h>
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include "riscv_internal.h"
#ifdef CONFIG_ARCH_PERF_EVENTS
/****************************************************************************
* Private Data
****************************************************************************/
static unsigned long g_clock_frequency = ULONG_MAX;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_perf_init
****************************************************************************/
void up_perf_init(void *arg)
{
g_clock_frequency = (unsigned long)(uintptr_t)arg;
}
/****************************************************************************
* Name: up_perf_gettime
****************************************************************************/
unsigned long up_perf_gettime(void)
{
return READ_CSR(CSR_TIME);
}
/****************************************************************************
* Name: up_perf_getfreq
****************************************************************************/
unsigned long up_perf_getfreq(void)
{
return g_clock_frequency;
}
/****************************************************************************
* Name: up_perf_convert
****************************************************************************/
void up_perf_convert(unsigned long elapsed, struct timespec *ts)
{
DEBUGASSERT(g_clock_frequency && (g_clock_frequency != ULONG_MAX));
ts->tv_sec = elapsed / g_clock_frequency;
elapsed -= ts->tv_sec * g_clock_frequency;
ts->tv_nsec = elapsed * (NSEC_PER_SEC / g_clock_frequency);
}
#endif

View File

@ -40,6 +40,7 @@ CHIP_ASRCS += litex_cache.S
ifeq ($(CONFIG_SCHED_TICKLESS),y)
ifeq ($(CONFIG_SCHED_TICKLESS_ALARM),y)
CHIP_CSRCS += litex_arch_alarm.c
CHIP_CSRCS += riscv_perf_time.c
else
CHIP_CSRCS += litex_tickless.c
endif

View File

@ -52,5 +52,9 @@ void up_timer_initialize(void)
DEBUGASSERT(lower);
#ifdef CONFIG_ARCH_HAVE_PERF_EVENTS
up_perf_init((void *)CONFIG_LITEX_SYS_CORE_FREQ_HZ);
#endif
up_alarm_set_lowerhalf(lower);
}

View File

@ -64,12 +64,14 @@ CONFIG_NSH_FILE_APPS=y
CONFIG_NSH_READLINE=y
CONFIG_ONESHOT=y
CONFIG_PATH_INITIAL="/system/bin"
CONFIG_PERF_OVERFLOW_CORRECTION=y
CONFIG_RAM_SIZE=4194304
CONFIG_RAM_START=0x40400000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_IRQMONITOR=y
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_TICKLESS=y
CONFIG_SCHED_WAITPID=y
@ -81,6 +83,7 @@ CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_CLE=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_SYSTEM_TIME64=y
CONFIG_TESTING_GETPRIME=y
CONFIG_UART0_RXBUFSIZE=128
CONFIG_UART0_SERIAL_CONSOLE=y