From 9a4c2508f6e7c00a75857eea27d5ebf7a13ec05e Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Thu, 19 Dec 2024 00:50:10 +0000 Subject: [PATCH] Add a timer device --- example/example.c | 24 ++++++++++++++++-------- src/vm.cpp | 14 +++++++++++++- src/vm.hpp | 9 +++++++++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/example/example.c b/example/example.c index 91aa3f1..b2d7eda 100644 --- a/example/example.c +++ b/example/example.c @@ -16,19 +16,27 @@ uint64_t read_mtime_atomic() { return ((uint64_t)upper1 << 32) | lower; } -int fact(int n) { - if (n == 0) +uint32_t timediff_ms(uint64_t start, uint64_t end) { + uint64_t total = end-start; + // Clock rate is currently 1MHz + return (uint32_t)total / 1000; +} + +int fib(int n) { + if (n == 0 || n == 1) return 1; - return n * fact(n-1); + return fib(n-1) + fib(n-2); } int main() { - int n = 8; - int res = fact(8); - - printf("sizeof(long) = %d\n", sizeof(long long)); - printf("%d! = %d\n", n, res); + int n = 24; + uint64_t start = read_mtime_atomic(); + int res = fib(n); + uint64_t end = read_mtime_atomic(); + uint32_t total_msec = timediff_ms(start, end); + printf("fib(%d) = %d\n", n, res); + printf("time: %dms\n", total_msec); return 0; } diff --git a/src/vm.cpp b/src/vm.cpp index 8fc0371..94d210c 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1,5 +1,6 @@ #include "vm.hpp" +#include #include #include #include @@ -14,9 +15,10 @@ inline int32_t sign_extend(int32_t value, int bits) { VM::VM(const std::vector& memory, const std::string& file_path) : ram(memory), pc(PROGRAM_ADDR), file_path(file_path) { - devices = std::vector(2, 0); + devices = std::vector(3, 0); devices[0] = &ram; devices[1] = &uart; + devices[2] = &timer; } void VM::setreg(size_t regnum, uint32_t value) { @@ -73,6 +75,16 @@ void UART::write_mem(uint8_t* src, size_t addr, size_t size) { } } +void Timer::read_mem(uint8_t* dst, size_t addr, size_t size) { + using Clock = std::chrono::high_resolution_clock; + constexpr auto den = Clock::period::den; + constexpr auto num = Clock::period::num; + + // Let's assume that clock rate is 1MHz for now + set(Clock::now().time_since_epoch().count() / (den / (1000000 * num))); + Device::read_mem(dst, addr, size); +} + void VM::read_mem(uint8_t* dst, size_t addr, size_t size) { for (Device* dev : devices) { if (addr >= dev->base() && addr + size <= dev->base() + dev->size()) { diff --git a/src/vm.hpp b/src/vm.hpp index d8ce4b2..d73c5d3 100644 --- a/src/vm.hpp +++ b/src/vm.hpp @@ -11,6 +11,7 @@ class EbreakException : std::exception {}; const int NUM_REGISTERS = 32; // Standard RISC-V has 32 registers const uint32_t UART_ADDR = 0x10000000; const uint32_t PROGRAM_ADDR = 0x80000000; +const uint32_t MTIME_ADDR = 0x0200BFF8; class Device { public: @@ -56,6 +57,13 @@ class RAM final : public Device { RAM(const std::vector &memory) : Device(PROGRAM_ADDR, memory) {} }; +class Timer final : public Device { + public: + Timer() : Device(MTIME_ADDR, 8) {} + virtual void read_mem(uint8_t *dst, size_t addr, size_t size); + void set(uint64_t value) { write_mem((uint8_t *)&value, MTIME_ADDR, 8); } +}; + class VM { public: VM(const std::vector &memory, const std::string &file_path); @@ -81,5 +89,6 @@ class VM { std::string file_path; UART uart; + Timer timer; std::vector devices; };