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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [mmu/] [immu.c] - Diff between revs 1717 and 1748

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

Rev 1717 Rev 1748
Line 1... Line 1...
/* immu.c -- Instruction MMU simulation
/* immu.c -- Instruction MMU simulation
 
 
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
   Copyright (C) 2008 Embecosm Limited
 
 
 
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
 
 
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
   This program is free software; you can redistribute it and/or modify it
 
   under the terms of the GNU General Public License as published by the Free
 
   Software Foundation; either version 3 of the License, or (at your option)
 
   any later version.
 
 
This program is free software; you can redistribute it and/or modify
   This program is distributed in the hope that it will be useful, but WITHOUT
it under the terms of the GNU General Public License as published by
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
the Free Software Foundation; either version 2 of the License, or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
(at your option) any later version.
   more details.
 
 
This program is distributed in the hope that it will be useful,
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
GNU General Public License for more details.
 
 
 
You should have received a copy of the GNU General Public License
 
along with this program; if not, write to the Free Software
 
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
 
/* IMMU model, perfectly functional. */
   You should have received a copy of the GNU General Public License along
 
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 
/* This program is commented throughout in a fashion suitable for processing
 
   with Doxygen. */
 
 
 
 
 
/* Autoconf and/or portability configuration */
#include "config.h"
#include "config.h"
 
 
#ifdef HAVE_INTTYPES_H
/* System includes */
#include <inttypes.h>
#include <stdlib.h>
#endif
 
 
 
#include "port.h"
/* Package includes */
#include "arch.h"
 
#include "immu.h"
#include "immu.h"
#include "abstract.h"
#include "sim-config.h"
#include "opcode/or32.h"
 
#include "spr_defs.h"
 
#include "execute.h"
#include "execute.h"
 
#include "debug.h"
#include "stats.h"
#include "stats.h"
#include "sprs.h"
 
#include "except.h"
#include "except.h"
#include "sim-config.h"
#include "spr-dump.h"
#include "debug.h"
 
#include "misc.h"
#include "misc.h"
 
#include "sim-cmd.h"
 
 
 
 
DEFAULT_DEBUG_CHANNEL(immu);
DEFAULT_DEBUG_CHANNEL(immu);
 
 
struct immu *immu_state;
struct immu *immu_state;
 
 
/* Insn MMU */
/* Insn MMU */
 
 
static inline uorreg_t *immu_find_tlbmr(oraddr_t virtaddr,
static uorreg_t *
                                        uorreg_t **itlbmr_lru,
immu_find_tlbmr (oraddr_t virtaddr, uorreg_t ** itlbmr_lru, struct immu *immu)
                                        struct immu *immu)
 
{
{
  int set;
  int set;
  int i;
  int i;
  oraddr_t vpn;
  oraddr_t vpn;
  uorreg_t *itlbmr;
  uorreg_t *itlbmr;
Line 62... Line 64...
  itlbmr = &cpu_state.sprs[SPR_ITLBMR_BASE(0) + set];
  itlbmr = &cpu_state.sprs[SPR_ITLBMR_BASE(0) + set];
  *itlbmr_lru = itlbmr;
  *itlbmr_lru = itlbmr;
 
 
  /* Scan all ways and try to find a matching way. */
  /* Scan all ways and try to find a matching way. */
  /* FIXME: Should this be reversed? */
  /* FIXME: Should this be reversed? */
  for(i = immu->nways; i; i--, itlbmr += (128 * 2)) {
  for (i = immu->nways; i; i--, itlbmr += (128 * 2))
 
    {
    if(((*itlbmr & immu->vpn_mask) == vpn) && (*itlbmr & SPR_ITLBMR_V))
    if(((*itlbmr & immu->vpn_mask) == vpn) && (*itlbmr & SPR_ITLBMR_V))
      return itlbmr;
      return itlbmr;
  }
  }
 
 
  return NULL;
  return NULL;
}
}
 
 
oraddr_t immu_translate(oraddr_t virtaddr)
oraddr_t
 
immu_translate (oraddr_t virtaddr)
{
{
  int i;
  int i;
  uorreg_t *itlbmr;
  uorreg_t *itlbmr;
  uorreg_t *itlbtr;
  uorreg_t *itlbtr;
  uorreg_t *itlbmr_lru;
  uorreg_t *itlbmr_lru;
  struct immu *immu = immu_state;
  struct immu *immu = immu_state;
 
 
  if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) ||
  if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) ||
      !(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) {
      !(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP))
 
    {
    insn_ci = (virtaddr >= 0x80000000);
    insn_ci = (virtaddr >= 0x80000000);
    return virtaddr;
    return virtaddr;
  }
  }
 
 
  itlbmr = immu_find_tlbmr(virtaddr, &itlbmr_lru, immu);
  itlbmr = immu_find_tlbmr(virtaddr, &itlbmr_lru, immu);
 
 
  /* Did we find our tlb entry? */
  /* Did we find our tlb entry? */
  if(itlbmr) { /* Yes, we did. */
  if (itlbmr)
 
    {                           /* 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);
 
 
    itlbtr = itlbmr + 128;
    itlbtr = itlbmr + 128;
 
 
    /* Set LRUs */
    /* Set LRUs */
    for(i = 0; i < immu->nways; i++, itlbmr_lru += (128 * 2)) {
      for (i = 0; i < immu->nways; i++, itlbmr_lru += (128 * 2))
 
        {
      if(*itlbmr_lru & SPR_ITLBMR_LRU)
      if(*itlbmr_lru & SPR_ITLBMR_LRU)
        *itlbmr_lru = (*itlbmr_lru & ~SPR_ITLBMR_LRU) |
        *itlbmr_lru = (*itlbmr_lru & ~SPR_ITLBMR_LRU) |
                                        ((*itlbmr_lru & SPR_ITLBMR_LRU) - 0x40);
                                        ((*itlbmr_lru & SPR_ITLBMR_LRU) - 0x40);
    }
    }
 
 
Line 112... Line 119...
    insn_ci = *itlbtr & SPR_ITLBTR_CI;
    insn_ci = *itlbtr & SPR_ITLBTR_CI;
 
 
    runtime.sim.mem_cycles += immu->hitdelay;
    runtime.sim.mem_cycles += immu->hitdelay;
 
 
    /* Test for page fault */
    /* Test for page fault */
    if (cpu_state.sprs[SPR_SR] & SPR_SR_SM) {
      if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
 
        {
      if (!(*itlbtr & SPR_ITLBTR_SXE))
      if (!(*itlbtr & SPR_ITLBTR_SXE))
        except_handle(EXCEPT_IPF, virtaddr);
        except_handle(EXCEPT_IPF, virtaddr);
    } else {
        }
 
      else
 
        {
      if (!(*itlbtr & SPR_ITLBTR_UXE))
      if (!(*itlbtr & SPR_ITLBTR_UXE))
        except_handle(EXCEPT_IPF, virtaddr);
        except_handle(EXCEPT_IPF, virtaddr);
    }
    }
 
 
    TRACE("Returning physical address %"PRIxADDR"\n",
    TRACE("Returning physical address %"PRIxADDR"\n",
          (*itlbtr & SPR_ITLBTR_PPN) | (virtaddr & immu->page_offset_mask));
             (*itlbtr & SPR_ITLBTR_PPN) | (virtaddr & immu->
 
                                           page_offset_mask));
    return (*itlbtr & SPR_ITLBTR_PPN) | (virtaddr & immu->page_offset_mask);
    return (*itlbtr & SPR_ITLBTR_PPN) | (virtaddr & immu->page_offset_mask);
  }
  }
 
 
  /* No, we didn't. */
  /* No, we didn't. */
  immu_stats.fetch_tlbmiss++;
  immu_stats.fetch_tlbmiss++;
#if 0
#if 0
  for (i = 0; i < immu->nways; i++)
  for (i = 0; i < immu->nways; i++)
    if (((cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_LRU) >> 6) < minlru)
    if (((cpu_state.sprs[SPR_ITLBMR_BASE (i) + set] & SPR_ITLBMR_LRU) >> 6) <
 
        minlru)
      minway = i;
      minway = i;
 
 
  cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] &= ~SPR_ITLBMR_VPN;
  cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] &= ~SPR_ITLBMR_VPN;
  cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= vpn << 12;
  cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= vpn << 12;
  for (i = 0; i < immu->nways; i++) {
  for (i = 0; i < immu->nways; i++)
 
    {
    uorreg_t lru = cpu_state.sprs[SPR_ITLBMR_BASE(i) + set];
    uorreg_t lru = cpu_state.sprs[SPR_ITLBMR_BASE(i) + set];
    if (lru & SPR_ITLBMR_LRU) {
      if (lru & SPR_ITLBMR_LRU)
 
        {
      lru = (lru & ~SPR_ITLBMR_LRU) | ((lru & SPR_ITLBMR_LRU) - 0x40);
      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(i) + set] = lru;
    }
    }
  }
  }
  cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] &= ~SPR_ITLBMR_LRU;
  cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] &= ~SPR_ITLBMR_LRU;
Line 169... Line 183...
 *
 *
 * RTRN: 0         - no IMMU, IMMU disabled or ITLB miss
 * RTRN: 0         - no IMMU, IMMU disabled or ITLB miss
 *       else      - appropriate PA (note it IMMU is not present
 *       else      - appropriate PA (note it IMMU is not present
 *                   PA === EA)
 *                   PA === EA)
 */
 */
oraddr_t peek_into_itlb(oraddr_t virtaddr)
oraddr_t
 
peek_into_itlb (oraddr_t virtaddr)
{
{
  uorreg_t *itlbmr;
  uorreg_t *itlbmr;
  uorreg_t *itlbtr;
  uorreg_t *itlbtr;
  uorreg_t *itlbmr_lru;
  uorreg_t *itlbmr_lru;
  struct immu *immu = immu_state;
  struct immu *immu = immu_state;
 
 
  if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) ||
  if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) ||
      !(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) {
      !(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP))
 
    {
     return(virtaddr);
     return(virtaddr);
  }
  }
 
 
  itlbmr = immu_find_tlbmr(virtaddr, &itlbmr_lru, immu);
  itlbmr = immu_find_tlbmr(virtaddr, &itlbmr_lru, immu);
 
 
  /* Did we find our tlb entry? */
  /* Did we find our tlb entry? */
  if(itlbmr) { /* Yes, we did. */
  if (itlbmr)
 
    {                           /* Yes, we did. */
    itlbtr = itlbmr + 128;
    itlbtr = itlbmr + 128;
 
 
    /* Test for page fault */
    /* Test for page fault */
    if (cpu_state.sprs[SPR_SR] & SPR_SR_SM) {
      if (cpu_state.sprs[SPR_SR] & SPR_SR_SM)
      if (!(*itlbtr & SPR_ITLBTR_SXE)) {
        {
 
          if (!(*itlbtr & SPR_ITLBTR_SXE))
 
            {
        /* no luck, giving up */
        /* no luck, giving up */
        return(0);
        return(0);
      }
      }
    } else {
        }
      if (!(*itlbtr & SPR_ITLBTR_UXE)) {
      else
 
        {
 
          if (!(*itlbtr & SPR_ITLBTR_UXE))
 
            {
        /* no luck, giving up */
        /* no luck, giving up */
        return(0);
        return(0);
      }
      }
    }
    }
 
 
Line 221... Line 243...
    - find lru way and entry and invoke ITLB miss exception handler
    - find lru way and entry and invoke ITLB miss exception handler
    - set 'lru' with immu->ustates - 1 and decrement 'lru' of other
    - set 'lru' with immu->ustates - 1 and decrement 'lru' of other
      ways unless they have reached 0
      ways unless they have reached 0
*/
*/
 
 
static void itlb_status(void *dat)
static void
 
itlb_status (void *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
  int set;
  int set;
  int way;
  int way;
  int end_set = immu->nsets;
  int end_set = immu->nsets;
 
 
  if (!(cpu_state.sprs[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 (0 < end_set) PRINTF("\nIMMU: ");
  if (0 < end_set)
 
    PRINTF ("\nIMMU: ");
  /* Scan set(s) and way(s). */
  /* Scan set(s) and way(s). */
  for (set = 0; set < end_set; set++) {
  for (set = 0; set < end_set; set++)
    for (way = 0; way < immu->nways; way++) {
    {
 
      for (way = 0; way < immu->nways; way++)
 
        {
      PRINTF("%s\n", dump_spr(SPR_ITLBMR_BASE(way) + set,
      PRINTF("%s\n", dump_spr(SPR_ITLBMR_BASE(way) + set,
                              cpu_state.sprs[SPR_ITLBMR_BASE(way) + set]));
                                    cpu_state.sprs[SPR_ITLBMR_BASE (way) +
      PRINTF("%s\n", dump_spr(SPR_ITLBTR_BASE(way) + set,
                                                   set]));
 
          PRINTF ("%s\n",
 
                  dump_spr (SPR_ITLBTR_BASE (way) + set,
                              cpu_state.sprs[SPR_ITLBTR_BASE(way) + set]));
                              cpu_state.sprs[SPR_ITLBTR_BASE(way) + set]));
    }
    }
  }
  }
  if (0 < end_set) PRINTF("\n");
  if (0 < end_set)
 
    PRINTF ("\n");
}
}
 
 
/*---------------------------------------------------[ IMMU configuration ]---*/
/*---------------------------------------------------[ IMMU configuration ]---*/
static void immu_enabled(union param_val val, void *dat)
 
 
/*---------------------------------------------------------------------------*/
 
/*!Enable or disable the IMMU
 
 
 
   Set the corresponding field in the UPR
 
 
 
   @param[in] val  The value to use
 
   @param[in] dat  The config data structure                                 */
 
/*---------------------------------------------------------------------------*/
 
static void
 
immu_enabled (union param_val val, void *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  if(val.int_val)
  if(val.int_val)
 
    {
    cpu_state.sprs[SPR_UPR] |= SPR_UPR_IMP;
    cpu_state.sprs[SPR_UPR] |= SPR_UPR_IMP;
 
    }
  else
  else
 
    {
    cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_IMP;
    cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_IMP;
 
    }
 
 
  immu->enabled = val.int_val;
  immu->enabled = val.int_val;
}
}
 
 
static void immu_nsets(union param_val val, void *dat)
 
 
/*---------------------------------------------------------------------------*/
 
/*!Set the number of DMMU sets
 
 
 
   Value must be a power of 2 <= 256. Ignore any other values with a
 
   warning. Set the corresponding IMMU configuration flags.
 
 
 
   @param[in] val  The value to use
 
   @param[in] dat  The config data structure                                 */
 
/*---------------------------------------------------------------------------*/
 
static void
 
immu_nsets (union param_val  val,
 
            void            *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  if (is_power2(val.int_val) && val.int_val <= 256) {
  if (is_power2 (val.int_val) && (val.int_val <= 128))
 
    {
 
      int  set_bits = log2_int (val.int_val);
 
 
    immu->nsets = val.int_val;
    immu->nsets = val.int_val;
 
 
    cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTS;
    cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTS;
    cpu_state.sprs[SPR_IMMUCFGR] |= log2_int(val.int_val) << 3;
      cpu_state.sprs[SPR_IMMUCFGR] |= set_bits << SPR_IMMUCFGR_NTS_OFF;
  }
  }
  else
  else
    CONFIG_ERROR("value of power of two and lower or equal than 256 expected.");
    {
 
      fprintf (stderr, "Warning IMMU nsets not a power of 2 <= 128: ignored\n");
}
}
 
}       /* immu_nsets() */
 
 
static void immu_nways(union param_val val, void *dat)
 
 
/*---------------------------------------------------------------------------*/
 
/*!Set the number of IMMU ways
 
 
 
   Value must be in the range 1-4. Ignore other values with a warning.  Set
 
   the corresponding IMMU configuration flags.
 
 
 
   @param[in] val  The value to use
 
   @param[in] dat  The config data structure                                 */
 
/*---------------------------------------------------------------------------*/
 
static void
 
immu_nways (union param_val  val,
 
            void            *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  if (val.int_val >= 1 && val.int_val <= 4) {
  if (val.int_val >= 1 && val.int_val <= 4)
 
    {
 
      int  way_bits = val.int_val - 1;
 
 
    immu->nways = val.int_val;
    immu->nways = val.int_val;
 
 
    cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTW;
    cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTW;
    cpu_state.sprs[SPR_IMMUCFGR] |= val.int_val - 1;
      cpu_state.sprs[SPR_IMMUCFGR] |= way_bits << SPR_IMMUCFGR_NTW_OFF;
  }
  }
  else
  else
    CONFIG_ERROR("value 1, 2, 3 or 4 expected.");
    {
 
      fprintf (stderr, "Warning IMMU nways not in range 1-4: ignored\n");
}
}
 
}       /* immu_nways() */
 
 
 
 
 
/*---------------------------------------------------------------------------*/
 
/*!Set the IMMU page size
 
 
static void immu_pagesize(union param_val val, void *dat)
   Value must be a power of 2. Ignore other values with a warning
 
 
 
   @param[in] val  The value to use
 
   @param[in] dat  The config data structure                                 */
 
/*---------------------------------------------------------------------------*/
 
static void
 
immu_pagesize (union param_val  val,
 
               void            *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  if (is_power2(val.int_val))
  if (is_power2(val.int_val))
 
    {
    immu->pagesize = val.int_val;
    immu->pagesize = val.int_val;
 
    }
  else
  else
    CONFIG_ERROR("value of power of two expected.");
    {
 
      fprintf (stderr, "Warning IMMU page size must be power of 2: ignored\n");
}
}
 
}       /* immu_pagesize() */
 
 
 
 
 
/*---------------------------------------------------------------------------*/
 
/*!Set the IMMU entry size
 
 
static void immu_entrysize(union param_val val, void *dat)
   Value must be a power of 2. Ignore other values with a warning
 
 
 
   @param[in] val  The value to use
 
   @param[in] dat  The config data structure                                 */
 
/*---------------------------------------------------------------------------*/
 
static void
 
immu_entrysize (union param_val  val,
 
                void            *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  if (is_power2(val.int_val))
  if (is_power2(val.int_val))
 
    {
    immu->entrysize = val.int_val;
    immu->entrysize = val.int_val;
 
    }
  else
  else
    CONFIG_ERROR("value of power of two expected.");
    {
 
      fprintf (stderr, "Warning IMMU entry size must be power of 2: ignored\n");
}
}
 
}       /* immu_entrysize() */
 
 
 
 
 
/*---------------------------------------------------------------------------*/
 
/*!Set the number of IMMU usage states
 
 
static void immu_ustates(union param_val val, void *dat)
   Value must be 2, 3 or 4. Ignore other values with a warning
 
 
 
   @param[in] val  The value to use
 
   @param[in] dat  The config data structure                                 */
 
/*---------------------------------------------------------------------------*/
 
static void
 
immu_ustates (union param_val  val,
 
              void            *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  if (val.int_val >= 2 && val.int_val <= 4)
  if ((val.int_val >= 2) && (val.int_val <= 4))
 
    {
    immu->ustates = val.int_val;
    immu->ustates = val.int_val;
 
    }
  else
  else
    CONFIG_ERROR("invalid USTATE.");
    {
 
      fprintf (stderr, "Warning number of IMMU usage states must be 2, 3 or 4:"
 
               "ignored\n");
}
}
 
}       /* immu_ustates() */
 
 
 
 
static void immu_missdelay(union param_val val, void *dat)
static void
 
immu_missdelay (union param_val val, void *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  immu->missdelay = val.int_val;
  immu->missdelay = val.int_val;
}
}
 
 
static void immu_hitdelay(union param_val val, void *dat)
static void
 
immu_hitdelay (union param_val val, void *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  immu->hitdelay = val.int_val;
  immu->hitdelay = val.int_val;
}
}
 
 
static void *immu_start_sec(void)
/*---------------------------------------------------------------------------*/
 
/*!Initialize a new DMMU configuration
 
 
 
   ALL parameters are set explicitly to default values.                      */
 
/*---------------------------------------------------------------------------*/
 
static void *
 
immu_start_sec ()
{
{
  struct immu *immu;
  struct immu *immu;
 
  int          set_bits;
 
  int          way_bits;
 
 
  if(!(immu = malloc(sizeof(struct immu)))) {
  if (NULL == (immu = malloc (sizeof (struct immu))))
 
    {
    fprintf(stderr, "OOM\n");
    fprintf(stderr, "OOM\n");
    exit(1);
    exit(1);
  }
  }
 
 
  immu->enabled = 0;
  immu->enabled = 0;
 
  immu->nsets     = 1;
 
  immu->nways     = 1;
 
  immu->pagesize  = 8192;
 
  immu->entrysize = 1;          /* Not currently used */
 
  immu->ustates   = 2;
  immu->hitdelay = 1;
  immu->hitdelay = 1;
  immu->missdelay = 1;
  immu->missdelay = 1;
  immu->pagesize = 8192;
 
  /* FIXME: Something sane */
 
  immu->entrysize = 0;
 
 
 
  immu_state = immu;
  if (immu->enabled)
 
    {
 
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_IMP;
 
    }
 
  else
 
    {
 
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_IMP;
 
    }
 
 
 
  set_bits = log2_int (immu->nsets);
 
  cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTS;
 
  cpu_state.sprs[SPR_IMMUCFGR] |= set_bits << SPR_IMMUCFGR_NTS_OFF;
 
 
 
  way_bits = immu->nways - 1;
 
  cpu_state.sprs[SPR_IMMUCFGR] &= ~SPR_IMMUCFGR_NTW;
 
  cpu_state.sprs[SPR_IMMUCFGR] |= way_bits << SPR_IMMUCFGR_NTW_OFF;
 
 
 
  immu_state = immu;
  return immu;
  return immu;
}
 
 
 
static void immu_end_sec(void *dat)
}       /* immu_start_sec() */
 
 
 
 
 
static void
 
immu_end_sec (void *dat)
{
{
  struct immu *immu = dat;
  struct immu *immu = dat;
 
 
  /* Precalculate some values for use during address translation */
  /* Precalculate some values for use during address translation */
  immu->pagesize_log2 = log2_int(immu->pagesize);
  immu->pagesize_log2 = log2_int(immu->pagesize);
Line 361... Line 521...
  immu->page_mask = ~immu->page_offset_mask;
  immu->page_mask = ~immu->page_offset_mask;
  immu->vpn_mask = ~((immu->pagesize * immu->nsets) - 1);
  immu->vpn_mask = ~((immu->pagesize * immu->nsets) - 1);
  immu->set_mask = immu->nsets - 1;
  immu->set_mask = immu->nsets - 1;
  immu->lru_reload = (immu->set_mask << 6) & SPR_ITLBMR_LRU;
  immu->lru_reload = (immu->set_mask << 6) & SPR_ITLBMR_LRU;
 
 
  if(immu->enabled) {
  if (immu->enabled)
 
    {
    PRINTF("Insn MMU %dKB: %d ways, %d sets, entry size %d bytes\n",
    PRINTF("Insn MMU %dKB: %d ways, %d sets, entry size %d bytes\n",
           immu->nsets * immu->entrysize * immu->nways / 1024, immu->nways,
           immu->nsets * immu->entrysize * immu->nways / 1024, immu->nways,
           immu->nsets, immu->entrysize);
           immu->nsets, immu->entrysize);
    reg_sim_stat(itlb_status, immu);
    reg_sim_stat(itlb_status, immu);
  }
  }
}
}
 
 
void reg_immu_sec(void)
void
 
reg_immu_sec (void)
{
{
  struct config_section *sec = reg_config_sec("immu", immu_start_sec,
  struct config_section *sec = reg_config_sec("immu", immu_start_sec,
                                              immu_end_sec);
                                              immu_end_sec);
 
 
  reg_config_param(sec, "enabled", paramt_int, immu_enabled);
  reg_config_param(sec, "enabled", paramt_int, immu_enabled);

powered by: WebSVN 2.1.0

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