Add a timer device

This commit is contained in:
Konstantin Nazarov 2024-12-19 00:50:10 +00:00
parent 1a556bba10
commit 9a4c2508f6
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
3 changed files with 38 additions and 9 deletions

View file

@ -16,19 +16,27 @@ uint64_t read_mtime_atomic() {
return ((uint64_t)upper1 << 32) | lower; return ((uint64_t)upper1 << 32) | lower;
} }
int fact(int n) { uint32_t timediff_ms(uint64_t start, uint64_t end) {
if (n == 0) 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 1;
return n * fact(n-1); return fib(n-1) + fib(n-2);
} }
int main() { int main() {
int n = 8; int n = 24;
int res = fact(8); uint64_t start = read_mtime_atomic();
int res = fib(n);
printf("sizeof(long) = %d\n", sizeof(long long)); uint64_t end = read_mtime_atomic();
printf("%d! = %d\n", n, res); uint32_t total_msec = timediff_ms(start, end);
printf("fib(%d) = %d\n", n, res);
printf("time: %dms\n", total_msec);
return 0; return 0;
} }

View file

@ -1,5 +1,6 @@
#include "vm.hpp" #include "vm.hpp"
#include <chrono>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
@ -14,9 +15,10 @@ inline int32_t sign_extend(int32_t value, int bits) {
VM::VM(const std::vector<uint8_t>& memory, const std::string& file_path) VM::VM(const std::vector<uint8_t>& memory, const std::string& file_path)
: ram(memory), pc(PROGRAM_ADDR), file_path(file_path) { : ram(memory), pc(PROGRAM_ADDR), file_path(file_path) {
devices = std::vector<Device*>(2, 0); devices = std::vector<Device*>(3, 0);
devices[0] = &ram; devices[0] = &ram;
devices[1] = &uart; devices[1] = &uart;
devices[2] = &timer;
} }
void VM::setreg(size_t regnum, uint32_t value) { 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) { void VM::read_mem(uint8_t* dst, size_t addr, size_t size) {
for (Device* dev : devices) { for (Device* dev : devices) {
if (addr >= dev->base() && addr + size <= dev->base() + dev->size()) { if (addr >= dev->base() && addr + size <= dev->base() + dev->size()) {

View file

@ -11,6 +11,7 @@ class EbreakException : std::exception {};
const int NUM_REGISTERS = 32; // Standard RISC-V has 32 registers const int NUM_REGISTERS = 32; // Standard RISC-V has 32 registers
const uint32_t UART_ADDR = 0x10000000; const uint32_t UART_ADDR = 0x10000000;
const uint32_t PROGRAM_ADDR = 0x80000000; const uint32_t PROGRAM_ADDR = 0x80000000;
const uint32_t MTIME_ADDR = 0x0200BFF8;
class Device { class Device {
public: public:
@ -56,6 +57,13 @@ class RAM final : public Device {
RAM(const std::vector<uint8_t> &memory) : Device(PROGRAM_ADDR, memory) {} RAM(const std::vector<uint8_t> &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 { class VM {
public: public:
VM(const std::vector<uint8_t> &memory, const std::string &file_path); VM(const std::vector<uint8_t> &memory, const std::string &file_path);
@ -81,5 +89,6 @@ class VM {
std::string file_path; std::string file_path;
UART uart; UART uart;
Timer timer;
std::vector<Device *> devices; std::vector<Device *> devices;
}; };