simx refactoring, fixed simple.hex, compatibility with rtlsim and vlsim complete, added to regression suite
This commit is contained in:
256
simX/mem.cpp
256
simX/mem.cpp
@@ -28,31 +28,52 @@ RamMemDevice::RamMemDevice(const char *filename, Size wordSize)
|
||||
contents_.push_back(input.get());
|
||||
} while (input);
|
||||
|
||||
while (contents_.size() % wordSize)
|
||||
while (contents_.size() & (wordSize-1))
|
||||
contents_.push_back(0x00);
|
||||
}
|
||||
|
||||
RamMemDevice::RamMemDevice(Size size, Size wordSize)
|
||||
: wordSize_(wordSize)
|
||||
, contents_(size)
|
||||
: contents_(size)
|
||||
, wordSize_(wordSize)
|
||||
{}
|
||||
|
||||
void RomMemDevice::write(Addr, Word) {
|
||||
std::cout << "Attempt to write to ROM.\n";
|
||||
void RamMemDevice::read(Addr addr, void *data, Size size) {
|
||||
auto addr_end = addr + size;
|
||||
if ((addr & (wordSize_-1))
|
||||
|| (addr_end & (wordSize_-1))
|
||||
|| (addr_end <= contents_.size())) {
|
||||
std::cout << "lookup of 0x" << std::hex << (addr_end-1) << " failed.\n";
|
||||
throw BadAddress();
|
||||
}
|
||||
|
||||
const Byte *s = contents_.data() + addr;
|
||||
for (Byte *d = (Byte*)data, *de = d + size; d != de;) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
|
||||
void RamMemDevice::write(Addr addr, const void *data, Size size) {
|
||||
auto addr_end = addr + size;
|
||||
if ((addr & (wordSize_-1))
|
||||
|| (addr_end & (wordSize_-1))
|
||||
|| (addr_end <= contents_.size())) {
|
||||
std::cout << "lookup of 0x" << std::hex << (addr_end-1) << " failed.\n";
|
||||
throw BadAddress();
|
||||
}
|
||||
|
||||
const Byte *s = (const Byte*)data;
|
||||
for (Byte *d = contents_.data() + addr, *de = d + size; d != de;) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RomMemDevice::write(Addr /*addr*/, const void* /*data*/, Size /*size*/) {
|
||||
std::cout << "attempt to write to ROM.\n";
|
||||
std::abort();
|
||||
}
|
||||
|
||||
Word RamMemDevice::read(Addr addr) {
|
||||
D(2, "RAM read, addr=0x" << std::hex << addr);
|
||||
Word w = readWord(contents_, addr, wordSize_ - addr % wordSize_);
|
||||
return w;
|
||||
}
|
||||
|
||||
void RamMemDevice::write(Addr addr, Word w) {
|
||||
D(2, "RAM write, addr=0x" << std::hex << addr);
|
||||
writeWord(contents_, addr, wordSize_ - addr % wordSize_, w);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool MemoryUnit::ADecoder::lookup(Addr a, Size wordSize, mem_accessor_t* ma) {
|
||||
@@ -74,32 +95,22 @@ void MemoryUnit::ADecoder::map(Addr a, Addr e, MemDevice &m) {
|
||||
entries_.emplace_back(entry);
|
||||
}
|
||||
|
||||
Word MemoryUnit::ADecoder::read(Addr a, bool /*sup*/, Size wordSize) {
|
||||
void MemoryUnit::ADecoder::read(Addr addr, void *data, Size size) {
|
||||
mem_accessor_t ma;
|
||||
if (!this->lookup(a, wordSize, &ma)) {
|
||||
std::cout << "lookup of 0x" << std::hex << a << " failed.\n";
|
||||
if (!this->lookup(addr, size, &ma)) {
|
||||
std::cout << "lookup of 0x" << std::hex << addr << " failed.\n";
|
||||
throw BadAddress();
|
||||
}
|
||||
return ma.md->read(ma.addr);
|
||||
ma.md->read(ma.addr, data, size);
|
||||
}
|
||||
|
||||
void MemoryUnit::ADecoder::write(Addr a, Word w, bool /*sup*/, Size wordSize) {
|
||||
void MemoryUnit::ADecoder::write(Addr addr, const void *data, Size size) {
|
||||
mem_accessor_t ma;
|
||||
if (!this->lookup(a, wordSize, &ma)) {
|
||||
std::cout << "lookup of 0x" << std::hex << a << " failed.\n";
|
||||
if (!this->lookup(addr, size, &ma)) {
|
||||
std::cout << "lookup of 0x" << std::hex << addr << " failed.\n";
|
||||
throw BadAddress();
|
||||
}
|
||||
RAM *ram = (RAM *)ma.md;
|
||||
switch (wordSize) {
|
||||
case 1:
|
||||
ram->writeByte(ma.addr, &w);
|
||||
break;
|
||||
case 2:
|
||||
ram->writeHalf(ma.addr, &w);
|
||||
break;
|
||||
default:
|
||||
ram->writeWord(ma.addr, &w);
|
||||
}
|
||||
ma.md->write(ma.addr, data, size);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -132,44 +143,28 @@ MemoryUnit::TLBEntry MemoryUnit::tlbLookup(Addr vAddr, Word flagMask) {
|
||||
}
|
||||
}
|
||||
|
||||
Word MemoryUnit::read(Addr vAddr, bool sup) {
|
||||
void MemoryUnit::read(Addr addr, void *data, Size size, bool sup) {
|
||||
Addr pAddr;
|
||||
if (disableVm_) {
|
||||
pAddr = vAddr;
|
||||
pAddr = addr;
|
||||
} else {
|
||||
Word flagMask = sup ? 8 : 1;
|
||||
TLBEntry t = this->tlbLookup(vAddr, flagMask);
|
||||
pAddr = t.pfn * pageSize_ + vAddr % pageSize_;
|
||||
TLBEntry t = this->tlbLookup(addr, flagMask);
|
||||
pAddr = t.pfn * pageSize_ + addr % pageSize_;
|
||||
}
|
||||
return decoder_.read(pAddr, sup, addrBytes_);
|
||||
return decoder_.read(pAddr, data, size);
|
||||
}
|
||||
|
||||
Word MemoryUnit::fetch(Addr vAddr, bool sup) {
|
||||
void MemoryUnit::write(Addr addr, const void *data, Size size, bool sup) {
|
||||
Addr pAddr;
|
||||
|
||||
if (disableVm_) {
|
||||
pAddr = vAddr;
|
||||
} else {
|
||||
Word flagMask = sup ? 32 : 4;
|
||||
TLBEntry t = this->tlbLookup(vAddr, flagMask);
|
||||
pAddr = t.pfn * pageSize_ + vAddr % pageSize_;
|
||||
}
|
||||
|
||||
Word instruction = decoder_.read(pAddr, sup, addrBytes_);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
void MemoryUnit::write(Addr vAddr, Word w, bool sup, Size bytes) {
|
||||
Addr pAddr;
|
||||
|
||||
if (disableVm_) {
|
||||
pAddr = vAddr;
|
||||
pAddr = addr;
|
||||
} else {
|
||||
Word flagMask = sup ? 16 : 2;
|
||||
TLBEntry t = tlbLookup(vAddr, flagMask);
|
||||
pAddr = t.pfn * pageSize_ + vAddr % pageSize_;
|
||||
TLBEntry t = tlbLookup(addr, flagMask);
|
||||
pAddr = t.pfn * pageSize_ + addr % pageSize_;
|
||||
}
|
||||
decoder_.write(pAddr, w, sup, bytes);
|
||||
decoder_.write(pAddr, data, size);
|
||||
}
|
||||
|
||||
void MemoryUnit::tlbAdd(Addr virt, Addr phys, Word flags) {
|
||||
@@ -182,70 +177,6 @@ void MemoryUnit::tlbRm(Addr va) {
|
||||
tlb_.erase(tlb_.find(va / pageSize_));
|
||||
}
|
||||
|
||||
void *vortex::consoleInputThread(void * /*arg_vp*/) {
|
||||
//--
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DiskControllerMemDevice::DiskControllerMemDevice(Size wordSize, Size blockSize, Core &c)
|
||||
: wordSize_(wordSize)
|
||||
, blockSize_(blockSize)
|
||||
, core_(c)
|
||||
{}
|
||||
|
||||
Word DiskControllerMemDevice::read(Addr a) {
|
||||
switch (a / 8) {
|
||||
case 0:
|
||||
return curDisk_;
|
||||
case 1:
|
||||
return curBlock_;
|
||||
case 2:
|
||||
return disks_[curDisk_].blocks * blockSize_;
|
||||
case 3:
|
||||
return physAddr_;
|
||||
case 4:
|
||||
return command_;
|
||||
case 5:
|
||||
return status_;
|
||||
default:
|
||||
std::cout << "Attempt to read invalid disk controller register.\n";
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
void DiskControllerMemDevice::write(Addr a, Word w) {
|
||||
switch (a / 8) {
|
||||
case 0:
|
||||
if (w <= disks_.size()) {
|
||||
curDisk_ = w;
|
||||
status_ = OK;
|
||||
} else {
|
||||
status_ = INVALID_DISK;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (w < disks_[curDisk_].blocks) {
|
||||
curBlock_ = w;
|
||||
} else {
|
||||
status_ = INVALID_BLOCK;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
nBlocks_ = w >= disks_[curDisk_].blocks ? disks_[curDisk_].blocks - 1 : w;
|
||||
status_ = OK;
|
||||
break;
|
||||
case 3:
|
||||
physAddr_ = w;
|
||||
status_ = OK;
|
||||
break;
|
||||
case 4:
|
||||
std::cout << "TODO: Implement disk read and write!\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RAM::RAM(uint32_t num_pages, uint32_t page_size)
|
||||
@@ -290,81 +221,20 @@ uint8_t *RAM::get(uint32_t address) {
|
||||
return page + byte_offset;
|
||||
}
|
||||
|
||||
void RAM::read(uint32_t address, uint32_t length, uint8_t *data) {
|
||||
for (unsigned i = 0; i < length; i++) {
|
||||
data[i] = *this->get(address + i);
|
||||
void RAM::read(Addr addr, void *data, Size size) {
|
||||
Byte* d = (Byte*)data;
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
d[i] = *this->get(addr + i);
|
||||
}
|
||||
}
|
||||
|
||||
void RAM::write(uint32_t address, uint32_t length, uint8_t *data) {
|
||||
for (unsigned i = 0; i < length; i++) {
|
||||
*this->get(address + i) = data[i];
|
||||
void RAM::write(Addr addr, const void *data, Size size) {
|
||||
const Byte* s = (const Byte*)data;
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
*this->get(addr + i) = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
Byte *RAM::base() {
|
||||
return (Byte *)this->get(0);
|
||||
}
|
||||
|
||||
void RAM::getBlock(uint32_t address, uint8_t *data) {
|
||||
uint32_t block_number = address & 0xffffff00; // To zero out block offset
|
||||
uint32_t bytes_num = 256;
|
||||
this->read(block_number, bytes_num, data);
|
||||
}
|
||||
|
||||
void RAM::getWord(uint32_t address, uint32_t *data) {
|
||||
data[0] = 0;
|
||||
|
||||
uint8_t first = *get(address + 0);
|
||||
uint8_t second = *get(address + 1);
|
||||
uint8_t third = *get(address + 2);
|
||||
uint8_t fourth = *get(address + 3);
|
||||
|
||||
data[0] = (data[0] << 0) | fourth;
|
||||
data[0] = (data[0] << 8) | third;
|
||||
data[0] = (data[0] << 8) | second;
|
||||
data[0] = (data[0] << 8) | first;
|
||||
}
|
||||
|
||||
void RAM::writeWord(uint32_t address, uint32_t *data) {
|
||||
uint32_t data_to_write = *data;
|
||||
uint32_t byte_mask = 0xFF;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
*this->get(address + i) = data_to_write & byte_mask;
|
||||
data_to_write = data_to_write >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void RAM::writeHalf(uint32_t address, uint32_t *data) {
|
||||
uint32_t data_to_write = *data;
|
||||
uint32_t byte_mask = 0xFF;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
*this->get(address + i) = data_to_write & byte_mask;
|
||||
data_to_write = data_to_write >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void RAM::writeByte(uint32_t address, uint32_t *data) {
|
||||
uint32_t data_to_write = *data;
|
||||
uint32_t byte_mask = 0xFF;
|
||||
|
||||
*this->get(address) = data_to_write & byte_mask;
|
||||
data_to_write = data_to_write >> 8;
|
||||
}
|
||||
|
||||
void RAM::write(Addr addr, Word w) {
|
||||
uint32_t word = (uint32_t)w;
|
||||
writeWord(addr, &word);
|
||||
}
|
||||
|
||||
Word RAM::read(Addr addr) {
|
||||
uint32_t w;
|
||||
getWord(addr, &w);
|
||||
return (Word)w;
|
||||
}
|
||||
|
||||
static uint32_t hti_old(char c) {
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
|
||||
Reference in New Issue
Block a user