Fix I$ simulator not making forward progress
authorAndrew Waterman <waterman@eecs.berkeley.edu>
Fri, 14 Feb 2014 02:46:42 +0000 (18:46 -0800)
committerAndrew Waterman <waterman@eecs.berkeley.edu>
Fri, 14 Feb 2014 02:46:42 +0000 (18:46 -0800)
riscv/mmu.h
riscv/processor.cc

index c09cfc4e2371bc36a5d6254e5b6d1f401f7eed79..c3d8f41b78ce458595add5b378e23b6b61b9f4e6 100644 (file)
@@ -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(); }
index 83bfbec5451acce3083f3bfbaac699679747121a..e931c6b346cc3d99d3639f7fc061bebc5dede131 100644 (file)
@@ -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)