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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [peripheral/] [mc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 239 markom
/* mc.c -- Simulation of Memory Controller
2
 
3 1748 jeremybenn
   Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5 239 markom
 
6 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7 239 markom
 
8 1748 jeremybenn
   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 239 markom
/* Enable memory controller, via:
28
  section mc
29
    enable = 1
30
    POC = 0x13243545
31
  end
32
 
33 261 markom
   Limitations:
34
    - memory refresh is not simulated
35 742 ivang
*/
36 239 markom
 
37 1308 phoenix
 
38 1748 jeremybenn
/* Autoconf and/or portability configuration */
39 1350 nogj
#include "config.h"
40 1748 jeremybenn
#include "port.h"
41 1350 nogj
 
42 1748 jeremybenn
/* System includes */
43
#include <stdlib.h>
44 1350 nogj
 
45 1748 jeremybenn
/* Package includes */
46 1350 nogj
#include "arch.h"
47 239 markom
#include "abstract.h"
48 261 markom
#include "sim-config.h"
49 1748 jeremybenn
#include "toplevel-support.h"
50
#include "sim-cmd.h"
51 261 markom
 
52 1490 nogj
 
53 1748 jeremybenn
#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 1486 nogj
  struct dev_memarea *mem;
143
  unsigned int cs;
144
  int mc;
145
  struct mc_area *next;
146
};
147 539 simons
 
148 1748 jeremybenn
struct mc
149
{
150 1557 nogj
  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 1486 nogj
  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 1748 jeremybenn
void
173
set_csc_tms (int cs, uint32_t csc, uint32_t tms, struct mc *mc)
174 1486 nogj
{
175
  struct mc_area *cur = mc->mc_areas;
176 1519 nogj
 
177 1748 jeremybenn
  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 539 simons
    }
214 261 markom
}
215
 
216
/* Set a specific MC register with value. */
217 1748 jeremybenn
void
218
mc_write_word (oraddr_t addr, uint32_t value, void *dat)
219 261 markom
{
220 1748 jeremybenn
  struct mc *mc = dat;
221
  int chipsel;
222 261 markom
 
223 1748 jeremybenn
  switch (addr)
224
    {
225
    case MC_CSR:
226
      mc->csr = value;
227
      break;
228
    case MC_POC:
229 1751 jeremybenn
      fprintf (stderr, "Warning: write to MC's POC register!");
230 1748 jeremybenn
      break;
231
    case MC_BA_MASK:
232
      mc->ba_mask = value & MC_BA_MASK_VALID;
233 543 simons
      for (chipsel = 0; chipsel < N_CE; chipsel++)
234 1748 jeremybenn
        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 261 markom
 
245 1748 jeremybenn
          set_csc_tms (addr >> 3, mc->csc[addr >> 3], mc->tms[addr >> 3], mc);
246
          break;
247
        }
248
    }
249 261 markom
}
250
 
251
/* Read a specific MC register. */
252 1748 jeremybenn
uint32_t
253
mc_read_word (oraddr_t addr, void *dat)
254 261 markom
{
255 1748 jeremybenn
  struct mc *mc = dat;
256
  uint32_t value = 0;
257 261 markom
 
258 1748 jeremybenn
  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 261 markom
        }
278 1751 jeremybenn
 
279 1748 jeremybenn
      break;
280
    }
281
  return value;
282 261 markom
}
283
 
284
/* Read POC register and init memory controler regs. */
285 1748 jeremybenn
void
286
mc_reset (void *dat)
287 261 markom
{
288 1373 nogj
  struct mc *mc = dat;
289 1486 nogj
  struct mc_area *cur, *prev, *tmp;
290 543 simons
 
291 1748 jeremybenn
  PRINTF ("Resetting memory controller.\n");
292 261 markom
 
293 1748 jeremybenn
  memset (mc->csc, 0, sizeof (mc->csc));
294
  memset (mc->tms, 0, sizeof (mc->tms));
295 539 simons
 
296 1373 nogj
  mc->csr = 0;
297
  mc->ba_mask = 0;
298 539 simons
 
299 1373 nogj
  /* Set CS0 */
300 1748 jeremybenn
  mc->csc[0] =
301
    (((mc->poc & 0x0c) >> 2) << MC_CSC_MEMTYPE_OFFSET) | ((mc->
302
                                                           poc & 0x03) <<
303
                                                          MC_CSC_BW_OFFSET) |
304
    1;
305 539 simons
 
306 1748 jeremybenn
  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 543 simons
 
326 1486 nogj
  /* Grab control over all the devices we are destined to control */
327
  cur = mc_areas;
328
  prev = NULL;
329 1748 jeremybenn
  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 1486 nogj
    }
349 261 markom
 
350 1486 nogj
  for (cur = mc->mc_areas; cur; cur = cur->next)
351 1748 jeremybenn
    set_mem_valid (cur->mem, 0);
352 1486 nogj
 
353 1373 nogj
  set_csc_tms (0, mc->csc[0], mc->tms[0], mc);
354 261 markom
}
355 742 ivang
 
356 1748 jeremybenn
/*---------------------------------------------------------------------------*/
357
/*!Free all allocated memory                                                 */
358
/*---------------------------------------------------------------------------*/
359
void
360
mc_done ()
361 742 ivang
{
362 1748 jeremybenn
  while (NULL != mc_areas)
363
    {
364
      struct mc_area *next = mc_areas->next;
365 742 ivang
 
366 1748 jeremybenn
      free (mc_areas);
367
      mc_areas = next;
368
    }
369
}       /* mc_done () */
370 742 ivang
 
371 1748 jeremybenn
 
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 742 ivang
    }
388
}
389 1358 nogj
 
390 1486 nogj
/*--------------------------------------------[ Peripheral<->MC interface ]---*/
391
/* Registers some memory to be under the memory controllers control */
392 1748 jeremybenn
void
393
mc_reg_mem_area (struct dev_memarea *mem, unsigned int cs, int mc)
394 1486 nogj
{
395 1748 jeremybenn
  struct mc_area *new = malloc (sizeof (struct mc_area));
396 1486 nogj
 
397 1748 jeremybenn
  if (NULL == new)
398
    {
399
      fprintf (stderr, "Out-of-memory\n");
400
      exit (-1);
401
    }
402 1486 nogj
 
403 1748 jeremybenn
  new->cs   = cs;
404
  new->mem  = mem;
405
  new->mc   = mc;
406
 
407 1486 nogj
  new->next = mc_areas;
408 1748 jeremybenn
 
409
  mc_areas  = new;
410 1486 nogj
}
411
 
412
/*-----------------------------------------------------[ MC configuration ]---*/
413 1748 jeremybenn
static void
414
mc_enabled (union param_val val, void *dat)
415 1358 nogj
{
416 1373 nogj
  struct mc *mc = dat;
417
  mc->enabled = val.int_val;
418 1358 nogj
}
419
 
420 1748 jeremybenn
static void
421
mc_baseaddr (union param_val val, void *dat)
422 1358 nogj
{
423 1373 nogj
  struct mc *mc = dat;
424
  mc->baseaddr = val.addr_val;
425 1358 nogj
}
426
 
427 1748 jeremybenn
 
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 1358 nogj
{
441 1373 nogj
  struct mc *mc = dat;
442 1358 nogj
 
443 1748 jeremybenn
  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 1486 nogj
{
456
  struct mc *mc = dat;
457
  mc->index = val.int_val;
458
}
459
 
460 1748 jeremybenn
/*---------------------------------------------------------------------------*/
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 1373 nogj
{
468 1748 jeremybenn
  struct mc *new = malloc (sizeof (struct mc));
469 1373 nogj
 
470 1748 jeremybenn
  if (!new)
471
    {
472
      fprintf (stderr, "Peripheral MC: Run out of memory\n");
473
      exit (-1);
474
    }
475 1373 nogj
 
476 1748 jeremybenn
  new->enabled  = 1;
477
  new->baseaddr = 0;
478
  new->poc      = 0;
479
  new->index    = 0;
480
 
481 1486 nogj
  new->mc_areas = NULL;
482 1373 nogj
 
483
  return new;
484
}
485
 
486 1748 jeremybenn
static void
487
mc_sec_end (void *dat)
488 1373 nogj
{
489
  struct mc *mc = dat;
490 1486 nogj
  struct mem_ops ops;
491 1373 nogj
 
492 1748 jeremybenn
  if (!mc->enabled)
493
    {
494
      free (dat);
495
      return;
496
    }
497 1461 nogj
 
498 1486 nogj
  /* FIXME: Check to see that the index given to this mc is unique */
499
 
500
  mc->next = mcs;
501
  mcs = mc;
502
 
503 1748 jeremybenn
  memset (&ops, 0, sizeof (struct mem_ops));
504 1486 nogj
 
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 1748 jeremybenn
  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 1373 nogj
}
518
 
519 1748 jeremybenn
void
520
reg_mc_sec (void)
521 1358 nogj
{
522 1748 jeremybenn
  struct config_section *sec =
523
    reg_config_sec ("mc", mc_sec_start, mc_sec_end);
524 1358 nogj
 
525 1748 jeremybenn
  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 1358 nogj
}

powered by: WebSVN 2.1.0

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