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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [peripheral/] [memory.c] - Diff between revs 1586 and 1646

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

Rev 1586 Rev 1646
/* memory.c -- Generic memory model
/* memory.c -- Generic memory model
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
This file is part of OpenRISC 1000 Architectural Simulator.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#include <stdio.h>
#include <stdio.h>
#include <time.h>
#include <time.h>
#include <string.h>
#include <string.h>
 
 
#include "config.h"
#include "config.h"
 
 
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "port.h"
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "abstract.h"
#include "abstract.h"
#include "sim-config.h"
#include "sim-config.h"
 
 
struct mem_config {
struct mem_config {
  int ce;                         /* Which ce this memory is associated with */
  int ce;                         /* Which ce this memory is associated with */
  int mc;                         /* Which mc this memory is connected to */
  int mc;                         /* Which mc this memory is connected to */
  oraddr_t baseaddr;              /* Start address of the memory */
  oraddr_t baseaddr;              /* Start address of the memory */
  unsigned int size;              /* Memory size */
  unsigned int size;              /* Memory size */
  char *name;                     /* Memory type string */
  char *name;                     /* Memory type string */
  char *log;                      /* Memory log filename */
  char *log;                      /* Memory log filename */
  int delayr;                     /* Read cycles */
  int delayr;                     /* Read cycles */
  int delayw;                     /* Write cycles */
  int delayw;                     /* Write cycles */
 
 
  void *mem;                      /* malloced memory for this memory */
  void *mem;                      /* malloced memory for this memory */
 
 
  int pattern;                    /* A user specified memory initialization
  int pattern;                    /* A user specified memory initialization
                                   * pattern */
                                   * pattern */
  int random_seed;                /* Initialize the memory with random values,
  int random_seed;                /* Initialize the memory with random values,
                                   * starting with seed */
                                   * starting with seed */
  enum {
  enum {
    MT_UNKNOWN,
    MT_UNKNOWN,
    MT_PATTERN,
    MT_PATTERN,
    MT_RANDOM
    MT_RANDOM
  } type;
  } type;
};
};
 
 
uint32_t simmem_read32(oraddr_t addr, void *dat)
uint32_t simmem_read32(oraddr_t addr, void *dat)
{
{
  return *(uint32_t *)(dat + addr);
  return *(uint32_t *)(dat + addr);
}
}
 
 
uint16_t simmem_read16(oraddr_t addr, void *dat)
uint16_t simmem_read16(oraddr_t addr, void *dat)
{
{
#ifdef WORDS_BIGENDIAN
#ifdef WORDS_BIGENDIAN
  return *(uint16_t *)(dat + addr);
  return *(uint16_t *)(dat + addr);
#else
#else
  return *(uint16_t *)(dat + (addr ^ 2));
  return *(uint16_t *)(dat + (addr ^ 2));
#endif
#endif
}
}
 
 
uint8_t simmem_read8(oraddr_t addr, void *dat)
uint8_t simmem_read8(oraddr_t addr, void *dat)
{
{
#ifdef WORDS_BIGENDIAN
#ifdef WORDS_BIGENDIAN
  return *(uint8_t *)(dat + addr);
  return *(uint8_t *)(dat + addr);
#else
#else
  return *(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - (addr & 3))));
  return *(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - (addr & 3))));
#endif
#endif
}
}
 
 
void simmem_write32(oraddr_t addr, uint32_t value, void *dat)
void simmem_write32(oraddr_t addr, uint32_t value, void *dat)
{
{
  *(uint32_t *)(dat + addr) = value;
  *(uint32_t *)(dat + addr) = value;
}
}
 
 
void simmem_write16(oraddr_t addr, uint16_t value, void *dat)
void simmem_write16(oraddr_t addr, uint16_t value, void *dat)
{
{
#ifdef WORDS_BIGENDIAN
#ifdef WORDS_BIGENDIAN
  *(uint16_t *)(dat + addr) = value;
  *(uint16_t *)(dat + addr) = value;
#else
#else
  *(uint16_t *)(dat + (addr ^ 2)) = value;
  *(uint16_t *)(dat + (addr ^ 2)) = value;
#endif
#endif
}
}
 
 
void simmem_write8(oraddr_t addr, uint8_t value, void *dat)
void simmem_write8(oraddr_t addr, uint8_t value, void *dat)
{
{
#ifdef WORDS_BIGENDIAN
#ifdef WORDS_BIGENDIAN
  *(uint8_t *)(dat + addr) = value;
  *(uint8_t *)(dat + addr) = value;
#else
#else
  *(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - (addr & 3)))) = value;
  *(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - (addr & 3)))) = value;
#endif
#endif
}
}
 
 
uint32_t simmem_read_zero32(oraddr_t addr, void *dat)
uint32_t simmem_read_zero32(oraddr_t addr, void *dat)
{
{
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: 32-bit memory read from non-read memory area 0x%"
    fprintf (stderr, "WARNING: 32-bit memory read from non-read memory area 0x%"
                     PRIxADDR".\n", addr);
                     PRIxADDR".\n", addr);
  return 0;
  return 0;
}
}
 
 
uint16_t simmem_read_zero16(oraddr_t addr, void *dat)
uint16_t simmem_read_zero16(oraddr_t addr, void *dat)
{
{
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: 16-bit memory read from non-read memory area 0x%"
    fprintf (stderr, "WARNING: 16-bit memory read from non-read memory area 0x%"
                     PRIxADDR".\n", addr);
                     PRIxADDR".\n", addr);
  return 0;
  return 0;
}
}
 
 
uint8_t simmem_read_zero8(oraddr_t addr, void *dat)
uint8_t simmem_read_zero8(oraddr_t addr, void *dat)
{
{
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: 8-bit memory read from non-read memory area 0x%"
    fprintf (stderr, "WARNING: 8-bit memory read from non-read memory area 0x%"
                     PRIxADDR".\n", addr);
                     PRIxADDR".\n", addr);
  return 0;
  return 0;
}
}
 
 
void simmem_write_null32(oraddr_t addr, uint32_t value, void *dat)
void simmem_write_null32(oraddr_t addr, uint32_t value, void *dat)
{
{
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: 32-bit memory write to 0x%"PRIxADDR", non-write "
    fprintf (stderr, "WARNING: 32-bit memory write to 0x%"PRIxADDR", non-write "
                     "memory area (value 0x%08"PRIx32").\n", addr, value);
                     "memory area (value 0x%08"PRIx32").\n", addr, value);
}
}
 
 
void simmem_write_null16(oraddr_t addr, uint16_t value, void *dat)
void simmem_write_null16(oraddr_t addr, uint16_t value, void *dat)
{
{
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: 16-bit memory write to 0x%"PRIxADDR", non-write "
    fprintf (stderr, "WARNING: 16-bit memory write to 0x%"PRIxADDR", non-write "
                     "memory area (value 0x%08"PRIx32").\n", addr, value);
                     "memory area (value 0x%08"PRIx32").\n", addr, value);
}
}
 
 
void simmem_write_null8(oraddr_t addr, uint8_t value, void *dat)
void simmem_write_null8(oraddr_t addr, uint8_t value, void *dat)
{
{
  if (config.sim.verbose)
  if (config.sim.verbose)
    fprintf (stderr, "WARNING: 8-bit memory write to 0x%"PRIxADDR", non-write "
    fprintf (stderr, "WARNING: 8-bit memory write to 0x%"PRIxADDR", non-write "
                     "memory area (value 0x%08"PRIx32").\n", addr, value);
                     "memory area (value 0x%08"PRIx32").\n", addr, value);
}
}
 
 
void mem_reset(void *dat)
void mem_reset(void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  int seed;
  int seed;
  int i;
  int i;
  uint8_t *mem_area = mem->mem;
  uint8_t *mem_area = mem->mem;
 
 
  /* Initialize memory */
  /* Initialize memory */
  switch(mem->type) {
  switch(mem->type) {
  case MT_RANDOM:
  case MT_RANDOM:
    if (mem->random_seed == -1) {
    if (mem->random_seed == -1) {
      seed = time(NULL);
      seed = time(NULL);
      /* Print out the seed just in case we ever need to debug */
      /* Print out the seed just in case we ever need to debug */
      PRINTF("Seeding random generator with value %d\n", seed);
      PRINTF("Seeding random generator with value %d\n", seed);
    } else
    } else
      seed = mem->random_seed;
      seed = mem->random_seed;
    srandom(seed);
    srandom(seed);
 
 
    for(i = 0; i < mem->size; i++, mem_area++)
    for(i = 0; i < mem->size; i++, mem_area++)
      *mem_area = random() & 0xFF;
      *mem_area = random() & 0xFF;
    break;
    break;
  case MT_PATTERN:
  case MT_PATTERN:
    for(i = 0; i < mem->size; i++, mem_area++)
    for(i = 0; i < mem->size; i++, mem_area++)
      *mem_area = mem->pattern;
      *mem_area = mem->pattern;
    break;
    break;
  case MT_UNKNOWN:
  case MT_UNKNOWN:
    break;
    break;
  default:
  default:
    fprintf(stderr, "Invalid memory configuration type.\n");
    fprintf(stderr, "Invalid memory configuration type.\n");
    exit(1);
    exit(1);
  }
  }
}
}
 
 
/*-------------------------------------------------[ Memory configuration ]---*/
/*-------------------------------------------------[ Memory configuration ]---*/
void memory_random_seed(union param_val val, void *dat)
void memory_random_seed(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->random_seed = val.int_val;
  mem->random_seed = val.int_val;
}
}
 
 
void memory_pattern(union param_val val, void *dat)
void memory_pattern(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->pattern = val.int_val;
  mem->pattern = val.int_val;
}
}
 
 
void memory_type(union param_val val, void *dat)
void memory_type(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  if(!strcmp(val.str_val, "unknown"))
  if(!strcmp(val.str_val, "unknown"))
    mem->type = MT_UNKNOWN;
    mem->type = MT_UNKNOWN;
  else if(!strcmp (val.str_val, "random"))
  else if(!strcmp (val.str_val, "random"))
    mem->type = MT_RANDOM;
    mem->type = MT_RANDOM;
  else if(!strcmp (val.str_val, "pattern"))
  else if(!strcmp (val.str_val, "pattern"))
    mem->type = MT_PATTERN;
    mem->type = MT_PATTERN;
  else if(!strcmp (val.str_val, "zero")) {
  else if(!strcmp (val.str_val, "zero")) {
    mem->type = MT_PATTERN;
    mem->type = MT_PATTERN;
    mem->pattern = 0;
    mem->pattern = 0;
  } else {
  } else {
    char tmp[200];
    char tmp[200];
    sprintf (tmp, "invalid memory type '%s'.\n", val.str_val);
    sprintf (tmp, "invalid memory type '%s'.\n", val.str_val);
    CONFIG_ERROR(tmp);
    CONFIG_ERROR(tmp);
  }
  }
}
}
 
 
void memory_ce(union param_val val, void *dat)
void memory_ce(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->ce = val.int_val;
  mem->ce = val.int_val;
}
}
 
 
void memory_mc(union param_val val, void *dat)
void memory_mc(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->mc = val.int_val;
  mem->mc = val.int_val;
}
}
 
 
void memory_baseaddr(union param_val val, void *dat)
void memory_baseaddr(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->baseaddr = val.addr_val;
  mem->baseaddr = val.addr_val;
}
}
 
 
void memory_size(union param_val val, void *dat)
void memory_size(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->size = val.int_val;
  mem->size = val.int_val;
}
}
 
 
/* FIXME: Check use */
/* FIXME: Check use */
void memory_name(union param_val val, void *dat)
void memory_name(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->name = strdup(val.str_val);
  mem->name = strdup(val.str_val);
}
}
 
 
void memory_log(union param_val val, void *dat)
void memory_log(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->log = strdup(val.str_val);
  mem->log = strdup(val.str_val);
}
}
 
 
void memory_delayr(union param_val val, void *dat)
void memory_delayr(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->delayr = val.int_val;
  mem->delayr = val.int_val;
}
}
 
 
void memory_delayw(union param_val val, void *dat)
void memory_delayw(union param_val val, void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  mem->delayw = val.int_val;
  mem->delayw = val.int_val;
}
}
 
 
void *memory_sec_start(void)
void *memory_sec_start(void)
{
{
  struct mem_config *mem = malloc(sizeof(struct mem_config));
  struct mem_config *mem = malloc(sizeof(struct mem_config));
 
 
  if(!mem) {
  if(!mem) {
    fprintf(stderr, "Memory Peripheral: Run out of memory\n");
    fprintf(stderr, "Memory Peripheral: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
  mem->size = 0;
  mem->size = 0;
  mem->log = NULL;
  mem->log = NULL;
  mem->name = NULL;
  mem->name = NULL;
  mem->delayr = 1;
  mem->delayr = 1;
  mem->delayw = 1;
  mem->delayw = 1;
  mem->random_seed = -1;
  mem->random_seed = -1;
  mem->ce = -1;
  mem->ce = -1;
  mem->mc = 0;
  mem->mc = 0;
 
 
  return mem;
  return mem;
}
}
 
 
void memory_sec_end(void *dat)
void memory_sec_end(void *dat)
{
{
  struct mem_config *mem = dat;
  struct mem_config *mem = dat;
  struct dev_memarea *mema;
  struct dev_memarea *mema;
 
 
  struct mem_ops ops;
  struct mem_ops ops;
 
 
  if(!mem->size) {
  if(!mem->size) {
    free(dat);
    free(dat);
    return;
    return;
  }
  }
 
 
  /* Round up to the next 32-bit boundry */
  /* Round up to the next 32-bit boundry */
  if(mem->size & 3) {
  if(mem->size & 3) {
    mem->size &= ~3;
    mem->size &= ~3;
    mem->size += 4;
    mem->size += 4;
  }
  }
 
 
  if(!(mem->mem = malloc(mem->size))) {
  if(!(mem->mem = malloc(mem->size))) {
    fprintf(stderr, "Unable to allocate memory at %"PRIxADDR", length %i\n",
    fprintf(stderr, "Unable to allocate memory at %"PRIxADDR", length %i\n",
            mem->baseaddr, mem->size);
            mem->baseaddr, mem->size);
    exit(-1);
    exit(-1);
  }
  }
 
 
  if(mem->delayr > 0) {
  if(mem->delayr > 0) {
    ops.readfunc32 = simmem_read32;
    ops.readfunc32 = simmem_read32;
    ops.readfunc16 = simmem_read16;
    ops.readfunc16 = simmem_read16;
    ops.readfunc8 = simmem_read8;
    ops.readfunc8 = simmem_read8;
  } else {
  } else {
    ops.readfunc32 = simmem_read_zero32;
    ops.readfunc32 = simmem_read_zero32;
    ops.readfunc16 = simmem_read_zero16;
    ops.readfunc16 = simmem_read_zero16;
    ops.readfunc8 = simmem_read_zero8;
    ops.readfunc8 = simmem_read_zero8;
  }
  }
 
 
  if(mem->delayw > 0) {
  if(mem->delayw > 0) {
    ops.writefunc32 = simmem_write32;
    ops.writefunc32 = simmem_write32;
    ops.writefunc16 = simmem_write16;
    ops.writefunc16 = simmem_write16;
    ops.writefunc8 = simmem_write8;
    ops.writefunc8 = simmem_write8;
  } else {
  } else {
    ops.writefunc32 = simmem_write_null32;
    ops.writefunc32 = simmem_write_null32;
    ops.writefunc16 = simmem_write_null16;
    ops.writefunc16 = simmem_write_null16;
    ops.writefunc8 = simmem_write_null8;
    ops.writefunc8 = simmem_write_null8;
  }
  }
 
 
  ops.writeprog8 = simmem_write8;
  ops.writeprog8 = simmem_write8;
  ops.writeprog32 = simmem_write32;
  ops.writeprog32 = simmem_write32;
  ops.writeprog8_dat = mem->mem;
  ops.writeprog8_dat = mem->mem;
  ops.writeprog32_dat = mem->mem;
  ops.writeprog32_dat = mem->mem;
 
 
  ops.read_dat32 = mem->mem;
  ops.read_dat32 = mem->mem;
  ops.read_dat16 = mem->mem;
  ops.read_dat16 = mem->mem;
  ops.read_dat8 = mem->mem;
  ops.read_dat8 = mem->mem;
 
 
  ops.write_dat32 = mem->mem;
  ops.write_dat32 = mem->mem;
  ops.write_dat16 = mem->mem;
  ops.write_dat16 = mem->mem;
  ops.write_dat8 = mem->mem;
  ops.write_dat8 = mem->mem;
 
 
  ops.delayr = mem->delayr;
  ops.delayr = mem->delayr;
  ops.delayw = mem->delayw;
  ops.delayw = mem->delayw;
 
 
  ops.log = mem->log;
  ops.log = mem->log;
 
 
  mema = reg_mem_area(mem->baseaddr, mem->size, 0, &ops);
  mema = reg_mem_area(mem->baseaddr, mem->size, 0, &ops);
 
 
  /* Set valid */
  /* Set valid */
  /* FIXME: Should this be done during reset? */
  /* FIXME: Should this be done during reset? */
  set_mem_valid(mema, 1);
  set_mem_valid(mema, 1);
 
 
  if(mem->ce >= 0)
  if(mem->ce >= 0)
    mc_reg_mem_area(mema, mem->ce, mem->mc);
    mc_reg_mem_area(mema, mem->ce, mem->mc);
 
 
  reg_sim_reset(mem_reset, dat);
  reg_sim_reset(mem_reset, dat);
}
}
 
 
void reg_memory_sec(void)
void reg_memory_sec(void)
{
{
  struct config_section *sec = reg_config_sec("memory", memory_sec_start,
  struct config_section *sec = reg_config_sec("memory", memory_sec_start,
                                              memory_sec_end);
                                              memory_sec_end);
 
 
  reg_config_param(sec, "random_seed", paramt_int, memory_random_seed);
  reg_config_param(sec, "random_seed", paramt_int, memory_random_seed);
  reg_config_param(sec, "pattern", paramt_int, memory_pattern);
  reg_config_param(sec, "pattern", paramt_int, memory_pattern);
  reg_config_param(sec, "type", paramt_word, memory_type);
  reg_config_param(sec, "type", paramt_word, memory_type);
  reg_config_param(sec, "ce", paramt_int, memory_ce);
  reg_config_param(sec, "ce", paramt_int, memory_ce);
  reg_config_param(sec, "mc", paramt_int, memory_mc);
  reg_config_param(sec, "mc", paramt_int, memory_mc);
  reg_config_param(sec, "baseaddr", paramt_addr, memory_baseaddr);
  reg_config_param(sec, "baseaddr", paramt_addr, memory_baseaddr);
  reg_config_param(sec, "size", paramt_int, memory_size);
  reg_config_param(sec, "size", paramt_int, memory_size);
  reg_config_param(sec, "name", paramt_str, memory_name);
  reg_config_param(sec, "name", paramt_str, memory_name);
  reg_config_param(sec, "log", paramt_str, memory_log);
  reg_config_param(sec, "log", paramt_str, memory_log);
  reg_config_param(sec, "delayr", paramt_int, memory_delayr);
  reg_config_param(sec, "delayr", paramt_int, memory_delayr);
  reg_config_param(sec, "delayw", paramt_int, memory_delayw);
  reg_config_param(sec, "delayw", paramt_int, memory_delayw);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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