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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [mc.c] - Blame information for rev 72

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

Line No. Rev Author Line
1 19 jeremybenn
/* mc.c -- Simulation of Memory Controller
2
 
3
   Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Enable memory controller, via:
28
  section mc
29
    enable = 1
30
    POC = 0x13243545
31
  end
32
 
33
   Limitations:
34
    - memory refresh is not simulated
35
*/
36
 
37
 
38
/* Autoconf and/or portability configuration */
39
#include "config.h"
40
#include "port.h"
41
 
42
/* System includes */
43
#include <stdlib.h>
44
 
45
/* Package includes */
46
#include "arch.h"
47
#include "abstract.h"
48
#include "sim-config.h"
49
#include "toplevel-support.h"
50
#include "sim-cmd.h"
51
 
52
 
53
#define N_CE        8
54
 
55
#define MC_CSR      0x00
56
#define MC_POC      0x04
57
#define MC_BA_MASK  0x08
58
#define MC_CSC(i)   (0x10 + (i) * 8)
59
#define MC_TMS(i)   (0x14 + (i) * 8)
60
 
61
#define MC_ADDR_SPACE (MC_CSC(N_CE))
62
 
63
/* POC register field definition */
64
#define MC_POC_EN_BW_OFFSET       0
65
#define MC_POC_EN_BW_WIDTH        2
66
#define MC_POC_EN_MEMTYPE_OFFSET  2
67
#define MC_POC_EN_MEMTYPE_WIDTH   2
68
 
69
/* CSC register field definition */
70
#define MC_CSC_EN_OFFSET          0
71
#define MC_CSC_MEMTYPE_OFFSET     1
72
#define MC_CSC_MEMTYPE_WIDTH      2 
73
#define MC_CSC_BW_OFFSET          4
74
#define MC_CSC_BW_WIDTH           2
75
#define MC_CSC_MS_OFFSET          6
76
#define MC_CSC_MS_WIDTH           2
77
#define MC_CSC_WP_OFFSET          8
78
#define MC_CSC_BAS_OFFSET         9
79
#define MC_CSC_KRO_OFFSET        10
80
#define MC_CSC_PEN_OFFSET        11
81
#define MC_CSC_SEL_OFFSET        16
82
#define MC_CSC_SEL_WIDTH          8
83
 
84
#define MC_CSC_MEMTYPE_SDRAM      0
85
#define MC_CSC_MEMTYPE_SSRAM      1
86
#define MC_CSC_MEMTYPE_ASYNC      2
87
#define MC_CSC_MEMTYPE_SYNC       3
88
 
89
#define MC_CSR_VALID            0xFF000703LU
90
#define MC_POC_VALID            0x0000000FLU
91
#define MC_BA_MASK_VALID        0x000003FFLU
92
#define MC_CSC_VALID            0x00FF0FFFLU
93
#define MC_TMS_SDRAM_VALID      0x0FFF83FFLU
94
#define MC_TMS_SSRAM_VALID      0x00000000LU
95
#define MC_TMS_ASYNC_VALID      0x03FFFFFFLU
96
#define MC_TMS_SYNC_VALID       0x01FFFFFFLU
97
#define MC_TMS_VALID            0xFFFFFFFFLU    /* reg test compat. */
98
 
99
/* TMS register field definition SDRAM */
100
#define MC_TMS_SDRAM_TRFC_OFFSET        24
101
#define MC_TMS_SDRAM_TRFC_WIDTH          4
102
#define MC_TMS_SDRAM_TRP_OFFSET         20
103
#define MC_TMS_SDRAM_TRP_WIDTH           4
104
#define MC_TMS_SDRAM_TRCD_OFFSET        17
105
#define MC_TMS_SDRAM_TRCD_WIDTH          4
106
#define MC_TMS_SDRAM_TWR_OFFSET         15
107
#define MC_TMS_SDRAM_TWR_WIDTH           2
108
#define MC_TMS_SDRAM_WBL_OFFSET          9
109
#define MC_TMS_SDRAM_OM_OFFSET           7
110
#define MC_TMS_SDRAM_OM_WIDTH            2
111
#define MC_TMS_SDRAM_CL_OFFSET           4
112
#define MC_TMS_SDRAM_CL_WIDTH            3
113
#define MC_TMS_SDRAM_BT_OFFSET           3
114
#define MC_TMS_SDRAM_BL_OFFSET           0
115
#define MC_TMS_SDRAM_BL_WIDTH            3
116
 
117
/* TMS register field definition ASYNC */
118
#define MC_TMS_ASYNC_TWWD_OFFSET        20
119
#define MC_TMS_ASYNC_TWWD_WIDTH          6
120
#define MC_TMS_ASYNC_TWD_OFFSET         16
121
#define MC_TMS_ASYNC_TWD_WIDTH           4
122
#define MC_TMS_ASYNC_TWPW_OFFSET        12
123
#define MC_TMS_ASYNC_TWPW_WIDTH          4
124
#define MC_TMS_ASYNC_TRDZ_OFFSET         8
125
#define MC_TMS_ASYNC_TRDZ_WIDTH          4
126
#define MC_TMS_ASYNC_TRDV_OFFSET         0
127
#define MC_TMS_ASYNC_TRDV_WIDTH          8
128
 
129
/* TMS register field definition SYNC  */
130
#define MC_TMS_SYNC_TTO_OFFSET          16
131
#define MC_TMS_SYNC_TTO_WIDTH            9
132
#define MC_TMS_SYNC_TWR_OFFSET          12
133
#define MC_TMS_SYNC_TWR_WIDTH            4
134
#define MC_TMS_SYNC_TRDZ_OFFSET          8
135
#define MC_TMS_SYNC_TRDZ_WIDTH           4
136
#define MC_TMS_SYNC_TRDV_OFFSET          0
137
#define MC_TMS_SYNC_TRDV_WIDTH           8
138
 
139
 
140
struct mc_area
141
{
142
  struct dev_memarea *mem;
143
  unsigned int cs;
144
  int mc;
145
  struct mc_area *next;
146
};
147
 
148
struct mc
149
{
150
  uint32_t csr;
151
  uint32_t poc;
152
  uint32_t ba_mask;
153
  uint32_t csc[N_CE];
154
  uint32_t tms[N_CE];
155
  oraddr_t baseaddr;
156
  int enabled;
157
 
158
  /* Index of this memory controler amongst all the memory controlers */
159
  int index;
160
  /* List of memory devices under this mc's control */
161
  struct mc_area *mc_areas;
162
 
163
  struct mc *next;
164
};
165
 
166
static struct mc *mcs = NULL;
167
 
168
/* List used to temporarily hold memory areas registered with the mc, while the
169
 * mc configureation has not been loaded */
170
static struct mc_area *mc_areas = NULL;
171
 
172
void
173
set_csc_tms (int cs, uint32_t csc, uint32_t tms, struct mc *mc)
174
{
175
  struct mc_area *cur = mc->mc_areas;
176
 
177
  while (cur)
178
    {
179
      if (cur->cs == cs)
180
        {
181
          /* FIXME: No peripheral should _ever_ acess a dev_memarea structure
182
           * directly */
183
          cur->mem->addr_mask = mc->ba_mask << 22;
184
          cur->mem->addr_compare =
185
            ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff */ ) << 22;
186
          set_mem_valid (cur->mem, (csc >> MC_CSC_EN_OFFSET) & 0x01);
187
 
188
          if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC)
189
            {
190
              adjust_rw_delay (cur->mem, (tms & 0xff) + ((tms >> 8) & 0x0f),
191
                               ((tms >> 12) & 0x0f) + ((tms >> 16) & 0x0f) +
192
                               ((tms >> 20) & 0x3f));
193
            }
194
          else if ((csc >> MC_CSC_MEMTYPE_OFFSET)
195
                   && 0x07 == MC_CSC_MEMTYPE_SDRAM)
196
            {
197
              adjust_rw_delay (cur->mem, 3 + ((tms >> 4) & 0x03),
198
                               3 + ((tms >> 4) & 0x03));
199
            }
200
          else if ((csc >> MC_CSC_MEMTYPE_OFFSET)
201
                   && 0x07 == MC_CSC_MEMTYPE_SSRAM)
202
            {
203
              adjust_rw_delay (cur->mem, 2, 2);
204
            }
205
          else if ((csc >> MC_CSC_MEMTYPE_OFFSET)
206
                   && 0x07 == MC_CSC_MEMTYPE_SYNC)
207
            {
208
              adjust_rw_delay (cur->mem, 2, 2);
209
            }
210
          return;
211
        }
212
      cur = cur->next;
213
    }
214
}
215
 
216
/* Set a specific MC register with value. */
217
void
218
mc_write_word (oraddr_t addr, uint32_t value, void *dat)
219
{
220
  struct mc *mc = dat;
221
  int chipsel;
222
 
223
  switch (addr)
224
    {
225
    case MC_CSR:
226
      mc->csr = value;
227
      break;
228
    case MC_POC:
229
      fprintf (stderr, "Warning: write to MC's POC register!");
230
      break;
231
    case MC_BA_MASK:
232
      mc->ba_mask = value & MC_BA_MASK_VALID;
233
      for (chipsel = 0; chipsel < N_CE; chipsel++)
234
        set_csc_tms (chipsel, mc->csc[chipsel], mc->tms[chipsel], mc);
235
      break;
236
    default:
237
      if (addr >= MC_CSC (0) && addr <= MC_TMS (N_CE - 1))
238
        {
239
          addr -= MC_CSC (0);
240
          if ((addr >> 2) & 1)
241
            mc->tms[addr >> 3] = value;
242
          else
243
            mc->csc[addr >> 3] = value;
244
 
245
          set_csc_tms (addr >> 3, mc->csc[addr >> 3], mc->tms[addr >> 3], mc);
246
          break;
247
        }
248
    }
249
}
250
 
251
/* Read a specific MC register. */
252
uint32_t
253
mc_read_word (oraddr_t addr, void *dat)
254
{
255
  struct mc *mc = dat;
256
  uint32_t value = 0;
257
 
258
  switch (addr)
259
    {
260
    case MC_CSR:
261
      value = mc->csr;
262
      break;
263
    case MC_POC:
264
      value = mc->poc;
265
      break;
266
    case MC_BA_MASK:
267
      value = mc->ba_mask;
268
      break;
269
    default:
270
      if (addr >= MC_CSC (0) && addr <= MC_TMS (N_CE - 1))
271
        {
272
          addr -= MC_CSC (0);
273
          if ((addr >> 2) & 1)
274
            value = mc->tms[addr >> 3];
275
          else
276
            value = mc->csc[addr >> 3];
277
        }
278
 
279
      break;
280
    }
281
  return value;
282
}
283
 
284
/* Read POC register and init memory controler regs. */
285
void
286
mc_reset (void *dat)
287
{
288
  struct mc *mc = dat;
289
  struct mc_area *cur, *prev, *tmp;
290
 
291
  PRINTF ("Resetting memory controller.\n");
292
 
293
  memset (mc->csc, 0, sizeof (mc->csc));
294
  memset (mc->tms, 0, sizeof (mc->tms));
295
 
296
  mc->csr = 0;
297
  mc->ba_mask = 0;
298
 
299
  /* Set CS0 */
300
  mc->csc[0] =
301
    (((mc->poc & 0x0c) >> 2) << MC_CSC_MEMTYPE_OFFSET) | ((mc->
302
                                                           poc & 0x03) <<
303
                                                          MC_CSC_BW_OFFSET) |
304
    1;
305
 
306
  if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC)
307
    {
308
      mc->tms[0] = MC_TMS_ASYNC_VALID;
309
    }
310
  else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET)
311
           && 0x07 == MC_CSC_MEMTYPE_SDRAM)
312
    {
313
      mc->tms[0] = MC_TMS_SDRAM_VALID;
314
    }
315
  else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET)
316
           && 0x07 == MC_CSC_MEMTYPE_SSRAM)
317
    {
318
      mc->tms[0] = MC_TMS_SSRAM_VALID;
319
    }
320
  else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET)
321
           && 0x07 == MC_CSC_MEMTYPE_SYNC)
322
    {
323
      mc->tms[0] = MC_TMS_SYNC_VALID;
324
    }
325
 
326
  /* Grab control over all the devices we are destined to control */
327
  cur = mc_areas;
328
  prev = NULL;
329
  while (cur)
330
    {
331
      if (cur->mc == mc->index)
332
        {
333
          if (prev)
334
            prev->next = cur->next;
335
          else
336
            mc_areas = cur->next;
337
          prev = cur;
338
          tmp = cur->next;
339
          cur->next = mc->mc_areas;
340
          mc->mc_areas = cur;
341
          cur = tmp;
342
        }
343
      else
344
        {
345
          prev = cur;
346
          cur = cur->next;
347
        }
348
    }
349
 
350
  for (cur = mc->mc_areas; cur; cur = cur->next)
351
    set_mem_valid (cur->mem, 0);
352
 
353
  set_csc_tms (0, mc->csc[0], mc->tms[0], mc);
354
}
355
 
356
/*---------------------------------------------------------------------------*/
357
/*!Free all allocated memory                                                 */
358
/*---------------------------------------------------------------------------*/
359
void
360
mc_done ()
361
{
362
  while (NULL != mc_areas)
363
    {
364
      struct mc_area *next = mc_areas->next;
365
 
366
      free (mc_areas);
367
      mc_areas = next;
368
    }
369
}       /* mc_done () */
370
 
371
 
372
void
373
mc_status (void *dat)
374
{
375
  struct mc *mc = dat;
376
  int i;
377
 
378
  PRINTF ("\nMemory Controller at 0x%" PRIxADDR ":\n", mc->baseaddr);
379
  PRINTF ("POC: 0x%" PRIx32 "\n", mc->poc);
380
  PRINTF ("BAS: 0x%" PRIx32 "\n", mc->ba_mask);
381
  PRINTF ("CSR: 0x%" PRIx32 "\n", mc->csr);
382
 
383
  for (i = 0; i < N_CE; i++)
384
    {
385
      PRINTF ("CE %02d -  CSC: 0x%" PRIx32 "  TMS: 0x%" PRIx32 "\n", i,
386
              mc->csc[i], mc->tms[i]);
387
    }
388
}
389
 
390
/*--------------------------------------------[ Peripheral<->MC interface ]---*/
391
/* Registers some memory to be under the memory controllers control */
392
void
393
mc_reg_mem_area (struct dev_memarea *mem, unsigned int cs, int mc)
394
{
395
  struct mc_area *new = malloc (sizeof (struct mc_area));
396
 
397
  if (NULL == new)
398
    {
399
      fprintf (stderr, "Out-of-memory\n");
400
      exit (-1);
401
    }
402
 
403
  new->cs   = cs;
404
  new->mem  = mem;
405
  new->mc   = mc;
406
 
407
  new->next = mc_areas;
408
 
409
  mc_areas  = new;
410
}
411
 
412
/*-----------------------------------------------------[ MC configuration ]---*/
413
static void
414
mc_enabled (union param_val val, void *dat)
415
{
416
  struct mc *mc = dat;
417
  mc->enabled = val.int_val;
418
}
419
 
420
static void
421
mc_baseaddr (union param_val val, void *dat)
422
{
423
  struct mc *mc = dat;
424
  mc->baseaddr = val.addr_val;
425
}
426
 
427
 
428
/*---------------------------------------------------------------------------*/
429
/*!Set the power on configuration state
430
 
431
   Only the bottom 4 bits are signficant. Other bits are truncated with a
432
   warning.
433
 
434
   @param[in] val  The value to use
435
   @param[in] dat  The config data structure                                 */
436
/*---------------------------------------------------------------------------*/
437
static void
438
mc_poc (union param_val  val,
439
        void            *dat)
440
{
441
  struct mc *mc = dat;
442
 
443
  if (val.int_val > 0xf)
444
    {
445
      fprintf (stderr, "Warning: memory controller PoC > 4 bits: truncated\n");
446
    }
447
 
448
  mc->poc = val.int_val & 0xf;
449
 
450
}       /* mc_poc() */
451
 
452
 
453
static void
454
mc_index (union param_val val, void *dat)
455
{
456
  struct mc *mc = dat;
457
  mc->index = val.int_val;
458
}
459
 
460
/*---------------------------------------------------------------------------*/
461
/*!Initialize a new memory controller configuration
462
 
463
   ALL parameters are set explicitly to default values.                      */
464
/*---------------------------------------------------------------------------*/
465
static void *
466
mc_sec_start ()
467
{
468
  struct mc *new = malloc (sizeof (struct mc));
469
 
470
  if (!new)
471
    {
472
      fprintf (stderr, "Peripheral MC: Run out of memory\n");
473
      exit (-1);
474
    }
475
 
476
  new->enabled  = 1;
477
  new->baseaddr = 0;
478
  new->poc      = 0;
479
  new->index    = 0;
480
 
481
  new->mc_areas = NULL;
482
 
483
  return new;
484
}
485
 
486
static void
487
mc_sec_end (void *dat)
488
{
489
  struct mc *mc = dat;
490
  struct mem_ops ops;
491
 
492
  if (!mc->enabled)
493
    {
494
      free (dat);
495
      return;
496
    }
497
 
498
  /* FIXME: Check to see that the index given to this mc is unique */
499
 
500
  mc->next = mcs;
501
  mcs = mc;
502
 
503
  memset (&ops, 0, sizeof (struct mem_ops));
504
 
505
  ops.readfunc32 = mc_read_word;
506
  ops.writefunc32 = mc_write_word;
507
  ops.write_dat32 = dat;
508
  ops.read_dat32 = dat;
509
 
510
  /* FIXME: Correct delays? */
511
  ops.delayr = 2;
512
  ops.delayw = 2;
513
 
514
  reg_mem_area (mc->baseaddr, MC_ADDR_SPACE, 1, &ops);
515
  reg_sim_reset (mc_reset, dat);
516
  reg_sim_stat (mc_status, dat);
517
}
518
 
519
void
520
reg_mc_sec (void)
521
{
522
  struct config_section *sec =
523
    reg_config_sec ("mc", mc_sec_start, mc_sec_end);
524
 
525
  reg_config_param (sec, "enabled", paramt_int, mc_enabled);
526
  reg_config_param (sec, "baseaddr", paramt_addr, mc_baseaddr);
527
  reg_config_param (sec, "POC", paramt_int, mc_poc);
528
  reg_config_param (sec, "index", paramt_int, mc_index);
529
}

powered by: WebSVN 2.1.0

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