mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-04-24 05:47:35 -04:00
simx refactoring, fixed simple.hex, compatibility with rtlsim and vlsim complete, added to regression suite
This commit is contained in:
parent
71e9745e68
commit
907e6868cd
19 changed files with 88376 additions and 95959 deletions
|
@ -8,6 +8,7 @@ set -e
|
|||
./ci/test_riscv_isa.sh
|
||||
./ci/test_opencl.sh
|
||||
./ci/test_driver.sh
|
||||
./ci/test_simx.sh
|
||||
|
||||
# Build tests disabling extensions
|
||||
CONFIGS=-DEXT_M_DISABLE make -C hw/simulate
|
||||
|
|
6
ci/test_riscv.sh
Normal file
6
ci/test_riscv.sh
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
# exit when any command fails
|
||||
set -e
|
||||
|
||||
make -C simx run
|
|
@ -23,8 +23,8 @@ DBG_FLAGS += -DDBG_CACHE_REQ_INFO
|
|||
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=2 -DNUM_CORES=4 -DL2_ENABLE=1
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=4 -DL2_ENABLE=1
|
||||
CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=2 -DL2_ENABLE=0
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=1
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=2 -DL2_ENABLE=0
|
||||
CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=1
|
||||
|
||||
CFLAGS += -fPIC
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ DBG_FLAGS += -DDBG_CACHE_REQ_INFO
|
|||
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=2 -DNUM_CORES=4 -DL2_ENABLE=1
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=4 -DL2_ENABLE=1
|
||||
CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=2 -DL2_ENABLE=0
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=1
|
||||
#CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=2 -DL2_ENABLE=0
|
||||
CONFIGS ?= -DNUM_CLUSTERS=1 -DNUM_CORES=1
|
||||
|
||||
CFLAGS += $(CONFIGS)
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int upload(void* src, size_t dest_addr, size_t size, size_t src_offset) {
|
||||
int upload(const void* src, size_t dest_addr, size_t size, size_t src_offset) {
|
||||
size_t asize = align_size(size, CACHE_BLOCK_SIZE);
|
||||
if (dest_addr + asize > ram_.size())
|
||||
return -1;
|
||||
|
@ -93,11 +93,11 @@ public:
|
|||
}
|
||||
printf("\n");*/
|
||||
|
||||
ram_.write(dest_addr, asize, (uint8_t*)src + src_offset);
|
||||
ram_.write(dest_addr, asize, (const uint8_t*)src + src_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int download(const void* dest, size_t src_addr, size_t size, size_t dest_offset) {
|
||||
int download(void* dest, size_t src_addr, size_t size, size_t dest_offset) {
|
||||
size_t asize = align_size(size, CACHE_BLOCK_SIZE);
|
||||
if (src_addr + asize > ram_.size())
|
||||
return -1;
|
||||
|
|
|
@ -96,12 +96,12 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int upload(void* src, size_t dest_addr, size_t size, size_t src_offset) {
|
||||
int upload(const void* src, size_t dest_addr, size_t size, size_t src_offset) {
|
||||
auto asize = align_size(size, CACHE_BLOCK_SIZE);
|
||||
if (dest_addr + asize > ram_.size())
|
||||
return -1;
|
||||
|
||||
ram_.write(dest_addr, asize, (uint8_t*)src + src_offset);
|
||||
ram_.write(dest_addr, (const uint8_t*)src + src_offset, asize);
|
||||
|
||||
/*printf("VXDRV: upload %d bytes to 0x%x\n", size, dest_addr);
|
||||
for (int i = 0; i < size; i += 4) {
|
||||
|
@ -111,12 +111,12 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int download(const void* dest, size_t src_addr, size_t size, size_t dest_offset) {
|
||||
int download(void* dest, size_t src_addr, size_t size, size_t dest_offset) {
|
||||
size_t asize = align_size(size, CACHE_BLOCK_SIZE);
|
||||
if (src_addr + asize > ram_.size())
|
||||
return -1;
|
||||
|
||||
ram_.read(src_addr, asize, (uint8_t*)dest + dest_offset);
|
||||
ram_.read(src_addr, (uint8_t*)dest + dest_offset, asize);
|
||||
|
||||
/*printf("VXDRV: download %d bytes from 0x%x\n", size, src_addr);
|
||||
for (int i = 0; i < size; i += 4) {
|
||||
|
|
|
@ -20689,7 +20689,7 @@ Disassembly of section .rodata:
|
|||
80013654: 6c69 lui s8,0x1a
|
||||
80013656: 2065 jal 800136fe <zeroes.4448+0xe2>
|
||||
80013658: 2522 fld fa0,8(sp)
|
||||
8001365a: 202c2273 csrrs tp,hedeleg,s8
|
||||
8001365a: 202c2273 csrrs tp,0x202,s8
|
||||
8001365e: 696c flw fa1,84(a0)
|
||||
80013660: 656e flw fa0,216(sp)
|
||||
80013662: 2520 fld fs0,72(a0)
|
||||
|
|
|
@ -22939,7 +22939,7 @@ Disassembly of section .rodata:
|
|||
80015918: 6c69 lui s8,0x1a
|
||||
8001591a: 2065 jal 800159c2 <zeroes.4462+0xe2>
|
||||
8001591c: 2522 fld fa0,8(sp)
|
||||
8001591e: 202c2273 csrrs tp,hedeleg,s8
|
||||
8001591e: 202c2273 csrrs tp,0x202,s8
|
||||
80015922: 696c flw fa1,84(a0)
|
||||
80015924: 656e flw fa0,216(sp)
|
||||
80015926: 2520 fld fs0,72(a0)
|
||||
|
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -27,8 +27,10 @@ all: $(PROJECT)
|
|||
$(PROJECT): $(SRCS)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
run: $(PROJECT)
|
||||
./$(PROJECT)
|
||||
run:
|
||||
./test_rv32i.sh
|
||||
./test_rv32f.sh
|
||||
./test_runtime.sh
|
||||
|
||||
.depend: $(SRCS)
|
||||
$(CXX) $(CXXFLAGS) -MM $^ > .depend;
|
||||
|
|
|
@ -311,31 +311,36 @@ void Core::barrier(int bar_id, int count, int warp_id) {
|
|||
barrier.reset();
|
||||
}
|
||||
|
||||
Word Core::icache_fetch(Addr addr, bool sup) {
|
||||
return mem_.fetch(addr, sup);
|
||||
Word Core::icache_fetch(Addr addr) {
|
||||
Word data;
|
||||
mem_.read(addr, &data, sizeof(Word), 0);
|
||||
return data;
|
||||
}
|
||||
|
||||
Word Core::dcache_read(Addr addr, bool sup) {
|
||||
Word Core::dcache_read(Addr addr, Size size) {
|
||||
++loads_;
|
||||
Word data = 0;
|
||||
#ifdef SM_ENABLE
|
||||
if ((addr >= (SHARED_MEM_BASE_ADDR - SMEM_SIZE))
|
||||
&& ((addr + 4) <= SHARED_MEM_BASE_ADDR)) {
|
||||
return shared_mem_.read(addr & (SMEM_SIZE-1));
|
||||
&& ((addr + 3) < SHARED_MEM_BASE_ADDR)) {
|
||||
shared_mem_.read(addr & (SMEM_SIZE-1), &data, size);
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
return mem_.read(addr, sup);
|
||||
mem_.read(addr, &data, size, 0);
|
||||
return data;
|
||||
}
|
||||
|
||||
void Core::dcache_write(Addr addr, Word data, bool sup, Size size) {
|
||||
void Core::dcache_write(Addr addr, Word data, Size size) {
|
||||
++stores_;
|
||||
#ifdef SM_ENABLE
|
||||
if ((addr >= (SHARED_MEM_BASE_ADDR - SMEM_SIZE))
|
||||
&& ((addr + 4) <= SHARED_MEM_BASE_ADDR)) {
|
||||
shared_mem_.write(addr & (SMEM_SIZE-1), data);
|
||||
&& ((addr + 3) < SHARED_MEM_BASE_ADDR)) {
|
||||
shared_mem_.write(addr & (SMEM_SIZE-1), &data, size);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
mem_.write(addr, data, sup, size);
|
||||
mem_.write(addr, &data, size, 0);
|
||||
}
|
||||
|
||||
bool Core::running() const {
|
||||
|
|
|
@ -64,11 +64,11 @@ public:
|
|||
|
||||
void barrier(int bar_id, int count, int warp_id);
|
||||
|
||||
Word icache_fetch(Addr, bool sup);
|
||||
Word icache_fetch(Addr);
|
||||
|
||||
Word dcache_read(Addr, bool sup);
|
||||
Word dcache_read(Addr, Size);
|
||||
|
||||
void dcache_write(Addr, Word, bool sup, Size);
|
||||
void dcache_write(Addr, Word, Size);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -351,8 +351,8 @@ void Warp::execute(const Instr &instr, Pipeline *pipeline) {
|
|||
case L_INST: {
|
||||
Word memAddr = ((rsdata[0] + immsrc) & 0xFFFFFFFC); // word aligned
|
||||
Word shift_by = ((rsdata[0] + immsrc) & 0x00000003) * 8;
|
||||
Word data_read = core_->dcache_read(memAddr, 0);
|
||||
D(3, "LOAD MEM ADDRESS: " << std::hex << memAddr << ", DATA=0x" << data_read);
|
||||
Word data_read = core_->dcache_read(memAddr, 4);
|
||||
D(3, "LOAD MEM: ADDRESS=0x" << std::hex << memAddr << ", DATA=0x" << data_read);
|
||||
switch (func3) {
|
||||
case 0:
|
||||
// LBI
|
||||
|
@ -380,23 +380,23 @@ void Warp::execute(const Instr &instr, Pipeline *pipeline) {
|
|||
} break;
|
||||
case S_INST: {
|
||||
Word memAddr = rsdata[0] + immsrc;
|
||||
D(3, "STORE MEM: ADDRESS=0x" << std::hex << memAddr);
|
||||
switch (func3) {
|
||||
case 0:
|
||||
// SB
|
||||
core_->dcache_write(memAddr, rsdata[1] & 0x000000FF, 0, 1);
|
||||
core_->dcache_write(memAddr, rsdata[1] & 0x000000FF, 1);
|
||||
break;
|
||||
case 1:
|
||||
// SH
|
||||
core_->dcache_write(memAddr, rsdata[1], 0, 2);
|
||||
core_->dcache_write(memAddr, rsdata[1], 2);
|
||||
break;
|
||||
case 2:
|
||||
// SW
|
||||
core_->dcache_write(memAddr, rsdata[1], 0, 4);
|
||||
core_->dcache_write(memAddr, rsdata[1], 4);
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
D(3, "STORE MEM ADDRESS: " << std::hex << memAddr);
|
||||
} break;
|
||||
case SYS_INST: {
|
||||
Word csr_addr = immsrc & 0x00000FFF;
|
||||
|
@ -452,8 +452,8 @@ void Warp::execute(const Instr &instr, Pipeline *pipeline) {
|
|||
case (FL | VL):
|
||||
if (func3 == 0x2) {
|
||||
Word memAddr = rsdata[0] + immsrc;
|
||||
Word data_read = core_->dcache_read(memAddr, 0);
|
||||
D(3, "LOAD MEM ADDRESS: " << std::hex << memAddr << ", DATA=0x" << data_read);
|
||||
Word data_read = core_->dcache_read(memAddr, 4);
|
||||
D(3, "LOAD MEM: ADDRESS=0x" << std::hex << memAddr << ", DATA=0x" << data_read);
|
||||
rddata = data_read;
|
||||
} else {
|
||||
D(3, "Executing vector load");
|
||||
|
@ -465,14 +465,15 @@ void Warp::execute(const Instr &instr, Pipeline *pipeline) {
|
|||
auto &vd = vRegFile_[rdest];
|
||||
|
||||
switch (instr.getVlsWidth()) {
|
||||
case 6: { //load word and unit strided (not checking for unit stride)
|
||||
case 6: {
|
||||
//load word and unit strided (not checking for unit stride)
|
||||
for (int i = 0; i < vl_; i++) {
|
||||
Word memAddr = ((rsdata[0]) & 0xFFFFFFFC) + (i * vtype_.vsew / 8);
|
||||
Word data_read = core_->dcache_read(memAddr, 0);
|
||||
D(3, "STORE MEM: ADDRESS=0x" << std::hex << memAddr);
|
||||
Word data_read = core_->dcache_read(memAddr, 4);
|
||||
D(4, "Mem addr: " << std::hex << memAddr << " Data read " << data_read);
|
||||
int *result_ptr = (int *)(vd.data() + i);
|
||||
*result_ptr = data_read;
|
||||
D(3, "STORE MEM ADDRESS: " << std::hex << memAddr);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
|
@ -484,22 +485,22 @@ void Warp::execute(const Instr &instr, Pipeline *pipeline) {
|
|||
case (FS | VS):
|
||||
if (func3 == 0x2) {
|
||||
Word memAddr = rsdata[0] + immsrc;
|
||||
core_->dcache_write(memAddr, rsdata[1], 0, 4);
|
||||
D(3, "STORE MEM ADDRESS: " << std::hex << memAddr);
|
||||
core_->dcache_write(memAddr, rsdata[1], 4);
|
||||
D(3, "STORE MEM: ADDRESS=0x" << std::hex << memAddr);
|
||||
} else {
|
||||
for (int i = 0; i < vl_; i++) {
|
||||
Word memAddr = rsdata[0] + (i * vtype_.vsew / 8);
|
||||
D(3, "STORE MEM: ADDRESS=0x" << std::hex << memAddr);
|
||||
switch (instr.getVlsWidth()) {
|
||||
case 6: {
|
||||
//store word and unit strided (not checking for unit stride)
|
||||
uint32_t value = *(uint32_t *)(vRegFile_[instr.getVs3()].data() + i);
|
||||
core_->dcache_write(memAddr, value, 0, 4);
|
||||
core_->dcache_write(memAddr, value, 4);
|
||||
D(4, "store: " << memAddr << " value:" << value);
|
||||
} break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
D(3, "STORE MEM ADDRESS: " << std::hex << memAddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
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;
|
||||
|
|
112
simX/mem.h
112
simX/mem.h
|
@ -7,18 +7,14 @@
|
|||
#include "types.h"
|
||||
|
||||
namespace vortex {
|
||||
void *consoleInputThread(void *);
|
||||
struct BadAddress {};
|
||||
|
||||
class MemDevice {
|
||||
public:
|
||||
virtual ~MemDevice() {}
|
||||
virtual Size size() const = 0;
|
||||
virtual Word read(Addr) = 0;
|
||||
virtual void write(Addr, Word) = 0;
|
||||
virtual Byte *base() {
|
||||
return NULL;
|
||||
}
|
||||
virtual void read(Addr addr, void *data, Size size) = 0;
|
||||
virtual void write(Addr addr, const void *data, Size size) = 0;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -29,20 +25,16 @@ public:
|
|||
RamMemDevice(const char *filename, Size wordSize);
|
||||
~RamMemDevice() {}
|
||||
|
||||
virtual Word read(Addr);
|
||||
virtual void write(Addr, Word);
|
||||
void read(Addr addr, void *data, Size size) override;
|
||||
void write(Addr addr, const void *data, Size size) override;
|
||||
|
||||
virtual Size size() const {
|
||||
return contents_.size();
|
||||
};
|
||||
|
||||
virtual Byte *base() {
|
||||
return &contents_[0];
|
||||
}
|
||||
|
||||
protected:
|
||||
Size wordSize_;
|
||||
std::vector<Byte> contents_;
|
||||
Size wordSize_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -59,65 +51,14 @@ public:
|
|||
|
||||
~RomMemDevice();
|
||||
|
||||
virtual void write(Addr, Word);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Core;
|
||||
|
||||
class DiskControllerMemDevice : public MemDevice {
|
||||
public:
|
||||
DiskControllerMemDevice(Size wordSize, Size blockSize, Core &c);
|
||||
|
||||
virtual Word read(Addr);
|
||||
virtual void write(Addr, Word);
|
||||
|
||||
virtual Size size() const {
|
||||
return uint64_t(wordSize_) * 6;
|
||||
}
|
||||
|
||||
void addDisk(Byte *file, Size n) {
|
||||
disks_.push_back(Disk(file, n));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum Status {
|
||||
OK = 0,
|
||||
INVALID_DISK,
|
||||
INVALID_BLOCK
|
||||
};
|
||||
|
||||
struct Disk {
|
||||
Disk(Byte *f, Size n)
|
||||
: file(f)
|
||||
, blocks(n)
|
||||
{}
|
||||
Byte *file;
|
||||
Size blocks;
|
||||
};
|
||||
|
||||
Word curDisk_;
|
||||
Word curBlock_;
|
||||
Word nBlocks_;
|
||||
Word physAddr_;
|
||||
Word command_;
|
||||
Word status_;
|
||||
Size wordSize_;
|
||||
Size blockSize_;
|
||||
Core &core_;
|
||||
std::vector<Disk> disks_;
|
||||
void write(Addr addr, const void *data, Size size) override;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class MemoryUnit {
|
||||
public:
|
||||
MemoryUnit(Size pageSize, Size addrBytes, bool disableVm = false);
|
||||
|
||||
void attach(MemDevice &m, Addr start, Addr end);
|
||||
|
||||
|
||||
struct PageFault {
|
||||
PageFault(Addr a, bool nf)
|
||||
: faultAddr(a)
|
||||
|
@ -127,24 +68,27 @@ public:
|
|||
bool notFound;
|
||||
};
|
||||
|
||||
Word read(Addr, bool sup);
|
||||
Word fetch(Addr, bool sup);
|
||||
void write(Addr, Word, bool sup, Size);
|
||||
MemoryUnit(Size pageSize, Size addrBytes, bool disableVm = false);
|
||||
|
||||
void attach(MemDevice &m, Addr start, Addr end);
|
||||
|
||||
void read(Addr addr, void *data, Size size, bool sup);
|
||||
void write(Addr addr, const void *data, Size size, bool sup);
|
||||
|
||||
void tlbAdd(Addr virt, Addr phys, Word flags);
|
||||
void tlbRm(Addr va);
|
||||
|
||||
void tlbFlush() {
|
||||
tlb_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
class ADecoder {
|
||||
public:
|
||||
ADecoder() {}
|
||||
|
||||
Word read(Addr a, bool sup, Size wordSize);
|
||||
void write(Addr a, Word w, bool sup, Size wordSize);
|
||||
void read(Addr addr, void *data, Size size);
|
||||
void write(Addr addr, const void *data, Size size);
|
||||
|
||||
void map(Addr start, Addr end, MemDevice &md);
|
||||
|
||||
private:
|
||||
|
@ -196,22 +140,8 @@ public:
|
|||
void clear();
|
||||
|
||||
Size size() const override;
|
||||
|
||||
void write(Addr addr, Word w) override;
|
||||
|
||||
Word read(Addr addr) override;
|
||||
|
||||
Byte *base() override;
|
||||
|
||||
void read(uint32_t address, uint32_t length, uint8_t *data);
|
||||
|
||||
void write(uint32_t address, uint32_t length, uint8_t *data);
|
||||
|
||||
void writeWord(uint32_t address, uint32_t *data);
|
||||
|
||||
void writeHalf(uint32_t address, uint32_t *data);
|
||||
|
||||
void writeByte(uint32_t address, uint32_t *data);
|
||||
void read(Addr addr, void *data, Size size) override;
|
||||
void write(Addr addr, const void *data, Size size) override;
|
||||
|
||||
void loadHexImage(std::string path);
|
||||
|
||||
|
@ -219,10 +149,6 @@ private:
|
|||
|
||||
uint8_t *get(uint32_t address);
|
||||
|
||||
void getBlock(uint32_t address, uint8_t *data);
|
||||
|
||||
void getWord(uint32_t address, uint32_t *data);
|
||||
|
||||
std::vector<uint8_t*> mem_;
|
||||
uint32_t page_bits_;
|
||||
uint32_t size_;
|
||||
|
|
|
@ -11,4 +11,4 @@ make -C ../runtime/tests/simple
|
|||
./simX -a rv32i -i ../runtime/tests/dev/vx_dev_main.hex
|
||||
./simX -a rv32i -i ../runtime/tests/hello/hello.hex
|
||||
./simX -a rv32i -i ../runtime/tests/nlTest/vx_nl_main.hex
|
||||
./simX -a rv32i -i ../runtime/tests/simple/vx_simple_main.hex
|
||||
./simX -a rv32i -i ../runtime/tests/simple/vx_simple.hex
|
||||
|
|
|
@ -32,7 +32,7 @@ void Warp::step(Pipeline *pipeline) {
|
|||
|
||||
/* Fetch and decode. */
|
||||
|
||||
Word fetched = core_->icache_fetch(PC_, 0);
|
||||
Word fetched = core_->icache_fetch(PC_);
|
||||
auto instr = core_->decoder().decode(fetched);
|
||||
|
||||
// Update pipeline
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue