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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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