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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [tests/] [or1200/] [sim/] [or1200-mmu.c] - Diff between revs 425 and 439

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

Rev 425 Rev 439
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////                                                              ////
////                                                              ////
//// OR1200 MMU test                                              ////
//// OR1200 MMU test                                              ////
////                                                              ////
////                                                              ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG                 ////
//// Copyright (C) 2010 Authors and OPENCORES.ORG                 ////
////                                                              ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
//// later version.                                               ////
////                                                              ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
//// details.                                                     ////
////                                                              ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
 
 
// Tests most functions of the MMUs.
// Tests most functions of the MMUs.
// The tests attempt to keep the areas of instruction and data memory working 
// The tests attempt to keep the areas of instruction and data memory working 
// as they should, while testing around them, higher in memory. Some linker 
// as they should, while testing around them, higher in memory. Some linker 
// variables are relied upon by the interrupt routines for checking if areas 
// variables are relied upon by the interrupt routines for checking if areas 
// are within the expected text areas of memory, but usually we just keep 
// are within the expected text areas of memory, but usually we just keep 
// above the stack (also set in the linker script) and things go OK.
// above the stack (also set in the linker script) and things go OK.
 
 
// The tests for translation setup address translation in the MMU from areas 
// The tests for translation setup address translation in the MMU from areas 
// in the 512kB - 1024kB region (64 sets in OR1200, 8kByte per set) to halfway
// in the 512kB - 1024kB region (64 sets in OR1200, 8kByte per set) to halfway
// through RAM. Usually the sets taht would encompass the actual program are 
// through RAM. Usually the sets taht would encompass the actual program are 
// skipped (TLB_TEXT_SET_NB) ie, we say how many sets encompass the program 
// skipped (TLB_TEXT_SET_NB) ie, we say how many sets encompass the program 
// text for itlb tests and only do tests above it (so, on sets 8-64, meaning 
// text for itlb tests and only do tests above it (so, on sets 8-64, meaning 
// when we enable the iMMU and say have the execution bits disabled to force a
// when we enable the iMMU and say have the execution bits disabled to force a
// page fault the program gets to continue and is translated 1-1 while 
// page fault the program gets to continue and is translated 1-1 while 
// accesses to the areas we are testing will cause a page fault) but it should
// accesses to the areas we are testing will cause a page fault) but it should
//  still work to test all sets.
//  still work to test all sets.
 
 
// In essense, the tests are aware that they could be operating out of the 
// In essense, the tests are aware that they could be operating out of the 
// same memory the tests are being performed in and takes care of this.
// same memory the tests are being performed in and takes care of this.
 
 
// The use of the "match_space" variable is for the addresses we'll access 
// The use of the "match_space" variable is for the addresses we'll access 
// when a non-1-1 translation will occur, otherwise usually the 
// when a non-1-1 translation will occur, otherwise usually the 
// "translate_space" variable by itself is used (it's first setup to the 
// "translate_space" variable by itself is used (it's first setup to the 
// desired address, and either data or the return instructions are placed 
// desired address, and either data or the return instructions are placed 
// where we expect the MMU to translate to)
// where we expect the MMU to translate to)
 
 
#include "cpu-utils.h"
#include "cpu-utils.h"
#include "spr-defs.h"
#include "spr-defs.h"
#include "board.h"
#include "board.h"
// Uncomment uart.h include for UART output
// Uncomment uart.h include for UART output
//#include "uart.h"
//#include "uart.h"
//#include "printf.h"
//#include "printf.h"
 
 
// Uncomment the following to completely remove all printfs, or comment them
// Uncomment the following to completely remove all printfs, or comment them
// out to enable printf()s, but slows down RTL simulation a lot.
// out to enable printf()s, but slows down RTL simulation a lot.
#undef printf
#undef printf
#define printf(a, ...)
#define printf(a, ...)
 
 
#include "or1200-defines.h"
#include "or1200-defines.h"
 
 
#ifdef OR1200_NO_IMMU
#ifdef OR1200_NO_IMMU
# error
# error
# error Processor has no instruction MMU. Cannot run this test without it.
# error Processor has no instruction MMU. Cannot run this test without it.
# error
# error
#endif
#endif
 
 
#ifdef OR1200_NO_DMMU
#ifdef OR1200_NO_DMMU
# error
# error
# error Processor has no data MMU. Cannot run this test without it.
# error Processor has no data MMU. Cannot run this test without it.
# error
# error
#endif
#endif
 
 
 
 
// Reduce the number of sets tested
// Reduce the number of sets tested
#define SHORT_TEST
#define SHORT_TEST
 
 
// Set this to 1 to enable the DMMU tests
// Set this to 1 to enable the DMMU tests
#define DO_DMMU_TESTS 1
#define DO_DMMU_TESTS 1
 
 
// Symbols defined in linker script
// Symbols defined in linker script
extern unsigned long _endtext;
extern unsigned long _endtext;
extern unsigned long _stext;
extern unsigned long _stext;
extern unsigned long _edata;
extern unsigned long _edata;
extern unsigned long _stack;
extern unsigned long _stack;
 
 
unsigned long start_text_addr;
unsigned long start_text_addr;
unsigned long end_text_addr;
unsigned long end_text_addr;
unsigned long end_data_addr;
unsigned long end_data_addr;
 
 
/* For shorter simulation run */
/* For shorter simulation run */
#define RTL_SIM 1
#define RTL_SIM 1
 
 
/* 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 RAM_START   0x00000000
#define RAM_START   0x00000000
// Assume only 8MB memory
// Assume only 8MB memory
#define RAM_SIZE    0x00800000
#define RAM_SIZE    0x00800000
 
 
#define VM_BASE 0xc0000000
#define VM_BASE 0xc0000000
 
 
/* 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_START_ADD start_text_addr
#define TEXT_START_ADD start_text_addr
#define TEXT_END_ADD end_text_addr
#define TEXT_END_ADD end_text_addr
#define DATA_END_ADD end_data_addr
#define DATA_END_ADD end_data_addr
 
 
// Pages to start tests at. This should correspond to where the stack is set. 
// Pages to start tests at. This should correspond to where the stack is set. 
// We can set this by hand or figure it out at runtime.
// We can set this by hand or figure it out at runtime.
// Uncomment the following 3 lines to hard-set the bottom page to test at:
// Uncomment the following 3 lines to hard-set the bottom page to test at:
//#define TLB_BOTTOM_TEST_PAGE_HARDSET
//#define TLB_BOTTOM_TEST_PAGE_HARDSET
//#define TLB_TEXT_SET_NB 16
//#define TLB_TEXT_SET_NB 16
//#define TLB_DATA_SET_NB 16
//#define TLB_DATA_SET_NB 16
 
 
// Uncomment the following to determine the page to test from at run-time
// Uncomment the following to determine the page to test from at run-time
unsigned long TLB_TEXT_SET_NB;
unsigned long TLB_TEXT_SET_NB;
unsigned long TLB_DATA_SET_NB;
unsigned long TLB_DATA_SET_NB;
 
 
/* MMU page size */
/* MMU page size */
#define PAGE_SIZE 8192
#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 64
#define DTLB_SETS 64
 
 
/* 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 64
#define ITLB_SETS 64
 
 
/* 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
 
 
 
 
 
 
/* 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__))
 
 
// iMMU and dMMU enable functions
// iMMU and dMMU enable 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);
 
 
/* Local functions prototypes */
/* Local functions prototypes */
void dmmu_disable (void);
void dmmu_disable (void);
void immu_disable (void);
void immu_disable (void);
 
 
// Machine code for l.jr r9 and then l.nop
// Machine code for l.jr r9 and then l.nop
#define OR32_L_JR_R9 0x44004800
#define OR32_L_JR_R9 0x44004800
#define OR32_L_NOP 0x15000000
#define OR32_L_NOP 0x15000000
 
 
/* 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;
 
 
 
 
#define sys_call() __asm__ __volatile__("l.sys\t0");
#define sys_call() __asm__ __volatile__("l.sys\t0");
/*
/*
void sys_call (void)
void sys_call (void)
{
{
  asm("l.sys\t0");
  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 ();
 
 
  report(line);
  report(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)
{
{
  return;
  return;
  /*asm("_jr:");
  /*asm("_jr:");
  asm("l.jr\t\tr9") ;
  asm("l.jr\t\tr9") ;
  asm("l.nop" : :);*/
  asm("l.nop" : :);*/
}
}
 
 
void copy_jump(unsigned long phy_add)
void copy_jump(unsigned long phy_add)
{
{
  memcpy((void *)phy_add, (void *)&jump, (8*4));
  memcpy((void *)phy_add, (void *)&jump, (8*4));
}
}
 
 
/* 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 */
  printf("Test failed: Bus error\n");
  printf("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 */
  printf("Test failed: Illegal insn\n");
  printf("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_SM);
  mtspr (SPR_ESR_BASE, mfspr (SPR_ESR_BASE) | SPR_SR_SM);
}
}
 
 
/* 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;
    }
    }
  }
  }
 
 
  printf("dtlb miss ea = %.8lx set = %d way = %d\n", ea, set, way);
  printf("dtlb miss ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  // Anything under the stack belongs to the program, direct tranlsate it
  // Anything under the stack belongs to the program, direct tranlsate it
  if (ea < (unsigned long)&_stack){
  if (ea < (unsigned long)&_stack){
    /* 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;
 
 
  // Everything gets translated back to the space halfway through RAM
  // Everything gets translated back to the space halfway through RAM
  ta = (set*PAGE_SIZE) + RAM_START + (RAM_SIZE/2);
  ta = (set*PAGE_SIZE) + 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);
  printf("ta = %.8lx tlbtr = %.8lx dtlb_val = %.8lx\n",ta, tlbtr, dtlb_val);
  printf("ta = %.8lx tlbtr = %.8lx dtlb_val = %.8lx\n",ta, 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) ==
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_VPN) ==
        (ea & SPR_DTLBMR_VPN)) {
        (ea & SPR_DTLBMR_VPN)) {
      way = i;
      way = i;
      break;
      break;
    }
    }
  }
  }
 
 
  printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
  printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  if (((RAM_START <= ea) & (ea < DATA_END_ADD) ) |
  if (((RAM_START <= ea) & (ea < DATA_END_ADD) ) |
      ((TEXT_START_ADD <= ea) & (ea < TEXT_END_ADD))) {
      ((TEXT_START_ADD <= 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,
  mtspr (SPR_DTLBTR_BASE(way) + set,
         (mfspr (SPR_DTLBTR_BASE(way) + set) & ~DTLB_PR_NOLIMIT) | dtlb_val);
         (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_EEAR_BASE);
  ea = mfspr (SPR_EEAR_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;
    }
    }
  }
  }
 
 
  printf("itlb miss ea = %.8lx set = %d way = %d\n", ea, set, way);
  printf("itlb miss ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  if ((TEXT_START_ADD <= ea) && (ea < TEXT_END_ADD)) {
  if ((TEXT_START_ADD <= 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
  /* Whatever access is in progress, translated address have to point to
     physical RAM */
     physical RAM */
 
 
  ta = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  ta = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  tlbtr = (ta & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
  tlbtr = (ta & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
 
 
  printf("ta = %.8lx\n", ta);
  printf("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_EEAR_BASE);
  ea = mfspr (SPR_EEAR_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;
    }
    }
  }
  }
 
 
  printf("ipage fault: ea = %.8lx set = %d way = %d\n", ea, set, way);
  printf("ipage fault: ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
  if ((TEXT_START_ADD <= ea) && (ea < TEXT_END_ADD)) {
  if ((TEXT_START_ADD <= 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;
  }
  }
 
 
  printf("ipage fault was outside of code area\n", ea, set, way);
  printf("ipage fault was outside of code area\n", ea, set, way);
 
 
  /* 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 */
  add_handler(0x9, dtlb_miss_handler);
  add_handler(0x9, 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 */
  add_handler(0x3, dpage_fault_handler);
  add_handler(0x3, dpage_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 */
  add_handler(0xa, itlb_miss_handler);
  add_handler(0xa, 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 */
  add_handler(0x4, ipage_fault_handler);
  add_handler(0x4, ipage_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();
 
 
  printf("dtlb translation test set\n");
  printf("dtlb translation test set\n");
 
 
  /* 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 program's data space */
  /* Set one to one translation for program's data space */
  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++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    REG32(ea) = i;
    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;
    REG32(ea) = 0xffffffff - i;
    REG32(ea) = 0xffffffff - i;
  }
  }
 
 
  /* Set one to one translation */
  /* Set one to one 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) + (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++) {
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    REG32(ea) = 0xffffffff - i;
    REG32(ea) = 0xffffffff - i;
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
    REG32(ea) = i;
    REG32(ea) = 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)*
    ta = RAM_START + (RAM_SIZE/2) + ((DTLB_SETS - i - 1 + TLB_DATA_SET_NB)*
                                     PAGE_SIZE);
                                     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));
  }
  }
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  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();
 
 
  printf("dtlb_match_test - way %d set %d\n",way, set);
  printf("dtlb_match_test - way %d set %d\n",way, set);
 
 
  /* 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);
    }
    }
  }
  }
 
 
  // Program text/data pages should be 1-1 translation
  // Program text/data pages should be 1-1 translation
  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;
 
 
  // Setup match area address - based at halfway through RAM, 
  // Setup match area address - based at halfway through RAM, 
  // and then offset by the area encompassed by the set we wish to test.
  // and then offset by the area encompassed by the set we wish to test.
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
 
 
  /* Set pattern */
  /* Set pattern */
  // Last word of page before the one covered by this set
  // Last word of page before the one covered by this set
  REG32(translate_space - 4) = 0x00112233;
  REG32(translate_space - 4) = 0x00112233;
  //printf("pattern0 @ 0x%.8lx = 0x%.8lx\n", translate_space-4, REG32(translate_space - 4) );
  //printf("pattern0 @ 0x%.8lx = 0x%.8lx\n", translate_space-4, REG32(translate_space - 4) );
  // First word of page covered by this set
  // First word of page covered by this set
  REG32(translate_space) = 0x44556677;
  REG32(translate_space) = 0x44556677;
  // Last word of page covered by this set
  // Last word of page covered by this set
  REG32(translate_space + PAGE_SIZE - 4) = 0x8899aabb;
  REG32(translate_space + PAGE_SIZE - 4) = 0x8899aabb;
  // First word of page covered by next set
  // First word of page covered by next set
  REG32(translate_space + PAGE_SIZE) = 0xccddeeff;
  REG32(translate_space + PAGE_SIZE) = 0xccddeeff;
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  dmmu_enable();
  dmmu_enable();
 
 
  /* Shifting one in DTLBMR */
  /* Shifting one in DTLBMR */
  i = 0;
  i = 0;
 
 
  // Setup match space - place we will do accesses to, and have them
  // Setup match space - place we will do accesses to, and have them
  // tranlsated into the translate space addresses
  // tranlsated into the translate space addresses
  unsigned long match_space = (PAGE_SIZE*DTLB_SETS) + (set*PAGE_SIZE);  // 
  unsigned long match_space = (PAGE_SIZE*DTLB_SETS) + (set*PAGE_SIZE);  // 
 
 
  //add = (PAGE_SIZE*DTLB_SETS); // 8kB * 64, 512KB
  //add = (PAGE_SIZE*DTLB_SETS); // 8kB * 64, 512KB
  //t_add = add + (set*PAGE_SIZE); // 
  //t_add = add + (set*PAGE_SIZE); // 
  while (add != 0x00000000) {
  while (add != 0x00000000) {
    // Set MATCH register for the areas we will access explicitly, and validate it
    // Set MATCH register for the areas we will access explicitly, and validate it
    mtspr (SPR_DTLBMR_BASE(way) + set, match_space | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(way) + set, match_space | SPR_DTLBMR_V);
    // Set TRANSLATE register to the areas where we have set our data
    // Set TRANSLATE register to the areas where we have set our data
    mtspr (SPR_DTLBTR_BASE(way) + set, translate_space | DTLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(way) + set, translate_space | 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 (((match_space < RAM_START) || (t_add >= DATA_END_ADD)) && 
    //if (((match_space < RAM_START) || (t_add >= DATA_END_ADD)) && 
    //  ((t_add < TEXT_START_ADD) || (t_add >= TEXT_END_ADD))) {
    //  ((t_add < TEXT_START_ADD) || (t_add >= TEXT_END_ADD))) {
    if (match_space > DATA_END_ADD){
    if (match_space > DATA_END_ADD){
 
 
      /* Read last address of previous page */
      /* Read last address of previous page */
      tmp = REG32(match_space - 4);
      tmp = REG32(match_space - 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(match_space);
      tmp = REG32(match_space);
      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(match_space + PAGE_SIZE - 4);
      tmp = REG32(match_space + 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(match_space + PAGE_SIZE);
      tmp = REG32(match_space + 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;
    match_space = add + (set*PAGE_SIZE);
    match_space = 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();
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  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();
 
 
  printf("dtlb_valid_bit_test, set %d\n", set);
  printf("dtlb_valid_bit_test, set %d\n", set);
 
 
  /* 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();
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  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_permission_test (int set)
int dtlb_permission_test (int set)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta, tmp;
  unsigned long ea, ta, tmp;
 
 
  printf("dtlb_permission_test, set %d\n", set);
  printf("dtlb_permission_test, set %d\n", set);
 
 
  /* 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_SM);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SM);
 
 
  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_SM);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SM);
 
 
  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();
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  return 0;
  return 0;
}
}
 
 
 
 
/* Dcache test - check inhibit
/* Dcache test - check inhibit
Write data with cache inhibit on and off, check for coherency
Write data with cache inhibit on and off, check for coherency
 */
 */
int dtlb_dcache_test (int set)
int dtlb_dcache_test (int set)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta, vmea;
  unsigned long ea, ta, vmea;
 
 
  // Check data cache is present and enabled
  // Check data cache is present and enabled
  if (!(mfspr(SPR_UPR)& SPR_UPR_DCP))
  if (!(mfspr(SPR_UPR)& SPR_UPR_DCP))
    return 0;
    return 0;
 
 
  if (!(mfspr(SPR_SR) & SPR_SR_DCE))
  if (!(mfspr(SPR_SR) & SPR_SR_DCE))
    return 0;
    return 0;
 
 
  printf("dtlb_dcache_test, set %d\n", set);
  printf("dtlb_dcache_test, set %d\n", set);
 
 
  /* 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);
 
 
  ta = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  ta = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
 
 
  vmea = VM_BASE + RAM_START + (RAM_SIZE/2) + ((DTLB_SETS-1)*PAGE_SIZE);
  vmea = VM_BASE + RAM_START + (RAM_SIZE/2) + ((DTLB_SETS-1)*PAGE_SIZE);
 
 
  // Set a 1-1 translation for this page without cache inhibited
  // Set a 1-1 translation for this page without cache inhibited
 
 
  /* Set match register */
  /* Set match register */
  mtspr (SPR_DTLBMR_BASE(0) + set, ea | SPR_DTLBMR_V);
  mtspr (SPR_DTLBMR_BASE(0) + set, ea | SPR_DTLBMR_V);
  /* Set translate register */
  /* Set translate register */
  mtspr (SPR_DTLBTR_BASE(0) + set, ta | DTLB_PR_NOLIMIT);
  mtspr (SPR_DTLBTR_BASE(0) + set, ta | DTLB_PR_NOLIMIT);
 
 
  // Now set a far-off translation, VM_BASE, for this page with cache inhibited
  // Now set a far-off translation, VM_BASE, for this page with cache inhibited
  // Use the last set
  // Use the last set
 
 
  /* Set match register */
  /* Set match register */
  mtspr (SPR_DTLBMR_BASE(0) + (DTLB_SETS-1),
  mtspr (SPR_DTLBMR_BASE(0) + (DTLB_SETS-1),
         vmea | SPR_DTLBMR_V);
         vmea | SPR_DTLBMR_V);
  /* Set translate register */
  /* Set translate register */
  mtspr (SPR_DTLBTR_BASE(0) + (DTLB_SETS-1),
  mtspr (SPR_DTLBTR_BASE(0) + (DTLB_SETS-1),
         ta | DTLB_PR_NOLIMIT | SPR_DTLBTR_CI);
         ta | DTLB_PR_NOLIMIT | SPR_DTLBTR_CI);
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  dmmu_enable();
  dmmu_enable();
 
 
  // First do a write with the cache inhibited mapping
  // First do a write with the cache inhibited mapping
  unsigned long int testwrite_to_be_cached = 0xfeca1d0d ^ set;
  unsigned long int testwrite_to_be_cached = 0xfeca1d0d ^ set;
  REG32((vmea)) = testwrite_to_be_cached;
  REG32((vmea)) = testwrite_to_be_cached;
  // Read it back to check that it's the same, this read should get cached
  // Read it back to check that it's the same, this read should get cached
  ASSERT(REG32(ea) == testwrite_to_be_cached);
  ASSERT(REG32(ea) == testwrite_to_be_cached);
  // Now write again to the cache inhibited location
  // Now write again to the cache inhibited location
  unsigned long int testwrite_not_to_be_cached = 0xbaadbeef ^ set;
  unsigned long int testwrite_not_to_be_cached = 0xbaadbeef ^ set;
  REG32((vmea)) = testwrite_not_to_be_cached;
  REG32((vmea)) = testwrite_not_to_be_cached;
  // Now check that the cached mapping doesn't read this value back
  // Now check that the cached mapping doesn't read this value back
  ASSERT(REG32(ea) == testwrite_to_be_cached);
  ASSERT(REG32(ea) == testwrite_to_be_cached);
 
 
  // Now disable cache inhibition on the 1-1 mapping
  // Now disable cache inhibition on the 1-1 mapping
  /* Set translate register */
  /* Set translate register */
  mtspr (SPR_DTLBTR_BASE(0) + set,
  mtspr (SPR_DTLBTR_BASE(0) + set,
         ea | DTLB_PR_NOLIMIT | SPR_DTLBTR_CI);
         ea | DTLB_PR_NOLIMIT | SPR_DTLBTR_CI);
 
 
  // Check that we now get the second value we wrote
  // Check that we now get the second value we wrote
  testwrite_to_be_cached = testwrite_not_to_be_cached;
  testwrite_to_be_cached = testwrite_not_to_be_cached;
  ASSERT(REG32(ea) == testwrite_to_be_cached);
  ASSERT(REG32(ea) == testwrite_to_be_cached);
 
 
  /* Disable DMMU */
  /* Disable DMMU */
  dmmu_disable();
  dmmu_disable();
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  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;
  unsigned long translate_space;
  unsigned long translate_space;
  unsigned long match_space;
  unsigned long match_space;
  printf("itlb_translation_test\n");
  printf("itlb_translation_test\n");
 
 
  /* 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++) {
    match_space = TEXT_START_ADD + (i*PAGE_SIZE);
    match_space = TEXT_START_ADD + (i*PAGE_SIZE);
    translate_space = TEXT_START_ADD + (i*PAGE_SIZE);
    translate_space = TEXT_START_ADD + (i*PAGE_SIZE);
    mtspr (SPR_ITLBMR_BASE(0) + i, match_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(0) + i, match_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(0) + i, translate_space | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(0) + i, translate_space | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Set itlb permisions */
  /* Set itlb 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++) {
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    //printf("writing app to 0x%.8lx to be translated in set %d\n",translate_space, i);
    //printf("writing app to 0x%.8lx to be translated in set %d\n",translate_space, i);
    REG32(translate_space) = OR32_L_JR_R9;
    REG32(translate_space) = OR32_L_JR_R9;
    REG32(translate_space + 4) = OR32_L_NOP;
    REG32(translate_space + 4) = OR32_L_NOP;
    // Now flush this in case DC isn't on write-through
    // Now flush this in case DC isn't on write-through
    mtspr(SPR_DCBFR, translate_space);
    mtspr(SPR_DCBFR, translate_space);
    mtspr(SPR_DCBFR, translate_space+4);
    mtspr(SPR_DCBFR, translate_space+4);
 
 
  }
  }
 
 
  /* 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++) {
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, translate_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, translate_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i,
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i,
           translate_space | ITLB_PR_NOLIMIT);
           translate_space | ITLB_PR_NOLIMIT);
  }
  }
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  immu_enable();
  immu_enable();
 
 
  /* Check the tranlsation works by jumping there */
  /* Check the tranlsation works by jumping there */
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    //printf("calling 0x%.8lx - should use set %d\n",translate_space, i);
    //printf("calling 0x%.8lx - should use set %d\n",translate_space, i);
    call (translate_space);
    call (translate_space);
  }
  }
 
 
  /* 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++) {
    match_space = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    match_space = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
    translate_space = RAM_START + (RAM_SIZE/2) +
    translate_space = RAM_START + (RAM_SIZE/2) +
      (((ITLB_SETS-1)+TLB_TEXT_SET_NB - i)*PAGE_SIZE);
      (((ITLB_SETS-1)+TLB_TEXT_SET_NB - i)*PAGE_SIZE);
    printf("setting itlb set %d match -> trans = 0x%.8lx -> 0x%.8lx\n",
    printf("setting itlb set %d match -> trans = 0x%.8lx -> 0x%.8lx\n",
           i, match_space, translate_space);
           i, match_space, translate_space);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, match_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, match_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, translate_space|ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, translate_space|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++) {
    match_space = RAM_START + (RAM_SIZE/2) + (((ITLB_SETS-1)+TLB_TEXT_SET_NB - i)*PAGE_SIZE) + (i*0x10);
    match_space = RAM_START + (RAM_SIZE/2) + (((ITLB_SETS-1)+TLB_TEXT_SET_NB - i)*PAGE_SIZE) + (i*0x10);
    printf("immu hi->lo check - calling 0x%.8lx\n",match_space);
    printf("immu hi->lo check - calling 0x%.8lx\n",match_space);
    call(match_space);
    call(match_space);
  }
  }
 
 
  /* 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++) {
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    //call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    //call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
    //printf("immu disabled check of set %d - calling 0x%.8lx\n",i, translate_space);
    //printf("immu disabled check of set %d - calling 0x%.8lx\n",i, translate_space);
    call (translate_space);
    call (translate_space);
  }
  }
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  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;
 
 
  printf("itlb_match_test\n");
  printf("itlb_match_test\n");
 
 
  /* 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 = TEXT_START_ADD + (i*PAGE_SIZE);
    ea = TEXT_START_ADD + (i*PAGE_SIZE);
    ta = TEXT_START_ADD + (i*PAGE_SIZE);
    ta = TEXT_START_ADD + (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 program which will just return into these places
  // Write program which will just return into these places
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) - 8);
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) - 8);
  REG32(translate_space-8) = OR32_L_JR_R9;
  REG32(translate_space-8) = OR32_L_JR_R9;
  REG32(translate_space-4) = OR32_L_NOP;
  REG32(translate_space-4) = OR32_L_NOP;
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE));
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE));
  REG32(translate_space) = OR32_L_JR_R9;
  REG32(translate_space) = OR32_L_JR_R9;
  REG32(translate_space+4) = OR32_L_NOP;
  REG32(translate_space+4) = OR32_L_NOP;
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE - 8);
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE - 8);
  REG32(translate_space + PAGE_SIZE - 8) = OR32_L_JR_R9;
  REG32(translate_space + PAGE_SIZE - 8) = OR32_L_JR_R9;
  REG32(translate_space + PAGE_SIZE - 4) = OR32_L_NOP;
  REG32(translate_space + PAGE_SIZE - 4) = OR32_L_NOP;
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE);
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE);
  REG32(translate_space + PAGE_SIZE) = OR32_L_JR_R9;
  REG32(translate_space + PAGE_SIZE) = OR32_L_JR_R9;
  REG32(translate_space + PAGE_SIZE + 4) = OR32_L_NOP;
  REG32(translate_space + PAGE_SIZE + 4) = OR32_L_NOP;
  // Flush these areas incase cache doesn't write them through immediately
  // Flush these areas incase cache doesn't write them through immediately
  mtspr(SPR_DCBFR, translate_space-8);
  mtspr(SPR_DCBFR, translate_space-8);
  mtspr(SPR_DCBFR, translate_space);
  mtspr(SPR_DCBFR, translate_space);
  mtspr(SPR_DCBFR, translate_space+4);
  mtspr(SPR_DCBFR, translate_space+4);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE - 8);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE - 8);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE - 4);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE - 4);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE + 4);
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE + 4);
 
 
  /* 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);
  // Space we'll access and expect the MMU to translate our requests
  // Space we'll access and expect the MMU to translate our requests
  unsigned long match_space = (PAGE_SIZE*DTLB_SETS) + (set*PAGE_SIZE);
  unsigned long match_space = (PAGE_SIZE*DTLB_SETS) + (set*PAGE_SIZE);
  while (add != 0x00000000) {
  while (add != 0x00000000) {
    mtspr (SPR_ITLBMR_BASE(way) + set,  match_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBMR_BASE(way) + set,  match_space | SPR_ITLBMR_V);
    mtspr (SPR_ITLBTR_BASE(way) + set,  translate_space | ITLB_PR_NOLIMIT);
    mtspr (SPR_ITLBTR_BASE(way) + set,  translate_space | 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 < TEXT_START_ADD) || (t_add >= TEXT_END_ADD))) {
    //if (((t_add < RAM_START) || (t_add >= DATA_END_ADD)) && ((t_add < TEXT_START_ADD) || (t_add >= TEXT_END_ADD))) {
 
 
      /* Jump on last address of previous page */
      /* Jump on last address of previous page */
      call (match_space - 8);
      call (match_space - 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 (match_space);
      call (match_space);
      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 (match_space + PAGE_SIZE - 8);
      call (match_space + 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 (match_space + PAGE_SIZE);
      call (match_space + 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;
    match_space = add + (set*PAGE_SIZE);
    match_space = 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);
    }
    }
  }
  }
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  /* 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;
 
 
  printf("itlb_valid_bit_test set = %d\n", set);
  printf("itlb_valid_bit_test set = %d\n", set);
 
 
  /* 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 = TEXT_START_ADD + (i*PAGE_SIZE);
    ea = TEXT_START_ADD + (i*PAGE_SIZE);
    ta = TEXT_START_ADD + (i*PAGE_SIZE);
    ta = TEXT_START_ADD + (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 after the program code */
  /* Resetv ITLBMR for every way after the program code */
  for (i = TLB_TEXT_SET_NB; i < ITLB_WAYS; i++) {
  for (i = TLB_TEXT_SET_NB; 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();
  // Address we'll jump to and expect it to be translated
  // Address we'll jump to and expect it to be translated
  unsigned long match_space = (PAGE_SIZE*ITLB_SETS) + (set*PAGE_SIZE);
  unsigned long match_space = (PAGE_SIZE*ITLB_SETS) + (set*PAGE_SIZE);
  // Address that we will actually access
  // Address that we will actually access
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  /* Perform jumps to address, that is not in ITLB */
  /* Perform jumps to address, that is not in ITLB */
  printf("writing program to 0x%.8lx\n", translate_space);
  printf("writing program to 0x%.8lx\n", translate_space);
  REG32(translate_space) = OR32_L_JR_R9;
  REG32(translate_space) = OR32_L_JR_R9;
  REG32(translate_space+4) = OR32_L_NOP;
  REG32(translate_space+4) = OR32_L_NOP;
  mtspr(SPR_DCBFR, translate_space);
  mtspr(SPR_DCBFR, translate_space);
  mtspr(SPR_DCBFR, translate_space+4);
  mtspr(SPR_DCBFR, translate_space+4);
  printf("jumping to 0x%.8lx, should be itlb miss\n",match_space);
  printf("jumping to 0x%.8lx, should be itlb miss\n",match_space);
  call (match_space);
  call (match_space);
 
 
  /* Check if there was ITLB miss */
  /* Check if there was ITLB miss */
  ASSERT(itlb_miss_count == 1);
  ASSERT(itlb_miss_count == 1);
  ASSERT(itlb_miss_ea == match_space);
  ASSERT(itlb_miss_ea == match_space);
 
 
  /* 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;
  printf("jumping to 0x%.8lx again - should not be a miss\n", match_space);
  printf("jumping to 0x%.8lx again - should not be a miss\n", match_space);
  /* Perform jumps to address, that is now in ITLB */
  /* Perform jumps to address, that is now in ITLB */
  call (match_space);
  call (match_space);
 
 
  /* 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);
  }
  }
  printf("jumping to 0x%.8lx again - mmu entries invalidated, so should be a miss\n", match_space);
  printf("jumping to 0x%.8lx again - mmu entries invalidated, so should be a miss\n", match_space);
  /* Perform jumps to address, that is now in ITLB but is invalid */
  /* Perform jumps to address, that is now in ITLB but is invalid */
  call (match_space);
  call (match_space);
 
 
  /* Check if there was ITLB miss */
  /* Check if there was ITLB miss */
  ASSERT(itlb_miss_count == 1);
  ASSERT(itlb_miss_count == 1);
  ASSERT(itlb_miss_ea == match_space);
  ASSERT(itlb_miss_ea == match_space);
 
 
  /* Disable IMMU */
  /* Disable IMMU */
  immu_disable ();
  immu_disable ();
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  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_permission_test (int set)
int itlb_permission_test (int set)
{
{
  int i, j;
  int i, j;
  unsigned long ea, ta;
  unsigned long ea, ta;
 
 
  printf("itlb_permission_test set = %d\n", set);
  printf("itlb_permission_test set = %d\n", set);
 
 
  /* 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 = TEXT_START_ADD + (i*PAGE_SIZE);
    ea = TEXT_START_ADD + (i*PAGE_SIZE);
    ta = TEXT_START_ADD + (i*PAGE_SIZE);
    ta = TEXT_START_ADD + (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);
  }
  }
 
 
  // Address that we will actually access
  // Address that we will actually access
  unsigned long match_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
  unsigned long match_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
 
 
  /* Set match register */
  /* Set match register */
  mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + set, match_space | SPR_ITLBMR_V);
  mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + set, match_space | 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 */
  REG32(match_space+0x0) = OR32_L_JR_R9;
  REG32(match_space+0x0) = OR32_L_JR_R9;
  REG32(match_space+0x4) = OR32_L_NOP;
  REG32(match_space+0x4) = OR32_L_NOP;
  REG32(match_space+0x8) = OR32_L_JR_R9;
  REG32(match_space+0x8) = OR32_L_JR_R9;
  REG32(match_space+0xc) = OR32_L_NOP;
  REG32(match_space+0xc) = OR32_L_NOP;
  mtspr(SPR_DCBFR, match_space);
  mtspr(SPR_DCBFR, match_space);
  mtspr(SPR_DCBFR, match_space+4);
  mtspr(SPR_DCBFR, match_space+4);
  mtspr(SPR_DCBFR, match_space+8);
  mtspr(SPR_DCBFR, match_space+8);
  mtspr(SPR_DCBFR, match_space+12);
  mtspr(SPR_DCBFR, match_space+12);
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  immu_enable ();
  immu_enable ();
 
 
  /* Execute supervisor */
  /* Execute supervisor */
  printf("execute disable for supervisor - should cause ipage fault\n");
  printf("execute disable for supervisor - should cause ipage fault\n");
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, match_space | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_SXE));
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, match_space | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_SXE));
  printf("calling address 0x%.8lx\n", match_space);
  printf("calling address 0x%.8lx\n", match_space);
  call (match_space);
  call (match_space);
  ASSERT(ipage_fault_count == 1);
  ASSERT(ipage_fault_count == 1);
  call (match_space + 8);
  call (match_space + 8);
  ASSERT(ipage_fault_count == 1);
  ASSERT(ipage_fault_count == 1);
 
 
  /* Execute user */
  /* Execute user */
  printf("execute disable for user - should cause ipage fault\n");
  printf("execute disable for user - should cause ipage fault\n");
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_UXE;
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_UXE;
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, match_space | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_UXE));
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, match_space | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_UXE));
 
 
  /* Set user mode */
  /* Set user mode */
  printf("disabling supervisor mode\n");
  printf("disabling supervisor mode\n");
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SM);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SM);
  printf("calling address 0x%.8lx\n", match_space);
  printf("calling address 0x%.8lx\n", match_space);
  printf("instruction at jump space: 0x%.8lx\n",REG32(match_space));
  printf("instruction at jump space: 0x%.8lx\n",REG32(match_space));
  call (match_space);
  call (match_space);
  ASSERT(ipage_fault_count == 2);
  ASSERT(ipage_fault_count == 2);
  call (match_space + 8);
  call (match_space + 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 ();
 
 
  printf("-------------------------------------------\n");
  printf("-------------------------------------------\n");
 
 
  return 0;
  return 0;
}
}
 
 
int main (void)
int main (void)
{
{
  int i, j;
  int i, j;
 
 
  start_text_addr = (unsigned long*)&_stext;
  start_text_addr = (unsigned long*)&_stext;
  end_text_addr = (unsigned long*)&_endtext;
  end_text_addr = (unsigned long*)&_endtext;
  end_data_addr = (unsigned long*)&_stack;
  end_data_addr = (unsigned long*)&_stack;
 
  end_data_addr += 4;
 
 
#ifndef TLB_BOTTOM_TEST_PAGE_HARDSET
#ifndef TLB_BOTTOM_TEST_PAGE_HARDSET
  TLB_TEXT_SET_NB =  TLB_DATA_SET_NB = (end_data_addr+PAGE_SIZE) / PAGE_SIZE;
  TLB_TEXT_SET_NB =  TLB_DATA_SET_NB = (end_data_addr+PAGE_SIZE) / PAGE_SIZE;
#endif
#endif
 
 
#ifdef _UART_H_
#ifdef _UART_H_
  uart_init(DEFAULT_UART);
  uart_init(DEFAULT_UART);
#endif
#endif
 
 
  i = j = 0; /* Get rid of warnings */
  i = j = 0; /* Get rid of warnings */
 
 
  /* Register bus error handler */
  /* Register bus error handler */
  add_handler(0x2, bus_err_handler);
  add_handler(0x2, bus_err_handler);
 
 
  /* Register illegal insn handler */
  /* Register illegal insn handler */
  add_handler(0x7, ill_insn_handler);
  add_handler(0x7, ill_insn_handler);
 
 
  /* Register sys call handler */
  /* Register sys call handler */
  add_handler(0xc, sys_call_handler);
  add_handler(0xc, sys_call_handler);
  // Skip all DTLB tests for now while we tweak itlb ones...
  // Skip all DTLB tests for now while we tweak itlb ones...
 
 
#if DO_DMMU_TESTS==1
#if DO_DMMU_TESTS==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++) {
#ifdef SHORT_TEST
#ifdef SHORT_TEST
    for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
    for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
#else
#else
    for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
    for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
#endif
#endif
      dtlb_match_test (j, i);
      dtlb_match_test (j, i);
  }
  }
 
 
  /* Valid bit testing */
  /* Valid bit testing */
 
 
#ifdef SHORT_TEST
#ifdef SHORT_TEST
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
#else
#else
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
#endif
#endif
      dtlb_valid_bit_test (i);
      dtlb_valid_bit_test (i);
 
 
  /* Permission test */
  /* Permission test */
#ifdef SHORT_TEST
#ifdef SHORT_TEST
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
#else
#else
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
#endif
#endif
    dtlb_permission_test (i);
    dtlb_permission_test (i);
 
 
  /* Data cache test */
  /* Data cache test */
 
 
#ifndef OR1200_NO_DC
#ifndef OR1200_NO_DC
#ifdef SHORT_TEST
#ifdef SHORT_TEST
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
#else
#else
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 2); i++)
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 2); i++)
#endif
#endif
    dtlb_dcache_test (i);
    dtlb_dcache_test (i);
#endif // ifndef OR1200_NO_DC
#endif // ifndef OR1200_NO_DC
 
 
 
 
#endif
#endif
 
 
 
 
  /* 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++) {
#ifdef SHORT_TEST
#ifdef SHORT_TEST
  for (i = TLB_DATA_SET_NB + 1; i < (TLB_DATA_SET_NB+4 - 1); i++)
  for (i = TLB_DATA_SET_NB + 1; i < (TLB_DATA_SET_NB+4 - 1); i++)
#else
#else
  for (i = TLB_DATA_SET_NB + 1; i < (ITLB_SETS - 1); i++)
  for (i = TLB_DATA_SET_NB + 1; i < (ITLB_SETS - 1); i++)
#endif
#endif
      itlb_match_test (j, i);
      itlb_match_test (j, i);
  }
  }
 
 
  /* Valid bit testing */
  /* Valid bit testing */
#ifdef SHORT_TEST
#ifdef SHORT_TEST
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB+4 - 1); i++)
#else
#else
  for (i = TLB_DATA_SET_NB; i < (ITLB_SETS - 1); i++)
  for (i = TLB_DATA_SET_NB; i < (ITLB_SETS - 1); i++)
#endif
#endif
    itlb_valid_bit_test (i);
    itlb_valid_bit_test (i);
 
 
 
 
 
 
  /* Permission test */
  /* Permission test */
#ifdef SHORT_TEST
#ifdef SHORT_TEST
  for (i = TLB_TEXT_SET_NB; i < (TLB_TEXT_SET_NB + 4); i++)
  for (i = TLB_TEXT_SET_NB; i < (TLB_TEXT_SET_NB + 4); i++)
#else
#else
  for (i = TLB_TEXT_SET_NB; i < (ITLB_SETS - 1); i++)
  for (i = TLB_TEXT_SET_NB; i < (ITLB_SETS - 1); i++)
#endif
#endif
    itlb_permission_test (i);
    itlb_permission_test (i);
 
 
 
 
  printf("Tests completed\n");
  printf("Tests completed\n");
  report (0xdeaddead);
  report (0xdeaddead);
  report (0x8000000d);
  report (0x8000000d);
  exit (0);
  exit (0);
}
}
 
 

powered by: WebSVN 2.1.0

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