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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_58/] [or1ksim/] [testbench/] [mmu.c] - Diff between revs 410 and 412

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

Rev 410 Rev 412
/* This is MMU test for OpenRISC 1200 */
/* This is MMU test for OpenRISC 1200 */
 
 
#include "spr_defs.h"
#include "spr_defs.h"
#include "support.h"
#include "support.h"
 
 
/* Define RAM physical location and size
/* Define RAM physical location and size
   Bottom half will be used for this program, the rest
   Bottom half will be used for this program, the rest
   will be used for testing */
   will be used for testing */
#define RAM_START 0x40000000
#define RAM_START 0x40000000
#define RAM_SIZE  0x00200000
#define RAM_SIZE  0x00200000
 
 
/* What is the last address in ram that is used by this program */
/* What is the last address in ram that is used by this program */
#define CODE_END_ADD (RAM_START + (RAM_SIZE / 2))
#define CODE_END_ADD (RAM_START + (RAM_SIZE / 2))
 
 
/* MMU page size */
/* MMU page size */
#define PAGE_SIZE 4096
#define PAGE_SIZE 4096
 
 
/* 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 16
#define DTLB_SETS 16
 
 
/* 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 2
#define DTLB_WAYS 2
 
 
/* 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 16
#define ITLB_SETS 16
 
 
/* 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 2
#define ITLB_WAYS 2
 
 
/* TLB mode codes */
/* TLB mode codes */
#define TLB_CODE_ONE_TO_ONE     0x00000000
#define TLB_CODE_ONE_TO_ONE     0x00000000
#define TLB_CODE_PLUS_ONE_PAGE  0x10000000
#define TLB_CODE_PLUS_ONE_PAGE  0x10000000
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
 
 
#define TLB_CODE_MASK 0xfffff000
#define TLB_CODE_MASK   0xfffff000
#define TLB_PR_MASK   0x00000fff
#define TLB_PR_MASK   0x00000fff
 
#define TLB_PR_NOLIMIT  ( SPR_DTLBTR_CI   | \
 
                          SPR_DTLBTR_URE  | \
 
                          SPR_DTLBTR_UWE  | \
 
                          SPR_DTLBTR_SRE  | \
 
                          SPR_DTLBTR_SWE  )
 
 
 
/* fails if x is false */
 
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
 
 
/* Extern functions */
/* Extern functions */
extern void lo_dmmu_en (void);
extern void lo_dmmu_en (void);
extern void lo_immu_en (void);
extern void lo_immu_en (void);
 
 
/* Global variables */
/* Global variables */
extern unsigned long ram_end;
extern unsigned long ram_end;
 
 
/* DTLB mode status */
/* DTLB mode status */
unsigned long dtlb_val;
unsigned long dtlb_val;
 
 
/* ITLB mode status */
/* ITLB mode status */
unsigned long itlb_val;
unsigned long itlb_val;
 
 
 
/* DTLB miss counter */
 
int dtlb_miss_count;
 
 
 
/* ITLB miss counter */
 
int itlb_miss_count;
 
 
 
/* EA of last DTLB miss exception */
 
unsigned long dtlb_miss_ea;
 
 
 
/* EA of last ITLB miss exception */
 
unsigned long itlb_miss_ea;
 
 
/*inline static
/*inline static
unsigned int dtlb_write_entry (int way, int entry, unsigned int val)
unsigned int dtlb_write_entry (int way, int entry, unsigned int val)
{
{
  mtspr (SPR_DTLBMR_BASE(way) + entry, val);
  mtspr (SPR_DTLBMR_BASE(way) + entry, val);
}
}
*/
*/
 
 
 
void fail (char *func, int line)
 
{
 
#ifndef __FUNCTION__
 
#define __FUNCTION__ "?"
 
#endif
 
  printf ("Test failed in %s:%i\n", func, line);
 
  report(0xeeeeeeee);
 
  exit (1);
 
}
 
 
/* 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);
printf("ea = %.8lx\n", ea);
 
  /* 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("set = %.8lx\n", set);
printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
  if (RAM_START < ea < CODE_END_ADD) {
 
 
 
printf("RAM_START< ea < CODE_END_ADD\n", ea);
  if ((RAM_START <= ea) && (ea < CODE_END_ADD)) {
    /* If this is acces to data of this program set one to one translation */
    /* If this is acces to data of this program set one to one translation */
    mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
    mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | SPR_DTLBTR_CI | SPR_DTLBTR_URE | SPR_DTLBTR_UWE | SPR_DTLBTR_SRE | SPR_DTLBTR_SWE);
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | TLB_PR_NOLIMIT);
    return;
    return;
  }
  }
 
 
 
  /* Update DTLB miss counter and EA */
 
  dtlb_miss_count++;
 
  dtlb_miss_ea = ea;
 
 
  /* Whatever access is in progress, translated address have to point to physical RAM */
  /* Whatever access is in progress, translated address have to point to physical RAM */
  ta = (ea & ((RAM_SIZE/2) - 1)) + RAM_START;
  ta = (ea & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2);
 
printf("ta = %.8lx\n", ta);
 
 
  /* Set appropriate TLB entry */
  /* Set appropriate TLB entry */
  switch (dtlb_val & TLB_CODE_MASK) {
  switch (dtlb_val & TLB_CODE_MASK) {
    case TLB_CODE_ONE_TO_ONE:
    case TLB_CODE_ONE_TO_ONE:
      tlbtr = (ta & SPR_DTLBTR_PPN) | (dtlb_val | TLB_PR_MASK);
      tlbtr = (ta & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
 
printf("1: tlbtr = %.8lx\n", tlbtr);
      break;
      break;
    case TLB_CODE_PLUS_ONE_PAGE:
    case TLB_CODE_PLUS_ONE_PAGE:
      if ((ta + PAGE_SIZE) >= (RAM_START + RAM_SIZE))
      if ((ta + PAGE_SIZE) >= (RAM_START + RAM_SIZE))
        /* Wrapp last page */
        /* Wrapp last page */
        tlbtr = (((ta & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val | TLB_PR_MASK);
        tlbtr = (((ta & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
      else
      else
        tlbtr = ((ta + PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val | TLB_PR_MASK);
        tlbtr = ((ta + PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
 
printf("2: tlbtr = %.8lx\n", tlbtr);
      break;
      break;
    case TLB_CODE_MINUS_ONE_PAGE:
    case TLB_CODE_MINUS_ONE_PAGE:
      if ((ta - PAGE_SIZE) < (RAM_START + (RAM_SIZE/2)))
      if ((ta - PAGE_SIZE) < (RAM_START + (RAM_SIZE/2)))
        /* Wrapp first page */
        /* Wrapp first page */
        tlbtr = ((ta - PAGE_SIZE + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val | TLB_PR_MASK);
        tlbtr = ((ta - PAGE_SIZE + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
      else
      else
        tlbtr = ((ta - PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val | TLB_PR_MASK);
        tlbtr = ((ta - PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
 
printf("3: tlbtr = %.8lx\n", tlbtr);
      break;
      break;
  }
  }
 
 
  /* 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);
}
}
 
 
 
 
/* ITLB miss exception handler */
/* ITLB miss exception handler */
void itlb_miss_handler (void)
void itlb_miss_handler (void)
{
{
 
 
 
 
}
}
 
 
/* Invalidate all entries in DTLB and enable DMMU */
/* Invalidate all entries in DTLB and enable DMMU */
void dmmu_enable (void)
void dmmu_enable (void)
{
{
  int i, j;
  int i, j;
 
 
  /* 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);
    }
    }
  }
  }
 
 
  /* Register DTLB miss handler */
  /* Register DTLB miss handler */
  excpt_dtlbmiss = (unsigned long)dtlb_miss_handler;
  excpt_dtlbmiss = (unsigned long)dtlb_miss_handler;
 
 
  /* Enable DMMU */
  /* Enable DMMU */
  lo_dmmu_en ();
  lo_dmmu_en ();
}
}
 
 
/* Invalidate all entries in ITLB and enable IMMU */
/* Invalidate all entries in ITLB and enable IMMU */
void immu_enable (void)
void immu_enable (void)
{
{
  int i, j;
  int i, j;
 
 
  /* 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; i++) {
    for (j = 0; j < ITLB_SETS; i++) {
      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);
    }
    }
  }
  }
 
 
  /* Register ITLB miss handler */
  /* Register ITLB miss handler */
  excpt_itlbmiss = (unsigned long)itlb_miss_handler;
  excpt_itlbmiss = (unsigned long)itlb_miss_handler;
 
 
  /* Enable IMMU */
  /* Enable IMMU */
  lo_immu_en ();
  lo_immu_en ();
}
}
 
 
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;
  }
  }
 
 
}
}
 
 
 
/* Valid bit test
 
   Set all ways of one set to be invalid, perform
 
   access so miss handler will set them to valid,
 
   try access again - there should be no miss exceptions */
 
int dtlb_valid_bit_test (int set)
 
{
 
  int i;
 
 
 
  /* Reset DTLB miss counter and EA */
 
  dtlb_miss_count = 0;
 
  dtlb_miss_ea = 0;
 
 
 
  /* Set dtlb permisions */
 
  dtlb_val = TLB_PR_NOLIMIT;
 
 
 
  /* Resetv DTLBMR for every way */
 
  for (i = 0; i < DTLB_WAYS; i++) {
 
    mtspr (SPR_DTLBMR_BASE(i) + set, 0);
 
  }
 
 
 
  /* Perform writes to address, that is not in DTLB */
 
  for (i = 0; i < DTLB_WAYS; i++) {
 
    REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) = i;
 
 
 
    /* Check if there was DTLB miss */
 
    ASSERT(dtlb_miss_count == (i + 1));
 
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
 
  }
 
 
 
  /* Reset DTLB miss counter and EA */
 
  dtlb_miss_count = 0;
 
  dtlb_miss_ea = 0;
 
 
 
  /* Perform reads to address, that is now in DTLB */
 
  for (i = 0; i < DTLB_WAYS; i++) {
 
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
 
 
 
    /* Check if there was DTLB miss */
 
    ASSERT(dtlb_miss_count == 0);
 
  }
 
 
 
  /* Reset valid bits */
 
  for (i = 0; i < DTLB_WAYS; i++) {
 
    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 */
 
  for (i = 0; i < DTLB_WAYS; i++) {
 
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
 
 
 
    /* Check if there was DTLB miss */
 
    ASSERT(dtlb_miss_count == (i + 1));
 
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
 
  }
 
 
 
  return 0;
 
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
int main (void)
int main (void)
{
{
 
  int i;
 
 
  dtlb_val = SPR_DTLBTR_CI | SPR_DTLBTR_URE | SPR_DTLBTR_UWE | SPR_DTLBTR_SRE | SPR_DTLBTR_SWE;
 
  /* Enable DMMU */
  /* Enable DMMU */
  dmmu_enable();
  dmmu_enable();
 
 
 
  /* Valid bit testing */
 
  for (i = 0; i < 15; i++)
 
    dtlb_valid_bit_test (DTLB_SETS - i - 1);
 
 
  /* Write pattern */
  /* Write pattern */
  write_pattern(0x40000000, 0x40100000);
//  write_pattern(0x40000000, 0x40100000);
 
 
  /* Enable IMMU */
  /* Enable IMMU */
//  immu_enable();
//  immu_enable();
 
 
  exit(0);
  exit(0);
  return 0;
  return 0;
}
}
 
 

powered by: WebSVN 2.1.0

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