Projects
Eulaceura:Factory
perftest
_service:obs_scm:0009-Get-CPU-cycles-on-RISC-V....
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0009-Get-CPU-cycles-on-RISC-V.patch of Package perftest
From df20eb17a10aa4c930887c92a4d5a3832402a096 Mon Sep 17 00:00:00 2001 From: "v.v.mitrofanov" <v.v.mitrofanov@yadro.com> Date: Mon, 31 Jan 2022 13:41:30 +0300 Subject: [PATCH 2/2] Get CPU cycles on RISC-V This test acquires CPU cycles to perform output calculations and get timestamps. There is no cpu_cycles() implementation on RISC-V arch. This patch gets cycles using perf events. One of the most notable reasons to use perf event instead of reading counter registers is to avoid modifying MUCOUNTEREN register. Due to the RISC-V ISA specification (riscv-privileged-v1.9) before getting any access to counter registers it is necessary to enable it in MUCOUNTEREN in a privileged mode. On the other hand, perf events are free to use. This patch is tested on the SiFive HiFive Unmatched board. Signed-off-by: v.v.mitrofanov <v.v.mitrofanov@yadro.com> --- src/get_clock.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ src/get_clock.h | 9 +++++++ 2 files changed, 71 insertions(+) diff --git a/src/get_clock.c b/src/get_clock.c index 78ad865..c6adbdc 100755 --- a/src/get_clock.c +++ b/src/get_clock.c @@ -237,3 +237,65 @@ double get_cpu_mhz(int no_cpu_freq_warn) return proc; #endif } + +#if defined(__riscv) +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sys/syscall.h> +#include <linux/perf_event.h> +#include <asm/unistd.h> + +static long perf_event_open(struct perf_event_attr *hw_event, + pid_t pid, int cpu, int group_fd, + unsigned long flags) +{ + return syscall(__NR_perf_event_open, hw_event, pid, + cpu, group_fd, flags); +} + +cycles_t perf_get_cycles() +{ + cycles_t cycles = 0; + struct perf_event_attr pe; + const pid_t pid = 0; // Current task + const int cpu = -1; // On any CPU + const int group_fd = -1; // Use leader group + const unsigned long flags = 0; + /* Use this variable just to open perf event here and once. + It is appropriate because it touches only this function and + not fix other code */ + static int is_open = 0; + /* Make file discriptor static just to keep it valid during + programm execution. It will be closed automatically when + test finishes. It is a hack just not to fix other part of test */ + static int fd = -1; + + if (!is_open) { + memset(&pe, 0, sizeof(pe)); + + pe.type = PERF_TYPE_HARDWARE; + pe.size = sizeof(pe); + pe.config = PERF_COUNT_HW_CPU_CYCLES; + pe.disabled = 0; + pe.exclude_kernel = 0; + pe.exclude_hv = 0; + + fd = perf_event_open(&pe, pid, cpu, group_fd, flags); + if (fd == -1) { + fprintf(stderr, "Error opening perf event (%llx)\n", pe.config); + exit(EXIT_FAILURE); + } + + is_open = 1; + } + + if(read(fd, &cycles, sizeof(cycles)) < 0) { + fprintf(stderr, "Error reading perf event (%llx)\n", pe.config); + exit(EXIT_FAILURE); + } + + return cycles; +} +#endif diff --git a/src/get_clock.h b/src/get_clock.h index dacbcd0..97c3500 100755 --- a/src/get_clock.h +++ b/src/get_clock.h @@ -104,6 +104,15 @@ static inline cycles_t get_cycles() asm volatile("mrs %0, cntvct_el0" : "=r" (cval)); return cval; } +#elif defined(__riscv) +typedef unsigned long cycles_t; + +cycles_t perf_get_cycles(); + +static inline cycles_t get_cycles() +{ + return perf_get_cycles(); +} #elif defined(__loongarch64) typedef unsigned long cycles_t; -- 2.40.1
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2