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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [testbench/] [mmu.c] - Diff between revs 448 and 457

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 448 Rev 457
/* This is MMU test for OpenRISC 1200 */
/* This is MMU test for OpenRISC 1200 */
 
 
#include "spr_defs.h"
#include "spr_defs.h"
#include "support.h"
#include "support.h"
 
 
/* Define RAM physical location and size
/* Define RAM physical location and size
   Bottom half will be used for this program, the rest
   Bottom half will be used for this program, the rest
   will be used for testing */
   will be used for testing */
#define FLASH_START 0x00000000
#define FLASH_START 0x00000000
#define FLASH_SIZE  0x00200000
#define FLASH_SIZE  0x00200000
#define RAM_START   0x40000000
#define RAM_START   0x40000000
#define RAM_SIZE    0x00200000
#define RAM_SIZE    0x00200000
 
 
/* What is the last address in ram that is used by this program */
/* What is the last address in ram that is used by this program */
#define TEXT_END_ADD (FLASH_START + (FLASH_SIZE / 2))
#define TEXT_END_ADD (FLASH_START + (FLASH_SIZE / 2))
#define DATA_END_ADD (RAM_START + (RAM_SIZE / 2))
#define DATA_END_ADD (RAM_START + (RAM_SIZE / 2))
 
 
#define TLB_TEXT_SET_NB 6
#define TLB_TEXT_SET_NB 6
#define TLB_DATA_SET_NB 2
#define TLB_DATA_SET_NB 2
 
 
/* MMU page size */
/* MMU page size */
#define PAGE_SIZE 4096
#define PAGE_SIZE 8192
 
 
/* Number of DTLB sets used (power of 2, max is 256) */
/* Number of DTLB sets used (power of 2, max is 256) */
#define DTLB_SETS 32
#define DTLB_SETS 32
 
 
/* Number of DTLB ways (1, 2, 3 etc., max is 4). */
/* Number of DTLB ways (1, 2, 3 etc., max is 4). */
#define DTLB_WAYS 1
#define DTLB_WAYS 1
 
 
/* Number of ITLB sets used (power of 2, max is 256) */
/* Number of ITLB sets used (power of 2, max is 256) */
#define ITLB_SETS 32
#define ITLB_SETS 32
 
 
/* Number of ITLB ways (1, 2, 3 etc., max is 4). */
/* Number of ITLB ways (1, 2, 3 etc., max is 4). */
#define ITLB_WAYS 1
#define ITLB_WAYS 1
 
 
/* TLB mode codes */
/* TLB mode codes */
#define TLB_CODE_ONE_TO_ONE     0x00000000
#define TLB_CODE_ONE_TO_ONE     0x00000000
#define TLB_CODE_PLUS_ONE_PAGE  0x10000000
#define TLB_CODE_PLUS_ONE_PAGE  0x10000000
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
 
 
#define TLB_CODE_MASK   0xfffff000
#define TLB_CODE_MASK   0xfffff000
#define TLB_PR_MASK     0x00000fff
#define TLB_PR_MASK     0x00000fff
#define DTLB_PR_NOLIMIT  ( SPR_DTLBTR_CI   | \
#define DTLB_PR_NOLIMIT  ( SPR_DTLBTR_CI   | \
                          SPR_DTLBTR_URE  | \
                          SPR_DTLBTR_URE  | \
                          SPR_DTLBTR_UWE  | \
                          SPR_DTLBTR_UWE  | \
                          SPR_DTLBTR_SRE  | \
                          SPR_DTLBTR_SRE  | \
                          SPR_DTLBTR_SWE  )
                          SPR_DTLBTR_SWE  )
 
 
#define ITLB_PR_NOLIMIT  ( SPR_ITLBTR_CI   | \
#define ITLB_PR_NOLIMIT  ( SPR_ITLBTR_CI   | \
                          SPR_ITLBTR_SXE  | \
                          SPR_ITLBTR_SXE  | \
                          SPR_ITLBTR_UXE  )
                          SPR_ITLBTR_UXE  )
 
 
#if 1
#if 1
#define debug printf
#define debug printf
#else
#else
#define debug
#define debug
#endif
#endif
 
 
/* fails if x is false */
/* fails if x is false */
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
 
 
//#define TEST_JUMP(x) testjump( ((x) & (RAM_SIZE/2 - 1)) + DATA_END_ADD, (x))
//#define TEST_JUMP(x) testjump( ((x) & (RAM_SIZE/2 - 1)) + DATA_END_ADD, (x))
#define TEST_JUMP(x) copy_jump (((x) & (RAM_SIZE/2 - 1)) + DATA_END_ADD); call (x)
#define TEST_JUMP(x) copy_jump (((x) & (RAM_SIZE/2 - 1)) + DATA_END_ADD); call (x)
 
 
/* Extern functions */
/* Extern functions */
extern void lo_dmmu_en (void);
extern void lo_dmmu_en (void);
extern void lo_immu_en (void);
extern void lo_immu_en (void);
extern void testjump(unsigned long phy_addr, unsigned long virt_addr);
extern void testjump(unsigned long phy_addr, unsigned long virt_addr);
extern void (*jr)(void);
extern void (*jr)(void);
 
 
/* Local functions prototypes */
/* Local functions prototypes */
void dmmu_disable (void);
void dmmu_disable (void);
void immu_disable (void);
void immu_disable (void);
 
 
/* Global variables */
/* Global variables */
extern unsigned long ram_end;
extern unsigned long ram_end;
 
 
/* DTLB mode status */
/* DTLB mode status */
volatile unsigned long dtlb_val;
volatile unsigned long dtlb_val;
 
 
/* ITLB mode status */
/* ITLB mode status */
volatile unsigned long itlb_val;
volatile unsigned long itlb_val;
 
 
/* DTLB miss counter */
/* DTLB miss counter */
volatile int dtlb_miss_count;
volatile int dtlb_miss_count;
 
 
/* Data page fault counter */
/* Data page fault counter */
volatile int dpage_fault_count;
volatile int dpage_fault_count;
 
 
/* ITLB miss counter */
/* ITLB miss counter */
volatile int itlb_miss_count;
volatile int itlb_miss_count;
 
 
/* Instruction page fault counter */
/* Instruction page fault counter */
volatile int ipage_fault_count;
volatile int ipage_fault_count;
 
 
/* EA of last DTLB miss exception */
/* EA of last DTLB miss exception */
unsigned long dtlb_miss_ea;
unsigned long dtlb_miss_ea;
 
 
/* EA of last data page fault exception */
/* EA of last data page fault exception */
unsigned long dpage_fault_ea;
unsigned long dpage_fault_ea;
 
 
/* EA of last ITLB miss exception */
/* EA of last ITLB miss exception */
unsigned long itlb_miss_ea;
unsigned long itlb_miss_ea;
 
 
/* EA of last insn page fault exception */
/* EA of last insn page fault exception */
unsigned long ipage_fault_ea;
unsigned long ipage_fault_ea;
 
 
 
void sys_call (void)
 
{
 
  asm("l.sys\t0");
 
}
 
 
void fail (char *func, int line)
void fail (char *func, int line)
{
{
#ifndef __FUNCTION__
#ifndef __FUNCTION__
#define __FUNCTION__ "?"
#define __FUNCTION__ "?"
#endif
#endif
 
 
  /* Trigger sys call exception to enable supervisor mode again */
  /* Trigger sys call exception to enable supervisor mode again */
  sys_call ();
  sys_call ();
 
 
  immu_disable ();
  immu_disable ();
  dmmu_disable ();
  dmmu_disable ();
 
 
  debug("Test failed in %s:%i\n", func, line);
  debug("Test failed in %s:%i\n", func, line);
  report (0xeeeeeeee);
  report (0xeeeeeeee);
  exit (1);
  exit (1);
}
}
 
 
void call(unsigned long add)
void call(unsigned long add)
{
{
        asm("l.jalr\t\t%0" : : "r" (add) : "r9", "r11");
        asm("l.jalr\t\t%0" : : "r" (add) : "r9", "r11");
        asm("l.nop" : :);
        asm("l.nop" : :);
}
}
 
 
void jump(void)
void jump(void)
{
{
        asm("_jr:");
        asm("_jr:");
        asm("l.jr\t\tr9") ;
        asm("l.jr\t\tr9") ;
        asm("l.nop" : :);
        asm("l.nop" : :);
}
}
 
 
void sys_call (void)
 
{
 
  asm("l.sys\t0");
 
}
 
 
 
void copy_jump(unsigned long phy_add)
void copy_jump(unsigned long phy_add)
{
{
        memcpy((void *)phy_add, (void *)&jr, 8);
        memcpy((void *)phy_add, (void *)&jr, 8);
}
}
 
 
/* Bus error exception handler */
/* Bus error exception handler */
void bus_err_handler (void)
void bus_err_handler (void)
{
{
  /* This shouldn't happend */
  /* This shouldn't happend */
  debug("Test failed: Bus error\n");
  debug("Test failed: Bus error\n");
  report (0xeeeeeeee);
  report (0xeeeeeeee);
  exit (1);
  exit (1);
}
}
 
 
/* Illegal insn exception handler */
/* Illegal insn exception handler */
void ill_insn_handler (void)
void ill_insn_handler (void)
{
{
  /* This shouldn't happend */
  /* This shouldn't happend */
  debug("Test failed: Illegal insn\n");
  debug("Test failed: Illegal insn\n");
  report (0xeeeeeeee);
  report (0xeeeeeeee);
  exit (1);
  exit (1);
}
}
 
 
/* Sys call exception handler */
/* Sys call exception handler */
void sys_call_handler (void)
void sys_call_handler (void)
{
{
  /* Set supervisor mode */
  /* Set supervisor mode */
  mtspr (SPR_ESR_BASE, mfspr (SPR_ESR_BASE) | SPR_SR_SUPV);
  mtspr (SPR_ESR_BASE, mfspr (SPR_ESR_BASE) | SPR_SR_SUPV);
}
}
 
 
/* DTLB miss exception handler */
/* DTLB miss exception handler */
void dtlb_miss_handler (void)
void dtlb_miss_handler (void)
{
{
  unsigned long ea, ta, tlbtr;
  unsigned long ea, ta, tlbtr;
  int set, way = 0;
  int set, way = 0;
  int i;
  int i;
 
 
  /* Get EA that cause the exception */
  /* Get EA that cause the exception */
  ea = mfspr (SPR_EEAR_BASE);
  ea = mfspr (SPR_EEAR_BASE);
 
 
  /* Find TLB set and LRU way */
  /* Find TLB set and LRU way */
  set = (ea / PAGE_SIZE) % DTLB_SETS;
  set = (ea / PAGE_SIZE) % DTLB_SETS;
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_LRU) == 0) {
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_LRU) == 0) {
      way = i;
      way = i;
      break;
      break;
    }
    }
  }
  }
 
 
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  if (((RAM_START <= ea) && (ea < DATA_END_ADD) ) || ((FLASH_START <= ea) && (ea < TEXT_END_ADD))) {
  if (((RAM_START <= ea) && (ea < DATA_END_ADD) ) || ((FLASH_START <= ea) && (ea < TEXT_END_ADD))) {
    /* If this is acces to data of this program set one to one translation */
    /* If this is acces to data of this program set one to one translation */
    mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | DTLB_PR_NOLIMIT);
    return;
    return;
  }
  }
 
 
  /* Update DTLB miss counter and EA */
  /* Update DTLB miss counter and EA */
  dtlb_miss_count++;
  dtlb_miss_count++;
  dtlb_miss_ea = ea;
  dtlb_miss_ea = ea;
 
 
  /* Whatever access is in progress, translated address have to point to physical RAM */
  /* Whatever access is in progress, translated address have to point to physical RAM */
  ta = (ea & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2);
  ta = (ea & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2);
  tlbtr = (ta & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
  tlbtr = (ta & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
  debug("tlbtr = %.8lx dtlb_val = %.8lx\n", tlbtr, dtlb_val);
  debug("tlbtr = %.8lx dtlb_val = %.8lx\n", tlbtr, dtlb_val);
 
 
  /* Set DTLB entry */
  /* Set DTLB entry */
  mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
  mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
  mtspr (SPR_DTLBTR_BASE(way) + set, tlbtr);
  mtspr (SPR_DTLBTR_BASE(way) + set, tlbtr);
}
}
 
 
/* Data page fault exception handler */
/* Data page fault exception handler */
void dpage_fault_handler (void)
void dpage_fault_handler (void)
{
{
  unsigned long ea;
  unsigned long ea;
  int set, way = 0;
  int set, way = 0;
  int i;
  int i;
 
 
  /* Get EA that cause the exception */
  /* Get EA that cause the exception */
  ea = mfspr (SPR_EEAR_BASE);
  ea = mfspr (SPR_EEAR_BASE);
 
 
  /* Find TLB set and way */
  /* Find TLB set and way */
  set = (ea / PAGE_SIZE) % DTLB_SETS;
  set = (ea / PAGE_SIZE) % DTLB_SETS;
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_VPN) == (ea & SPR_DTLBMR_VPN)) {
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_VPN) == (ea & SPR_DTLBMR_VPN)) {
      way = i;
      way = i;
      break;
      break;
    }
    }
  }
  }
 
 
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  if (((RAM_START <= ea) && (ea < DATA_END_ADD) ) || ((FLASH_START <= ea) && (ea < TEXT_END_ADD))) {
  if (((RAM_START <= ea) && (ea < DATA_END_ADD) ) || ((FLASH_START <= ea) && (ea < TEXT_END_ADD))) {
    /* If this is acces to data of this program set one to one translation */
    /* If this is acces to data of this program set one to one translation */
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | DTLB_PR_NOLIMIT);
    return;
    return;
  }
  }
 
 
  /* Update data page fault counter and EA */
  /* Update data page fault counter and EA */
  dpage_fault_count++;
  dpage_fault_count++;
  dpage_fault_ea = ea;
  dpage_fault_ea = ea;
 
 
  /* Give permission */
  /* Give permission */
  mtspr (SPR_DTLBTR_BASE(way) + set, (mfspr (SPR_DTLBTR_BASE(way) + set) & ~DTLB_PR_NOLIMIT) | dtlb_val);
  mtspr (SPR_DTLBTR_BASE(way) + set, (mfspr (SPR_DTLBTR_BASE(way) + set) & ~DTLB_PR_NOLIMIT) | dtlb_val);
}
}
 
 
 
 
/* ITLB miss exception handler */
/* ITLB miss exception handler */
void itlb_miss_handler (void)
void itlb_miss_handler (void)
{
{
  unsigned long ea, ta, tlbtr;
  unsigned long ea, ta, tlbtr;
  int set, way = 0;
  int set, way = 0;
  int i;
  int i;
 
 
  /* Get EA that cause the exception */
  /* Get EA that cause the exception */
  ea = mfspr (SPR_EPCR_BASE);
  ea = mfspr (SPR_EPCR_BASE);
 
 
  /* Find TLB set and LRU way */
  /* Find TLB set and LRU way */
  set = (ea / PAGE_SIZE) % ITLB_SETS;
  set = (ea / PAGE_SIZE) % ITLB_SETS;
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_LRU) == 0) {
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_LRU) == 0) {
      way = i;
      way = i;
      break;
      break;
    }
    }
  }
  }
 
 
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  if ((FLASH_START <= ea) && (ea < TEXT_END_ADD)) {
  if ((FLASH_START <= ea) && (ea < TEXT_END_ADD)) {
    /* If this is acces to data of this program set one to one translation */
    /* If this is acces to data of this program set one to one translation */
    mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(way) + set, (ea & SPR_ITLBTR_PPN) | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(way) + set, (ea & SPR_ITLBTR_PPN) | ITLB_PR_NOLIMIT);
    return;
    return;
  }
  }
 
 
  /* Update ITLB miss counter and EA */
  /* Update ITLB miss counter and EA */
  itlb_miss_count++;
  itlb_miss_count++;
  itlb_miss_ea = ea;
  itlb_miss_ea = ea;
 
 
  /* Whatever access is in progress, translated address have to point to physical RAM */
  /* Whatever access is in progress, translated address have to point to physical RAM */
  ta = (ea & ((RAM_SIZE/2) - 1)) + DATA_END_ADD;
  ta = (ea & ((RAM_SIZE/2) - 1)) + DATA_END_ADD;
  tlbtr = (ta & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
  tlbtr = (ta & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
 
 
  debug("ta = %.8lx\n", ta);
  debug("ta = %.8lx\n", ta);
 
 
  /* Set ITLB entry */
  /* Set ITLB entry */
  mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
  mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
  mtspr (SPR_ITLBTR_BASE(way) + set, tlbtr);
  mtspr (SPR_ITLBTR_BASE(way) + set, tlbtr);
}
}
 
 
/* Intstruction page fault exception handler */
/* Intstruction page fault exception handler */
void ipage_fault_handler (void)
void ipage_fault_handler (void)
{
{
  unsigned long ea;
  unsigned long ea;
  int set, way = 0;
  int set, way = 0;
  int i;
  int i;
 
 
  /* Get EA that cause the exception */
  /* Get EA that cause the exception */
  ea = mfspr (SPR_EPCR_BASE);
  ea = mfspr (SPR_EPCR_BASE);
 
 
  /* Find TLB set and way */
  /* Find TLB set and way */
  set = (ea / PAGE_SIZE) % ITLB_SETS;
  set = (ea / PAGE_SIZE) % ITLB_SETS;
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_VPN) == (ea & SPR_ITLBMR_VPN)) {
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_VPN) == (ea & SPR_ITLBMR_VPN)) {
      way = i;
      way = i;
      break;
      break;
    }
    }
  }
  }
 
 
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
  debug("ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  if ((FLASH_START <= ea) && (ea < TEXT_END_ADD)) {
  if ((FLASH_START <= ea) && (ea < TEXT_END_ADD)) {
    /* If this is acces to data of this program set one to one translation */
    /* If this is acces to data of this program set one to one translation */
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | ITLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | ITLB_PR_NOLIMIT);
    return;
    return;
  }
  }
 
 
  /* Update instruction page fault counter and EA */
  /* Update instruction page fault counter and EA */
  ipage_fault_count++;
  ipage_fault_count++;
  ipage_fault_ea = ea;
  ipage_fault_ea = ea;
 
 
  /* Give permission */
  /* Give permission */
  mtspr (SPR_ITLBTR_BASE(way) + set, (mfspr (SPR_ITLBTR_BASE(way) + set) & ~ITLB_PR_NOLIMIT) | itlb_val);
  mtspr (SPR_ITLBTR_BASE(way) + set, (mfspr (SPR_ITLBTR_BASE(way) + set) & ~ITLB_PR_NOLIMIT) | itlb_val);
}
}
 
 
/* Invalidate all entries in DTLB and enable DMMU */
/* Invalidate all entries in DTLB and enable DMMU */
void dmmu_enable (void)
void dmmu_enable (void)
{
{
  /* Register DTLB miss handler */
  /* Register DTLB miss handler */
  excpt_dtlbmiss = (unsigned long)dtlb_miss_handler;
  excpt_dtlbmiss = (unsigned long)dtlb_miss_handler;
 
 
  /* Register data page fault handler */
  /* Register data page fault handler */
  excpt_dpfault = (unsigned long)dpage_fault_handler;
  excpt_dpfault = (unsigned long)dpage_fault_handler;
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  lo_dmmu_en ();
  lo_dmmu_en ();
}
}
 
 
/* Disable DMMU */
/* Disable DMMU */
void dmmu_disable (void)
void dmmu_disable (void)
{
{
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_DME);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_DME);
}
}
 
 
/* Invalidate all entries in ITLB and enable IMMU */
/* Invalidate all entries in ITLB and enable IMMU */
void immu_enable (void)
void immu_enable (void)
{
{
  /* Register ITLB miss handler */
  /* Register ITLB miss handler */
  excpt_itlbmiss = (unsigned long)itlb_miss_handler;
  excpt_itlbmiss = (unsigned long)itlb_miss_handler;
 
 
  /* Register instruction page fault handler */
  /* Register instruction page fault handler */
  excpt_ipfault = (unsigned long)ipage_fault_handler;
  excpt_ipfault = (unsigned long)ipage_fault_handler;
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  lo_immu_en ();
  lo_immu_en ();
}
}
 
 
/* Disable IMMU */
/* Disable IMMU */
void immu_disable (void)
void immu_disable (void)
{
{
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_IME);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_IME);
}
}
 
 
void write_pattern(unsigned long start, unsigned long end)
void write_pattern(unsigned long start, unsigned long end)
{
{
  unsigned long add;
  unsigned long add;
 
 
  add = start;
  add = start;
  while (add < end) {
  while (add < end) {
    REG32(add) = add;
    REG32(add) = add;
    add += PAGE_SIZE;
    add += PAGE_SIZE;
  }
  }
 
 
}
}
 
 
/* Translation address register test
/* Translation address register test
   Set various translation and check the pattern */
   Set various translation and check the pattern */
int dtlb_translation_test (void)
int dtlb_translation_test (void)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta;
  unsigned long ea, ta;
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  /* Invalidate all entries in DTLB */
  /* Invalidate all entries in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    for (j = 0; j < DTLB_SETS; j++) {
    for (j = 0; j < DTLB_SETS; j++) {
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
  }
  }
 
 
  /* Set dtlb permisions */
  /* Set dtlb permisions */
  dtlb_val = DTLB_PR_NOLIMIT;
  dtlb_val = DTLB_PR_NOLIMIT;
 
 
  /* Write test pattern */
  /* Write test pattern */
  for (i = 0; i < DTLB_SETS; i++) {
  for (i = 0; i < DTLB_SETS; i++) {
    REG32(RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE)) = i;
    REG32(RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE)) = i;
    REG32(RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4) = 0xffffffff - i;
    REG32(RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4) = 0xffffffff - i;
  }
  }
 
 
  /* Set one to one translation of the last way of DTLB */
  /* Set one to one translation of the last way of DTLB */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
  }
  }
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  dmmu_enable();
  dmmu_enable();
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ASSERT(REG32(ea) == i);
    ASSERT(REG32(ea) == i);
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    ASSERT(REG32(ea) == (0xffffffff - i));
    ASSERT(REG32(ea) == (0xffffffff - i));
  }
  }
 
 
  /* Write new pattern */
  /* Write new pattern */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    REG32(RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE)) = 0xffffffff - i;
    REG32(RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE)) = 0xffffffff - i;
    REG32(RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4) = i;
    REG32(RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4) = i;
  }
  }
 
 
  /* Set 0 -> RAM_START + (RAM_SIZE/2) translation */
  /* Set 0 -> RAM_START + (RAM_SIZE/2) translation */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    ea = i*PAGE_SIZE;
    ea = i*PAGE_SIZE;
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
  }
  }
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    ea = i*PAGE_SIZE;
    ea = i*PAGE_SIZE;
    ASSERT(REG32(ea) == (0xffffffff - i));
    ASSERT(REG32(ea) == (0xffffffff - i));
    ea = ((i + 1)*PAGE_SIZE) - 4;
    ea = ((i + 1)*PAGE_SIZE) - 4;
    ASSERT(REG32(ea) == i);
    ASSERT(REG32(ea) == i);
  }
  }
 
 
  /* Write new pattern */
  /* Write new pattern */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    REG32(i*PAGE_SIZE) = i;
    REG32(i*PAGE_SIZE) = i;
    REG32(((i + 1)*PAGE_SIZE) - 4) = 0xffffffff - i;
    REG32(((i + 1)*PAGE_SIZE) - 4) = 0xffffffff - i;
  }
  }
 
 
  /* Set hi -> lo, lo -> hi translation */
  /* Set hi -> lo, lo -> hi translation */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + ((DTLB_SETS - i - 1 + TLB_DATA_SET_NB)*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + ((DTLB_SETS - i - 1 + TLB_DATA_SET_NB)*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
  }
  }
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ASSERT(REG32(ea) == (DTLB_SETS - i - 1 + TLB_DATA_SET_NB));
    ASSERT(REG32(ea) == (DTLB_SETS - i - 1 + TLB_DATA_SET_NB));
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    ASSERT(REG32(ea) == (0xffffffff - DTLB_SETS + i + 1 - TLB_DATA_SET_NB));
    ASSERT(REG32(ea) == (0xffffffff - DTLB_SETS + i + 1 - TLB_DATA_SET_NB));
  }
  }
 
 
  /* Write new pattern */
  /* Write new pattern */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    REG32(RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE)) = 0xffffffff - i;
    REG32(RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE)) = 0xffffffff - i;
    REG32(RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4) = i;
    REG32(RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4) = i;
  }
  }
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ASSERT(REG32(ea) == (0xffffffff - DTLB_SETS + i + 1 - TLB_DATA_SET_NB));
    ASSERT(REG32(ea) == (0xffffffff - DTLB_SETS + i + 1 - TLB_DATA_SET_NB));
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    ASSERT(REG32(ea) == (DTLB_SETS - i - 1 + TLB_DATA_SET_NB));
    ASSERT(REG32(ea) == (DTLB_SETS - i - 1 + TLB_DATA_SET_NB));
  }
  }
 
 
  return 0;
  return 0;
}
}
 
 
/* EA match register test
/* EA match register test
   Shifting one in DTLBMR and performing accesses to boundaries
   Shifting one in DTLBMR and performing accesses to boundaries
   of the page, checking the triggering of exceptions */
   of the page, checking the triggering of exceptions */
int dtlb_match_test (int way, int set)
int dtlb_match_test (int way, int set)
{
{
  int i, j, tmp;
  int i, j, tmp;
  unsigned long add, t_add;
  unsigned long add, t_add;
  unsigned long ea, ta;
  unsigned long ea, ta;
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  /* Invalidate all entries in DTLB */
  /* Invalidate all entries in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    for (j = 0; j < DTLB_SETS; j++) {
    for (j = 0; j < DTLB_SETS; j++) {
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
  }
  }
 
 
  /* Set dtlb permisions */
  /* Set dtlb permisions */
  dtlb_val = DTLB_PR_NOLIMIT;
  dtlb_val = DTLB_PR_NOLIMIT;
 
 
  /* Set pattern */
  /* Set pattern */
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) - 4) = 0x00112233;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) - 4) = 0x00112233;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE)) = 0x44556677;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE)) = 0x44556677;
  REG32(RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE - 4) = 0x8899aabb;
  REG32(RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE - 4) = 0x8899aabb;
  REG32(RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE) = 0xccddeeff;
  REG32(RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE) = 0xccddeeff;
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  dmmu_enable();
  dmmu_enable();
 
 
  /* Shifting one in DTLBMR */
  /* Shifting one in DTLBMR */
  i = 0;
  i = 0;
  add = (PAGE_SIZE*DTLB_SETS);
  add = (PAGE_SIZE*DTLB_SETS);
  t_add = add + (set*PAGE_SIZE);
  t_add = add + (set*PAGE_SIZE);
  while (add != 0x00000000) {
  while (add != 0x00000000) {
    mtspr (SPR_DTLBMR_BASE(way) + set, t_add | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(way) + set, t_add | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(way) + set, (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE)) | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(way) + set, (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE)) | DTLB_PR_NOLIMIT);
 
 
    /* Reset DTLB miss counter and EA */
    /* Reset DTLB miss counter and EA */
    dtlb_miss_count = 0;
    dtlb_miss_count = 0;
    dtlb_miss_ea = 0;
    dtlb_miss_ea = 0;
 
 
    if (((t_add < RAM_START) || (t_add >= DATA_END_ADD)) && ((t_add < FLASH_START) || (t_add >= TEXT_END_ADD))) {
    if (((t_add < RAM_START) || (t_add >= DATA_END_ADD)) && ((t_add < FLASH_START) || (t_add >= TEXT_END_ADD))) {
 
 
      /* Read last address of previous page */
      /* Read last address of previous page */
      tmp = REG32(t_add - 4);
      tmp = REG32(t_add - 4);
      ASSERT(tmp == 0x00112233);
      ASSERT(tmp == 0x00112233);
      ASSERT(dtlb_miss_count == 1);
      ASSERT(dtlb_miss_count == 1);
 
 
      /* Read first address of the page */
      /* Read first address of the page */
      tmp = REG32(t_add);
      tmp = REG32(t_add);
      ASSERT(tmp == 0x44556677);
      ASSERT(tmp == 0x44556677);
      ASSERT(dtlb_miss_count == 1);
      ASSERT(dtlb_miss_count == 1);
 
 
      /* Read last address of the page */
      /* Read last address of the page */
      tmp = REG32(t_add + PAGE_SIZE - 4);
      tmp = REG32(t_add + PAGE_SIZE - 4);
      ASSERT(tmp == 0x8899aabb);
      ASSERT(tmp == 0x8899aabb);
      ASSERT(dtlb_miss_count == 1);
      ASSERT(dtlb_miss_count == 1);
 
 
      /* Read first address of next page */
      /* Read first address of next page */
      tmp = REG32(t_add + PAGE_SIZE);
      tmp = REG32(t_add + PAGE_SIZE);
      ASSERT(tmp == 0xccddeeff);
      ASSERT(tmp == 0xccddeeff);
      ASSERT(dtlb_miss_count == 2);
      ASSERT(dtlb_miss_count == 2);
    }
    }
 
 
    i++;
    i++;
    add = (PAGE_SIZE*DTLB_SETS) << i;
    add = (PAGE_SIZE*DTLB_SETS) << i;
    t_add = add + (set*PAGE_SIZE);
    t_add = add + (set*PAGE_SIZE);
 
 
    for (j = 0; j < DTLB_WAYS; j++) {
    for (j = 0; j < DTLB_WAYS; j++) {
      mtspr (SPR_DTLBMR_BASE(j) + ((set - 1) & (DTLB_SETS - 1)), 0);
      mtspr (SPR_DTLBMR_BASE(j) + ((set - 1) & (DTLB_SETS - 1)), 0);
      mtspr (SPR_DTLBMR_BASE(j) + ((set + 1) & (DTLB_SETS - 1)), 0);
      mtspr (SPR_DTLBMR_BASE(j) + ((set + 1) & (DTLB_SETS - 1)), 0);
    }
    }
  }
  }
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  return 0;
  return 0;
}
}
 
 
/* Valid bit test
/* Valid bit test
   Set all ways of one set to be invalid, perform
   Set all ways of one set to be invalid, perform
   access so miss handler will set them to valid,
   access so miss handler will set them to valid,
   try access again - there should be no miss exceptions */
   try access again - there should be no miss exceptions */
int dtlb_valid_bit_test (int set)
int dtlb_valid_bit_test (int set)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta;
  unsigned long ea, ta;
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  /* Invalidate all entries in DTLB */
  /* Invalidate all entries in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    for (j = 0; j < DTLB_SETS; j++) {
    for (j = 0; j < DTLB_SETS; j++) {
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
  }
  }
 
 
  /* Reset DTLB miss counter and EA */
  /* Reset DTLB miss counter and EA */
  dtlb_miss_count = 0;
  dtlb_miss_count = 0;
  dtlb_miss_ea = 0;
  dtlb_miss_ea = 0;
 
 
  /* Set dtlb permisions */
  /* Set dtlb permisions */
  dtlb_val = DTLB_PR_NOLIMIT;
  dtlb_val = DTLB_PR_NOLIMIT;
 
 
  /* Resetv DTLBMR for every way */
  /* Resetv DTLBMR for every way */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    mtspr (SPR_DTLBMR_BASE(i) + set, 0);
    mtspr (SPR_DTLBMR_BASE(i) + set, 0);
  }
  }
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  dmmu_enable();
  dmmu_enable();
 
 
  /* Perform writes to address, that is not in DTLB */
  /* Perform writes to address, that is not in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) = i;
    REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) = i;
 
 
    /* Check if there was DTLB miss */
    /* Check if there was DTLB miss */
    ASSERT(dtlb_miss_count == (i + 1));
    ASSERT(dtlb_miss_count == (i + 1));
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
  }
  }
 
 
  /* Reset DTLB miss counter and EA */
  /* Reset DTLB miss counter and EA */
  dtlb_miss_count = 0;
  dtlb_miss_count = 0;
  dtlb_miss_ea = 0;
  dtlb_miss_ea = 0;
 
 
  /* Perform reads to address, that is now in DTLB */
  /* Perform reads to address, that is now in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
 
 
    /* Check if there was DTLB miss */
    /* Check if there was DTLB miss */
    ASSERT(dtlb_miss_count == 0);
    ASSERT(dtlb_miss_count == 0);
  }
  }
 
 
  /* Reset valid bits */
  /* Reset valid bits */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    mtspr (SPR_DTLBMR_BASE(i) + set, mfspr (SPR_DTLBMR_BASE(i) + set) & ~SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(i) + set, mfspr (SPR_DTLBMR_BASE(i) + set) & ~SPR_DTLBMR_V);
  }
  }
 
 
  /* Perform reads to address, that is now in DTLB but is invalid */
  /* Perform reads to address, that is now in DTLB but is invalid */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
 
 
    /* Check if there was DTLB miss */
    /* Check if there was DTLB miss */
    ASSERT(dtlb_miss_count == (i + 1));
    ASSERT(dtlb_miss_count == (i + 1));
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
  }
  }
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  return 0;
  return 0;
}
}
 
 
/* Permission test
/* Permission test
   Set various permissions, perform r/w access
   Set various permissions, perform r/w access
   in user and supervisor mode and chack triggering
   in user and supervisor mode and chack triggering
   of page fault exceptions */
   of page fault exceptions */
int dtlb_premission_test (int set)
int dtlb_premission_test (int set)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta, tmp;
  unsigned long ea, ta, tmp;
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  /* Invalidate all entries in DTLB */
  /* Invalidate all entries in DTLB */
  for (i = 0; i < DTLB_WAYS; i++) {
  for (i = 0; i < DTLB_WAYS; i++) {
    for (j = 0; j < DTLB_SETS; j++) {
    for (j = 0; j < DTLB_SETS; j++) {
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
    ea = RAM_START + (i*PAGE_SIZE);
    ea = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    ta = RAM_START + (i*PAGE_SIZE);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
  }
  }
 
 
  /* Testing page */
  /* Testing page */
  ea = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  ea = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
 
 
  /* Set match register */
  /* Set match register */
  mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + set, ea | SPR_DTLBMR_V);
  mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + set, ea | SPR_DTLBMR_V);
 
 
  /* Reset page fault counter and EA */
  /* Reset page fault counter and EA */
  dpage_fault_count = 0;
  dpage_fault_count = 0;
  dpage_fault_ea = 0;
  dpage_fault_ea = 0;
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  dmmu_enable();
  dmmu_enable();
 
 
  /* Write supervisor */
  /* Write supervisor */
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_SWE;
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_SWE;
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_SWE));
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_SWE));
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0) = 0x00112233;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0) = 0x00112233;
  ASSERT(dpage_fault_count == 1);
  ASSERT(dpage_fault_count == 1);
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4) = 0x44556677;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4) = 0x44556677;
  ASSERT(dpage_fault_count == 1);
  ASSERT(dpage_fault_count == 1);
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8) = 0x8899aabb;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8) = 0x8899aabb;
  ASSERT(dpage_fault_count == 1);
  ASSERT(dpage_fault_count == 1);
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12) = 0xccddeeff;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12) = 0xccddeeff;
  ASSERT(dpage_fault_count == 1);
  ASSERT(dpage_fault_count == 1);
 
 
  /* Read supervisor */
  /* Read supervisor */
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_SRE;
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_SRE;
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_SRE));
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_SRE));
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0);
  ASSERT(dpage_fault_count == 2);
  ASSERT(dpage_fault_count == 2);
  ASSERT(tmp == 0x00112233);
  ASSERT(tmp == 0x00112233);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4);
  ASSERT(dpage_fault_count == 2);
  ASSERT(dpage_fault_count == 2);
  ASSERT(tmp == 0x44556677);
  ASSERT(tmp == 0x44556677);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8);
  ASSERT(dpage_fault_count == 2);
  ASSERT(dpage_fault_count == 2);
  ASSERT(tmp == 0x8899aabb);
  ASSERT(tmp == 0x8899aabb);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12);
  ASSERT(dpage_fault_count == 2);
  ASSERT(dpage_fault_count == 2);
  ASSERT(tmp == 0xccddeeff);
  ASSERT(tmp == 0xccddeeff);
 
 
  /* Write user */
  /* Write user */
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_UWE;
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_UWE;
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_UWE));
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_UWE));
 
 
  /* Set user mode */
  /* Set user mode */
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SUPV);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SUPV);
 
 
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0) = 0xffeeddcc;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0) = 0xffeeddcc;
  ASSERT(dpage_fault_count == 3);
  ASSERT(dpage_fault_count == 3);
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4) = 0xbbaa9988;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4) = 0xbbaa9988;
  ASSERT(dpage_fault_count == 3);
  ASSERT(dpage_fault_count == 3);
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8) = 0x77665544;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8) = 0x77665544;
  ASSERT(dpage_fault_count == 3);
  ASSERT(dpage_fault_count == 3);
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12) = 0x33221100;
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12) = 0x33221100;
  ASSERT(dpage_fault_count == 3);
  ASSERT(dpage_fault_count == 3);
 
 
  /* Trigger sys call exception to enable supervisor mode again */
  /* Trigger sys call exception to enable supervisor mode again */
  sys_call ();
  sys_call ();
 
 
  /* Read user mode */
  /* Read user mode */
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_URE;
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_URE;
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_URE));
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_URE));
 
 
  /* Set user mode */
  /* Set user mode */
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SUPV);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SUPV);
 
 
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0);
  ASSERT(dpage_fault_count == 4);
  ASSERT(dpage_fault_count == 4);
  ASSERT(tmp == 0xffeeddcc);
  ASSERT(tmp == 0xffeeddcc);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4);
  ASSERT(dpage_fault_count == 4);
  ASSERT(dpage_fault_count == 4);
  ASSERT(tmp == 0xbbaa9988);
  ASSERT(tmp == 0xbbaa9988);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8);
  ASSERT(dpage_fault_count == 4);
  ASSERT(dpage_fault_count == 4);
  ASSERT(tmp == 0x77665544);
  ASSERT(tmp == 0x77665544);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12);
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12);
  ASSERT(dpage_fault_count == 4);
  ASSERT(dpage_fault_count == 4);
  ASSERT(tmp == 0x33221100);
  ASSERT(tmp == 0x33221100);
 
 
  /* Trigger sys call exception to enable supervisor mode again */
  /* Trigger sys call exception to enable supervisor mode again */
  sys_call ();
  sys_call ();
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  return 0;
  return 0;
}
}
 
 
/* Translation address register test
/* Translation address register test
   Set various translation and check the pattern */
   Set various translation and check the pattern */
int itlb_translation_test (void)
int itlb_translation_test (void)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta;
  unsigned long ea, ta;
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable();
  immu_disable();
 
 
  /* Invalidate all entries in DTLB */
  /* Invalidate all entries in DTLB */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    for (j = 0; j < ITLB_SETS; j++) {
    for (j = 0; j < ITLB_SETS; j++) {
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
    ea = FLASH_START + (i*PAGE_SIZE);
    ea = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Set dtlb permisions */
  /* Set dtlb permisions */
  itlb_val = ITLB_PR_NOLIMIT;
  itlb_val = ITLB_PR_NOLIMIT;
 
 
  /* Write test program */
  /* Write test program */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    copy_jump (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    copy_jump (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
  }
  }
 
 
  /* Set one to one translation of the last way of ITLB */
  /* Set one to one translation of the last way of ITLB */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, ta | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, ta | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  immu_enable();
  immu_enable();
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
  }
  }
 
 
  /* Set FLASH_END -> RAM_START + (RAM_SIZE/2) translation */
  /* Set FLASH_END -> RAM_START + (RAM_SIZE/2) translation */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    ea = FLASH_START + FLASH_SIZE + i*PAGE_SIZE;
    ea = FLASH_START + FLASH_SIZE + i*PAGE_SIZE;
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, ta | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, ta | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    call (FLASH_START + FLASH_SIZE + (i*PAGE_SIZE) + (i*0x10));
    call (FLASH_START + FLASH_SIZE + (i*PAGE_SIZE) + (i*0x10));
  }
  }
 
 
  /* Set hi -> lo, lo -> hi translation */
  /* Set hi -> lo, lo -> hi translation */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + ((ITLB_SETS - i - 1 + TLB_TEXT_SET_NB)*PAGE_SIZE);
    ta = RAM_START + (RAM_SIZE/2) + ((ITLB_SETS - i - 1 + TLB_TEXT_SET_NB)*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, ta | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, ta | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + ((ITLB_SETS - i - 1 + TLB_TEXT_SET_NB)*0x10));
    call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + ((ITLB_SETS - i - 1 + TLB_TEXT_SET_NB)*0x10));
  }
  }
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable ();
  immu_disable ();
 
 
  /* Check the pattern */
  /* Check the pattern */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
  }
  }
 
 
  return 0;
  return 0;
}
}
 
 
/* EA match register test
/* EA match register test
   Shifting one in ITLBMR and performing accesses to boundaries
   Shifting one in ITLBMR and performing accesses to boundaries
   of the page, checking the triggering of exceptions */
   of the page, checking the triggering of exceptions */
int itlb_match_test (int way, int set)
int itlb_match_test (int way, int set)
{
{
  int i, j;
  int i, j;
  unsigned long add, t_add;
  unsigned long add, t_add;
  unsigned long ea, ta;
  unsigned long ea, ta;
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable();
  immu_disable();
 
 
  /* Invalidate all entries in ITLB */
  /* Invalidate all entries in ITLB */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    for (j = 0; j < ITLB_SETS; j++) {
    for (j = 0; j < ITLB_SETS; j++) {
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
    ea = FLASH_START + (i*PAGE_SIZE);
    ea = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Set dtlb permisions */
  /* Set dtlb permisions */
  itlb_val = ITLB_PR_NOLIMIT;
  itlb_val = ITLB_PR_NOLIMIT;
 
 
  /* Set pattern */
  /* Set pattern */
  copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) - 8);
  copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) - 8);
  copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE));
  copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE));
  copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE - 8);
  copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE - 8);
  copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE);
  copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE);
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  immu_enable();
  immu_enable();
 
 
  /* Shifting one in ITLBMR */
  /* Shifting one in ITLBMR */
  i = 0;
  i = 0;
  add = (PAGE_SIZE*ITLB_SETS);
  add = (PAGE_SIZE*ITLB_SETS);
  t_add = add + (set*PAGE_SIZE);
  t_add = add + (set*PAGE_SIZE);
  while (add != 0x00000000) {
  while (add != 0x00000000) {
    mtspr (SPR_ITLBMR_BASE(way) + set, t_add | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(way) + set, t_add | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(way) + set, (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE)) | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(way) + set, (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE)) | ITLB_PR_NOLIMIT);
 
 
    /* Reset ITLB miss counter and EA */
    /* Reset ITLB miss counter and EA */
    itlb_miss_count = 0;
    itlb_miss_count = 0;
    itlb_miss_ea = 0;
    itlb_miss_ea = 0;
 
 
    if (((t_add < RAM_START) || (t_add >= DATA_END_ADD)) && ((t_add < FLASH_START) || (t_add >= TEXT_END_ADD))) {
    if (((t_add < RAM_START) || (t_add >= DATA_END_ADD)) && ((t_add < FLASH_START) || (t_add >= TEXT_END_ADD))) {
 
 
      /* Jump on last address of previous page */
      /* Jump on last address of previous page */
      call (t_add - 8);
      call (t_add - 8);
      ASSERT(itlb_miss_count == 1);
      ASSERT(itlb_miss_count == 1);
 
 
      /* Jump on first address of the page */
      /* Jump on first address of the page */
      call (t_add);
      call (t_add);
      ASSERT(itlb_miss_count == 1);
      ASSERT(itlb_miss_count == 1);
 
 
      /* Jump on last address of the page */
      /* Jump on last address of the page */
      call (t_add + PAGE_SIZE - 8);
      call (t_add + PAGE_SIZE - 8);
      ASSERT(itlb_miss_count == 1);
      ASSERT(itlb_miss_count == 1);
 
 
      /* Jump on first address of next page */
      /* Jump on first address of next page */
      call (t_add + PAGE_SIZE);
      call (t_add + PAGE_SIZE);
      ASSERT(itlb_miss_count == 2);
      ASSERT(itlb_miss_count == 2);
    }
    }
 
 
    i++;
    i++;
    add = (PAGE_SIZE*ITLB_SETS) << i;
    add = (PAGE_SIZE*ITLB_SETS) << i;
    t_add = add + (set*PAGE_SIZE);
    t_add = add + (set*PAGE_SIZE);
 
 
    for (j = 0; j < ITLB_WAYS; j++) {
    for (j = 0; j < ITLB_WAYS; j++) {
      mtspr (SPR_ITLBMR_BASE(j) + ((set - 1) & (ITLB_SETS - 1)), 0);
      mtspr (SPR_ITLBMR_BASE(j) + ((set - 1) & (ITLB_SETS - 1)), 0);
      mtspr (SPR_ITLBMR_BASE(j) + ((set + 1) & (ITLB_SETS - 1)), 0);
      mtspr (SPR_ITLBMR_BASE(j) + ((set + 1) & (ITLB_SETS - 1)), 0);
    }
    }
  }
  }
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable();
  immu_disable();
 
 
  return 0;
  return 0;
}
}
 
 
/* Valid bit test
/* Valid bit test
   Set all ways of one set to be invalid, perform
   Set all ways of one set to be invalid, perform
   access so miss handler will set them to valid,
   access so miss handler will set them to valid,
   try access again - there should be no miss exceptions */
   try access again - there should be no miss exceptions */
int itlb_valid_bit_test (int set)
int itlb_valid_bit_test (int set)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta;
  unsigned long ea, ta;
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable();
  immu_disable();
 
 
  /* Invalidate all entries in ITLB */
  /* Invalidate all entries in ITLB */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    for (j = 0; j < ITLB_SETS; j++) {
    for (j = 0; j < ITLB_SETS; j++) {
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
    ea = FLASH_START + (i*PAGE_SIZE);
    ea = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Reset ITLB miss counter and EA */
  /* Reset ITLB miss counter and EA */
  itlb_miss_count = 0;
  itlb_miss_count = 0;
  itlb_miss_ea = 0;
  itlb_miss_ea = 0;
 
 
  /* Set itlb permisions */
  /* Set itlb permisions */
  itlb_val = ITLB_PR_NOLIMIT;
  itlb_val = ITLB_PR_NOLIMIT;
 
 
  /* Resetv ITLBMR for every way */
  /* Resetv ITLBMR for every way */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    mtspr (SPR_ITLBMR_BASE(i) + set, 0);
    mtspr (SPR_ITLBMR_BASE(i) + set, 0);
  }
  }
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  immu_enable();
  immu_enable();
 
 
  /* Perform jumps to address, that is not in ITLB */
  /* Perform jumps to address, that is not in ITLB */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    TEST_JUMP(RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
    TEST_JUMP(RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
 
 
    /* Check if there was ITLB miss */
    /* Check if there was ITLB miss */
    ASSERT(itlb_miss_count == (i + 1));
    ASSERT(itlb_miss_count == (i + 1));
    ASSERT(itlb_miss_ea == (RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
    ASSERT(itlb_miss_ea == (RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
  }
  }
 
 
  /* Reset ITLB miss counter and EA */
  /* Reset ITLB miss counter and EA */
  itlb_miss_count = 0;
  itlb_miss_count = 0;
  itlb_miss_ea = 0;
  itlb_miss_ea = 0;
 
 
  /* Perform jumps to address, that is now in ITLB */
  /* Perform jumps to address, that is now in ITLB */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    TEST_JUMP(RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
    TEST_JUMP(RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
 
 
    /* Check if there was ITLB miss */
    /* Check if there was ITLB miss */
    ASSERT(itlb_miss_count == 0);
    ASSERT(itlb_miss_count == 0);
  }
  }
 
 
  /* Reset valid bits */
  /* Reset valid bits */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    mtspr (SPR_ITLBMR_BASE(i) + set, mfspr (SPR_ITLBMR_BASE(i) + set) & ~SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(i) + set, mfspr (SPR_ITLBMR_BASE(i) + set) & ~SPR_ITLBMR_V);
  }
  }
 
 
  /* Perform jumps to address, that is now in ITLB but is invalid */
  /* Perform jumps to address, that is now in ITLB but is invalid */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    TEST_JUMP(RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
    TEST_JUMP(RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
 
 
    /* Check if there was ITLB miss */
    /* Check if there was ITLB miss */
    ASSERT(itlb_miss_count == (i + 1));
    ASSERT(itlb_miss_count == (i + 1));
    ASSERT(itlb_miss_ea == (RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
    ASSERT(itlb_miss_ea == (RAM_START + RAM_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
  }
  }
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable ();
  immu_disable ();
 
 
  return 0;
  return 0;
}
}
 
 
/* Permission test
/* Permission test
   Set various permissions, perform r/w access
   Set various permissions, perform r/w access
   in user and supervisor mode and chack triggering
   in user and supervisor mode and chack triggering
   of page fault exceptions */
   of page fault exceptions */
int itlb_premission_test (int set)
int itlb_premission_test (int set)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta, tmp;
  unsigned long ea, ta;
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable();
  immu_disable();
 
 
  /* Invalidate all entries in ITLB */
  /* Invalidate all entries in ITLB */
  for (i = 0; i < ITLB_WAYS; i++) {
  for (i = 0; i < ITLB_WAYS; i++) {
    for (j = 0; j < ITLB_SETS; j++) {
    for (j = 0; j < ITLB_SETS; j++) {
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
    }
    }
  }
  }
 
 
  /* Set one to one translation for the use of this program */
  /* Set one to one translation for the use of this program */
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
    ea = FLASH_START + (i*PAGE_SIZE);
    ea = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    ta = FLASH_START + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Testing page */
  /* Testing page */
  ea = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  ea = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
 
 
  /* Set match register */
  /* Set match register */
  mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + set, ea | SPR_ITLBMR_V);
  mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + set, ea | SPR_ITLBMR_V);
 
 
  /* Reset page fault counter and EA */
  /* Reset page fault counter and EA */
  ipage_fault_count = 0;
  ipage_fault_count = 0;
  ipage_fault_ea = 0;
  ipage_fault_ea = 0;
 
 
  /* Copy the code */
  /* Copy the code */
  copy_jump (ea);
  copy_jump (ea);
  copy_jump (ea + 8);
  copy_jump (ea + 8);
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  immu_enable ();
  immu_enable ();
 
 
  /* Execute supervisor */
  /* Execute supervisor */
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, ea | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_SXE));
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, ea | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_SXE));
 
 
  call (ea);
  call (ea);
  ASSERT(ipage_fault_count == 1);
  ASSERT(ipage_fault_count == 1);
  call (ea + 8);
  call (ea + 8);
  ASSERT(ipage_fault_count == 1);
  ASSERT(ipage_fault_count == 1);
 
 
  /* Execute user */
  /* Execute user */
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_UXE;
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_UXE;
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, ea | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_UXE));
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, ea | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_UXE));
 
 
  /* Set user mode */
  /* Set user mode */
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SUPV);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SUPV);
 
 
  call (ea);
  call (ea);
  ASSERT(ipage_fault_count == 2);
  ASSERT(ipage_fault_count == 2);
  call (ea + 8);
  call (ea + 8);
  ASSERT(ipage_fault_count == 2);
  ASSERT(ipage_fault_count == 2);
 
 
  /* Trigger sys call exception to enable supervisor mode again */
  /* Trigger sys call exception to enable supervisor mode again */
  sys_call ();
  sys_call ();
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable ();
  immu_disable ();
 
 
  return 0;
  return 0;
}
}
 
 
int main (void)
int main (void)
{
{
  int i, j;
  int i, j;
 
 
  /* Register bus error handler */
  /* Register bus error handler */
  excpt_buserr = (unsigned long)bus_err_handler;
  excpt_buserr = (unsigned long)bus_err_handler;
 
 
  /* Register illegal insn handler */
  /* Register illegal insn handler */
  excpt_illinsn = (unsigned long)ill_insn_handler;
  excpt_illinsn = (unsigned long)ill_insn_handler;
 
 
  /* Register illegal insn handler */
  /* Register illegal insn handler */
  excpt_syscall = (unsigned long)sys_call_handler;
  excpt_syscall = (unsigned long)sys_call_handler;
 
 
#if 1
#if 1
  /* Translation test */
  /* Translation test */
  dtlb_translation_test ();
  dtlb_translation_test ();
 
 
  /* Virtual address match test */
  /* Virtual address match test */
  for (j = 0; j < DTLB_WAYS; j++) {
  for (j = 0; j < DTLB_WAYS; j++) {
    for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
    for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
      dtlb_match_test (j, i);
      dtlb_match_test (j, i);
  }
  }
 
 
  /* Valid bit testing */
  /* Valid bit testing */
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
    dtlb_valid_bit_test (i);
    dtlb_valid_bit_test (i);
 
 
  /* Permission test */
  /* Permission test */
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
    dtlb_premission_test (i);
    dtlb_premission_test (i);
 
 
#endif
#endif
 
 
#if 1
#if 1
  /* Translation test */
  /* Translation test */
  itlb_translation_test ();
  itlb_translation_test ();
 
 
  /* Virtual address match test */
  /* Virtual address match test */
  for (j = 0; j < DTLB_WAYS; j++) {
  for (j = 0; j < DTLB_WAYS; j++) {
    for (i = TLB_TEXT_SET_NB + 1; i < (DTLB_SETS - 1); i++)
    for (i = TLB_TEXT_SET_NB + 1; i < (DTLB_SETS - 1); i++)
      itlb_match_test (j, i);
      itlb_match_test (j, i);
  }
  }
 
 
  /* Valid bit testing */
  /* Valid bit testing */
  for (i = TLB_TEXT_SET_NB; i < (ITLB_SETS); i++)
  for (i = TLB_TEXT_SET_NB; i < (ITLB_SETS); i++)
    itlb_valid_bit_test (i);
    itlb_valid_bit_test (i);
 
 
  /* Permission test */
  /* Permission test */
  for (i = TLB_TEXT_SET_NB; i < (ITLB_SETS - 1); i++)
  for (i = TLB_TEXT_SET_NB; i < (ITLB_SETS - 1); i++)
    itlb_premission_test (i);
    itlb_premission_test (i);
 
 
#endif
#endif
 
 
  report (0xdeaddead);
  report (0xdeaddead);
  exit (0);
  exit (0);
  return 0;
  return 0;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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