Refactored arch_if to save unneeded constructor calls
This commit is contained in:
parent
8092326437
commit
d160a34c5d
2
dbt-core
2
dbt-core
|
@ -1 +1 @@
|
||||||
Subproject commit 54cf894c3f3897a57f366905345514f5e94a5166
|
Subproject commit d73fee68dd164c016721ae76d1538136513e6b37
|
|
@ -467,8 +467,10 @@ public:
|
||||||
|
|
||||||
virtual phys_addr_t virt2phys(const iss::addr_t &addr) override;
|
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 address_type type, const access_type access, const uint32_t space,
|
||||||
iss::status write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) override;
|
const uint64_t addr, const unsigned length, uint8_t *const data) override;
|
||||||
|
iss::status write(const address_type type, const access_type access, const uint32_t space,
|
||||||
|
const uint64_t addr, const unsigned length, const uint8_t *const data) override;
|
||||||
|
|
||||||
virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data); }
|
virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data); }
|
||||||
virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override;
|
virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override;
|
||||||
|
@ -624,8 +626,8 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
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(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE,
|
||||||
phys_addr_t(iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, pseg->get_physical_address()),
|
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
|
||||||
|
@ -647,36 +649,39 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
|
||||||
}
|
}
|
||||||
|
|
||||||
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 address_type type, const access_type access, const uint32_t space,
|
||||||
|
const uint64_t addr, const unsigned length, uint8_t *const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (addr.access && iss::access_type::DEBUG) {
|
if (access && iss::access_type::DEBUG) {
|
||||||
LOG(TRACE) << "debug read of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << "debug read of " << length << " bytes @addr " << addr;
|
||||||
} else {
|
} else {
|
||||||
LOG(TRACE) << "read of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << "read of " << length << " bytes @addr " << addr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
switch (addr.space) {
|
switch (space) {
|
||||||
case traits<BASE>::MEM: {
|
case traits<BASE>::MEM: {
|
||||||
if (unlikely((addr.access == iss::access_type::FETCH || addr.access == iss::access_type::DEBUG_FETCH) && (addr.val & 0x1) == 1)) {
|
if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr.val;
|
fault_data = addr;
|
||||||
if (addr.access && iss::access_type::DEBUG) throw trap_access(0, addr.val);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->reg.trap_state = (1 << 31); // issue trap 0
|
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (unlikely((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
||||||
vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
|
vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
|
||||||
if (vm.levels != 0) { // VM is active
|
if (vm.levels != 0) { // VM is active
|
||||||
auto split_addr = (addr.val + length) & ~PGMASK;
|
auto split_addr = (addr + length) & ~PGMASK;
|
||||||
auto len1 = split_addr - addr.val;
|
auto len1 = split_addr - addr;
|
||||||
auto res = read(addr, len1, data);
|
auto res = read(type, access, space, addr, len1, data);
|
||||||
if (res == iss::Ok)
|
if (res == iss::Ok)
|
||||||
res = read(iss::addr_t{addr.access, addr.type, addr.space, split_addr}, length - len1, data + len1);
|
res = read(type, access, space, split_addr, length - len1, data + len1);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto res = read_mem( BASE::v2p(addr), length, data);
|
auto res = type==iss::address_type::PHYSICAL?
|
||||||
|
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
|
||||||
|
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||||
if (unlikely(res != iss::Ok)) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
if (unlikely(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) {
|
||||||
|
@ -686,11 +691,11 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
case traits<BASE>::CSR: {
|
||||||
if (length != sizeof(reg_t)) return iss::Err;
|
if (length != sizeof(reg_t)) return iss::Err;
|
||||||
return read_csr(addr.val, *reinterpret_cast<reg_t *const>(data));
|
return read_csr(addr, *reinterpret_cast<reg_t *const>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr.val + length) > mem.size()) return iss::Err;
|
if ((addr + length) > mem.size()) return iss::Err;
|
||||||
switch (addr.val) {
|
switch (addr) {
|
||||||
case 2: // SFENCE:VMA lower
|
case 2: // SFENCE:VMA lower
|
||||||
case 3: { // SFENCE:VMA upper
|
case 3: { // SFENCE:VMA upper
|
||||||
auto tvm = state.mstatus.TVM;
|
auto tvm = state.mstatus.TVM;
|
||||||
|
@ -704,10 +709,10 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::RES: {
|
case traits<BASE>::RES: {
|
||||||
auto it = atomic_reservation.find(addr.val);
|
auto it = atomic_reservation.find(addr);
|
||||||
if (it != atomic_reservation.end() && it->second != 0) {
|
if (it != atomic_reservation.end() && it->second != 0) {
|
||||||
memset(data, 0xff, length);
|
memset(data, 0xff, length);
|
||||||
atomic_reservation.erase(addr.val);
|
atomic_reservation.erase(addr);
|
||||||
} else
|
} else
|
||||||
memset(data, 0, length);
|
memset(data, 0, length);
|
||||||
} break;
|
} break;
|
||||||
|
@ -722,9 +727,10 @@ 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 address_type type, const access_type access, const uint32_t space,
|
||||||
|
const uint64_t addr, const unsigned length, const uint8_t *const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
const char *prefix = (addr.access && iss::access_type::DEBUG) ? "debug " : "";
|
const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
||||||
switch (length) {
|
switch (length) {
|
||||||
case 8:
|
case 8:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
||||||
|
@ -747,27 +753,29 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned len
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
switch (addr.space) {
|
switch (space) {
|
||||||
case traits<BASE>::MEM: {
|
case traits<BASE>::MEM: {
|
||||||
if (unlikely((addr.access && iss::access_type::FETCH) && (addr.val & 0x1) == 1)) {
|
if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) {
|
||||||
fault_data = addr.val;
|
fault_data = addr;
|
||||||
if (addr.access && iss::access_type::DEBUG) throw trap_access(0, addr.val);
|
if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
|
||||||
this->reg.trap_state = (1 << 31); // issue trap 0
|
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (unlikely((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
|
||||||
vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
|
vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
|
||||||
if (vm.levels != 0) { // VM is active
|
if (vm.levels != 0) { // VM is active
|
||||||
auto split_addr = (addr.val + length) & ~PGMASK;
|
auto split_addr = (addr + length) & ~PGMASK;
|
||||||
auto len1 = split_addr - addr.val;
|
auto len1 = split_addr - addr;
|
||||||
auto res = write(addr, len1, data);
|
auto res = write(type, access, space, addr, len1, data);
|
||||||
if (res == iss::Ok)
|
if (res == iss::Ok)
|
||||||
res = write(iss::addr_t{addr.access, addr.type, addr.space, split_addr}, length - len1, data + len1);
|
res = write(type, access, space, split_addr, length - len1, data + len1);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto res = write_mem(BASE::v2p(addr), length, data);
|
auto res = type==iss::address_type::PHYSICAL?
|
||||||
|
write_mem(phys_addr_t{access, space, addr}, length, data):
|
||||||
|
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||||
if (unlikely(res != iss::Ok))
|
if (unlikely(res != iss::Ok))
|
||||||
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault)
|
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
return res;
|
return res;
|
||||||
|
@ -776,7 +784,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 = BASE::v2p(addr);
|
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, 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
|
||||||
|
@ -810,11 +818,11 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned len
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
case traits<BASE>::CSR: {
|
||||||
if (length != sizeof(reg_t)) return iss::Err;
|
if (length != sizeof(reg_t)) return iss::Err;
|
||||||
return write_csr(addr.val, *reinterpret_cast<const reg_t *>(data));
|
return write_csr(addr, *reinterpret_cast<const reg_t *>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
if ((addr.val + length) > mem.size()) return iss::Err;
|
if ((addr + length) > mem.size()) return iss::Err;
|
||||||
switch (addr.val) {
|
switch (addr) {
|
||||||
case 2:
|
case 2:
|
||||||
case 3: {
|
case 3: {
|
||||||
ptw.clear();
|
ptw.clear();
|
||||||
|
@ -829,7 +837,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned len
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::RES: {
|
case traits<BASE>::RES: {
|
||||||
atomic_reservation[addr.val] = data[0];
|
atomic_reservation[addr] = data[0];
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
|
@ -1182,8 +1190,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys
|
||||||
|
|
||||||
// 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 = this->read(phys_addr_t{addr.access, traits<BASE>::MEM, base + idx * vm.ptesize},
|
const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access,
|
||||||
vm.ptesize, (uint8_t *)&pte);
|
traits<BASE>::MEM, base + idx * vm.ptesize, vm.ptesize, (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;
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t ad
|
||||||
|
|
||||||
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::access_type::DEBUG_READ, iss::address_type::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());
|
auto f = [&]() -> status { return core->write(a, data.size(), data.data()); };
|
||||||
|
return srv->execute_syncronized(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
|
|
Loading…
Reference in New Issue