|
|
|
@ -36,11 +36,6 @@ public: |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
void set_icsim(icsim_t* _icsim) { icsim = _icsim; } |
|
|
|
void set_dcsim(icsim_t* _dcsim) { dcsim = _dcsim; } |
|
|
|
void set_itlbsim(icsim_t* _itlbsim) { itlbsim = _itlbsim; } |
|
|
|
void set_dtlbsim(icsim_t* _dtlbsim) { dtlbsim = _dtlbsim; } |
|
|
|
|
|
|
|
#ifdef RISCV_ENABLE_ICSIM |
|
|
|
# define dcsim_tick(dcsim, dtlbsim, addr, size, st) \ |
|
|
|
do { if(dcsim) (dcsim)->tick(addr, size, st); \ |
|
|
|
@ -69,9 +64,13 @@ public: |
|
|
|
{ |
|
|
|
insn_t insn; |
|
|
|
|
|
|
|
#ifdef RISCV_ENABLE_RVC |
|
|
|
check_align(addr, rvc ? 2 : 4, false, true); |
|
|
|
reg_t idx = (addr/sizeof(insn_t)) % ICACHE_ENTRIES; |
|
|
|
if(addr % 4 == 0 && icache_tag[idx] == (addr | 1)) |
|
|
|
return icache_data[idx]; |
|
|
|
|
|
|
|
#ifdef RISCV_ENABLE_RVC |
|
|
|
if(addr % 4 == 2 && rvc) |
|
|
|
{ |
|
|
|
reg_t paddr_lo = translate(addr, false, true); |
|
|
|
insn.bits = *(uint16_t*)(mem+paddr_lo); |
|
|
|
|
|
|
|
@ -80,11 +79,17 @@ public: |
|
|
|
reg_t paddr_hi = translate(addr+2, false, true); |
|
|
|
insn.bits |= (uint32_t)*(uint16_t*)(mem+paddr_hi) << 16; |
|
|
|
} |
|
|
|
#else |
|
|
|
} |
|
|
|
else |
|
|
|
#endif |
|
|
|
{ |
|
|
|
check_align(addr, 4, false, true); |
|
|
|
reg_t paddr = translate(addr, false, true); |
|
|
|
insn = *(insn_t*)(mem+paddr); |
|
|
|
#endif |
|
|
|
|
|
|
|
icache_tag[idx] = addr | 1; |
|
|
|
icache_data[idx] = insn; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef RISCV_ENABLE_ICSIM |
|
|
|
if(icsim) |
|
|
|
@ -112,9 +117,19 @@ public: |
|
|
|
store_func(uint64) |
|
|
|
|
|
|
|
reg_t get_badvaddr() { return badvaddr; } |
|
|
|
reg_t get_ptbr() { return ptbr; } |
|
|
|
|
|
|
|
void set_supervisor(bool sup) { supervisor = sup; } |
|
|
|
void set_vm_enabled(bool en) { vm_enabled = en; } |
|
|
|
void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); } |
|
|
|
void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); flush_tlb(); } |
|
|
|
|
|
|
|
void set_icsim(icsim_t* _icsim) { icsim = _icsim; } |
|
|
|
void set_dcsim(icsim_t* _dcsim) { dcsim = _dcsim; } |
|
|
|
void set_itlbsim(icsim_t* _itlbsim) { itlbsim = _itlbsim; } |
|
|
|
void set_dtlbsim(icsim_t* _dtlbsim) { dtlbsim = _dtlbsim; } |
|
|
|
|
|
|
|
void flush_tlb(); |
|
|
|
void flush_icache(); |
|
|
|
|
|
|
|
private: |
|
|
|
char* mem; |
|
|
|
@ -129,6 +144,10 @@ private: |
|
|
|
pte_t tlb_data[TLB_ENTRIES]; |
|
|
|
reg_t tlb_tag[TLB_ENTRIES]; |
|
|
|
|
|
|
|
static const reg_t ICACHE_ENTRIES = 32; |
|
|
|
insn_t icache_data[ICACHE_ENTRIES]; |
|
|
|
reg_t icache_tag[ICACHE_ENTRIES]; |
|
|
|
|
|
|
|
icsim_t* icsim; |
|
|
|
icsim_t* dcsim; |
|
|
|
icsim_t* itlbsim; |
|
|
|
@ -172,7 +191,7 @@ private: |
|
|
|
!store && !fetch && !(supervisor ? pte.sr : pte.ur)) |
|
|
|
throw trap; |
|
|
|
|
|
|
|
return (addr % PGSIZE) | (pte.ppn << PGSHIFT); |
|
|
|
return (addr & (PGSIZE-1)) | (pte.ppn << PGSHIFT); |
|
|
|
} |
|
|
|
|
|
|
|
pte_t walk(reg_t addr) |
|
|
|
@ -219,16 +238,5 @@ private: |
|
|
|
return pte; |
|
|
|
} |
|
|
|
|
|
|
|
void check_bounds(reg_t addr, int size, bool store, bool fetch) |
|
|
|
{ |
|
|
|
if(addr >= memsz || addr + size > memsz) |
|
|
|
{ |
|
|
|
badvaddr = addr; |
|
|
|
if(fetch) |
|
|
|
throw trap_instruction_access_fault; |
|
|
|
throw store ? trap_store_access_fault : trap_load_access_fault; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
friend class processor_t; |
|
|
|
}; |
|
|
|
|