diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-09-08 15:09:23 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-09-08 17:00:02 -0700 |
commit | 71d04ecd7ab631193a0943f8ddae222090d8e048 (patch) | |
tree | 91a80a22da66a18d28bc79c39d26111e69fab26a /riscv/mmu.h | |
parent | 26d7f0f08e861335dc7bb2b51759c2206915a25a (diff) | |
download | spike-71d04ecd7ab631193a0943f8ddae222090d8e048.zip spike-71d04ecd7ab631193a0943f8ddae222090d8e048.tar.gz spike-71d04ecd7ab631193a0943f8ddae222090d8e048.tar.bz2 |
Improve instruction fetch
- Performance for variable-length instructions is much better
- Refill is simpler and faster
- Support for instructions with overlapping opcodes (e.g. C.ADD + C.JALR)
Diffstat (limited to 'riscv/mmu.h')
-rw-r--r-- | riscv/mmu.h | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/riscv/mmu.h b/riscv/mmu.h index ddb1d51..ce8685d 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -72,18 +72,11 @@ public: inline size_t icache_index(reg_t addr) { - // for instruction sizes != 4, this hash still works but is suboptimal - return (addr / 4) % ICACHE_ENTRIES; + return (addr / PC_ALIGN) % ICACHE_ENTRIES; } - // load instruction from memory at aligned address. - icache_entry_t* access_icache(reg_t addr) __attribute__((always_inline)) + inline icache_entry_t* refill_icache(reg_t addr, icache_entry_t* entry) { - reg_t idx = icache_index(addr); - icache_entry_t* entry = &icache[idx]; - if (likely(entry->tag == addr)) - return entry; - char* iaddr = (char*)translate(addr, 1, false, true); insn_bits_t insn = *(uint16_t*)iaddr; int length = insn_length(insn); @@ -106,16 +99,23 @@ public: } insn_fetch_t fetch = {proc->decode_insn(insn), insn}; - icache[idx].tag = addr; - icache[idx].data = fetch; + entry->tag = addr; + entry->data = fetch; reg_t paddr = iaddr - mem; - if (!tracer.empty() && tracer.interested_in_range(paddr, paddr + 1, false, true)) - { - icache[idx].tag = -1; + if (tracer.interested_in_range(paddr, paddr + 1, false, true)) { + entry->tag = -1; tracer.trace(paddr, length, false, true); } - return &icache[idx]; + return entry; + } + + inline icache_entry_t* access_icache(reg_t addr) + { + icache_entry_t* entry = &icache[icache_index(addr)]; + if (likely(entry->tag == addr)) + return entry; + return refill_icache(addr, entry); } inline insn_fetch_t load_insn(reg_t addr) |