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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc3/] [or1ksim/] [peripheral/] [memory.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1486 nogj
/* memory.c -- Generic memory model
2 1748 jeremybenn
 
3 1486 nogj
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
5 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
6 1486 nogj
 
7 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8 1486 nogj
 
9 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10 1486 nogj
 
11 1748 jeremybenn
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15 1486 nogj
 
16 1748 jeremybenn
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20 1486 nogj
 
21 1748 jeremybenn
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
23 1486 nogj
 
24 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
25
   with Doxygen. */
26
 
27
 
28
/* Autoconf and/or portability configuration */
29 1486 nogj
#include "config.h"
30 1748 jeremybenn
#include "port.h"
31 1486 nogj
 
32 1748 jeremybenn
/* System includes */
33
#include <stdlib.h>
34
#include <stdio.h>
35
#include <time.h>
36 1486 nogj
 
37 1748 jeremybenn
/* Package includes */
38 1486 nogj
#include "arch.h"
39 1748 jeremybenn
#include "sim-config.h"
40 1486 nogj
#include "abstract.h"
41 1748 jeremybenn
#include "mc.h"
42
#include "toplevel-support.h"
43 1486 nogj
 
44
 
45 1748 jeremybenn
struct mem_config
46
{
47
  int ce;                       /* Which ce this memory is associated with */
48
  int mc;                       /* Which mc this memory is connected to */
49
  oraddr_t baseaddr;            /* Start address of the memory */
50
  unsigned int size;            /* Memory size */
51
  char *name;                   /* Memory type string */
52
  char *log;                    /* Memory log filename */
53
  int delayr;                   /* Read cycles */
54
  int delayw;                   /* Write cycles */
55 1486 nogj
 
56 1748 jeremybenn
  void *mem;                    /* malloced memory for this memory */
57
 
58
  int pattern;                  /* A user specified memory initialization
59
                                 * pattern */
60
  int random_seed;              /* Initialize the memory with random values,
61
                                 * starting with seed */
62
  enum
63
  {
64 1486 nogj
    MT_UNKNOWN,
65
    MT_PATTERN,
66
    MT_RANDOM
67
  } type;
68
};
69
 
70 1748 jeremybenn
static uint32_t
71
simmem_read32 (oraddr_t addr, void *dat)
72 1486 nogj
{
73 1748 jeremybenn
  return *(uint32_t *) (dat + addr);
74 1486 nogj
}
75
 
76 1748 jeremybenn
static uint16_t
77
simmem_read16 (oraddr_t addr, void *dat)
78 1486 nogj
{
79 1586 nogj
#ifdef WORDS_BIGENDIAN
80 1748 jeremybenn
  return *(uint16_t *) (dat + addr);
81 1586 nogj
#else
82 1748 jeremybenn
  return *(uint16_t *) (dat + (addr ^ 2));
83 1586 nogj
#endif
84 1486 nogj
}
85
 
86 1748 jeremybenn
static uint8_t
87
simmem_read8 (oraddr_t addr, void *dat)
88 1486 nogj
{
89 1586 nogj
#ifdef WORDS_BIGENDIAN
90 1748 jeremybenn
  return *(uint8_t *) (dat + addr);
91 1586 nogj
#else
92 1748 jeremybenn
  return *(uint8_t *) (dat + ((addr & ~ADDR_C (3)) | (3 - (addr & 3))));
93 1586 nogj
#endif
94 1486 nogj
}
95
 
96 1748 jeremybenn
static void
97
simmem_write32 (oraddr_t addr, uint32_t value, void *dat)
98 1486 nogj
{
99 1748 jeremybenn
  *(uint32_t *) (dat + addr) = value;
100 1486 nogj
}
101
 
102 1748 jeremybenn
static void
103
simmem_write16 (oraddr_t addr, uint16_t value, void *dat)
104 1486 nogj
{
105 1586 nogj
#ifdef WORDS_BIGENDIAN
106 1748 jeremybenn
  *(uint16_t *) (dat + addr) = value;
107 1586 nogj
#else
108 1748 jeremybenn
  *(uint16_t *) (dat + (addr ^ 2)) = value;
109 1586 nogj
#endif
110 1486 nogj
}
111
 
112 1748 jeremybenn
static void
113
simmem_write8 (oraddr_t addr, uint8_t value, void *dat)
114 1486 nogj
{
115 1586 nogj
#ifdef WORDS_BIGENDIAN
116 1748 jeremybenn
  *(uint8_t *) (dat + addr) = value;
117 1586 nogj
#else
118 1748 jeremybenn
  *(uint8_t *) (dat + ((addr & ~ADDR_C (3)) | (3 - (addr & 3)))) = value;
119 1586 nogj
#endif
120 1486 nogj
}
121
 
122 1748 jeremybenn
static uint32_t
123
simmem_read_zero32 (oraddr_t addr, void *dat)
124 1486 nogj
{
125
  if (config.sim.verbose)
126 1748 jeremybenn
    fprintf (stderr,
127
             "WARNING: 32-bit memory read from non-read memory area 0x%"
128
             PRIxADDR ".\n", addr);
129 1486 nogj
  return 0;
130
}
131
 
132 1748 jeremybenn
static uint16_t
133
simmem_read_zero16 (oraddr_t addr, void *dat)
134 1486 nogj
{
135
  if (config.sim.verbose)
136 1748 jeremybenn
    fprintf (stderr,
137
             "WARNING: 16-bit memory read from non-read memory area 0x%"
138
             PRIxADDR ".\n", addr);
139 1486 nogj
  return 0;
140
}
141
 
142 1748 jeremybenn
static uint8_t
143
simmem_read_zero8 (oraddr_t addr, void *dat)
144 1486 nogj
{
145
  if (config.sim.verbose)
146 1748 jeremybenn
    fprintf (stderr,
147
             "WARNING: 8-bit memory read from non-read memory area 0x%"
148
             PRIxADDR ".\n", addr);
149 1486 nogj
  return 0;
150
}
151
 
152 1748 jeremybenn
static void
153
simmem_write_null32 (oraddr_t addr, uint32_t value, void *dat)
154 1486 nogj
{
155
  if (config.sim.verbose)
156 1748 jeremybenn
    fprintf (stderr,
157
             "WARNING: 32-bit memory write to 0x%" PRIxADDR ", non-write "
158
             "memory area (value 0x%08" PRIx32 ").\n", addr, value);
159 1486 nogj
}
160
 
161 1748 jeremybenn
static void
162
simmem_write_null16 (oraddr_t addr, uint16_t value, void *dat)
163 1486 nogj
{
164
  if (config.sim.verbose)
165 1748 jeremybenn
    fprintf (stderr,
166
             "WARNING: 16-bit memory write to 0x%" PRIxADDR ", non-write "
167 1751 jeremybenn
             "memory area (value 0x%08" PRIx16 ").\n", addr, value);
168 1486 nogj
}
169
 
170 1748 jeremybenn
static void
171
simmem_write_null8 (oraddr_t addr, uint8_t value, void *dat)
172 1486 nogj
{
173
  if (config.sim.verbose)
174 1748 jeremybenn
    fprintf (stderr,
175
             "WARNING: 8-bit memory write to 0x%" PRIxADDR ", non-write "
176 1751 jeremybenn
             "memory area (value 0x%08" PRIx8 ").\n", addr, value);
177 1486 nogj
}
178
 
179 1748 jeremybenn
static void
180
mem_reset (void *dat)
181 1486 nogj
{
182
  struct mem_config *mem = dat;
183
  int seed;
184
  int i;
185
  uint8_t *mem_area = mem->mem;
186
 
187
  /* Initialize memory */
188 1748 jeremybenn
  switch (mem->type)
189
    {
190
    case MT_RANDOM:
191
      if (mem->random_seed == -1)
192
        {
193
          seed = time (NULL);
194
          /* Print out the seed just in case we ever need to debug */
195
          PRINTF ("Seeding random generator with value %d\n", seed);
196
        }
197
      else
198
        seed = mem->random_seed;
199
      srandom (seed);
200 1486 nogj
 
201 1748 jeremybenn
      for (i = 0; i < mem->size; i++, mem_area++)
202
        *mem_area = random () & 0xFF;
203
      break;
204
    case MT_PATTERN:
205
      for (i = 0; i < mem->size; i++, mem_area++)
206
        *mem_area = mem->pattern;
207
      break;
208
    case MT_UNKNOWN:
209
      break;
210
    default:
211
      fprintf (stderr, "Invalid memory configuration type.\n");
212
      exit (1);
213
    }
214 1486 nogj
}
215
 
216
/*-------------------------------------------------[ Memory configuration ]---*/
217 1748 jeremybenn
static void
218
memory_random_seed (union param_val val, void *dat)
219 1486 nogj
{
220
  struct mem_config *mem = dat;
221
  mem->random_seed = val.int_val;
222
}
223
 
224 1748 jeremybenn
/*---------------------------------------------------------------------------*/
225
/*!Set the memory pattern
226
 
227
   Value must be up to 8 bits. Larger values are truncated with a warning.
228
 
229
   @param[in] val  The value to use
230
   @param[in] dat  The config data structure                                 */
231
/*---------------------------------------------------------------------------*/
232
static void
233
memory_pattern (union param_val val, void *dat)
234 1486 nogj
{
235
  struct mem_config *mem = dat;
236
 
237 1748 jeremybenn
  if (val.int_val > 0xff)
238
    {
239
      fprintf (stderr, "Warning: memory pattern exceeds 8-bits: truncated\n");
240
    }
241
 
242
  mem->pattern = val.int_val & 0xff;
243
 
244
}       /* memory_pattern() */
245
 
246
 
247
/*---------------------------------------------------------------------------*/
248
/*!Set the memory type
249
 
250
   Value must be one of unknown, random, pattern or zero (case
251
   insensitive). Unrecognized values are ignored with a warning.
252
 
253
   @param[in] val  The value to use
254
   @param[in] dat  The config data structure                                 */
255
/*---------------------------------------------------------------------------*/
256
static void
257
memory_type (union param_val val, void *dat)
258 1486 nogj
{
259
  struct mem_config *mem = dat;
260
 
261 1748 jeremybenn
  if (0 == strcasecmp (val.str_val, "unknown"))
262
    {
263
      mem->type = MT_UNKNOWN;
264
    }
265
  else if (0 == strcasecmp (val.str_val, "random"))
266
    {
267
      mem->type = MT_RANDOM;
268
    }
269
  else if (0 == strcasecmp (val.str_val, "pattern"))
270
    {
271
      mem->type = MT_PATTERN;
272
    }
273
  else if (0 == strcasecmp (val.str_val, "zero"))
274
    {
275
      mem->type = MT_PATTERN;
276
      mem->pattern = 0;
277
    }
278
  else
279
    {
280
      fprintf (stderr, "Warning: memory type invalid. Ignored");
281
    }
282
}                               /* memory_type() */
283
 
284
 
285
static void
286
memory_ce (union param_val val, void *dat)
287 1486 nogj
{
288
  struct mem_config *mem = dat;
289
  mem->ce = val.int_val;
290
}
291
 
292 1748 jeremybenn
static void
293
memory_mc (union param_val val, void *dat)
294 1486 nogj
{
295
  struct mem_config *mem = dat;
296
  mem->mc = val.int_val;
297
}
298
 
299 1748 jeremybenn
static void
300
memory_baseaddr (union param_val val, void *dat)
301 1486 nogj
{
302
  struct mem_config *mem = dat;
303
  mem->baseaddr = val.addr_val;
304
}
305
 
306 1748 jeremybenn
static void
307
memory_size (union param_val val, void *dat)
308 1486 nogj
{
309
  struct mem_config *mem = dat;
310
  mem->size = val.int_val;
311
}
312
 
313
/* FIXME: Check use */
314 1748 jeremybenn
static void
315
memory_name (union param_val val, void *dat)
316 1486 nogj
{
317
  struct mem_config *mem = dat;
318 1748 jeremybenn
 
319
  if (NULL != mem->name)
320
    {
321
      free (mem->name);
322
    }
323
 
324
  mem->name = strdup (val.str_val);
325 1486 nogj
}
326
 
327 1748 jeremybenn
static void
328
memory_log (union param_val val, void *dat)
329 1486 nogj
{
330
  struct mem_config *mem = dat;
331 1748 jeremybenn
  mem->log = strdup (val.str_val);
332 1486 nogj
}
333
 
334 1748 jeremybenn
static void
335
memory_delayr (union param_val val, void *dat)
336 1486 nogj
{
337
  struct mem_config *mem = dat;
338
  mem->delayr = val.int_val;
339
}
340
 
341 1748 jeremybenn
static void
342
memory_delayw (union param_val val, void *dat)
343 1486 nogj
{
344
  struct mem_config *mem = dat;
345
  mem->delayw = val.int_val;
346
}
347
 
348 1748 jeremybenn
/*---------------------------------------------------------------------------*/
349
/*!Initialize a new block of memory configuration
350
 
351
   ALL parameters are set explicitly to default values.
352
 
353
   @return  The new memory configuration data structure                      */
354
/*---------------------------------------------------------------------------*/
355
static void *
356
memory_sec_start ()
357 1486 nogj
{
358 1748 jeremybenn
  struct mem_config *mem = malloc (sizeof (struct mem_config));
359 1486 nogj
 
360 1748 jeremybenn
  if (!mem)
361
    {
362
      fprintf (stderr, "Memory Peripheral: Run out of memory\n");
363
      exit (-1);
364
    }
365
 
366
  mem->type = MT_UNKNOWN;
367 1486 nogj
  mem->random_seed = -1;
368 1748 jeremybenn
  mem->pattern = 0;
369
  mem->baseaddr = 0;
370
  mem->size = 1024;
371
  mem->name = strdup ("anonymous memory block");
372 1486 nogj
  mem->ce = -1;
373
  mem->mc = 0;
374 1748 jeremybenn
  mem->delayr = 1;
375
  mem->delayw = 1;
376
  mem->log = NULL;
377 1486 nogj
 
378
  return mem;
379
 
380 1748 jeremybenn
}                               /* memory_sec_start() */
381
 
382
 
383
static void
384
memory_sec_end (void *dat)
385 1486 nogj
{
386
  struct mem_config *mem = dat;
387
  struct dev_memarea *mema;
388
 
389
  struct mem_ops ops;
390
 
391 1748 jeremybenn
  if (!mem->size)
392
    {
393
      free (dat);
394
      return;
395
    }
396 1486 nogj
 
397
  /* Round up to the next 32-bit boundry */
398 1748 jeremybenn
  if (mem->size & 3)
399
    {
400
      mem->size &= ~3;
401
      mem->size += 4;
402
    }
403 1486 nogj
 
404 1748 jeremybenn
  if (!(mem->mem = malloc (mem->size)))
405
    {
406
      fprintf (stderr,
407
               "Unable to allocate memory at %" PRIxADDR ", length %i\n",
408
               mem->baseaddr, mem->size);
409
      exit (-1);
410
    }
411 1486 nogj
 
412 1748 jeremybenn
  if (mem->delayr > 0)
413
    {
414
      ops.readfunc32 = simmem_read32;
415
      ops.readfunc16 = simmem_read16;
416
      ops.readfunc8 = simmem_read8;
417
    }
418
  else
419
    {
420
      ops.readfunc32 = simmem_read_zero32;
421
      ops.readfunc16 = simmem_read_zero16;
422
      ops.readfunc8 = simmem_read_zero8;
423
    }
424 1486 nogj
 
425 1748 jeremybenn
  if (mem->delayw > 0)
426
    {
427
      ops.writefunc32 = simmem_write32;
428
      ops.writefunc16 = simmem_write16;
429
      ops.writefunc8 = simmem_write8;
430
    }
431
  else
432
    {
433
      ops.writefunc32 = simmem_write_null32;
434
      ops.writefunc16 = simmem_write_null16;
435
      ops.writefunc8 = simmem_write_null8;
436
    }
437 1486 nogj
 
438 1556 nogj
  ops.writeprog8 = simmem_write8;
439
  ops.writeprog32 = simmem_write32;
440
  ops.writeprog8_dat = mem->mem;
441
  ops.writeprog32_dat = mem->mem;
442 1486 nogj
 
443
  ops.read_dat32 = mem->mem;
444
  ops.read_dat16 = mem->mem;
445
  ops.read_dat8 = mem->mem;
446
 
447
  ops.write_dat32 = mem->mem;
448
  ops.write_dat16 = mem->mem;
449
  ops.write_dat8 = mem->mem;
450
 
451
  ops.delayr = mem->delayr;
452
  ops.delayw = mem->delayw;
453
 
454
  ops.log = mem->log;
455
 
456 1748 jeremybenn
  mema = reg_mem_area (mem->baseaddr, mem->size, 0, &ops);
457 1486 nogj
 
458
  /* Set valid */
459
  /* FIXME: Should this be done during reset? */
460 1748 jeremybenn
  set_mem_valid (mema, 1);
461 1486 nogj
 
462 1748 jeremybenn
  if (mem->ce >= 0)
463
    mc_reg_mem_area (mema, mem->ce, mem->mc);
464 1486 nogj
 
465 1748 jeremybenn
  reg_sim_reset (mem_reset, dat);
466 1486 nogj
}
467
 
468 1748 jeremybenn
void
469
reg_memory_sec (void)
470 1486 nogj
{
471 1748 jeremybenn
  struct config_section *sec = reg_config_sec ("memory", memory_sec_start,
472
                                               memory_sec_end);
473 1486 nogj
 
474 1748 jeremybenn
  reg_config_param (sec, "type", paramt_word, memory_type);
475
  reg_config_param (sec, "random_seed", paramt_int, memory_random_seed);
476
  reg_config_param (sec, "pattern", paramt_int, memory_pattern);
477
  reg_config_param (sec, "baseaddr", paramt_addr, memory_baseaddr);
478
  reg_config_param (sec, "size", paramt_int, memory_size);
479
  reg_config_param (sec, "name", paramt_str, memory_name);
480
  reg_config_param (sec, "ce", paramt_int, memory_ce);
481
  reg_config_param (sec, "mc", paramt_int, memory_mc);
482
  reg_config_param (sec, "delayr", paramt_int, memory_delayr);
483
  reg_config_param (sec, "delayw", paramt_int, memory_delayw);
484
  reg_config_param (sec, "log", paramt_str, memory_log);
485 1486 nogj
}

powered by: WebSVN 2.1.0

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