aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-05-16 14:34:11 -0700
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-05-16 14:34:11 -0700
commit6e85b4332f8d5fa198b766afb73dde5506d5097f (patch)
tree29a840dffdecc6e79173bc86e43dd612ef478626
parent7a589027a771e00646c36bc09dde723c527a26bd (diff)
downloadspike-6e85b4332f8d5fa198b766afb73dde5506d5097f.zip
spike-6e85b4332f8d5fa198b766afb73dde5506d5097f.tar.gz
spike-6e85b4332f8d5fa198b766afb73dde5506d5097f.tar.bz2
[sim,pk] cleanups & initial virtual memory support
-rw-r--r--riscv/insns/fence_i.h1
-rw-r--r--riscv/insns/mfpcr.h6
-rw-r--r--riscv/insns/mtpcr.h4
-rw-r--r--riscv/mmu.cc12
-rw-r--r--riscv/mmu.h84
-rw-r--r--riscv/processor.cc1
-rw-r--r--riscv/riscv.mk.in1
7 files changed, 70 insertions, 39 deletions
diff --git a/riscv/insns/fence_i.h b/riscv/insns/fence_i.h
index e69de29..a2dbffe 100644
--- a/riscv/insns/fence_i.h
+++ b/riscv/insns/fence_i.h
@@ -0,0 +1 @@
+mmu.flush_icache();
diff --git a/riscv/insns/mfpcr.h b/riscv/insns/mfpcr.h
index e9d5350..fe00f5f 100644
--- a/riscv/insns/mfpcr.h
+++ b/riscv/insns/mfpcr.h
@@ -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:
diff --git a/riscv/insns/mtpcr.h b/riscv/insns/mtpcr.h
index 449f63d..f47781f 100644
--- a/riscv/insns/mtpcr.h
+++ b/riscv/insns/mtpcr.h
@@ -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
index 0000000..4c29000
--- /dev/null
+++ b/riscv/mmu.cc
@@ -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
+}
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 2f897ff..65186a5 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -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;
};
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 118d4d8..bb1a982 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -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;
}
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index f53bc13..62d6046 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -19,6 +19,7 @@ riscv_srcs = \
sim.cc \
trap.cc \
icsim.cc \
+ mmu.cc \
riscv_test_srcs =