/* 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
|
Copyright (C) 2008 Embecosm Limited
|
Copyright (C) 2008 Embecosm Limited
|
|
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
|
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify it
|
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 the Free
|
under the terms of the GNU General Public License as published by the Free
|
Software Foundation; either version 3 of the License, or (at your option)
|
Software Foundation; either version 3 of the License, or (at your option)
|
any later version.
|
any later version.
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
more details.
|
more details.
|
|
|
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
/* This program is commented throughout in a fashion suitable for processing
|
/* This program is commented throughout in a fashion suitable for processing
|
with Doxygen. */
|
with Doxygen. */
|
|
|
|
|
/* Autoconf and/or portability configuration */
|
/* Autoconf and/or portability configuration */
|
#include "config.h"
|
#include "config.h"
|
#include "port.h"
|
#include "port.h"
|
|
|
/* System includes */
|
/* System includes */
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <time.h>
|
#include <time.h>
|
|
|
/* Package includes */
|
/* Package includes */
|
#include "arch.h"
|
#include "arch.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "mc.h"
|
#include "mc.h"
|
#include "toplevel-support.h"
|
#include "toplevel-support.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,
|
MT_EXITNOPS
|
MT_EXITNOPS
|
} type;
|
} type;
|
};
|
};
|
|
|
static uint32_t
|
static uint32_t
|
simmem_read32 (oraddr_t addr, void *dat)
|
simmem_read32 (oraddr_t addr, void *dat)
|
{
|
{
|
return *(uint32_t *) (dat + addr);
|
return *(uint32_t *) (dat + addr);
|
}
|
}
|
|
|
static uint16_t
|
static uint16_t
|
simmem_read16 (oraddr_t addr, void *dat)
|
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
|
}
|
}
|
|
|
static uint8_t
|
static uint8_t
|
simmem_read8 (oraddr_t addr, void *dat)
|
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
|
}
|
}
|
|
|
static void
|
static void
|
simmem_write32 (oraddr_t addr, uint32_t value, void *dat)
|
simmem_write32 (oraddr_t addr, uint32_t value, void *dat)
|
{
|
{
|
*(uint32_t *) (dat + addr) = value;
|
*(uint32_t *) (dat + addr) = value;
|
}
|
}
|
|
|
static void
|
static void
|
simmem_write16 (oraddr_t addr, uint16_t value, void *dat)
|
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
|
}
|
}
|
|
|
static void
|
static void
|
simmem_write8 (oraddr_t addr, uint8_t value, void *dat)
|
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
|
}
|
}
|
|
|
static uint32_t
|
static uint32_t
|
simmem_read_zero32 (oraddr_t addr, void *dat)
|
simmem_read_zero32 (oraddr_t addr, void *dat)
|
{
|
{
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr,
|
fprintf (stderr,
|
"WARNING: 32-bit memory read from non-read memory area 0x%"
|
"WARNING: 32-bit memory read from non-read memory area 0x%"
|
PRIxADDR ".\n", addr);
|
PRIxADDR ".\n", addr);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static uint16_t
|
static uint16_t
|
simmem_read_zero16 (oraddr_t addr, void *dat)
|
simmem_read_zero16 (oraddr_t addr, void *dat)
|
{
|
{
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr,
|
fprintf (stderr,
|
"WARNING: 16-bit memory read from non-read memory area 0x%"
|
"WARNING: 16-bit memory read from non-read memory area 0x%"
|
PRIxADDR ".\n", addr);
|
PRIxADDR ".\n", addr);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static uint8_t
|
static uint8_t
|
simmem_read_zero8 (oraddr_t addr, void *dat)
|
simmem_read_zero8 (oraddr_t addr, void *dat)
|
{
|
{
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr,
|
fprintf (stderr,
|
"WARNING: 8-bit memory read from non-read memory area 0x%"
|
"WARNING: 8-bit memory read from non-read memory area 0x%"
|
PRIxADDR ".\n", addr);
|
PRIxADDR ".\n", addr);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static void
|
static void
|
simmem_write_null32 (oraddr_t addr, uint32_t value, void *dat)
|
simmem_write_null32 (oraddr_t addr, uint32_t value, void *dat)
|
{
|
{
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr,
|
fprintf (stderr,
|
"WARNING: 32-bit memory write to 0x%" PRIxADDR ", non-write "
|
"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);
|
}
|
}
|
|
|
static void
|
static void
|
simmem_write_null16 (oraddr_t addr, uint16_t value, void *dat)
|
simmem_write_null16 (oraddr_t addr, uint16_t value, void *dat)
|
{
|
{
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr,
|
fprintf (stderr,
|
"WARNING: 16-bit memory write to 0x%" PRIxADDR ", non-write "
|
"WARNING: 16-bit memory write to 0x%" PRIxADDR ", non-write "
|
"memory area (value 0x%08" PRIx16 ").\n", addr, value);
|
"memory area (value 0x%08" PRIx16 ").\n", addr, value);
|
}
|
}
|
|
|
static void
|
static void
|
simmem_write_null8 (oraddr_t addr, uint8_t value, void *dat)
|
simmem_write_null8 (oraddr_t addr, uint8_t value, void *dat)
|
{
|
{
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr,
|
fprintf (stderr,
|
"WARNING: 8-bit memory write to 0x%" PRIxADDR ", non-write "
|
"WARNING: 8-bit memory write to 0x%" PRIxADDR ", non-write "
|
"memory area (value 0x%08" PRIx8 ").\n", addr, value);
|
"memory area (value 0x%08" PRIx8 ").\n", addr, value);
|
}
|
}
|
|
|
static void
|
static void
|
mem_reset (void *dat)
|
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 */
|
/* srandom (seed); */
|
PRINTF ("Seeding random generator with value %d\n", seed);
|
/* /\* Print out the seed just in case we ever need to debug *\/ */
|
|
/* 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;
|
case MT_EXITNOPS:
|
case MT_EXITNOPS:
|
/* Fill memory with OR1K exit NOP */
|
/* Fill memory with OR1K exit NOP */
|
for (i = 0; i < mem->size; i++, mem_area++)
|
for (i = 0; i < mem->size; i++, mem_area++)
|
switch(i & 0x3) {
|
switch(i & 0x3) {
|
case 3:
|
case 3:
|
*mem_area = 0x15;
|
*mem_area = 0x15;
|
break;
|
break;
|
case 0:
|
case 0:
|
*mem_area = 0x01;
|
*mem_area = 0x01;
|
break;
|
break;
|
default:
|
default:
|
*mem_area = 0x00;
|
*mem_area = 0x00;
|
break;
|
break;
|
}
|
}
|
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 ]---*/
|
static void
|
static void
|
memory_random_seed (union param_val val, void *dat)
|
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;
|
}
|
}
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Set the memory pattern
|
/*!Set the memory pattern
|
|
|
Value must be up to 8 bits. Larger values are truncated with a warning.
|
Value must be up to 8 bits. Larger values are truncated with a warning.
|
|
|
@param[in] val The value to use
|
@param[in] val The value to use
|
@param[in] dat The config data structure */
|
@param[in] dat The config data structure */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
memory_pattern (union param_val val, void *dat)
|
memory_pattern (union param_val val, void *dat)
|
{
|
{
|
struct mem_config *mem = dat;
|
struct mem_config *mem = dat;
|
|
|
if (val.int_val > 0xff)
|
if (val.int_val > 0xff)
|
{
|
{
|
fprintf (stderr, "Warning: memory pattern exceeds 8-bits: truncated\n");
|
fprintf (stderr, "Warning: memory pattern exceeds 8-bits: truncated\n");
|
}
|
}
|
|
|
mem->pattern = val.int_val & 0xff;
|
mem->pattern = val.int_val & 0xff;
|
|
|
} /* memory_pattern() */
|
} /* memory_pattern() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Set the memory type
|
/*!Set the memory type
|
|
|
Value must be one of unknown, random, pattern or zero (case
|
Value must be one of unknown, random, pattern or zero (case
|
insensitive). Unrecognized values are ignored with a warning.
|
insensitive). Unrecognized values are ignored with a warning.
|
|
|
@param[in] val The value to use
|
@param[in] val The value to use
|
@param[in] dat The config data structure */
|
@param[in] dat The config data structure */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
memory_type (union param_val val, void *dat)
|
memory_type (union param_val val, void *dat)
|
{
|
{
|
struct mem_config *mem = dat;
|
struct mem_config *mem = dat;
|
|
|
if (0 == strcasecmp (val.str_val, "unknown"))
|
if (0 == strcasecmp (val.str_val, "unknown"))
|
{
|
{
|
mem->type = MT_UNKNOWN;
|
mem->type = MT_UNKNOWN;
|
}
|
}
|
else if (0 == strcasecmp (val.str_val, "random"))
|
else if (0 == strcasecmp (val.str_val, "random"))
|
{
|
{
|
mem->type = MT_RANDOM;
|
mem->type = MT_RANDOM;
|
}
|
}
|
else if (0 == strcasecmp (val.str_val, "pattern"))
|
else if (0 == strcasecmp (val.str_val, "pattern"))
|
{
|
{
|
mem->type = MT_PATTERN;
|
mem->type = MT_PATTERN;
|
}
|
}
|
else if (0 == strcasecmp (val.str_val, "zero"))
|
else if (0 == strcasecmp (val.str_val, "zero"))
|
{
|
{
|
mem->type = MT_PATTERN;
|
mem->type = MT_PATTERN;
|
mem->pattern = 0;
|
mem->pattern = 0;
|
}
|
}
|
else if (0 == strcasecmp (val.str_val, "exitnops"))
|
else if (0 == strcasecmp (val.str_val, "exitnops"))
|
{
|
{
|
mem->type = MT_EXITNOPS;
|
mem->type = MT_EXITNOPS;
|
mem->pattern = 0;
|
mem->pattern = 0;
|
}
|
}
|
else
|
else
|
{
|
{
|
fprintf (stderr, "Warning: memory type invalid. Ignored");
|
fprintf (stderr, "Warning: memory type invalid. Ignored");
|
}
|
}
|
} /* memory_type() */
|
} /* memory_type() */
|
|
|
|
|
static void
|
static void
|
memory_ce (union param_val val, void *dat)
|
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;
|
}
|
}
|
|
|
static void
|
static void
|
memory_mc (union param_val val, void *dat)
|
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;
|
}
|
}
|
|
|
static void
|
static void
|
memory_baseaddr (union param_val val, void *dat)
|
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;
|
}
|
}
|
|
|
static void
|
static void
|
memory_size (union param_val val, void *dat)
|
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 */
|
static void
|
static void
|
memory_name (union param_val val, void *dat)
|
memory_name (union param_val val, void *dat)
|
{
|
{
|
struct mem_config *mem = dat;
|
struct mem_config *mem = dat;
|
|
|
if (NULL != mem->name)
|
if (NULL != mem->name)
|
{
|
{
|
free (mem->name);
|
free (mem->name);
|
}
|
}
|
|
|
mem->name = strdup (val.str_val);
|
mem->name = strdup (val.str_val);
|
}
|
}
|
|
|
static void
|
static void
|
memory_log (union param_val val, void *dat)
|
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);
|
}
|
}
|
|
|
static void
|
static void
|
memory_delayr (union param_val val, void *dat)
|
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;
|
}
|
}
|
|
|
static void
|
static void
|
memory_delayw (union param_val val, void *dat)
|
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;
|
}
|
}
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Initialize a new block of memory configuration
|
/*!Initialize a new block of memory configuration
|
|
|
ALL parameters are set explicitly to default values.
|
ALL parameters are set explicitly to default values.
|
|
|
@return The new memory configuration data structure */
|
@return The new memory configuration data structure */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void *
|
static void *
|
memory_sec_start ()
|
memory_sec_start ()
|
{
|
{
|
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->type = MT_UNKNOWN;
|
mem->type = MT_UNKNOWN;
|
mem->random_seed = -1;
|
mem->random_seed = -1;
|
mem->pattern = 0;
|
mem->pattern = 0;
|
mem->baseaddr = 0;
|
mem->baseaddr = 0;
|
mem->size = 1024;
|
mem->size = 1024;
|
mem->name = strdup ("anonymous memory block");
|
mem->name = strdup ("anonymous memory block");
|
mem->ce = -1;
|
mem->ce = -1;
|
mem->mc = 0;
|
mem->mc = 0;
|
mem->delayr = 1;
|
mem->delayr = 1;
|
mem->delayw = 1;
|
mem->delayw = 1;
|
mem->log = NULL;
|
mem->log = NULL;
|
|
|
return mem;
|
return mem;
|
|
|
} /* memory_sec_start() */
|
} /* memory_sec_start() */
|
|
|
|
|
static void
|
static void
|
memory_sec_end (void *dat)
|
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,
|
fprintf (stderr,
|
"Unable to allocate memory at %" PRIxADDR ", length %i\n",
|
"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
|
void
|
reg_memory_sec (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, "type", PARAMT_WORD, memory_type);
|
reg_config_param (sec, "type", PARAMT_WORD, memory_type);
|
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, "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, "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, "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);
|
reg_config_param (sec, "log", PARAMT_STR, memory_log);
|
reg_config_param (sec, "log", PARAMT_STR, memory_log);
|
}
|
}
|
|
|