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

Subversion Repositories or1k_old

[/] [or1k_old/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [testbench/] [mmu.c] - Diff between revs 412 and 413

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

Rev 412 Rev 413
Line 4... Line 4...
#include "support.h"
#include "support.h"
 
 
/* Define RAM physical location and size
/* Define RAM physical location and size
   Bottom half will be used for this program, the rest
   Bottom half will be used for this program, the rest
   will be used for testing */
   will be used for testing */
 
#define FLASH_START 0x00000000
 
#define FLASH_SIZE  0x00200000
#define RAM_START 0x40000000
#define RAM_START 0x40000000
#define RAM_SIZE  0x00200000
#define RAM_SIZE  0x00200000
 
 
/* What is the last address in ram that is used by this program */
/* What is the last address in ram that is used by this program */
#define CODE_END_ADD (RAM_START + (RAM_SIZE / 2))
#define TEXT_END_ADD (FLASH_START + (FLASH_SIZE / 2))
 
#define DATA_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) */
Line 41... Line 44...
                          SPR_DTLBTR_SWE  )
                          SPR_DTLBTR_SWE  )
 
 
/* fails if x is false */
/* fails if x is false */
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
 
 
 
#define TEST_JUMP(x) 
 
 
/* 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 */
Line 104... Line 109...
    }
    }
  }
  }
 
 
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 < CODE_END_ADD)) {
  if ((RAM_START <= ea) && (ea < DATA_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) | TLB_PR_NOLIMIT);
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | TLB_PR_NOLIMIT);
    return;
    return;
  }
  }
Line 116... Line 121...
  /* Update DTLB miss counter and EA */
  /* Update DTLB miss counter and EA */
  dtlb_miss_count++;
  dtlb_miss_count++;
  dtlb_miss_ea = ea;
  dtlb_miss_ea = ea;
 
 
  /* Whatever access is in progress, translated address have to point to physical RAM */
  /* Whatever access is in progress, translated address have to point to physical RAM */
  ta = (ea & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2);
  ta = (ea & ((RAM_SIZE/2) - 1)) + DATA_END_ADD;
printf("ta = %.8lx\n", ta);
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:
Line 152... Line 157...
 
 
 
 
/* ITLB miss exception handler */
/* ITLB miss exception handler */
void itlb_miss_handler (void)
void itlb_miss_handler (void)
{
{
 
  unsigned long ea, ta, tlbtr;
 
  int set, way = 0;
 
  int i;
 
 
 
  /* Get EA that cause the exception */
 
  ea = mfspr (SPR_EEAR_BASE);
 
 
 
  /* Find TLB set and LRU way */
 
  set = (ea / PAGE_SIZE) % ITLB_SETS;
 
  for (i = 0; i < ITLB_WAYS; i++) {
 
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_LRU) == 0) {
 
      way = i;
 
      break;
 
    }
 
  }
 
 
 
printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
 
 
 
  if ((FLASH_START <= ea) && (ea < TEXT_END_ADD)) {
 
    /* 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_ITLBTR_BASE(way) + set, (ea & SPR_ITLBTR_PPN) | TLB_PR_NOLIMIT);
 
    return;
 
  }
 
 
 
  /* Update ITLB miss counter and EA */
 
  itlb_miss_count++;
 
  itlb_miss_ea = ea;
 
 
 
  /* Whatever access is in progress, translated address have to point to physical RAM */
 
  ta = (ea & ((FLASH_SIZE/2) - 1)) + TEXT_END_ADD;
 
printf("ta = %.8lx\n", ta);
 
 
 
  /* Set appropriate TLB entry */
 
  switch (itlb_val & TLB_CODE_MASK) {
 
    case TLB_CODE_ONE_TO_ONE:
 
      tlbtr = (ta & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
 
printf("1: tlbtr = %.8lx\n", tlbtr);
 
      break;
 
    case TLB_CODE_PLUS_ONE_PAGE:
 
      if ((ta + PAGE_SIZE) >= (FLASH_START + FLASH_SIZE))
 
        /* Wrapp last page */
 
        tlbtr = (((ta & ((FLASH_SIZE/2) - 1)) + TEXT_END_ADD) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
 
      else
 
        tlbtr = ((ta + PAGE_SIZE) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
 
printf("2: tlbtr = %.8lx\n", tlbtr);
 
      break;
 
    case TLB_CODE_MINUS_ONE_PAGE:
 
      if ((ta - PAGE_SIZE) < TEXT_END_ADD)
 
        /* Wrapp first page */
 
        tlbtr = ((ta - PAGE_SIZE + (FLASH_SIZE/2)) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
 
      else
 
        tlbtr = ((ta - PAGE_SIZE) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
 
printf("3: tlbtr = %.8lx\n", tlbtr);
 
      break;
 
  }
 
 
 
  /* Set ITLB entry */
 
  mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
 
  mtspr (SPR_ITLBTR_BASE(way) + set, tlbtr);
}
}
 
 
/* Invalidate all entries in DTLB and enable DMMU */
/* Invalidate all entries in DTLB and enable DMMU */
void dmmu_enable (void)
void dmmu_enable (void)
{
{
Line 266... Line 329...
  }
  }
 
 
  return 0;
  return 0;
}
}
 
 
 
/* 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 itlb_valid_bit_test (int set)
 
{
 
  int i;
 
 
 
  /* Reset ITLB miss counter and EA */
 
  itlb_miss_count = 0;
 
  itlb_miss_ea = 0;
 
 
 
  /* Set itlb permisions */
 
  itlb_val = TLB_PR_NOLIMIT;
 
 
 
  /* Resetv ITLBMR for every way */
 
  for (i = 0; i < ITLB_WAYS; i++) {
 
    mtspr (SPR_ITLBMR_BASE(i) + set, 0);
 
  }
 
 
 
  /* Perform jumps to address, that is not in ITLB */
 
  for (i = 0; i < ITLB_WAYS; i++) {
 
    TEST_JUMP(FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
 
 
 
    /* Check if there was ITLB miss */
 
    ASSERT(itlb_miss_count == (i + 1));
 
    ASSERT(itlb_miss_ea == (FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
 
  }
 
 
 
  /* Reset ITLB miss counter and EA */
 
  itlb_miss_count = 0;
 
  itlb_miss_ea = 0;
 
 
 
  /* Perform jumps to address, that is now in ITLB */
 
  for (i = 0; i < ITLB_WAYS; i++) {
 
    TEST_JUMP(FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
 
 
 
    /* Check if there was ITLB miss */
 
    ASSERT(itlb_miss_count == 0);
 
  }
 
 
 
  /* Reset valid bits */
 
  for (i = 0; i < ITLB_WAYS; i++) {
 
    mtspr (SPR_ITLBMR_BASE(i) + set, mfspr (SPR_ITLBMR_BASE(i) + set) & ~SPR_ITLBMR_V);
 
  }
 
 
 
  /* Perform jumps to address, that is now in ITLB but is invalid */
 
  for (i = 0; i < ITLB_WAYS; i++) {
 
    TEST_JUMP(FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
 
 
 
    /* Check if there was ITLB miss */
 
    ASSERT(itlb_miss_count == (i + 1));
 
    ASSERT(itlb_miss_ea == (FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
 
  }
 
 
 
  return 0;
 
}
 
 
int main (void)
int main (void)
{
{
  int i;
  int i;
 
 
Line 286... Line 398...
 
 
  /* Valid bit testing */
  /* Valid bit testing */
  for (i = 0; i < 15; i++)
  for (i = 0; i < 15; i++)
    dtlb_valid_bit_test (DTLB_SETS - i - 1);
    dtlb_valid_bit_test (DTLB_SETS - i - 1);
 
 
 
  /* Valid bit testing */
 
  for (i = 0; i < 15; i++)
 
    itlb_valid_bit_test (ITLB_SETS - i - 1);
 
 
  /* Write pattern */
  /* Write pattern */
//  write_pattern(0x40000000, 0x40100000);
//  write_pattern(0x40000000, 0x40100000);
 
 
  /* Enable IMMU */
  /* Enable IMMU */
//  immu_enable();
//  immu_enable();

powered by: WebSVN 2.1.0

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