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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [memory.c] - Blame information for rev 471

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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