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

Subversion Repositories openrisc_me

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

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 486 jeremybenn
          /* seed = time (NULL); */
195
          /* srandom (seed); */
196
          /* /\* Print out the seed just in case we ever need to debug *\/ */
197
          /* PRINTF ("Seeding random generator with value %d\n", seed); */
198 19 jeremybenn
        }
199
      else
200 486 jeremybenn
        {
201
          seed = mem->random_seed;
202
          srandom (seed);
203
        }
204 19 jeremybenn
 
205
      for (i = 0; i < mem->size; i++, mem_area++)
206
        *mem_area = random () & 0xFF;
207
      break;
208
    case MT_PATTERN:
209
      for (i = 0; i < mem->size; i++, mem_area++)
210
        *mem_area = mem->pattern;
211
      break;
212
    case MT_UNKNOWN:
213
      break;
214 418 julius
    case MT_EXITNOPS:
215
      /* Fill memory with OR1K exit NOP */
216
      for (i = 0; i < mem->size; i++, mem_area++)
217
        switch(i & 0x3) {
218
        case 3:
219
          *mem_area = 0x15;
220
          break;
221
        case 0:
222
          *mem_area = 0x01;
223
          break;
224
        default:
225
          *mem_area = 0x00;
226
          break;
227
        }
228
      break;
229 19 jeremybenn
    default:
230
      fprintf (stderr, "Invalid memory configuration type.\n");
231
      exit (1);
232
    }
233
}
234
 
235
/*-------------------------------------------------[ Memory configuration ]---*/
236
static void
237
memory_random_seed (union param_val val, void *dat)
238
{
239
  struct mem_config *mem = dat;
240
  mem->random_seed = val.int_val;
241
}
242
 
243
/*---------------------------------------------------------------------------*/
244
/*!Set the memory pattern
245
 
246
   Value must be up to 8 bits. Larger values are truncated with a warning.
247
 
248
   @param[in] val  The value to use
249
   @param[in] dat  The config data structure                                 */
250
/*---------------------------------------------------------------------------*/
251
static void
252
memory_pattern (union param_val val, void *dat)
253
{
254
  struct mem_config *mem = dat;
255
 
256
  if (val.int_val > 0xff)
257
    {
258
      fprintf (stderr, "Warning: memory pattern exceeds 8-bits: truncated\n");
259
    }
260
 
261
  mem->pattern = val.int_val & 0xff;
262
 
263
}       /* memory_pattern() */
264
 
265
 
266
/*---------------------------------------------------------------------------*/
267
/*!Set the memory type
268
 
269
   Value must be one of unknown, random, pattern or zero (case
270
   insensitive). Unrecognized values are ignored with a warning.
271
 
272
   @param[in] val  The value to use
273
   @param[in] dat  The config data structure                                 */
274
/*---------------------------------------------------------------------------*/
275
static void
276
memory_type (union param_val val, void *dat)
277
{
278
  struct mem_config *mem = dat;
279
 
280
  if (0 == strcasecmp (val.str_val, "unknown"))
281
    {
282
      mem->type = MT_UNKNOWN;
283
    }
284
  else if (0 == strcasecmp (val.str_val, "random"))
285
    {
286
      mem->type = MT_RANDOM;
287
    }
288
  else if (0 == strcasecmp (val.str_val, "pattern"))
289
    {
290
      mem->type = MT_PATTERN;
291
    }
292
  else if (0 == strcasecmp (val.str_val, "zero"))
293
    {
294
      mem->type = MT_PATTERN;
295
      mem->pattern = 0;
296
    }
297 418 julius
  else if (0 == strcasecmp (val.str_val, "exitnops"))
298
    {
299
      mem->type = MT_EXITNOPS;
300
      mem->pattern = 0;
301
    }
302 19 jeremybenn
  else
303
    {
304
      fprintf (stderr, "Warning: memory type invalid. Ignored");
305
    }
306
}                               /* memory_type() */
307
 
308
 
309
static void
310
memory_ce (union param_val val, void *dat)
311
{
312
  struct mem_config *mem = dat;
313
  mem->ce = val.int_val;
314
}
315
 
316
static void
317
memory_mc (union param_val val, void *dat)
318
{
319
  struct mem_config *mem = dat;
320
  mem->mc = val.int_val;
321
}
322
 
323
static void
324
memory_baseaddr (union param_val val, void *dat)
325
{
326
  struct mem_config *mem = dat;
327
  mem->baseaddr = val.addr_val;
328
}
329
 
330
static void
331
memory_size (union param_val val, void *dat)
332
{
333
  struct mem_config *mem = dat;
334
  mem->size = val.int_val;
335
}
336
 
337
/* FIXME: Check use */
338
static void
339
memory_name (union param_val val, void *dat)
340
{
341
  struct mem_config *mem = dat;
342
 
343
  if (NULL != mem->name)
344
    {
345
      free (mem->name);
346
    }
347
 
348
  mem->name = strdup (val.str_val);
349
}
350
 
351
static void
352
memory_log (union param_val val, void *dat)
353
{
354
  struct mem_config *mem = dat;
355
  mem->log = strdup (val.str_val);
356
}
357
 
358
static void
359
memory_delayr (union param_val val, void *dat)
360
{
361
  struct mem_config *mem = dat;
362
  mem->delayr = val.int_val;
363
}
364
 
365
static void
366
memory_delayw (union param_val val, void *dat)
367
{
368
  struct mem_config *mem = dat;
369
  mem->delayw = val.int_val;
370
}
371
 
372
/*---------------------------------------------------------------------------*/
373
/*!Initialize a new block of memory configuration
374
 
375
   ALL parameters are set explicitly to default values.
376
 
377
   @return  The new memory configuration data structure                      */
378
/*---------------------------------------------------------------------------*/
379
static void *
380
memory_sec_start ()
381
{
382
  struct mem_config *mem = malloc (sizeof (struct mem_config));
383
 
384
  if (!mem)
385
    {
386
      fprintf (stderr, "Memory Peripheral: Run out of memory\n");
387
      exit (-1);
388
    }
389
 
390
  mem->type = MT_UNKNOWN;
391
  mem->random_seed = -1;
392
  mem->pattern = 0;
393
  mem->baseaddr = 0;
394
  mem->size = 1024;
395
  mem->name = strdup ("anonymous memory block");
396
  mem->ce = -1;
397
  mem->mc = 0;
398
  mem->delayr = 1;
399
  mem->delayw = 1;
400
  mem->log = NULL;
401
 
402
  return mem;
403
 
404
}                               /* memory_sec_start() */
405
 
406
 
407
static void
408
memory_sec_end (void *dat)
409
{
410
  struct mem_config *mem = dat;
411
  struct dev_memarea *mema;
412
 
413
  struct mem_ops ops;
414
 
415
  if (!mem->size)
416
    {
417
      free (dat);
418
      return;
419
    }
420
 
421
  /* Round up to the next 32-bit boundry */
422
  if (mem->size & 3)
423
    {
424
      mem->size &= ~3;
425
      mem->size += 4;
426
    }
427
 
428
  if (!(mem->mem = malloc (mem->size)))
429
    {
430
      fprintf (stderr,
431
               "Unable to allocate memory at %" PRIxADDR ", length %i\n",
432
               mem->baseaddr, mem->size);
433
      exit (-1);
434
    }
435
 
436
  if (mem->delayr > 0)
437
    {
438
      ops.readfunc32 = simmem_read32;
439
      ops.readfunc16 = simmem_read16;
440
      ops.readfunc8 = simmem_read8;
441
    }
442
  else
443
    {
444
      ops.readfunc32 = simmem_read_zero32;
445
      ops.readfunc16 = simmem_read_zero16;
446
      ops.readfunc8 = simmem_read_zero8;
447
    }
448
 
449
  if (mem->delayw > 0)
450
    {
451
      ops.writefunc32 = simmem_write32;
452
      ops.writefunc16 = simmem_write16;
453
      ops.writefunc8 = simmem_write8;
454
    }
455
  else
456
    {
457
      ops.writefunc32 = simmem_write_null32;
458
      ops.writefunc16 = simmem_write_null16;
459
      ops.writefunc8 = simmem_write_null8;
460
    }
461
 
462
  ops.writeprog8 = simmem_write8;
463
  ops.writeprog32 = simmem_write32;
464
  ops.writeprog8_dat = mem->mem;
465
  ops.writeprog32_dat = mem->mem;
466
 
467
  ops.read_dat32 = mem->mem;
468
  ops.read_dat16 = mem->mem;
469
  ops.read_dat8 = mem->mem;
470
 
471
  ops.write_dat32 = mem->mem;
472
  ops.write_dat16 = mem->mem;
473
  ops.write_dat8 = mem->mem;
474
 
475
  ops.delayr = mem->delayr;
476
  ops.delayw = mem->delayw;
477
 
478
  ops.log = mem->log;
479
 
480
  mema = reg_mem_area (mem->baseaddr, mem->size, 0, &ops);
481
 
482
  /* Set valid */
483
  /* FIXME: Should this be done during reset? */
484
  set_mem_valid (mema, 1);
485
 
486
  if (mem->ce >= 0)
487
    mc_reg_mem_area (mema, mem->ce, mem->mc);
488
 
489
  reg_sim_reset (mem_reset, dat);
490
}
491
 
492
void
493
reg_memory_sec (void)
494
{
495
  struct config_section *sec = reg_config_sec ("memory", memory_sec_start,
496
                                               memory_sec_end);
497
 
498 224 jeremybenn
  reg_config_param (sec, "type",        PARAMT_WORD, memory_type);
499
  reg_config_param (sec, "random_seed", PARAMT_INT, memory_random_seed);
500
  reg_config_param (sec, "pattern",     PARAMT_INT, memory_pattern);
501
  reg_config_param (sec, "baseaddr",    PARAMT_ADDR, memory_baseaddr);
502
  reg_config_param (sec, "size",        PARAMT_INT, memory_size);
503
  reg_config_param (sec, "name",        PARAMT_STR, memory_name);
504
  reg_config_param (sec, "ce",          PARAMT_INT, memory_ce);
505
  reg_config_param (sec, "mc",          PARAMT_INT, memory_mc);
506
  reg_config_param (sec, "delayr",      PARAMT_INT, memory_delayr);
507
  reg_config_param (sec, "delayw",      PARAMT_INT, memory_delayw);
508
  reg_config_param (sec, "log",         PARAMT_STR, memory_log);
509 19 jeremybenn
}

powered by: WebSVN 2.1.0

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