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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
14
src/vm.cpp
14
src/vm.cpp
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue