diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-04-03 21:53:22 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-04-03 21:53:22 -0700 |
commit | c4350ef6ef6259e48509e125fd2d051969dc6efa (patch) | |
tree | 7f6b0900717eea640d687fc677d2cd39c97a9dd2 /riscv/mmu.cc | |
parent | d9d73d80c1b738b3b30eb40d192f61cbdb0e201f (diff) | |
download | riscv-isa-sim-c4350ef6ef6259e48509e125fd2d051969dc6efa.zip riscv-isa-sim-c4350ef6ef6259e48509e125fd2d051969dc6efa.tar.gz riscv-isa-sim-c4350ef6ef6259e48509e125fd2d051969dc6efa.tar.bz2 |
Support setting ISA/subsets with --isa flag
Default is RV64IMAFDC. Can do things like
--isa=RV32 (which implies IMAFDC)
--isa=IM (which implies RV64)
--isa=RV64IMAFDXhwacha
Diffstat (limited to 'riscv/mmu.cc')
-rw-r--r-- | riscv/mmu.cc | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 2519f84..e6bbbd4 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -4,6 +4,12 @@ #include "sim.h" #include "processor.h" +#define LEVELS(xlen) ((xlen) == 32 ? 2 : 3) +#define PPN_SHIFT(xlen) ((xlen) == 32 ? 10 : 26) +#define PTIDXBITS(xlen) ((xlen) == 32 ? 10 : 9) +#define VPN_BITS(xlen) (PTIDXBITS(xlen) * LEVELS(xlen)) +#define VA_BITS(xlen) (VPN_BITS(xlen) + PGSHIFT) + mmu_t::mmu_t(char* _mem, size_t _memsz) : mem(_mem), memsz(_memsz), proc(NULL) { @@ -79,25 +85,26 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) return mem + paddr; } -pte_t mmu_t::walk(reg_t addr, bool supervisor, bool store, bool fetch) +reg_t mmu_t::walk(reg_t addr, bool supervisor, bool store, bool fetch) { - reg_t msb_mask = -(reg_t(1) << (VA_BITS-1)); + reg_t msb_mask = -(reg_t(1) << (VA_BITS(proc->xlen) - 1)); if ((addr & msb_mask) != 0 && (addr & msb_mask) != msb_mask) return -1; // address isn't properly sign-extended reg_t base = proc->get_state()->sptbr; - int ptshift = (LEVELS-1)*PTIDXBITS; - for (reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS) { - reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS)-1); + int xlen = proc->max_xlen; + int ptshift = (LEVELS(xlen) - 1) * PTIDXBITS(xlen); + for (reg_t i = 0; i < LEVELS(xlen); i++, ptshift -= PTIDXBITS(xlen)) { + reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS(xlen))-1); // check that physical address of PTE is legal - reg_t pte_addr = base + idx*sizeof(pte_t); + reg_t pte_addr = base + idx*sizeof(reg_t); if (pte_addr >= memsz) return -1; - pte_t* ppte = (pte_t*)(mem+pte_addr); - reg_t ppn = *ppte >> PTE_PPN_SHIFT; + reg_t* ppte = (reg_t*)(mem+pte_addr); + reg_t ppn = *ppte >> PPN_SHIFT(xlen); if ((*ppte & PTE_TYPE) == PTE_TYPE_TABLE) { // next level of page table base = ppn << PGSHIFT; |