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

Subversion Repositories openrisc

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

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
    MT_RANDOM
67
  } type;
68
};
69
 
70
static uint32_t
71
simmem_read32 (oraddr_t addr, void *dat)
72
{
73
  return *(uint32_t *) (dat + addr);
74
}
75
 
76
static uint16_t
77
simmem_read16 (oraddr_t addr, void *dat)
78
{
79
#ifdef WORDS_BIGENDIAN
80
  return *(uint16_t *) (dat + addr);
81
#else
82
  return *(uint16_t *) (dat + (addr ^ 2));
83
#endif
84
}
85
 
86
static uint8_t
87
simmem_read8 (oraddr_t addr, void *dat)
88
{
89
#ifdef WORDS_BIGENDIAN
90
  return *(uint8_t *) (dat + addr);
91
#else
92
  return *(uint8_t *) (dat + ((addr & ~ADDR_C (3)) | (3 - (addr & 3))));
93
#endif
94
}
95
 
96
static void
97
simmem_write32 (oraddr_t addr, uint32_t value, void *dat)
98
{
99
  *(uint32_t *) (dat + addr) = value;
100
}
101
 
102
static void
103
simmem_write16 (oraddr_t addr, uint16_t value, void *dat)
104
{
105
#ifdef WORDS_BIGENDIAN
106
  *(uint16_t *) (dat + addr) = value;
107
#else
108
  *(uint16_t *) (dat + (addr ^ 2)) = value;
109
#endif
110
}
111
 
112
static void
113
simmem_write8 (oraddr_t addr, uint8_t value, void *dat)
114
{
115
#ifdef WORDS_BIGENDIAN
116
  *(uint8_t *) (dat + addr) = value;
117
#else
118
  *(uint8_t *) (dat + ((addr & ~ADDR_C (3)) | (3 - (addr & 3)))) = value;
119
#endif
120
}
121
 
122
static uint32_t
123
simmem_read_zero32 (oraddr_t addr, void *dat)
124
{
125
  if (config.sim.verbose)
126
    fprintf (stderr,
127
             "WARNING: 32-bit memory read from non-read memory area 0x%"
128
             PRIxADDR ".\n", addr);
129
  return 0;
130
}
131
 
132
static uint16_t
133
simmem_read_zero16 (oraddr_t addr, void *dat)
134
{
135
  if (config.sim.verbose)
136
    fprintf (stderr,
137
             "WARNING: 16-bit memory read from non-read memory area 0x%"
138
             PRIxADDR ".\n", addr);
139
  return 0;
140
}
141
 
142
static uint8_t
143
simmem_read_zero8 (oraddr_t addr, void *dat)
144
{
145
  if (config.sim.verbose)
146
    fprintf (stderr,
147
             "WARNING: 8-bit memory read from non-read memory area 0x%"
148
             PRIxADDR ".\n", addr);
149
  return 0;
150
}
151
 
152
static void
153
simmem_write_null32 (oraddr_t addr, uint32_t value, void *dat)
154
{
155
  if (config.sim.verbose)
156
    fprintf (stderr,
157
             "WARNING: 32-bit memory write to 0x%" PRIxADDR ", non-write "
158
             "memory area (value 0x%08" PRIx32 ").\n", addr, value);
159
}
160
 
161
static void
162
simmem_write_null16 (oraddr_t addr, uint16_t value, void *dat)
163
{
164
  if (config.sim.verbose)
165
    fprintf (stderr,
166
             "WARNING: 16-bit memory write to 0x%" PRIxADDR ", non-write "
167
             "memory area (value 0x%08" PRIx16 ").\n", addr, value);
168
}
169
 
170
static void
171
simmem_write_null8 (oraddr_t addr, uint8_t value, void *dat)
172
{
173
  if (config.sim.verbose)
174
    fprintf (stderr,
175
             "WARNING: 8-bit memory write to 0x%" PRIxADDR ", non-write "
176
             "memory area (value 0x%08" PRIx8 ").\n", addr, value);
177
}
178
 
179
static void
180
mem_reset (void *dat)
181
{
182
  struct mem_config *mem = dat;
183
  int seed;
184
  int i;
185
  uint8_t *mem_area = mem->mem;
186
 
187
  /* Initialize memory */
188
  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
 
201
      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
}
215
 
216
/*-------------------------------------------------[ Memory configuration ]---*/
217
static void
218
memory_random_seed (union param_val val, void *dat)
219
{
220
  struct mem_config *mem = dat;
221
  mem->random_seed = val.int_val;
222
}
223
 
224
/*---------------------------------------------------------------------------*/
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
{
235
  struct mem_config *mem = dat;
236
 
237
  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
{
259
  struct mem_config *mem = dat;
260
 
261
  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
{
288
  struct mem_config *mem = dat;
289
  mem->ce = val.int_val;
290
}
291
 
292
static void
293
memory_mc (union param_val val, void *dat)
294
{
295
  struct mem_config *mem = dat;
296
  mem->mc = val.int_val;
297
}
298
 
299
static void
300
memory_baseaddr (union param_val val, void *dat)
301
{
302
  struct mem_config *mem = dat;
303
  mem->baseaddr = val.addr_val;
304
}
305
 
306
static void
307
memory_size (union param_val val, void *dat)
308
{
309
  struct mem_config *mem = dat;
310
  mem->size = val.int_val;
311
}
312
 
313
/* FIXME: Check use */
314
static void
315
memory_name (union param_val val, void *dat)
316
{
317
  struct mem_config *mem = dat;
318
 
319
  if (NULL != mem->name)
320
    {
321
      free (mem->name);
322
    }
323
 
324
  mem->name = strdup (val.str_val);
325
}
326
 
327
static void
328
memory_log (union param_val val, void *dat)
329
{
330
  struct mem_config *mem = dat;
331
  mem->log = strdup (val.str_val);
332
}
333
 
334
static void
335
memory_delayr (union param_val val, void *dat)
336
{
337
  struct mem_config *mem = dat;
338
  mem->delayr = val.int_val;
339
}
340
 
341
static void
342
memory_delayw (union param_val val, void *dat)
343
{
344
  struct mem_config *mem = dat;
345
  mem->delayw = val.int_val;
346
}
347
 
348
/*---------------------------------------------------------------------------*/
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
{
358
  struct mem_config *mem = malloc (sizeof (struct mem_config));
359
 
360
  if (!mem)
361
    {
362
      fprintf (stderr, "Memory Peripheral: Run out of memory\n");
363
      exit (-1);
364
    }
365
 
366
  mem->type = MT_UNKNOWN;
367
  mem->random_seed = -1;
368
  mem->pattern = 0;
369
  mem->baseaddr = 0;
370
  mem->size = 1024;
371
  mem->name = strdup ("anonymous memory block");
372
  mem->ce = -1;
373
  mem->mc = 0;
374
  mem->delayr = 1;
375
  mem->delayw = 1;
376
  mem->log = NULL;
377
 
378
  return mem;
379
 
380
}                               /* memory_sec_start() */
381
 
382
 
383
static void
384
memory_sec_end (void *dat)
385
{
386
  struct mem_config *mem = dat;
387
  struct dev_memarea *mema;
388
 
389
  struct mem_ops ops;
390
 
391
  if (!mem->size)
392
    {
393
      free (dat);
394
      return;
395
    }
396
 
397
  /* Round up to the next 32-bit boundry */
398
  if (mem->size & 3)
399
    {
400
      mem->size &= ~3;
401
      mem->size += 4;
402
    }
403
 
404
  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
 
412
  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
 
425
  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
 
438
  ops.writeprog8 = simmem_write8;
439
  ops.writeprog32 = simmem_write32;
440
  ops.writeprog8_dat = mem->mem;
441
  ops.writeprog32_dat = mem->mem;
442
 
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
  mema = reg_mem_area (mem->baseaddr, mem->size, 0, &ops);
457
 
458
  /* Set valid */
459
  /* FIXME: Should this be done during reset? */
460
  set_mem_valid (mema, 1);
461
 
462
  if (mem->ce >= 0)
463
    mc_reg_mem_area (mema, mem->ce, mem->mc);
464
 
465
  reg_sim_reset (mem_reset, dat);
466
}
467
 
468
void
469
reg_memory_sec (void)
470
{
471
  struct config_section *sec = reg_config_sec ("memory", memory_sec_start,
472
                                               memory_sec_end);
473
 
474
  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
}

powered by: WebSVN 2.1.0

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