aboutsummaryrefslogtreecommitdiff
path: root/riscv/mmu.h
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-09-08 15:09:23 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-09-08 17:00:02 -0700
commit71d04ecd7ab631193a0943f8ddae222090d8e048 (patch)
tree91a80a22da66a18d28bc79c39d26111e69fab26a /riscv/mmu.h
parent26d7f0f08e861335dc7bb2b51759c2206915a25a (diff)
downloadspike-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.h30
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)