[Add] software simulator add
This commit is contained in:
1
labus/device.cc
Normal file
1
labus/device.cc
Normal file
@@ -0,0 +1 @@
|
||||
#include <device.hh>
|
||||
140
labus/include/device.hh
Normal file
140
labus/include/device.hh
Normal file
@@ -0,0 +1,140 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
class Device {
|
||||
public:
|
||||
Device() = default;
|
||||
|
||||
virtual const size_t &size() const = 0;
|
||||
|
||||
virtual void write(char *buf, size_t addr, size_t len) = 0;
|
||||
virtual void read(char *buf, size_t addr, size_t len) = 0;
|
||||
|
||||
virtual void write64(uint64_t &dword, size_t addr) = 0;
|
||||
virtual void read64(uint64_t &dword, size_t addr) = 0;
|
||||
|
||||
virtual void write32(uint32_t &word, size_t addr) = 0;
|
||||
virtual void read32(uint32_t &word, size_t addr) = 0;
|
||||
|
||||
virtual void write16(uint16_t &hword, size_t addr) = 0;
|
||||
virtual void read16(uint16_t &hword, size_t addr) = 0;
|
||||
|
||||
virtual void write8(uint8_t &byte, size_t addr) = 0;
|
||||
virtual void read8(uint8_t &byte, size_t addr) = 0;
|
||||
|
||||
virtual ~Device() = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class WRDevice : public Device{
|
||||
size_t devsiz;
|
||||
public:
|
||||
WRDevice(size_t siz);
|
||||
|
||||
virtual const size_t &size() const;
|
||||
|
||||
virtual void write(char *buf, size_t addr, size_t len);
|
||||
virtual void read(char *buf, size_t addr, size_t len);
|
||||
|
||||
virtual void write64(uint64_t &dword, size_t addr);
|
||||
virtual void read64(uint64_t &dword, size_t addr);
|
||||
|
||||
virtual void write32(uint32_t &word, size_t addr);
|
||||
virtual void read32(uint32_t &word, size_t addr);
|
||||
|
||||
virtual void write16(uint16_t &hword, size_t addr);
|
||||
virtual void read16(uint16_t &hword, size_t addr);
|
||||
|
||||
virtual void write8(uint8_t &byte, size_t addr);
|
||||
virtual void read8(uint8_t &byte, size_t addr);
|
||||
|
||||
virtual ~WRDevice() = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
WRDevice<T>::WRDevice(size_t siz) : devsiz(siz) {}
|
||||
|
||||
template <typename T>
|
||||
const size_t &WRDevice<T>::size() const { return devsiz; }
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::write(char *buf, size_t addr, size_t len) {}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::read(char *buf, size_t addr, size_t len) {}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::write64(uint64_t &dword, size_t addr) {
|
||||
uint8_t buf[sizeof(dword)];
|
||||
buf[0] = (dword >> 0) & 0xFF;
|
||||
buf[1] = (dword >> 8) & 0xFF;
|
||||
buf[2] = (dword >> 16) & 0xFF;
|
||||
buf[3] = (dword >> 24) & 0xFF;
|
||||
buf[4] = (dword >> 32) & 0xFF;
|
||||
buf[5] = (dword >> 40) & 0xFF;
|
||||
buf[6] = (dword >> 48) & 0xFF;
|
||||
buf[7] = (dword >> 56) & 0xFF;
|
||||
static_cast<T *>(this)->write((char *)buf, addr, sizeof(dword));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::read64(uint64_t &dword, size_t addr) {
|
||||
uint8_t buf[sizeof(dword)];
|
||||
static_cast<T *>(this)->read((char *)buf, addr, sizeof(dword));
|
||||
dword = (uint64_t) buf[0];
|
||||
dword |= (uint64_t) buf[1] << 8;
|
||||
dword |= (uint64_t) buf[2] << 16;
|
||||
dword |= (uint64_t) buf[3] << 24;
|
||||
dword |= (uint64_t) buf[4] << 32;
|
||||
dword |= (uint64_t) buf[5] << 40;
|
||||
dword |= (uint64_t) buf[6] << 48;
|
||||
dword |= (uint64_t) buf[7] << 56;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::write32(uint32_t &word, size_t addr) {
|
||||
uint8_t buf[sizeof(word)];
|
||||
buf[0] = (word >> 0) & 0xFF;
|
||||
buf[1] = (word >> 8) & 0xFF;
|
||||
buf[2] = (word >> 16) & 0xFF;
|
||||
buf[3] = (word >> 24) & 0xFF;
|
||||
static_cast<T *>(this)->write((char *)buf, addr, sizeof(word));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::read32(uint32_t &word, size_t addr) {
|
||||
uint8_t buf[sizeof(word)];
|
||||
static_cast<T *>(this)->read((char *)buf, addr, sizeof(word));
|
||||
word = (uint32_t) buf[0];
|
||||
word |= (uint32_t) buf[1] << 8;
|
||||
word |= (uint32_t) buf[2] << 16;
|
||||
word |= (uint32_t) buf[3] << 24;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::write16(uint16_t &hword, size_t addr) {
|
||||
uint8_t buf[sizeof(hword)];
|
||||
buf[0] = (hword >> 0) & 0xFF;
|
||||
buf[1] = (hword >> 8) & 0xFF;
|
||||
static_cast<T *>(this)->write((char *)buf, addr, sizeof(hword));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::read16(uint16_t &hword, size_t addr) {
|
||||
uint8_t buf[sizeof(hword)];
|
||||
static_cast<T *>(this)->read((char *)buf, addr, sizeof(hword));
|
||||
hword = (uint16_t) buf[0];
|
||||
hword |= (uint16_t) buf[1] << 8;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::write8(uint8_t &byte, size_t addr) {
|
||||
static_cast<T *>(this)->write((char *)&byte, addr, sizeof(byte));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WRDevice<T>::read8(uint8_t &byte, size_t addr) {
|
||||
static_cast<T *>(this)->read((char *)&byte, addr, sizeof(byte));
|
||||
}
|
||||
19
labus/include/memory.hh
Normal file
19
labus/include/memory.hh
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <device.hh>
|
||||
|
||||
class Memory : public WRDevice<Memory> {
|
||||
char *data;
|
||||
bool wen;
|
||||
bool ren;
|
||||
bool xen;
|
||||
public:
|
||||
Memory(size_t siz, bool w = true, bool r = true, bool x = true);
|
||||
~Memory();
|
||||
|
||||
void load(const char *path);
|
||||
void load(Memory *mem, size_t addr, size_t len);
|
||||
|
||||
void write(char *buf, size_t addr, size_t len);
|
||||
void read(char *buf, size_t addr, size_t len);
|
||||
};
|
||||
10
labus/include/serial.hh
Normal file
10
labus/include/serial.hh
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <device.hh>
|
||||
|
||||
class Serial : public WRDevice<Serial> {
|
||||
public:
|
||||
Serial(size_t siz);
|
||||
|
||||
void write(char *buf, size_t addr, size_t len);
|
||||
};
|
||||
@@ -1 +1,33 @@
|
||||
int fetch();
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
#include <device.hh>
|
||||
|
||||
class SystemBus {
|
||||
std::map<uint64_t, Device *> iomap;
|
||||
|
||||
std::pair<const uint64_t, Device *> &finddev(uint64_t addr);
|
||||
|
||||
public:
|
||||
SystemBus() = default;
|
||||
|
||||
void regdev(Device *dev, uint64_t addr);
|
||||
|
||||
void write(char *buf, size_t addr, size_t len);
|
||||
void read(char *buf, size_t addr, size_t len);
|
||||
|
||||
void write64(uint64_t &dword, size_t addr);
|
||||
void read64(uint64_t &dword, size_t addr);
|
||||
|
||||
void write32(uint32_t &word, size_t addr);
|
||||
void read32(uint32_t &word, size_t addr);
|
||||
|
||||
void write16(uint16_t &hword, size_t addr);
|
||||
void read16(uint16_t &hword, size_t addr);
|
||||
|
||||
void write8(uint8_t &byte, size_t addr);
|
||||
void read8(uint8_t &byte, size_t addr);
|
||||
};
|
||||
40
labus/memory.cc
Normal file
40
labus/memory.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <memory.hh>
|
||||
#include <common.h>
|
||||
|
||||
Memory::Memory(size_t siz, bool w, bool r, bool x)
|
||||
: WRDevice(siz), wen(w), ren(r), xen(x) {
|
||||
data = new char[siz];
|
||||
memset((void *)data, 0, siz);
|
||||
}
|
||||
|
||||
Memory::~Memory() {
|
||||
if (data) {
|
||||
delete [] data;
|
||||
}
|
||||
}
|
||||
|
||||
void Memory::load(const char *path) {
|
||||
std::fstream ifs(path, std::ios::in | std::ios::binary);
|
||||
panicifnot(ifs);
|
||||
ifs.read(data, this->size());
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
void Memory::load(Memory *mem, size_t addr, size_t len) {
|
||||
panicifnot(addr + len < this->size());
|
||||
memcpy(&data[addr], mem->data, len);
|
||||
}
|
||||
|
||||
void Memory::write(char *buf, size_t addr, size_t len) {
|
||||
if (!wen)
|
||||
panic("permission denied");
|
||||
size_t actlen = addr + len >= this->size() ? this->size() - addr : len;
|
||||
memcpy(&data[addr], buf, actlen);
|
||||
}
|
||||
|
||||
void Memory::read(char *buf, size_t addr, size_t len) {
|
||||
if (!ren)
|
||||
panic("permission denied");
|
||||
size_t actlen = addr + len >= this->size() ? this->size() - addr : len;
|
||||
memcpy(buf, &data[addr], actlen);
|
||||
}
|
||||
10
labus/serial.cc
Normal file
10
labus/serial.cc
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <serial.hh>
|
||||
#include <common.h>
|
||||
|
||||
Serial::Serial(size_t siz) : WRDevice(siz) {}
|
||||
|
||||
void Serial::write(char *buf, size_t addr, size_t len) {
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
putc(buf[i], stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -1,3 +1,66 @@
|
||||
int fetch() {
|
||||
return 0;
|
||||
#include <sysbus.hh>
|
||||
#include <common.h>
|
||||
|
||||
std::pair<const uint64_t, Device *> &SystemBus::finddev(uint64_t addr) {
|
||||
Device *dev = nullptr;
|
||||
auto &&iter = iomap.upper_bound(addr);
|
||||
if (iter == iomap.begin())
|
||||
panic("device not found");
|
||||
iter--;
|
||||
if (iter->first <= addr && iter->first + iter->second->size() > addr)
|
||||
dev = iter->second;
|
||||
panicifnot(dev);
|
||||
return *iter;
|
||||
}
|
||||
|
||||
void SystemBus::regdev(Device *dev, uint64_t addr) { iomap.emplace(addr, dev); }
|
||||
|
||||
void SystemBus::write(char *buf, size_t addr, size_t len) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->write(buf, addr - dev.first, len);
|
||||
}
|
||||
|
||||
void SystemBus::read(char *buf, size_t addr, size_t len) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->read(buf, addr - dev.first, len);
|
||||
}
|
||||
|
||||
void SystemBus::write64(uint64_t &dword, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->write64(dword, addr - dev.first);
|
||||
}
|
||||
|
||||
void SystemBus::read64(uint64_t &dword, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->read64(dword, addr - dev.first);
|
||||
}
|
||||
|
||||
void SystemBus::write32(uint32_t &word, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->write32(word, addr - dev.first);
|
||||
}
|
||||
|
||||
void SystemBus::read32(uint32_t &word, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->read32(word, addr - dev.first);
|
||||
}
|
||||
|
||||
void SystemBus::write16(uint16_t &hword, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->write16(hword, addr - dev.first);
|
||||
}
|
||||
|
||||
void SystemBus::read16(uint16_t &hword, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->read16(hword, addr - dev.first);
|
||||
}
|
||||
|
||||
void SystemBus::write8(uint8_t &byte, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->write8(byte, addr - dev.first);
|
||||
}
|
||||
|
||||
void SystemBus::read8(uint8_t &byte, size_t addr) {
|
||||
auto &&dev = finddev(addr);
|
||||
dev.second->read8(byte, addr - dev.first);
|
||||
}
|
||||
Reference in New Issue
Block a user