OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [mmu/] [immu.c] - Diff between revs 1446 and 1506

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 1446 Rev 1506
Line 38... Line 38...
#include "sim-config.h"
#include "sim-config.h"
#include "debug.h"
#include "debug.h"
 
 
DEFAULT_DEBUG_CHANNEL(immu);
DEFAULT_DEBUG_CHANNEL(immu);
 
 
extern int cont_run;
 
 
 
/* Insn MMU */
/* Insn MMU */
 
 
static inline oraddr_t immu_simulate_tlb(oraddr_t virtaddr)
static inline oraddr_t immu_simulate_tlb(oraddr_t virtaddr)
{
{
  int set, way = -1;
  int set, way = -1;
  int i;
  int i;
  oraddr_t tagaddr;
  oraddr_t tagaddr;
  oraddr_t vpn, ppn;
  oraddr_t vpn, ppn;
 
 
  if (!(mfspr(SPR_SR) & SPR_SR_IME) || !(testsprbits(SPR_UPR, SPR_UPR_IMP))) {
  if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) ||
 
      !(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) {
    insn_ci = (virtaddr >= 0x80000000);
    insn_ci = (virtaddr >= 0x80000000);
    return virtaddr;
    return virtaddr;
  }
  }
 
 
  TRACE("IMMU enabled, checking mmu ways\n");
  TRACE("IMMU enabled, checking mmu ways\n");
Line 64... Line 63...
  vpn = virtaddr / (config.immu.pagesize * config.immu.nsets);
  vpn = virtaddr / (config.immu.pagesize * config.immu.nsets);
 
 
  /* Scan all ways and try to find a matching way. */
  /* Scan all ways and try to find a matching way. */
  for (i = 0; i < config.immu.nways; i++)
  for (i = 0; i < config.immu.nways; i++)
    if (((mfspr(SPR_ITLBMR_BASE(i) + set) / (config.immu.pagesize * config.immu.nsets)) == vpn) &&
    if (((mfspr(SPR_ITLBMR_BASE(i) + set) / (config.immu.pagesize * config.immu.nsets)) == vpn) &&
        testsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_V))
        (cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_V))
      way = i;
      way = i;
 
 
  /* Did we find our tlb entry? */
  /* Did we find our tlb entry? */
  if (way >= 0) { /* Yes, we did. */
  if (way >= 0) { /* Yes, we did. */
    immu_stats.fetch_tlbhit++;
    immu_stats.fetch_tlbhit++;
    TRACE("ITLB hit (virtaddr=%"PRIxADDR").\n", virtaddr);
    TRACE("ITLB hit (virtaddr=%"PRIxADDR").\n", virtaddr);
 
 
    /* Set LRUs */
    /* Set LRUs */
    for (i = 0; i < config.immu.nways; i++)
    for (i = 0; i < config.immu.nways; i++) {
      if (testsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_LRU))
      uorreg_t lru = cpu_state.sprs[SPR_ITLBMR_BASE(i) + set];
        setsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_LRU, getsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_LRU) - 1);
      if (lru & SPR_ITLBMR_LRU) {
    setsprbits(SPR_ITLBMR_BASE(way) + set, SPR_ITLBMR_LRU, config.immu.nsets - 1);
        lru = (lru & ~SPR_ITLBMR_LRU) | ((lru & SPR_ITLBMR_LRU) - 0x40);
 
        cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] = lru;
 
      }
 
    }
 
    cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] &= ~SPR_ITLBMR_LRU;
 
    cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] |= (config.immu.nsets - 1) << 6;
 
 
    /* Check if page is cache inhibited */
    /* Check if page is cache inhibited */
    insn_ci = (mfspr(SPR_ITLBTR_BASE(way) + set) & SPR_ITLBTR_CI) == SPR_ITLBTR_CI;
    insn_ci = (mfspr(SPR_ITLBTR_BASE(way) + set) & SPR_ITLBTR_CI) == SPR_ITLBTR_CI;
 
 
    runtime.sim.mem_cycles += config.immu.hitdelay;
    runtime.sim.mem_cycles += config.immu.hitdelay;
Line 99... Line 103...
  }
  }
  else {  /* No, we didn't. */
  else {  /* No, we didn't. */
    immu_stats.fetch_tlbmiss++;
    immu_stats.fetch_tlbmiss++;
#if 0
#if 0
    for (i = 0; i < config.immu.nways; i++)
    for (i = 0; i < config.immu.nways; i++)
      if (getsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_LRU) < minlru)
      if (((cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_LRU) >> 6) < minlru)
        minway = i;
        minway = i;
 
 
    setsprbits(SPR_ITLBMR_BASE(minway) + set, SPR_ITLBMR_VPN, vpn);
    cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] &= ~SPR_ITLBMR_VPN;
    for (i = 0; i < config.immu.nways; i++)
    cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= vpn << 12;
      if (testsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_LRU))
    for (i = 0; i < config.immu.nways; i++) {
        setsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_LRU, getsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_LRU) - 1);
      uorreg_t lru = cpu_state.sprs[SPR_ITLBMR_BASE(i) + set];
    setsprbits(SPR_ITLBMR_BASE(minway) + set, SPR_ITLBMR_LRU, config.immu.ustates - 1);
      if (lru & SPR_ITLBMR_LRU) {
    setsprbits(SPR_ITLBTR_BASE(minway) + set, SPR_ITLBTR_PPN, vpn); /* 1 to 1 */
        lru = (lru & ~SPR_ITLBMR_LRU) | ((lru & SPR_ITLBMR_LRU) - 0x40);
    setsprbits(SPR_ITLBMR_BASE(minway) + set, SPR_ITLBMR_V, 1);
        cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] = lru;
 
      }
 
    }
 
    cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] &= ~SPR_ITLBMR_LRU;
 
    cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] |= (config.immu.nsets - 1) << 6;
 
 
 
    /* 1 to 1 mapping */
 
    cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] &= ~SPR_ITLBTR_PPN;
 
    cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] |= vpn << 12;
 
 
 
    cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= SPR_ITLBMR_V;
#endif
#endif
 
 
    /* if tlb refill implemented in HW */
    /* if tlb refill implemented in HW */
    /* return getsprbits(SPR_ITLBTR_BASE(minway) + set, SPR_ITLBTR_PPN) * config.immu.pagesize + (virtaddr % config.immu.pagesize); */
    /* return ((cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] & SPR_ITLBTR_PPN) >> 12) * config.immu.pagesize + (virtaddr % config.immu.pagesize); */
    runtime.sim.mem_cycles += config.immu.missdelay;
    runtime.sim.mem_cycles += config.immu.missdelay;
 
 
    except_handle(EXCEPT_ITLBMISS, virtaddr);
    except_handle(EXCEPT_ITLBMISS, virtaddr);
    return 0;
    return 0;
  }
  }
Line 137... Line 151...
  int set, way = -1;
  int set, way = -1;
  int i;
  int i;
  oraddr_t tagaddr;
  oraddr_t tagaddr;
  oraddr_t vpn, ppn;
  oraddr_t vpn, ppn;
 
 
  if (!(mfspr(SPR_SR) & SPR_SR_IME) || !(testsprbits(SPR_UPR, SPR_UPR_IMP))) {
  if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) ||
 
      !(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) {
     return(virtaddr);
     return(virtaddr);
  }
  }
 
 
  /* Which set to check out? */
  /* Which set to check out? */
  set = (virtaddr / config.immu.pagesize) % config.immu.nsets;
  set = (virtaddr / config.immu.pagesize) % config.immu.nsets;
Line 149... Line 164...
  vpn = virtaddr / (config.immu.pagesize * config.immu.nsets);
  vpn = virtaddr / (config.immu.pagesize * config.immu.nsets);
 
 
  /* Scan all ways and try to find a matching way. */
  /* Scan all ways and try to find a matching way. */
  for (i = 0; i < config.immu.nways; i++)
  for (i = 0; i < config.immu.nways; i++)
    if (((mfspr(SPR_ITLBMR_BASE(i) + set) / (config.immu.pagesize * config.immu.nsets)) == vpn) &&
    if (((mfspr(SPR_ITLBMR_BASE(i) + set) / (config.immu.pagesize * config.immu.nsets)) == vpn) &&
        testsprbits(SPR_ITLBMR_BASE(i) + set, SPR_ITLBMR_V))
        (cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_V))
      way = i;
      way = i;
 
 
  /* Did we find our tlb entry? */
  /* Did we find our tlb entry? */
  if (way >= 0) { /* Yes, we did. */
  if (way >= 0) { /* Yes, we did. */
 
 
Line 188... Line 203...
 
 
/*  PRINTF("IMMU translate(%x) = %x\n", virtaddr, phyaddr);*/
/*  PRINTF("IMMU translate(%x) = %x\n", virtaddr, phyaddr);*/
  return phyaddr;
  return phyaddr;
}
}
 
 
void itlb_info()
void itlb_info(void)
{
{
  if (!testsprbits(SPR_UPR, SPR_UPR_IMP)) {
  if (!(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) {
    PRINTF("IMMU not implemented. Set UPR[IMP].\n");
    PRINTF("IMMU not implemented. Set UPR[IMP].\n");
    return;
    return;
  }
  }
 
 
  PRINTF("Insn MMU %dKB: ", config.immu.nsets * config.immu.entrysize * config.immu.nways / 1024);
  PRINTF("Insn MMU %dKB: ", config.immu.nsets * config.immu.entrysize * config.immu.nways / 1024);
Line 218... Line 233...
{
{
  int set;
  int set;
  int way;
  int way;
  int end_set = config.immu.nsets;
  int end_set = config.immu.nsets;
 
 
  if (!testsprbits(SPR_UPR, SPR_UPR_IMP)) {
  if (!(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) {
    PRINTF("IMMU not implemented. Set UPR[IMP].\n");
    PRINTF("IMMU not implemented. Set UPR[IMP].\n");
    return;
    return;
  }
  }
 
 
  if ((start_set >= 0) && (start_set < end_set))
  if ((start_set >= 0) && (start_set < end_set))
Line 252... Line 267...
}
}
 
 
/*---------------------------------------------------[ IMMU configuration ]---*/
/*---------------------------------------------------[ IMMU configuration ]---*/
void immu_enabled(union param_val val, void *dat)
void immu_enabled(union param_val val, void *dat)
{
{
  setsprbits (SPR_UPR, SPR_UPR_IMP, val.int_val ? 1 : 0);
  if(val.int_val)
 
    cpu_state.sprs[SPR_UPR] |= SPR_UPR_IMP;
 
  else
 
    cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_IMP;
  config.immu.enabled = val.int_val;
  config.immu.enabled = val.int_val;
}
}
 
 
void immu_nsets(union param_val val, void *dat)
void immu_nsets(union param_val val, void *dat)
{
{
  if (is_power2(val.int_val) && val.int_val <= 256) {
  if (is_power2(val.int_val) && val.int_val <= 256) {
    config.immu.nsets = val.int_val;
    config.immu.nsets = val.int_val;
    setsprbits (SPR_IMMUCFGR, SPR_IMMUCFGR_NTS, log2(val.int_val));
    cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTS;
 
    cpu_state.sprs[SPR_IMMUCFGR] |= log2(val.int_val) << 3;
  }
  }
  else
  else
    CONFIG_ERROR("value of power of two and lower or equal than 256 expected.");
    CONFIG_ERROR("value of power of two and lower or equal than 256 expected.");
}
}
 
 
void immu_nways(union param_val val, void *dat)
void immu_nways(union param_val val, void *dat)
{
{
  if (val.int_val >= 1 && val.int_val <= 4) {
  if (val.int_val >= 1 && val.int_val <= 4) {
    config.immu.nways = val.int_val;
    config.immu.nways = val.int_val;
    setsprbits (SPR_DMMUCFGR, SPR_DMMUCFGR_NTW, val.int_val-1);
    cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTW;
 
    cpu_state.sprs[SPR_IMMUCFGR] |= val.int_val - 1;
  }
  }
  else
  else
    CONFIG_ERROR("value 1, 2, 3 or 4 expected.");
    CONFIG_ERROR("value 1, 2, 3 or 4 expected.");
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.