Skip to content

Commit 0a9a2bd

Browse files
committed
add riscv64 CPU compatibility
Add a riscv64 branch that uses the Zihintpause pause instruction when the target enables it, otherwise falls back to a nop that is valid for the baseline ISA. Read the Linux device-tree timebase-frequency value from procfs or sysfs as the counter frequency, and use rdtime for timestamps so both helpers use the RISC-V time counter units. Keep the stdio include inside the riscv64 Linux branch so the common compatibility header stays slim on other targets. If Linux device-tree data is unavailable, return a 10 MHz heuristic fallback for the channel timing heuristics. Validated by compiling and running a small riscv64 translation unit including tmc/ex_cpu.hpp and tmc/channel.hpp on real riscv64 hardware, where it reported the 50 MHz device-tree timebase. Also validated riscv64 header compilation in the Arch Linux riscv64 chroot and compiled the non-Linux fallback preprocessor path.
1 parent 76a16b0 commit 0a9a2bd

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

include/tmc/detail/compat.hpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,52 @@ static inline size_t TMC_LOONGARCH_CPU_FREQ() noexcept {
133133
}
134134

135135
static inline const size_t TMC_CPU_FREQ = TMC_LOONGARCH_CPU_FREQ();
136+
#elif defined(__riscv)
137+
#if defined(__linux__)
138+
#include <cstdio>
139+
#endif
140+
#define TMC_CPU_RISCV
141+
static inline void TMC_CPU_PAUSE() noexcept {
142+
#if defined(__riscv_zihintpause)
143+
asm volatile("pause" ::: "memory");
144+
#else
145+
asm volatile("nop" ::: "memory");
146+
#endif
147+
}
148+
static inline size_t TMC_RISCV_READ_TIMEBASE_FREQ() noexcept {
149+
#if defined(__linux__)
150+
const char* paths[] = {
151+
"/proc/device-tree/cpus/timebase-frequency",
152+
"/sys/firmware/devicetree/base/cpus/timebase-frequency",
153+
};
154+
for (const char* path : paths) {
155+
auto* file = std::fopen(path, "rb");
156+
if (file == nullptr) {
157+
continue;
158+
}
159+
unsigned char bytes[8] = {};
160+
const auto size = std::fread(bytes, 1, sizeof(bytes), file);
161+
std::fclose(file);
162+
if (size == 4 || size == 8) {
163+
size_t result = 0;
164+
for (size_t i = 0; i != size; ++i) {
165+
result = (result << 8) | bytes[i];
166+
}
167+
if (result != 0) {
168+
return result;
169+
}
170+
}
171+
}
172+
#endif
173+
// This is only used for heuristics if the real RISC-V timebase is unavailable.
174+
return 10000000;
175+
}
176+
static inline size_t TMC_CPU_TIMESTAMP() noexcept {
177+
size_t count;
178+
asm volatile("rdtime %0" : "=r"(count));
179+
return count;
180+
}
181+
static inline const size_t TMC_CPU_FREQ = TMC_RISCV_READ_TIMEBASE_FREQ();
136182
#endif
137183

138184
// clang-format tries to collapse the pragmas into one line...

0 commit comments

Comments
 (0)