Add a timer device
This commit is contained in:
parent
1a556bba10
commit
9a4c2508f6
3 changed files with 38 additions and 9 deletions
|
@ -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;
|
||||
}
|
||||
|
|
14
src/vm.cpp
14
src/vm.cpp
|
@ -1,5 +1,6 @@
|
|||
#include "vm.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#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)
|
||||
: 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[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()) {
|
||||
|
|
|
@ -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<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 {
|
||||
public:
|
||||
VM(const std::vector<uint8_t> &memory, const std::string &file_path);
|
||||
|
@ -81,5 +89,6 @@ class VM {
|
|||
std::string file_path;
|
||||
|
||||
UART uart;
|
||||
Timer timer;
|
||||
std::vector<Device *> devices;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue