#include "trap.h"
#include "common.h"
#include "config.h"
-#include "sim.h"
+#include "simif.h"
#include "processor.h"
#include "memtracer.h"
#include <stdlib.h>
struct icache_entry_t {
reg_t tag;
- reg_t pad;
+ struct icache_entry_t* next;
insn_fetch_t data;
};
class mmu_t
{
public:
- mmu_t(sim_t* sim, processor_t* proc);
+ mmu_t(simif_t* sim, processor_t* proc);
~mmu_t();
inline reg_t misaligned_load(reg_t addr, size_t size)
return lhs; \
} catch (trap_load_page_fault& t) { \
/* AMO faults should be reported as store faults */ \
- throw trap_store_page_fault(t.get_badaddr()); \
+ throw trap_store_page_fault(t.get_tval()); \
} catch (trap_load_access_fault& t) { \
/* AMO faults should be reported as store faults */ \
- throw trap_store_access_fault(t.get_badaddr()); \
+ throw trap_store_access_fault(t.get_tval()); \
} \
}
+ void store_float128(reg_t addr, float128_t val)
+ {
+#ifndef RISCV_ENABLE_MISALIGNED
+ if (unlikely(addr & (sizeof(float128_t)-1)))
+ throw trap_store_address_misaligned(addr);
+#endif
+ store_uint64(addr, val.v[0]);
+ store_uint64(addr + 8, val.v[1]);
+ }
+
+ float128_t load_float128(reg_t addr)
+ {
+#ifndef RISCV_ENABLE_MISALIGNED
+ if (unlikely(addr & (sizeof(float128_t)-1)))
+ throw trap_load_address_misaligned(addr);
+#endif
+ return (float128_t){load_uint64(addr), load_uint64(addr + 8)};
+ }
+
// store value to memory at aligned address
store_func(uint8)
store_func(uint16)
amo_func(uint32)
amo_func(uint64)
+ inline void yield_load_reservation()
+ {
+ load_reservation_address = (reg_t)-1;
+ }
+
+ inline void acquire_load_reservation(reg_t vaddr)
+ {
+ reg_t paddr = translate(vaddr, LOAD);
+ if (auto host_addr = sim->addr_to_mem(paddr))
+ load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr;
+ else
+ throw trap_load_access_fault(vaddr); // disallow LR to I/O space
+ }
+
+ inline bool check_load_reservation(reg_t vaddr)
+ {
+ reg_t paddr = translate(vaddr, STORE);
+ if (auto host_addr = sim->addr_to_mem(paddr))
+ return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr;
+ else
+ throw trap_store_access_fault(vaddr); // disallow SC to I/O space
+ }
+
static const reg_t ICACHE_ENTRIES = 1024;
inline size_t icache_index(reg_t addr)
insn_fetch_t fetch = {proc->decode_insn(insn), insn};
entry->tag = addr;
+ entry->next = &icache[icache_index(addr + length)];
entry->data = fetch;
reg_t paddr = tlb_entry.target_offset + addr;;
void register_memtracer(memtracer_t*);
+ int is_dirty_enabled()
+ {
+#ifdef RISCV_ENABLE_DIRTY
+ return 1;
+#else
+ return 0;
+#endif
+ }
+
+ int is_misaligned_enabled()
+ {
+#ifdef RISCV_ENABLE_MISALIGNED
+ return 1;
+#else
+ return 0;
+#endif
+ }
+
private:
- sim_t* sim;
+ simif_t* sim;
processor_t* proc;
memtracer_list_t tracer;
+ reg_t load_reservation_address;
uint16_t fetch_temp;
// implement an instruction cache for simulator performance
reg_t vpn = addr >> PGSHIFT;
if (likely(tlb_insn_tag[vpn % TLB_ENTRIES] == vpn))
return tlb_data[vpn % TLB_ENTRIES];
+ tlb_entry_t result;
+ if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) {
+ result = fetch_slow_path(addr);
+ } else {
+ result = tlb_data[vpn % TLB_ENTRIES];
+ }
if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) {
uint16_t* ptr = (uint16_t*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr);
int match = proc->trigger_match(OPERATION_EXECUTE, addr, *ptr);
- if (match >= 0)
+ if (match >= 0) {
throw trigger_matched_t(match, OPERATION_EXECUTE, addr, *ptr);
- return tlb_data[vpn % TLB_ENTRIES];
+ }
}
- return fetch_slow_path(addr);
+ return result;
}
inline const uint16_t* translate_insn_addr_to_host(reg_t addr) {
reg_t ptbase;
};
-inline vm_info decode_vm_info(int xlen, reg_t prv, reg_t sptbr)
+inline vm_info decode_vm_info(int xlen, reg_t prv, reg_t satp)
{
if (prv == PRV_M) {
return {0, 0, 0, 0};
} else if (prv <= PRV_S && xlen == 32) {
- switch (get_field(sptbr, SPTBR32_MODE)) {
- case SPTBR_MODE_OFF: return {0, 0, 0, 0};
- case SPTBR_MODE_SV32: return {2, 10, 4, (sptbr & SPTBR32_PPN) << PGSHIFT};
+ switch (get_field(satp, SATP32_MODE)) {
+ case SATP_MODE_OFF: return {0, 0, 0, 0};
+ case SATP_MODE_SV32: return {2, 10, 4, (satp & SATP32_PPN) << PGSHIFT};
default: abort();
}
} else if (prv <= PRV_S && xlen == 64) {
- switch (get_field(sptbr, SPTBR64_MODE)) {
- case SPTBR_MODE_OFF: return {0, 0, 0, 0};
- case SPTBR_MODE_SV39: return {3, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT};
- case SPTBR_MODE_SV48: return {4, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT};
- case SPTBR_MODE_SV57: return {5, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT};
- case SPTBR_MODE_SV64: return {6, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT};
+ switch (get_field(satp, SATP64_MODE)) {
+ case SATP_MODE_OFF: return {0, 0, 0, 0};
+ case SATP_MODE_SV39: return {3, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
+ case SATP_MODE_SV48: return {4, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
+ case SATP_MODE_SV57: return {5, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
+ case SATP_MODE_SV64: return {6, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
default: abort();
}
} else {