Restructured DBT function to encapsulate the compilation process

This should enable the implementation of multi-threading of the
compilation process
This commit is contained in:
Eyck Jentzsch 2017-12-15 14:13:22 +01:00
parent b4871ac725
commit 873e4257f2
17 changed files with 2317 additions and 2347 deletions

View File

@ -7,6 +7,7 @@
<buildSpec> <buildSpec>
<buildCommand> <buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments> <arguments>
</arguments> </arguments>
</buildCommand> </buildCommand>

View File

@ -4,7 +4,7 @@ Am instruction set simulator based on DBT-RISE implementing the RISC-V ISA
**DBT-RISE-RISCV README** **DBT-RISE-RISCV README**
This is work in progress, so use at your own risk. Goal is to implement an open-source ISS which can easily embedded e.g. into SystemC Virtual Prototypes. It used code generation to allow easy extension and adaptation of the used instruction. This is work in progress, so use at your own risk. Goal is to implement an open-source ISS which can easily embedded e.g. into SystemC Virtual Prototypes. It used code generation to allow easy extension and adaptation of the used instruction.
The RISC-V ISS reaches about 20MIPS at an Intel Core i7-2600K. The RISC-V ISS reaches about 30MIPS running on Intel Core i7-2600K.
The implementation is based on LLVM 4.0. Eclipse CDT 4.7 (Oxygen) is recommended as IDE. The implementation is based on LLVM 4.0. Eclipse CDT 4.7 (Oxygen) is recommended as IDE.

@ -1 +1 @@
Subproject commit cf9679475121f85a6333970f80bb6a40a8b4a0a5 Subproject commit 4bfcd8a10e81d610d46b329841ae3ba7cbc0627a

View File

@ -94,7 +94,9 @@ public:
base_type::hart_state<base_type::reg_t>& get_state() { return this->state; } base_type::hart_state<base_type::reg_t>& get_state() { return this->state; }
void notify_phase(iss::arch_if::exec_phase phase); void notify_phase(exec_phase) override;
iss::sync_type needed_sync() const override { return iss::PRE_SYNC; }
void disass_output(uint64_t pc, const std::string instr) override { void disass_output(uint64_t pc, const std::string instr) override {
if (logging::INFO <= logging::Log<logging::Output2FILE<logging::disass>>::reporting_level() && logging::Output2FILE<logging::disass>::stream()){ if (logging::INFO <= logging::Log<logging::Output2FILE<logging::disass>>::reporting_level() && logging::Output2FILE<logging::disass>::stream()){
@ -108,15 +110,15 @@ public:
}; };
iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) { iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) {
if (addr.type & iss::DEBUG) if (addr.access && iss::access_type::DEBUG)
return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
else { else {
return owner->read_mem(addr.val, length, data,addr.type && iss::FETCH) ? iss::Ok : iss::Err; return owner->read_mem(addr.val, length, data,addr.access && iss::access_type::FETCH) ? iss::Ok : iss::Err;
} }
} }
iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) { iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) {
if (addr.type & iss::DEBUG) if (addr.access && iss::access_type::DEBUG)
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
else{ else{
auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err; auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err;
@ -187,9 +189,9 @@ int cmd_sysc(int argc, char* argv[], iss::debugger::out_func of, iss::debugger::
} }
void core_wrapper::notify_phase(exec_phase phase) { void core_wrapper::notify_phase(exec_phase p) {
core_type::notify_phase(phase); if(p == ISTART)
if (phase == ISTART) owner->sync(); owner->sync();
} }
core_complex::core_complex(sc_core::sc_module_name name) core_complex::core_complex(sc_core::sc_module_name name)

View File

@ -222,6 +222,7 @@ struct vm_info {
int idxbits; int idxbits;
int ptesize; int ptesize;
uint64_t ptbase; uint64_t ptbase;
bool is_active() { return levels;}
}; };
class trap_load_access_fault : public trap_access { class trap_load_access_fault : public trap_access {
@ -450,7 +451,7 @@ public:
void load_file(std::string name, int type = -1) override; void load_file(std::string name, int type = -1) override;
virtual phys_addr_t v2p(const iss::addr_t &addr); virtual phys_addr_t virt2phys(const iss::addr_t &addr) override;
iss::status read(const iss::addr_t &addr, unsigned length, uint8_t *const data) override; iss::status read(const iss::addr_t &addr, unsigned length, uint8_t *const data) override;
iss::status write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) override; iss::status write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) override;
@ -460,8 +461,6 @@ public:
virtual uint64_t leave_trap(uint64_t flags) override; virtual uint64_t leave_trap(uint64_t flags) override;
void wait_until(uint64_t flags) override; void wait_until(uint64_t flags) override;
void notify_phase(iss::arch_if::exec_phase phase);
void disass_output(uint64_t pc, const std::string instr) override { void disass_output(uint64_t pc, const std::string instr) override {
std::stringstream s; std::stringstream s;
s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0')
@ -486,6 +485,8 @@ protected:
mem_type mem; mem_type mem;
csr_type csr; csr_type csr;
hart_state<reg_t> state; hart_state<reg_t> state;
vm_info vm[2];
void update_vm_info();
unsigned to_host_wr_cnt = 0; unsigned to_host_wr_cnt = 0;
std::stringstream uart_buf; std::stringstream uart_buf;
std::unordered_map<reg_t, uint64_t> ptw; std::unordered_map<reg_t, uint64_t> ptw;
@ -571,7 +572,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::load_file(std::string nam
const auto seg_data = pseg->get_data(); const auto seg_data = pseg->get_data();
if (fsize > 0) { if (fsize > 0) {
auto res = this->write( auto res = this->write(
typed_addr_t<PHYSICAL>(iss::DEBUG_WRITE, traits<BASE>::MEM, pseg->get_physical_address()), phys_addr_t(iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, pseg->get_physical_address()),
fsize, reinterpret_cast<const uint8_t *const>(seg_data)); fsize, reinterpret_cast<const uint8_t *const>(seg_data));
if (res != iss::Ok) if (res != iss::Ok)
LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex
@ -586,13 +587,15 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::load_file(std::string nam
} }
return; return;
} }
throw std::runtime_error("memory load file is not a valid elf file");
} }
throw std::runtime_error("memory load file not found");
} }
template <typename BASE> template <typename BASE>
iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned length, uint8_t *const data) { iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned length, uint8_t *const data) {
#ifndef NDEBUG #ifndef NDEBUG
if (addr.type & iss::DEBUG) { if (addr.access && iss::access_type::DEBUG) {
LOG(DEBUG) << "debug read of " << length << " bytes @addr " << addr; LOG(DEBUG) << "debug read of " << length << " bytes @addr " << addr;
} else { } else {
LOG(DEBUG) << "read of " << length << " bytes @addr " << addr; LOG(DEBUG) << "read of " << length << " bytes @addr " << addr;
@ -601,9 +604,9 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
try { try {
switch (addr.space) { switch (addr.space) {
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) { if ((addr.access == iss::access_type::FETCH || addr.access == iss::access_type::DEBUG_FETCH) && (addr.val & 0x1) == 1) {
fault_data = addr.val; fault_data = addr.val;
if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val); if (addr.access && iss::access_type::DEBUG) throw trap_access(0, addr.val);
this->reg.trap_state = (1 << 31); // issue trap 0 this->reg.trap_state = (1 << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -615,12 +618,11 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
auto len1 = split_addr - addr.val; auto len1 = split_addr - addr.val;
auto res = read(addr, len1, data); auto res = read(addr, len1, data);
if (res == iss::Ok) if (res == iss::Ok)
res = read(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1); res = read(iss::addr_t{addr.access, addr.type, addr.space, split_addr}, length - len1, data + len1);
return res; return res;
} }
} }
phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); auto res = read_mem( BASE::v2p(addr), length, data);
auto res = read_mem(paddr, length, data);
if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
return res; return res;
} catch (trap_access &ta) { } catch (trap_access &ta) {
@ -668,7 +670,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
template <typename BASE> template <typename BASE>
iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) { iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) {
#ifndef NDEBUG #ifndef NDEBUG
const char *prefix = addr.type & iss::DEBUG ? "debug " : ""; const char *prefix = (addr.access && iss::access_type::DEBUG)? "debug " : "";
switch (length) { switch (length) {
case 8: case 8:
LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
@ -693,9 +695,9 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned len
try { try {
switch (addr.space) { switch (addr.space) {
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) { if ((addr.access && iss::access_type::FETCH) && (addr.val & 0x1) == 1) {
fault_data = addr.val; fault_data = addr.val;
if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val); if (addr.access && iss::access_type::DEBUG) throw trap_access(0, addr.val);
this->reg.trap_state = (1 << 31); // issue trap 0 this->reg.trap_state = (1 << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -707,12 +709,11 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned len
auto len1 = split_addr - addr.val; auto len1 = split_addr - addr.val;
auto res = write(addr, len1, data); auto res = write(addr, len1, data);
if (res == iss::Ok) if (res == iss::Ok)
res = write(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1); res = write(iss::addr_t{addr.access, addr.type, addr.space, split_addr}, length - len1, data + len1);
return res; return res;
} }
} }
phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); auto res = write_mem(BASE::v2p(addr), length, data);
auto res = write_mem(paddr, length, data);
if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault) if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault)
return res; return res;
} catch (trap_access &ta) { } catch (trap_access &ta) {
@ -720,7 +721,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned len
return iss::Err; return iss::Err;
} }
phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); phys_addr_t paddr = BASE::v2p(addr);
if ((paddr.val + length) > mem.size()) return iss::Err; if ((paddr.val + length) > mem.size()) return iss::Err;
switch (paddr.val) { switch (paddr.val) {
case 0x10013000: // UART0 base, TXFIFO reg case 0x10013000: // UART0 base, TXFIFO reg
@ -842,6 +843,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_status(unsig
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
state.write_mstatus(val, req_priv_lvl); state.write_mstatus(val, req_priv_lvl);
check_interrupt(); check_interrupt();
update_vm_info();
return iss::Ok; return iss::Ok;
} }
@ -901,6 +903,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigne
return iss::Err; return iss::Err;
} }
state.satp = val; state.satp = val;
update_vm_info();
return iss::Ok; return iss::Ok;
} }
@ -909,8 +912,9 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
if ((paddr.val + length) > mem.size()) return iss::Err; if ((paddr.val + length) > mem.size()) return iss::Err;
switch (paddr.val) { switch (paddr.val) {
case 0x0200BFF8: { // CLINT base, mtime reg case 0x0200BFF8: { // CLINT base, mtime reg
if(sizeof(reg_t)<length) return iss::Err; if(sizeof(reg_t)<length) return iss::Err;
reg_t time_val=this->csr[time]; reg_t time_val;
this->read_csr(time, time_val);
std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data);
} break; } break;
case 0x10008000: { case 0x10008000: {
@ -960,7 +964,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
mem_type::page_type &p = mem(paddr.val / mem.page_size); mem_type::page_type &p = mem(paddr.val / mem.page_size);
std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
// tohost handling in case of riscv-test // tohost handling in case of riscv-test
if ((paddr.type & iss::DEBUG) == 0) { if (paddr.access && iss::access_type::FUNC) {
auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) || auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) ||
(traits<BASE>::XLEN == 64 && paddr.val == tohost); (traits<BASE>::XLEN == 64 && paddr.val == tohost);
auto tohost_lower = auto tohost_lower =
@ -1003,15 +1007,23 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt
return iss::Ok; return iss::Ok;
} }
template<typename BASE>
inline void riscv_hart_msu_vp<BASE>::notify_phase(iss::arch_if::exec_phase phase) {
BASE::notify_phase(phase);
}
template<typename BASE> template<typename BASE>
inline void riscv_hart_msu_vp<BASE>::reset(uint64_t address) { inline void riscv_hart_msu_vp<BASE>::reset(uint64_t address) {
BASE::reset(address); BASE::reset(address);
state.mstatus = hart_state<reg_t>::mstatus_reset_val; state.mstatus = hart_state<reg_t>::mstatus_reset_val;
update_vm_info();
}
template<typename BASE>
inline void riscv_hart_msu_vp<BASE>::update_vm_info() {
vm[1] = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
BASE::addr_mode[3]=BASE::addr_mode[2]=vm[1].is_active()?iss::address_type::VIRTUAL:iss::address_type::PHYSICAL;
if(state.mstatus.MPRV)
vm[0] = hart_state<reg_t>::decode_vm_info(state.mstatus.MPP, state.satp);
else
vm[0] = vm[1];
BASE::addr_mode[1]=BASE::addr_mode[0]=vm[0].is_active()?iss::address_type::VIRTUAL:iss::address_type::PHYSICAL;
ptw.clear();
} }
template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() { template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
@ -1042,37 +1054,12 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
} }
template <typename BASE> template <typename BASE>
typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const iss::addr_t &addr) { typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t &addr) {
const uint64_t tmp = reg_t(1) << (traits<BASE>::XLEN - 1); const auto type = addr.access & iss::access_type::FUNC;
const uint64_t msk = tmp | (tmp - 1);
if (addr.space != traits<BASE>::MEM) { // non-memory access
phys_addr_t ret(addr);
ret.val &= msk;
return ret;
}
const auto type = (access_type)(addr.getAccessType() & ~iss::DEBUG);
uint32_t mode = type != iss::FETCH && state.mstatus.MPRV ? // MPRV
mode = state.mstatus.MPP:
this->reg.machine_state;
const vm_info vm = hart_state<reg_t>::decode_vm_info(mode, state.satp);
if (vm.levels == 0) {
phys_addr_t ret(addr);
ret.val &= msk;
return ret;
}
const bool s_mode = mode == PRIV_S;
const bool sum = state.mstatus.SUM;
const bool mxr = state.mstatus.MXR;
auto it = ptw.find(addr.val >> PGSHIFT); auto it = ptw.find(addr.val >> PGSHIFT);
if (it != ptw.end()) { if (it != ptw.end()) {
const reg_t pte = it->second; const reg_t pte = it->second;
const reg_t ad = PTE_A | ((type == iss::WRITE) * PTE_D); const reg_t ad = PTE_A | (type == iss::access_type::WRITE) * PTE_D;
#ifdef RISCV_ENABLE_DIRTY #ifdef RISCV_ENABLE_DIRTY
// set accessed and possibly dirty bits. // set accessed and possibly dirty bits.
*(uint32_t *)ppte |= ad; *(uint32_t *)ppte |= ad;
@ -1080,11 +1067,21 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
#else #else
// take exception if access or possibly dirty bit is not set. // take exception if access or possibly dirty bit is not set.
if ((pte & ad) == ad) if ((pte & ad) == ad)
return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)}; return {addr.access, addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)};
else else
ptw.erase(it); ptw.erase(it); // throw an exception
#endif #endif
} else { } else {
uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
state.mstatus.MPP:
this->reg.machine_state;
const vm_info& vm = this->vm[static_cast<uint16_t>(type)/2];
const bool s_mode = mode == PRIV_S;
const bool sum = state.mstatus.SUM;
const bool mxr = state.mstatus.MXR;
// verify bits xlen-1:va_bits-1 are all equal // verify bits xlen-1:va_bits-1 are all equal
const int va_bits = PGSHIFT + vm.levels * vm.idxbits; const int va_bits = PGSHIFT + vm.levels * vm.idxbits;
const reg_t mask = (reg_t(1) << (traits<BASE>::XLEN > -(va_bits - 1))) - 1; const reg_t mask = (reg_t(1) << (traits<BASE>::XLEN > -(va_bits - 1))) - 1;
@ -1099,25 +1096,24 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
// check that physical address of PTE is legal // check that physical address of PTE is legal
reg_t pte = 0; reg_t pte = 0;
const uint8_t res = const uint8_t res =
this->read(phys_addr_t(addr.getAccessType(), traits<BASE>::MEM, base + idx * vm.ptesize), vm.ptesize, this->read(phys_addr_t{addr.access, traits<BASE>::MEM, base + idx * vm.ptesize}, vm.ptesize, (uint8_t *)&pte);
(uint8_t *)&pte);
if (res != 0) throw trap_load_access_fault(addr.val); if (res != 0) throw trap_load_access_fault(addr.val);
const reg_t ppn = pte >> PTE_PPN_SHIFT; const reg_t ppn = pte >> PTE_PPN_SHIFT;
if (PTE_TABLE(pte)) { // next level of page table if (PTE_TABLE(pte)) { // next level of page table
base = ppn << PGSHIFT; base = ppn << PGSHIFT;
} else if ((pte & PTE_U) ? s_mode && (type == iss::FETCH || !sum) : !s_mode) { } else if ((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) {
break; break;
} else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break; break;
} else if (type == iss::FETCH ? !(pte & PTE_X) } else if (type == iss::access_type::FETCH ? !(pte & PTE_X)
: type == iss::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
: !((pte & PTE_R) && (pte & PTE_W))) { : !((pte & PTE_R) && (pte & PTE_W))) {
break; break;
} else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break; break;
} else { } else {
const reg_t ad = PTE_A | ((type == iss::WRITE) * PTE_D); const reg_t ad = PTE_A | ((type == iss::access_type::WRITE) * PTE_D);
#ifdef RISCV_ENABLE_DIRTY #ifdef RISCV_ENABLE_DIRTY
// set accessed and possibly dirty bits. // set accessed and possibly dirty bits.
*(uint32_t *)ppte |= ad; *(uint32_t *)ppte |= ad;
@ -1130,18 +1126,18 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
const reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT; const reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
const reg_t offset = addr.val & PGMASK; const reg_t offset = addr.val & PGMASK;
ptw[vpn] = value | (pte & 0xff); ptw[vpn] = value | (pte & 0xff);
return {addr.getAccessType(), addr.space, value | offset}; return {addr.access, addr.space, value | offset};
} }
} }
} }
switch (type) { switch (type) {
case FETCH: case access_type::FETCH:
this->fault_data = addr.val; this->fault_data = addr.val;
throw trap_instruction_page_fault(addr.val); throw trap_instruction_page_fault(addr.val);
case READ: case access_type::READ:
this->fault_data = addr.val; this->fault_data = addr.val;
throw trap_load_page_fault(addr.val); throw trap_load_page_fault(addr.val);
case WRITE: case access_type::WRITE:
this->fault_data = addr.val; this->fault_data = addr.val;
throw trap_store_page_fault(addr.val); throw trap_store_page_fault(addr.val);
default: default:
@ -1217,6 +1213,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause])<<"' ("<<trap_id<<")" CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause])<<"' ("<<trap_id<<")"
<< " at address " << buffer << " occurred, changing privilege level from " << lvl[cur_priv] << " at address " << buffer << " occurred, changing privilege level from " << lvl[cur_priv]
<< " to " << lvl[new_priv]; << " to " << lvl[new_priv];
update_vm_info();
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }
@ -1253,6 +1250,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f
// sets the pc to the value stored in the x epc register. // sets the pc to the value stored in the x epc register.
this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.machine_state]; CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.machine_state];
update_vm_info();
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }

View File

@ -28,7 +28,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
// Created on: Sun Nov 19 14:05:47 CET 2017 // Created on: Fri Dec 15 14:41:57 CET 2017
// * rv32imac.h Author: <CoreDSL Generator> // * rv32imac.h Author: <CoreDSL Generator>
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -98,9 +98,9 @@ struct traits<rv32imac> {
using code_word_t = uint32_t; //TODO: check removal using code_word_t = uint32_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::VIRTUAL>; using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) { constexpr static unsigned reg_bit_width(unsigned r) {
const uint32_t RV32IMAC_reg_size[] = {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}; const uint32_t RV32IMAC_reg_size[] = {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64};
@ -112,6 +112,8 @@ struct traits<rv32imac> {
return RV32IMAC_reg_byte_offset[r]; return RV32IMAC_reg_byte_offset[r];
} }
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e {FLAGS}; enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM,CSR,FENCE,RES}; enum mem_type_e {MEM,CSR,FENCE,RES};
@ -140,19 +142,20 @@ struct rv32imac: public arch_if {
/// deprecated /// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
void notify_phase(exec_phase phase){
if(phase==ISTART){
++reg.icount;
reg.PC=reg.NEXT_PC;
reg.trap_state=reg.pending_trap;
}
}
uint64_t get_icount() { return reg.icount;} uint64_t get_icount() { return reg.icount;}
virtual phys_addr_t v2p(const iss::addr_t& pc); inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv32imac>::MEM ||
addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32imac>::addr_mask);
} else
return virt2phys(addr);
}
virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; } virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
protected: protected:
struct RV32IMAC_regs { struct RV32IMAC_regs {
@ -193,6 +196,8 @@ protected:
uint32_t trap_state, pending_trap, machine_state; uint32_t trap_state, pending_trap, machine_state;
uint64_t icount; uint64_t icount;
} reg; } reg;
address_type addr_mode[4];
}; };
} }

View File

@ -28,7 +28,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
// Created on: Sun Nov 19 14:05:47 CET 2017 // Created on: Fri Dec 15 14:41:58 CET 2017
// * rv64ia.h Author: <CoreDSL Generator> // * rv64ia.h Author: <CoreDSL Generator>
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -98,9 +98,9 @@ struct traits<rv64ia> {
using code_word_t = uint64_t; //TODO: check removal using code_word_t = uint64_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::VIRTUAL>; using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) { constexpr static unsigned reg_bit_width(unsigned r) {
const uint32_t RV64IA_reg_size[] = {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,64}; const uint32_t RV64IA_reg_size[] = {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,64};
@ -112,6 +112,8 @@ struct traits<rv64ia> {
return RV64IA_reg_byte_offset[r]; return RV64IA_reg_byte_offset[r];
} }
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e {FLAGS}; enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM,CSR,FENCE,RES}; enum mem_type_e {MEM,CSR,FENCE,RES};
@ -140,19 +142,20 @@ struct rv64ia: public arch_if {
/// deprecated /// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
void notify_phase(exec_phase phase){
if(phase==ISTART){
++reg.icount;
reg.PC=reg.NEXT_PC;
reg.trap_state=reg.pending_trap;
}
}
uint64_t get_icount() { return reg.icount;} uint64_t get_icount() { return reg.icount;}
virtual phys_addr_t v2p(const iss::addr_t& pc); inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv64ia>::MEM ||
addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv64ia>::addr_mask);
} else
return virt2phys(addr);
}
virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; } virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
protected: protected:
struct RV64IA_regs { struct RV64IA_regs {
@ -193,6 +196,8 @@ protected:
uint32_t trap_state, pending_trap, machine_state; uint32_t trap_state, pending_trap, machine_state;
uint64_t icount; uint64_t icount;
} reg; } reg;
address_type addr_mode[4];
}; };
} }

View File

@ -211,7 +211,7 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin()); std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
std::fill(avail.begin(), avail.end(), 0xff); std::fill(avail.begin(), avail.end(), 0xff);
} else { } else {
typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65); typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65);
data.resize(sizeof(typename traits<ARCH>::reg_t)); data.resize(sizeof(typename traits<ARCH>::reg_t));
avail.resize(sizeof(typename traits<ARCH>::reg_t)); avail.resize(sizeof(typename traits<ARCH>::reg_t));
std::fill(avail.begin(), avail.end(), 0xff); std::fill(avail.begin(), avail.end(), 0xff);
@ -228,20 +228,20 @@ status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, co
auto offset = traits<ARCH>::reg_byte_offset(reg_no); auto offset = traits<ARCH>::reg_byte_offset(reg_no);
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
} else { } else {
typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65); typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65);
core->write(a, data.size(), data.data()); core->write(a, data.size(), data.data());
} }
return Ok; return Ok;
} }
template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) { template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) {
auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr});
auto f = [&]() -> status { return core->read(a, data.size(), data.data()); }; auto f = [&]() -> status { return core->read(a, data.size(), data.data()); };
return srv->execute_syncronized(f); return srv->execute_syncronized(f);
} }
template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) { template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) {
auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr});
return srv->execute_syncronized(&arch_if::write, core, a, data.size(), data.data()); return srv->execute_syncronized(&arch_if::write, core, a, data.size(), data.data());
} }
@ -292,8 +292,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::packetsize_query(std
} }
template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) { template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) {
auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length});
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val);
LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex
<< saddr.val << std::dec; << saddr.val << std::dec;
@ -302,7 +302,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(int type,
} }
template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) { template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) {
auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
if (handle) { if (handle) {
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val

View File

@ -16,7 +16,8 @@ set(APP_SOURCES main.cpp)
set(LIBRARY_NAME risc-v) set(LIBRARY_NAME risc-v)
# Define the library # Define the library
add_library(${LIBRARY_NAME} SHARED ${LIB_SOURCES}) #add_library(${LIBRARY_NAME} SHARED ${LIB_SOURCES})
add_library(${LIBRARY_NAME} ${LIB_SOURCES})
SET(${LIBRARY_NAME} -Wl,-whole-archive -l${LIBRARY_NAME} -Wl,-no-whole-archive) SET(${LIBRARY_NAME} -Wl,-whole-archive -l${LIBRARY_NAME} -Wl,-no-whole-archive)
set_target_properties(${LIBRARY_NAME} PROPERTIES set_target_properties(${LIBRARY_NAME} PROPERTIES
VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists. VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists.

View File

@ -62,7 +62,7 @@ public:
vm_impl(); vm_impl();
vm_impl(ARCH &core, bool dump = false); vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
@ -102,13 +102,13 @@ protected:
inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) {
return this->builder->CreateLoad(get_reg_ptr(i), false); return this->builder.CreateLoad(get_reg_ptr(i), false);
} }
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
llvm::Value *next_pc_v = this->builder->CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val), llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
this->get_type(traits<ARCH>::XLEN)); this->get_type(traits<ARCH>::XLEN));
this->builder->CreateStore(next_pc_v, get_reg_ptr(reg_num), true); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
} }
// some compile time constants // some compile time constants
@ -186,30 +186,11 @@ private:
****************************************************************************/ ****************************************************************************/
std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr,
llvm::BasicBlock *bb) { llvm::BasicBlock *bb) {
bb->setName("illegal_instruction"); this->gen_sync(iss::PRE_SYNC);
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
// this->gen_sync(iss::PRE_SYNC);
// if(this->disass_enabled){
// /* generate console output when executing the command */
// boost::format ins_fmter("DB x%1$d");
// ins_fmter % (uint64_t)instr;
// std::vector<llvm::Value*> args {
// this->core_ptr,
// this->gen_const(64, pc.val),
// this->builder->CreateGlobalStringPtr(ins_fmter.str()),
// };
// this->builder->CreateCall(this->mod->getFunction("print_disass"), args);
// }
// pc = pc + ((instr & 3) == 3 ? 4 : 2);
// this->gen_raise_trap(0, 2); // illegal instruction trap
// this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */
// this->gen_trap_check(this->leave_blk);
// return std::make_tuple(iss::vm::BRANCH, nullptr);
// this->gen_sync(iss::PRE_SYNC);
this->builder->CreateStore(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true); get_reg_ptr(traits<ARCH>::PC), true);
this->builder->CreateStore( this->builder.CreateStore(
this->builder->CreateAdd(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true), this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
this->gen_const(64U, 1)), this->gen_const(64U, 1)),
get_reg_ptr(traits<ARCH>::ICOUNT), true); get_reg_ptr(traits<ARCH>::ICOUNT), true);
if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC);
@ -229,8 +210,8 @@ template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); } template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH> template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm::vm_base<ARCH>(core, dump) { : vm::vm_base<ARCH>(core, core_id, cluster_id) {
qlut[0] = lut_00.data(); qlut[0] = lut_00.data();
qlut[1] = lut_01.data(); qlut[1] = lut_01.data();
qlut[2] = lut_10.data(); qlut[2] = lut_10.data();
@ -239,7 +220,6 @@ vm_impl<ARCH>::vm_impl(ARCH &core, bool dump)
auto quantrant = instr.value & 0x3; auto quantrant = instr.value & 0x3;
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
} }
this->sync_exec = static_cast<sync_type>(this->sync_exec | core.needed_sync());
} }
template <typename ARCH> template <typename ARCH>
@ -278,44 +258,44 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock *leave_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock *leave_blk) {
this->builder->SetInsertPoint(leave_blk); this->builder.SetInsertPoint(leave_blk);
this->builder->CreateRet(this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false)); this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
} }
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) { template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder->CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true); this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
std::vector<llvm::Value *> args{ std::vector<llvm::Value *> args{
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)), this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
}; };
this->builder->CreateCall(this->mod->getFunction("leave_trap"), args); this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8); auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder->CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) { template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
std::vector<llvm::Value *> args{ std::vector<llvm::Value *> args{
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
}; };
this->builder->CreateCall(this->mod->getFunction("wait"), args); this->builder.CreateCall(this->mod->getFunction("wait"), args);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) {
this->builder->SetInsertPoint(trap_blk); this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true); auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val), std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))}; this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->builder->CreateCall(this->mod->getFunction("enter_trap"), args); this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false); auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder->CreateRet(trap_addr_val); this->builder.CreateRet(trap_addr_val);
} }
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock *bb) { template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock *bb) {
auto *v = this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true); auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
this->gen_cond_branch(this->builder->CreateICmp( this->gen_cond_branch(this->builder.CreateICmp(
ICmpInst::ICMP_EQ, v, ICmpInst::ICMP_EQ, v,
llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))),
bb, this->trap_blk, 1); bb, this->trap_blk, 1);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -67,6 +67,6 @@ void rv32imac::reset(uint64_t address) {
uint8_t *rv32imac::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); } uint8_t *rv32imac::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); }
rv32imac::phys_addr_t rv32imac::v2p(const iss::addr_t &pc) { rv32imac::phys_addr_t rv32imac::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address return phys_addr_t(pc); // change logical address to physical address
} }

View File

@ -67,6 +67,6 @@ void rv64ia::reset(uint64_t address) {
uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); } uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); }
rv64ia::phys_addr_t rv64ia::v2p(const iss::addr_t &pc) { rv64ia::phys_addr_t rv64ia::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address return phys_addr_t(pc); // change logical address to physical address
} }

View File

@ -54,7 +54,7 @@ int main(int argc, char *argv[]) {
// clang-format off // clang-format off
desc.add_options() desc.add_options()
("help,h", "Print help message") ("help,h", "Print help message")
("loglevel,l", po::value<int>()->implicit_value(2), "Sets logging verbosity") ("verbose,v", po::value<int>()->implicit_value(0), "Sets logging verbosity")
("logfile,f", po::value<std::string>(), "Sets default log file.") ("logfile,f", po::value<std::string>(), "Sets default log file.")
("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly") ("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly")
("elf", po::value<std::vector<std::string>>(), "ELF file(s) to load") ("elf", po::value<std::vector<std::string>>(), "ELF file(s) to load")
@ -62,10 +62,8 @@ int main(int argc, char *argv[]) {
("input,i", po::value<std::string>(), "the elf file to load (instead of hex files)") ("input,i", po::value<std::string>(), "the elf file to load (instead of hex files)")
("dump-ir", "dump the intermediate representation") ("dump-ir", "dump the intermediate representation")
("cycles,c", po::value<int64_t>()->default_value(-1), "number of cycles to run") ("cycles,c", po::value<int64_t>()->default_value(-1), "number of cycles to run")
("systemc,s", "Run as SystemC simulation")
("time", po::value<int>(), "SystemC simulation time in ms") ("time", po::value<int>(), "SystemC simulation time in ms")
("reset,r", po::value<std::string>(), "reset address") ("reset,r", po::value<std::string>(), "reset address")
("trace", po::value<uint8_t>(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite")
("mem,m", po::value<std::string>(), "the memory input file") ("mem,m", po::value<std::string>(), "the memory input file")
("isa", po::value<std::string>()->default_value("rv32imac"), "isa to use for simulation"); ("isa", po::value<std::string>()->default_value("rv32imac"), "isa to use for simulation");
// clang-format on // clang-format on
@ -86,8 +84,8 @@ int main(int argc, char *argv[]) {
} }
std::vector<std::string> args = collect_unrecognized(parsed.options, po::include_positional); std::vector<std::string> args = collect_unrecognized(parsed.options, po::include_positional);
if (clim.count("loglevel")) { if (clim.count("verbose")) {
auto l = logging::as_log_level(clim["loglevel"].as<int>()); auto l = logging::as_log_level(clim["verbose"].as<int>());
LOGGER(DEFAULT)::reporting_level() = l; LOGGER(DEFAULT)::reporting_level() = l;
LOGGER(connection)::reporting_level() = l; LOGGER(connection)::reporting_level() = l;
} }
@ -104,18 +102,20 @@ int main(int argc, char *argv[]) {
bool dump = clim.count("dump-ir"); bool dump = clim.count("dump-ir");
// instantiate the simulator // instantiate the simulator
std::unique_ptr<iss::vm_if> vm{nullptr}; std::unique_ptr<iss::vm_if> vm{nullptr};
if (clim["isa"].as<std::string>().substr(0, 4)=="rv64") { std::string isa_opt(clim["isa"].as<std::string>());
if (isa_opt.substr(0, 4)=="rv64") {
iss::arch::rv64ia* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64ia>(); iss::arch::rv64ia* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64ia>();
vm = iss::create(cpu, clim["gdb-port"].as<unsigned>(), dump); vm = iss::create(cpu, clim["gdb-port"].as<unsigned>());
} else if (clim["isa"].as<std::string>().substr(0, 4)=="rv32") { } else if (isa_opt.substr(0, 4)=="rv32") {
iss::arch::rv32imac* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv32imac>(); iss::arch::rv32imac* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv32imac>();
vm = iss::create(cpu, clim["gdb-port"].as<unsigned>(), dump); vm = iss::create(cpu, clim["gdb-port"].as<unsigned>());
} else { } else {
LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as<std::string>() << std::endl; LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as<std::string>() << std::endl;
return 127; return 127;
} }
if (clim.count("elf")) if (clim.count("elf"))
for (std::string input : clim["elf"].as<std::vector<std::string>>()) vm->get_arch()->load_file(input); for (std::string input : clim["elf"].as<std::vector<std::string>>())
vm->get_arch()->load_file(input);
if (clim.count("mem")) if (clim.count("mem"))
vm->get_arch()->load_file(clim["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM); vm->get_arch()->load_file(clim["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM);
for (std::string input : args) vm->get_arch()->load_file(input);// treat remaining arguments as elf files for (std::string input : args) vm->get_arch()->load_file(input);// treat remaining arguments as elf files
@ -138,7 +138,7 @@ int main(int argc, char *argv[]) {
} }
int64_t cycles = -1; int64_t cycles = -1;
cycles = clim["cycles"].as<int64_t>(); cycles = clim["cycles"].as<int64_t>();
return vm->start(cycles); return vm->start(cycles, dump);
} catch (std::exception &e) { } catch (std::exception &e) {
LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
<< std::endl; << std::endl;

@ -1 +1 @@
Subproject commit 02cb1756166adb7074f6e5dfa106ca5ab04176c6 Subproject commit 0122e4d3123eff995aa90a08b8fda3e5b94827d9

View File

@ -1,13 +1,13 @@
{ {
"i_simple_system":{ "i_simple_system":{
"i_uart0":{ "i_uart0":{
"write_to_ws": false "write_to_ws": true
}, },
"i_uart1":{ "i_uart1":{
"write_to_ws": false "write_to_ws": false
}, },
"i_gpio0":{ "i_gpio0":{
"write_to_ws": false "write_to_ws": true
} }
} }
} }