[sim,pk] cleanups & initial virtual memory support
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Mon, 16 May 2011 21:34:11 +0000 (14:34 -0700)
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>
Mon, 16 May 2011 21:34:11 +0000 (14:34 -0700)
riscv/insns/fence_i.h
riscv/insns/mfpcr.h
riscv/insns/mtpcr.h
riscv/mmu.cc [new file with mode: 0644]
riscv/mmu.h
riscv/processor.cc
riscv/riscv.mk.in

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a2dbffe1271b347559d5f75eaff20ff36774d3cb 100644 (file)
@@ -0,0 +1 @@
+mmu.flush_icache();
index e9d5350c4cc3af953d297e3b48296dbe77bed4e8..fe00f5ffe65d71283ec48c228bf03d8a22fc33d8 100644 (file)
@@ -27,7 +27,11 @@ switch(insn.rtype.rs2)
     break;
 
   case 8:
-    val = MEMSIZE >> 12;
+    val = MEMSIZE >> PGSHIFT;
+    break;
+
+  case 9:
+    val = mmu.get_ptbr();
     break;
 
   case 17:
index 449f63d22d079b105a6e46c80d8edfec34cd3496..f47781f9810a49421ebde2c36340eb0c36bc5225 100644 (file)
@@ -19,6 +19,10 @@ switch(insn.rtype.rs2)
     compare = RS1;
     break;
 
+  case 9:
+    mmu.set_ptbr(RS1);
+    break;
+
   case 16:
     tohost = RS1;
     sim->set_tohost(RS1);
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
new file mode 100644 (file)
index 0000000..4c29000
--- /dev/null
@@ -0,0 +1,12 @@
+#include "mmu.h"
+
+void mmu_t::flush_tlb()
+{
+  memset(tlb_data, 0, sizeof(tlb_data)); // TLB entry itself has valid bit
+  flush_icache();
+}
+
+void mmu_t::flush_icache()
+{
+  memset(icache_tag, 0, sizeof(icache_tag)); // I$ tag contains valid bit
+}
index 2f897ff07740d51c3aad580f1826a77521a2dd19..65186a5eb0555adee3af7c4989bcba78463feb51 100644 (file)
@@ -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,22 +64,32 @@ public:
   {
     insn_t insn;
 
-    #ifdef RISCV_ENABLE_RVC
-    check_align(addr, rvc ? 2 : 4, false, true);
-
-    reg_t paddr_lo = translate(addr, false, true);
-    insn.bits = *(uint16_t*)(mem+paddr_lo);
+    reg_t idx = (addr/sizeof(insn_t)) % ICACHE_ENTRIES;
+    if(addr % 4 == 0 && icache_tag[idx] == (addr | 1))
+      return icache_data[idx];
 
-    if(!INSN_IS_RVC(insn.bits))
+    #ifdef RISCV_ENABLE_RVC
+    if(addr % 4 == 2 && rvc)
     {
-      reg_t paddr_hi = translate(addr+2, false, true);
-      insn.bits |= (uint32_t)*(uint16_t*)(mem+paddr_hi) << 16;
+      reg_t paddr_lo = translate(addr, false, true);
+      insn.bits = *(uint16_t*)(mem+paddr_lo);
+
+      if(!INSN_IS_RVC(insn.bits))
+      {
+        reg_t paddr_hi = translate(addr+2, false, true);
+        insn.bits |= (uint32_t)*(uint16_t*)(mem+paddr_hi) << 16;
+      }
     }
-    #else
-    check_align(addr, 4, false, true);
-    reg_t paddr = translate(addr, false, true);
-    insn = *(insn_t*)(mem+paddr);
+    else
     #endif
+    {
+      check_align(addr, 4, false, true);
+      reg_t paddr = translate(addr, false, true);
+      insn = *(insn_t*)(mem+paddr);
+
+      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,13 +191,13 @@ 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)
   {
     pte_t pte;
-
+  
     if(!vm_enabled)
     {
       pte.v = addr < memsz;
@@ -190,45 +209,34 @@ private:
     else
     {
       pte.v = 0;
-
+  
       int lg_ptesz = sizeof(pte_t) == 4 ? 2
                    : sizeof(pte_t) == 8 ? 3
                    : 0;
       assert(lg_ptesz);
-
+  
       reg_t base = ptbr;
-
+  
       for(int i = LEVELS-1; i >= 0; i++)
       {
         reg_t idx = addr >> (PGSHIFT + i*(PGSHIFT - lg_ptesz));
         idx &= (1<<(PGSHIFT - lg_ptesz)) - 1;
-
+  
         reg_t pte_addr = base + idx*sizeof(pte_t);
         if(pte_addr >= memsz)
           break;
-
+  
         pte = *(pte_t*)(mem+pte_addr);
         if(!pte.v || pte.e)
           break;
-
+  
         base = pte.ppn << PGSHIFT;
       }
       pte.v &= pte.e;
     }
-
+  
     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;
 };
index 118d4d8592b033bc5d4a0724626f38ad555a9c29..bb1a9822012c35249687869328baa172705ed176 100644 (file)
@@ -123,6 +123,7 @@ void processor_t::set_sr(uint32_t val)
 
   mmu.set_vm_enabled(sr & SR_VM);
   mmu.set_supervisor(sr & SR_S);
+  mmu.flush_tlb();
 
   xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
 }
index f53bc13335d79817f07b2f72b07aa3ecde1ce63b..62d604631ef5a40593a32585b88b49ad3233ffa9 100644 (file)
@@ -19,6 +19,7 @@ riscv_srcs = \
        sim.cc \
        trap.cc \
        icsim.cc \
+       mmu.cc \
 
 riscv_test_srcs =