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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [cpu/] [common/] [abstract.c] - Diff between revs 1358 and 1359

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

Rev 1358 Rev 1359
Line 49... Line 49...
#include "dcache_model.h"
#include "dcache_model.h"
#include "icache_model.h"
#include "icache_model.h"
#include "debug.h"
#include "debug.h"
#include "stats.h"
#include "stats.h"
 
 
extern uorreg_t reg[];
 
extern char *disassembled;
extern char *disassembled;
 
 
/* This is an abstract+physical memory array rather than only physical
 
   memory array */
 
static uint32_t *simmem32;
 
 
 
/* Pointer to memory area descriptions that are assigned to individual
/* Pointer to memory area descriptions that are assigned to individual
   peripheral devices. */
   peripheral devices. */
struct dev_memarea *dev_list;
struct dev_memarea *dev_list;
 
 
/* Temporary variable to increase speed.  */
/* Temporary variable to increase speed.  */
Line 86... Line 81...
/* Register read and write function for a memory area.
/* Register read and write function for a memory area.
   addr is inside the area, if addr & addr_mask == addr_compare
   addr is inside the area, if addr & addr_mask == addr_compare
   (used also by peripheral devices like 16450 UART etc.) */
   (used also by peripheral devices like 16450 UART etc.) */
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare,
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare,
                         uint32_t size, unsigned granularity, unsigned mc_dev,
                         uint32_t size, unsigned granularity, unsigned mc_dev,
                         uint32_t (readfunc)(oraddr_t),
                         uint32_t (readfunc)(oraddr_t, void *),
                         void (writefunc)(oraddr_t, uint32_t))
                         void (writefunc)(oraddr_t, uint32_t, void *),
 
                         void *dat)
{
{
  struct dev_memarea **pptmp;
  struct dev_memarea **pptmp;
  unsigned int size_mask = bit_mask (size);
  unsigned int size_mask = bit_mask (size);
  int found_error = 0;
  int found_error = 0;
  addr_compare &= addr_mask;
  addr_compare &= addr_mask;
Line 134... Line 130...
  (*pptmp)->readfunc = readfunc;
  (*pptmp)->readfunc = readfunc;
  (*pptmp)->writefunc = writefunc;
  (*pptmp)->writefunc = writefunc;
  (*pptmp)->log = 0;
  (*pptmp)->log = 0;
  (*pptmp)->delayr = 2;
  (*pptmp)->delayr = 2;
  (*pptmp)->delayw = 2;
  (*pptmp)->delayw = 2;
 
  (*pptmp)->priv_dat = dat;
  (*pptmp)->next = NULL;
  (*pptmp)->next = NULL;
}
}
 
 
/* Register read and write function for a memory area.
/* Register read and write function for a memory area.
   Memory areas should be aligned. Memory area is rounded up to
   Memory areas should be aligned. Memory area is rounded up to
   fit the nearest 2^n aligment.
   fit the nearest 2^n aligment.
   (used also by peripheral devices like 16450 UART etc.)
   (used also by peripheral devices like 16450 UART etc.)
   If mc_dev is 1, this means that this device will be checked first for match
   If mc_dev is 1, this means that this device will be checked first for match
   and will be accessed in case in overlaping memory spaces.
   and will be accessed in case of overlaping memory spaces.
   Only one device can have this set to 1 (used for memory controller) */
   Only one device can have this set to 1 (used for memory controller) */
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity,
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity,
                         unsigned mc_dev,
                         unsigned mc_dev,
                         uint32_t (readfunc)(oraddr_t),
                         uint32_t (readfunc)(oraddr_t, void *),
                         void (writefunc)(oraddr_t, uint32_t))
                         void (writefunc)(oraddr_t, uint32_t, void *),
 
                         void *dat)
{
{
  unsigned int size_mask = bit_mask (size);
  unsigned int size_mask = bit_mask (size);
  unsigned int addr_mask = ~size_mask;
  unsigned int addr_mask = ~size_mask;
  register_memoryarea_mask (addr_mask, addr & addr_mask,
  register_memoryarea_mask (addr_mask, addr & addr_mask,
                      size_mask + 1, granularity, mc_dev,
                      size_mask + 1, granularity, mc_dev,
                      readfunc, writefunc);
                      readfunc, writefunc, dat);
}
}
 
 
 
 
/* Check if access is to registered area of memory. */
/* Check if access is to registered area of memory. */
inline struct dev_memarea *verify_memoryarea(oraddr_t addr)
inline struct dev_memarea *verify_memoryarea(oraddr_t addr)
Line 216... Line 214...
  uint32_t temp = 0;
  uint32_t temp = 0;
 
 
  if (verify_memoryarea(memaddr)) {
  if (verify_memoryarea(memaddr)) {
    switch(cur_area->granularity) {
    switch(cur_area->granularity) {
    case 4:
    case 4:
      temp = cur_area->readfunc(memaddr);
      temp = cur_area->readfunc(memaddr, cur_area->priv_dat);
      break;
      break;
    case 1:
    case 1:
      temp = cur_area->readfunc(memaddr) << 24;
      temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 24;
      temp |= cur_area->readfunc(memaddr + 1) << 16;
      temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat) << 16;
      temp |= cur_area->readfunc(memaddr + 2) << 8;
      temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat) << 8;
      temp |= cur_area->readfunc(memaddr + 3);
      temp |= cur_area->readfunc(memaddr + 3, cur_area->priv_dat);
      break;
      break;
    case 2:
    case 2:
      temp = cur_area->readfunc(memaddr) << 16;
      temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 16;
      temp |= cur_area->readfunc(memaddr + 2);
      temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat);
      break;
      break;
    default:
    default:
      /* if you add new memory granularity be sure to check the formula
      /* if you add new memory granularity be sure to check the formula
       * below for the read delay and fix it if necessery
       * below for the read delay and fix it if necessery
       */
       */
Line 260... Line 258...
  uint32_t temp = 0;
  uint32_t temp = 0;
 
 
  if (verify_memoryarea(memaddr)) {
  if (verify_memoryarea(memaddr)) {
    switch(cur_area->granularity) {
    switch(cur_area->granularity) {
    case 1:
    case 1:
      temp = cur_area->readfunc(memaddr) << 8;
      temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 8;
      temp |= cur_area->readfunc(memaddr + 1);
      temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayr * 2;
        runtime.sim.mem_cycles += cur_area->delayr * 2;
      break;
      break;
    case 2:
    case 2:
      temp = cur_area->readfunc(memaddr);
      temp = cur_area->readfunc(memaddr, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayr;
        runtime.sim.mem_cycles += cur_area->delayr;
      break;
      break;
    case 4:
    case 4:
      temp = evalsim_mem32_atomic (memaddr & ~UINT32_C(3), cpu_access);
      temp = evalsim_mem32_atomic (memaddr & ~UINT32_C(3), cpu_access);
Line 307... Line 305...
  uint32_t temp = 0;
  uint32_t temp = 0;
 
 
  if (verify_memoryarea(memaddr)) {
  if (verify_memoryarea(memaddr)) {
    switch(cur_area->granularity) {
    switch(cur_area->granularity) {
    case 1:
    case 1:
      temp = cur_area->readfunc(memaddr);
      temp = cur_area->readfunc(memaddr, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayr;
        runtime.sim.mem_cycles += cur_area->delayr;
      break;
      break;
    case 2:
    case 2:
      temp = evalsim_mem16_atomic (memaddr & ~ADDR_C(1), cpu_access);
      temp = evalsim_mem16_atomic (memaddr & ~ADDR_C(1), cpu_access);
Line 638... Line 636...
void setsim_mem32_atomic(oraddr_t memaddr, uint32_t value, int cpu_access)
void setsim_mem32_atomic(oraddr_t memaddr, uint32_t value, int cpu_access)
{
{
  if (verify_memoryarea(memaddr)) {
  if (verify_memoryarea(memaddr)) {
    switch(cur_area->granularity) {
    switch(cur_area->granularity) {
    case 4:
    case 4:
      cur_area->writefunc(memaddr, value);
      cur_area->writefunc(memaddr, value, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayw;
        runtime.sim.mem_cycles += cur_area->delayw;
      break;
      break;
    case 1:
    case 1:
      cur_area->writefunc(memaddr    , (value >> 24) & 0xFF);
      cur_area->writefunc(memaddr    , (value >> 24) & 0xFF, cur_area->priv_dat);
      cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF);
      cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF, cur_area->priv_dat);
      cur_area->writefunc(memaddr + 2, (value >>  8) & 0xFF);
      cur_area->writefunc(memaddr + 2, (value >>  8) & 0xFF, cur_area->priv_dat);
      cur_area->writefunc(memaddr + 3, (value      ) & 0xFF);
      cur_area->writefunc(memaddr + 3, (value      ) & 0xFF, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayw * 4;
        runtime.sim.mem_cycles += cur_area->delayw * 4;
      break;
      break;
    case 2:
    case 2:
      cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF);
      cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF, cur_area->priv_dat);
      cur_area->writefunc(memaddr + 2, value & 0xFFFF);
      cur_area->writefunc(memaddr + 2, value & 0xFFFF, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayw * 2;
        runtime.sim.mem_cycles += cur_area->delayw * 2;
      break;
      break;
    default:
    default:
      /* if you add new memory granularity be sure to check the formula
      /* if you add new memory granularity be sure to check the formula
Line 688... Line 686...
{
{
  uint32_t temp;
  uint32_t temp;
  if (verify_memoryarea(memaddr)) {
  if (verify_memoryarea(memaddr)) {
    switch(cur_area->granularity) {
    switch(cur_area->granularity) {
    case 1:
    case 1:
      cur_area->writefunc(memaddr, (value >> 8) & 0xFF);
      cur_area->writefunc(memaddr, (value >> 8) & 0xFF, cur_area->priv_dat);
      cur_area->writefunc(memaddr + 1, value & 0xFF);
      cur_area->writefunc(memaddr + 1, value & 0xFF, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayw * 2;
        runtime.sim.mem_cycles += cur_area->delayw * 2;
      break;
      break;
    case 2:
    case 2:
      cur_area->writefunc(memaddr, value & 0xFFFF);
      cur_area->writefunc(memaddr, value & 0xFFFF, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayw;
        runtime.sim.mem_cycles += cur_area->delayw;
      break;
      break;
    case 4:
    case 4:
      temp = evalsim_mem32_void(memaddr & ~ADDR_C(3));
      temp = evalsim_mem32_void(memaddr & ~ADDR_C(3));
Line 736... Line 734...
{
{
  uint32_t temp;
  uint32_t temp;
  if (verify_memoryarea(memaddr)) {
  if (verify_memoryarea(memaddr)) {
    switch (cur_area->granularity) {
    switch (cur_area->granularity) {
    case 1:
    case 1:
      cur_area->writefunc(memaddr, value);
      cur_area->writefunc(memaddr, value, cur_area->priv_dat);
      if (cpu_access)
      if (cpu_access)
        runtime.sim.mem_cycles += cur_area->delayw;
        runtime.sim.mem_cycles += cur_area->delayw;
      break;
      break;
    case 2:
    case 2:
      temp = evalsim_mem16_void (memaddr & ~ADDR_C(1));
      temp = evalsim_mem16_void (memaddr & ~ADDR_C(1));
Line 990... Line 988...
    if (nl)
    if (nl)
      PRINTF ("\n");
      PRINTF ("\n");
  }
  }
}
}
 
 
uint32_t simmem_read_word(oraddr_t addr) {
uint32_t simmem_read_word(oraddr_t addr, void *priv_dat) {
  return simmem32[(cur_area->misc + (addr & cur_area->size_mask)) >> 2];
  return *(uint32_t *)(priv_dat + (addr & cur_area->size_mask));
}
}
 
 
void simmem_write_word(oraddr_t addr, uint32_t value) {
void simmem_write_word(oraddr_t addr, uint32_t value, void *priv_dat) {
  simmem32[(cur_area->misc + (addr & cur_area->size_mask)) >> 2] = value;
  *(uint32_t *)(priv_dat + (addr & cur_area->size_mask)) = value;
}
}
 
 
uint32_t simmem_read_zero(oraddr_t addr) {
uint32_t simmem_read_zero(oraddr_t addr, void *dat) {
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: memory read from non-read memory area 0x%"
    fprintf (stderr, "WARNING: memory read from non-read memory area 0x%"
                     PRIxADDR".\n", addr);
                     PRIxADDR".\n", addr);
  return 0;
  return 0;
}
}
 
 
void simmem_write_null(oraddr_t addr, uint32_t value) {
void simmem_write_null(oraddr_t addr, uint32_t value, void *dat) {
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: memory write to 0x%"PRIxADDR", non-write memory area (value 0x%08"PRIx32").\n", addr, value);
    fprintf (stderr, "WARNING: memory write to 0x%"PRIxADDR", non-write memory area (value 0x%08"PRIx32").\n", addr, value);
}
}
 
 
/* Initialize memory table from a config struct */
/* Initialize memory table from a config struct */
 
 
void init_memory_table ()
void init_memory_table ()
{
{
  uint32_t memory_needed = 0;
 
 
 
  /* If nothing was defined, use default memory block */
  /* If nothing was defined, use default memory block */
  if (config.memory.nmemories) {
  if (config.memory.nmemories) {
    int i;
    int i;
    for (i = 0; i < config.memory.nmemories; i++) {
    for (i = 0; i < config.memory.nmemories; i++) {
      oraddr_t start = config.memory.table[i].baseaddr;
      oraddr_t start = config.memory.table[i].baseaddr;
      uint32_t length = config.memory.table[i].size;
      uint32_t length = config.memory.table[i].size;
      char *type = config.memory.table[i].name;
      char *type = config.memory.table[i].name;
      int rd = config.memory.table[i].delayr;
      int rd = config.memory.table[i].delayr;
      int wd = config.memory.table[i].delayw;
      int wd = config.memory.table[i].delayw;
      int ce = config.memory.table[i].ce;
      int ce = config.memory.table[i].ce;
 
      void *mem = malloc (length);
 
 
      if (config.sim.verbose)
      if (config.sim.verbose)
        debug (1, "%"PRIxADDR" %08"PRIx32" (%"PRIi32" KB): %s (activated by CE%i; read delay = %icyc, write delay = %icyc)\n",
        debug (1, "%"PRIxADDR" %08"PRIx32" (%"PRIi32" KB): %s (activated by CE%i; read delay = %icyc, write delay = %icyc)\n",
          start, length, length >> 10, type, ce, rd, wd);
          start, length, length >> 10, type, ce, rd, wd);
 
 
 
      if (!mem) {
 
        fprintf (stderr, "Failed to allocate sim memory. Aborting\n");
 
        exit (-1);
 
      }
 
 
      register_memoryarea(start, length, 4, 0, &simmem_read_word,
      register_memoryarea(start, length, 4, 0, &simmem_read_word,
                          &simmem_write_word);
                          &simmem_write_word, mem);
      cur_area->misc = memory_needed;
 
      cur_area->chip_select = ce;
      cur_area->chip_select = ce;
      cur_area->valid = 1;
      cur_area->valid = 1;
      cur_area->delayw = wd;
      cur_area->delayw = wd;
      cur_area->delayr = rd;
      cur_area->delayr = rd;
      if (config.memory.table[i].log[0] != '\0') {
      if (config.memory.table[i].log[0] != '\0') {
        if ((cur_area->log = fopen (config.memory.table[i].log, "wt+")) == NULL)
        if ((cur_area->log = fopen (config.memory.table[i].log, "wt+")) == NULL)
          fprintf (stderr, "WARNING: Cannot open '%s'.\n",
          fprintf (stderr, "WARNING: Cannot open '%s'.\n",
                   config.memory.table[i].log);
                   config.memory.table[i].log);
      } else
      } else
        cur_area->log = NULL;
        cur_area->log = NULL;
      memory_needed += cur_area->size;
 
    }
    }
    PRINTF ("\n");
    PRINTF ("\n");
  } else {
  } else {
 
    void *mem = malloc (DEFAULT_MEMORY_LEN);
    if (config.sim.verbose)
    if (config.sim.verbose)
      fprintf (stderr, "WARNING: Memory not defined, assuming standard configuration.\n");
      fprintf (stderr, "WARNING: Memory not defined, assuming standard configuration.\n");
 
 
 
    if (!mem) {
 
      fprintf (stderr, "Failed to allocate sim memory. Aborting\n");
 
      exit (-1);
 
    }
 
 
    register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 4, 0,
    register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 4, 0,
                        &simmem_read_word, &simmem_write_word);
                        &simmem_read_word, &simmem_write_word, mem);
    cur_area->misc = memory_needed;
 
    cur_area->chip_select = 0;
    cur_area->chip_select = 0;
    cur_area->valid = 1;
    cur_area->valid = 1;
    cur_area->delayw = 1;
    cur_area->delayw = 1;
    cur_area->delayr = 1;
    cur_area->delayr = 1;
    cur_area->log = NULL;
    cur_area->log = NULL;
    memory_needed += cur_area->size;
 
  }
 
 
 
  simmem32 = (uint32_t *) malloc (sizeof (uint32_t) * ((memory_needed + 3) / 4));
 
  if (!simmem32) {
 
    fprintf (stderr, "Failed to allocate sim memory. Aborting\n");
 
    exit (-1);
 
  }
  }
}
}
 
 
/* Changes read/write memory in read/write only */
/* Changes read/write memory in read/write only */
 
 

powered by: WebSVN 2.1.0

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