aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@eecs.berkeley.edu>2014-02-13 18:46:42 -0800
committerAndrew Waterman <waterman@eecs.berkeley.edu>2014-02-13 18:46:42 -0800
commit6c99f30d7848ab3b5f59a07ae5027cc4ec0c1322 (patch)
tree990b2db9c499bd7cbc6425a9a6347400b98e9fee
parentb227ec194fdea025724ec541c0b472708e439bbe (diff)
downloadspike-6c99f30d7848ab3b5f59a07ae5027cc4ec0c1322.zip
spike-6c99f30d7848ab3b5f59a07ae5027cc4ec0c1322.tar.gz
spike-6c99f30d7848ab3b5f59a07ae5027cc4ec0c1322.tar.bz2
Fix I$ simulator not making forward progress
-rw-r--r--riscv/mmu.h10
-rw-r--r--riscv/processor.cc28
2 files changed, 17 insertions, 21 deletions
diff --git a/riscv/mmu.h b/riscv/mmu.h
index c09cfc4..c3d8f41 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -78,11 +78,11 @@ public:
store_func(uint64)
// load instruction from memory at aligned address.
- inline icache_entry_t access_icache(reg_t addr)
+ inline icache_entry_t* access_icache(reg_t addr)
{
reg_t idx = (addr / sizeof(insn_t)) % ICACHE_SIZE;
- icache_entry_t entry = icache[idx];
- if (likely(entry.tag == addr))
+ icache_entry_t* entry = &icache[idx];
+ if (likely(entry->tag == addr))
return entry;
void* iaddr = translate(addr, sizeof(insn_t), false, true);
@@ -99,12 +99,12 @@ public:
icache[idx].tag = -1;
tracer.trace(paddr, sizeof(insn_t), false, true);
}
- return icache[idx];
+ return &icache[idx];
}
inline insn_fetch_t load_insn(reg_t addr)
{
- return access_icache(addr).data;
+ return access_icache(addr)->data;
}
void set_processor(processor_t* p) { proc = p; flush_tlb(); }
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 83bfbec..e931c6b 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -130,31 +130,27 @@ void processor_t::step(size_t n)
else while (n > 0)
{
size_t idx = (state.pc / sizeof(insn_t)) % ICACHE_SIZE;
- auto ic_entry_init = &_mmu->icache[idx], ic_entry = ic_entry_init;
-
- #define update_count() { \
- size_t i = ic_entry - ic_entry_init; \
- state.count += i; \
- if (i >= n) break; \
- n -= i; }
+ auto ic_entry = _mmu->access_icache(state.pc), ic_entry_init = ic_entry;
#define ICACHE_ACCESS(idx) { \
insn_t insn = ic_entry->data.insn.insn; \
insn_func_t func = ic_entry->data.func; \
- if (unlikely(ic_entry->tag != state.pc)) break; \
- ic_entry++; \
commit_log(&state, insn); \
- state.pc = func(this, insn, state.pc); }
+ ic_entry++; \
+ state.pc = func(this, insn, state.pc); \
+ if (idx < ICACHE_SIZE-1 && unlikely(ic_entry->tag != state.pc)) break; \
+ }
- switch (idx) while (true)
+ switch (idx)
{
- ICACHE_SWITCH;
- update_count();
- ic_entry_init = ic_entry = &_mmu->icache[0];
+ ICACHE_SWITCH; // auto-generated into icache.h
}
- _mmu->access_icache(state.pc);
- update_count();
+ size_t i = ic_entry - ic_entry_init;
+ state.count += i;
+ if (i >= n)
+ break;
+ n -= i;
}
}
catch(trap_t& t)