Browse Source

[xcc] tlb now stores host addresses

cs250
Andrew Waterman 15 years ago
parent
commit
f23ae8b0bc
  1. 6
      riscv/mmu.cc
  2. 32
      riscv/mmu.h

6
riscv/mmu.cc

@ -27,7 +27,7 @@ void mmu_t::flush_icache()
memset(icache_tag, -1, sizeof(icache_tag)); memset(icache_tag, -1, sizeof(icache_tag));
} }
reg_t mmu_t::refill(reg_t addr, bool store, bool fetch) void* mmu_t::refill(reg_t addr, bool store, bool fetch)
{ {
reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES; reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES;
reg_t expected_tag = addr & ~(PGSIZE-1); reg_t expected_tag = addr & ~(PGSIZE-1);
@ -51,9 +51,9 @@ reg_t mmu_t::refill(reg_t addr, bool store, bool fetch)
tlb_load_tag[idx] = (pte_perm & PTE_UR) ? expected_tag : -1; tlb_load_tag[idx] = (pte_perm & PTE_UR) ? expected_tag : -1;
tlb_store_tag[idx] = (pte_perm & PTE_UW) ? expected_tag : -1; tlb_store_tag[idx] = (pte_perm & PTE_UW) ? expected_tag : -1;
tlb_insn_tag[idx] = (pte_perm & PTE_UX) ? expected_tag : -1; tlb_insn_tag[idx] = (pte_perm & PTE_UX) ? expected_tag : -1;
tlb_data[idx] = pte >> PTE_PPN_SHIFT << PGSHIFT; tlb_data[idx] = (long)(pte >> PTE_PPN_SHIFT << PGSHIFT) + (long)mem;
return (addr & (PGSIZE-1)) | tlb_data[idx]; return (void*)(((long)addr & (PGSIZE-1)) | tlb_data[idx]);
} }
pte_t mmu_t::walk(reg_t addr) pte_t mmu_t::walk(reg_t addr)

32
riscv/mmu.h

@ -51,9 +51,9 @@ public:
badvaddr = addr; \ badvaddr = addr; \
throw trap_load_address_misaligned; \ throw trap_load_address_misaligned; \
} \ } \
addr = translate(addr, false, false); \ void* paddr = translate(addr, false, false); \
dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), false); \ dcsim_tick(dcsim, dtlbsim, paddr-mem, sizeof(type##_t), false); \
return *(type##_t*)(mem+addr); \ return *(type##_t*)paddr; \
} }
#define store_func(type) \ #define store_func(type) \
@ -63,9 +63,9 @@ public:
badvaddr = addr; \ badvaddr = addr; \
throw trap_store_address_misaligned; \ throw trap_store_address_misaligned; \
} \ } \
addr = translate(addr, true, false); \ void* paddr = translate(addr, true, false); \
dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), true); \ dcsim_tick(dcsim, dtlbsim, paddr-mem, sizeof(type##_t), true); \
*(type##_t*)(mem+addr) = val; \ *(type##_t*)paddr = val; \
} }
insn_t __attribute__((always_inline)) load_insn(reg_t addr, bool rvc) insn_t __attribute__((always_inline)) load_insn(reg_t addr, bool rvc)
@ -75,13 +75,13 @@ public:
#ifdef RISCV_ENABLE_RVC #ifdef RISCV_ENABLE_RVC
if(addr % 4 == 2 && rvc) // fetch across word boundary if(addr % 4 == 2 && rvc) // fetch across word boundary
{ {
reg_t paddr_lo = translate(addr, false, true); void* addr_lo = translate(addr, false, true);
insn.bits = *(uint16_t*)(mem+paddr_lo); insn.bits = *(uint16_t*)addr_lo;
if(!INSN_IS_RVC(insn.bits)) if(!INSN_IS_RVC(insn.bits))
{ {
reg_t paddr_hi = translate(addr+2, false, true); void* addr_hi = translate(addr+2, false, true);
insn.bits |= (uint32_t)*(uint16_t*)(mem+paddr_hi) << 16; insn.bits |= (uint32_t)*(uint16_t*)addr_hi << 16;
} }
} }
else else
@ -93,8 +93,8 @@ public:
return icache_data[idx]; return icache_data[idx];
// the processor guarantees alignment based upon rvc mode // the processor guarantees alignment based upon rvc mode
reg_t paddr = translate(addr, false, true); void* paddr = translate(addr, false, true);
insn = *(insn_t*)(mem+paddr); insn = *(insn_t*)paddr;
icache_tag[idx] = addr; icache_tag[idx] = addr;
icache_data[idx] = insn; icache_data[idx] = insn;
@ -150,7 +150,7 @@ private:
bool vm_enabled; bool vm_enabled;
static const reg_t TLB_ENTRIES = 256; static const reg_t TLB_ENTRIES = 256;
pte_t tlb_data[TLB_ENTRIES]; long tlb_data[TLB_ENTRIES];
reg_t tlb_insn_tag[TLB_ENTRIES]; reg_t tlb_insn_tag[TLB_ENTRIES];
reg_t tlb_load_tag[TLB_ENTRIES]; reg_t tlb_load_tag[TLB_ENTRIES];
reg_t tlb_store_tag[TLB_ENTRIES]; reg_t tlb_store_tag[TLB_ENTRIES];
@ -164,17 +164,17 @@ private:
icsim_t* itlbsim; icsim_t* itlbsim;
icsim_t* dtlbsim; icsim_t* dtlbsim;
reg_t refill(reg_t addr, bool store, bool fetch); void* refill(reg_t addr, bool store, bool fetch);
pte_t walk(reg_t addr); pte_t walk(reg_t addr);
reg_t translate(reg_t addr, bool store, bool fetch) void* translate(reg_t addr, bool store, bool fetch)
{ {
reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES; reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES;
reg_t* tlb_tag = fetch ? tlb_insn_tag : store ? tlb_store_tag :tlb_load_tag; reg_t* tlb_tag = fetch ? tlb_insn_tag : store ? tlb_store_tag :tlb_load_tag;
reg_t expected_tag = addr & ~(PGSIZE-1); reg_t expected_tag = addr & ~(PGSIZE-1);
if(likely(tlb_tag[idx] == expected_tag)) if(likely(tlb_tag[idx] == expected_tag))
return (addr & (PGSIZE-1)) | tlb_data[idx]; return (void*)(((long)addr & (PGSIZE-1)) | tlb_data[idx]);
return refill(addr, store, fetch); return refill(addr, store, fetch);
} }

Loading…
Cancel
Save