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

Subversion Repositories openrisc_me

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

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 82 jeremybenn
#include "mc.h"
52 19 jeremybenn
 
53
 
54
struct mc_area
55
{
56
  struct dev_memarea *mem;
57
  unsigned int cs;
58
  int mc;
59
  struct mc_area *next;
60
};
61
 
62
struct mc
63
{
64
  uint32_t csr;
65
  uint32_t poc;
66
  uint32_t ba_mask;
67
  uint32_t csc[N_CE];
68
  uint32_t tms[N_CE];
69
  oraddr_t baseaddr;
70
  int enabled;
71
 
72
  /* Index of this memory controler amongst all the memory controlers */
73
  int index;
74
  /* List of memory devices under this mc's control */
75
  struct mc_area *mc_areas;
76
 
77
  struct mc *next;
78
};
79
 
80
static struct mc *mcs = NULL;
81
 
82
/* List used to temporarily hold memory areas registered with the mc, while the
83
 * mc configureation has not been loaded */
84
static struct mc_area *mc_areas = NULL;
85
 
86
void
87
set_csc_tms (int cs, uint32_t csc, uint32_t tms, struct mc *mc)
88
{
89
  struct mc_area *cur = mc->mc_areas;
90
 
91
  while (cur)
92
    {
93
      if (cur->cs == cs)
94
        {
95
          /* FIXME: No peripheral should _ever_ acess a dev_memarea structure
96
           * directly */
97
          cur->mem->addr_mask = mc->ba_mask << 22;
98
          cur->mem->addr_compare =
99
            ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff */ ) << 22;
100
          set_mem_valid (cur->mem, (csc >> MC_CSC_EN_OFFSET) & 0x01);
101
 
102
          if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC)
103
            {
104
              adjust_rw_delay (cur->mem, (tms & 0xff) + ((tms >> 8) & 0x0f),
105
                               ((tms >> 12) & 0x0f) + ((tms >> 16) & 0x0f) +
106
                               ((tms >> 20) & 0x3f));
107
            }
108
          else if ((csc >> MC_CSC_MEMTYPE_OFFSET)
109
                   && 0x07 == MC_CSC_MEMTYPE_SDRAM)
110
            {
111
              adjust_rw_delay (cur->mem, 3 + ((tms >> 4) & 0x03),
112
                               3 + ((tms >> 4) & 0x03));
113
            }
114
          else if ((csc >> MC_CSC_MEMTYPE_OFFSET)
115
                   && 0x07 == MC_CSC_MEMTYPE_SSRAM)
116
            {
117
              adjust_rw_delay (cur->mem, 2, 2);
118
            }
119
          else if ((csc >> MC_CSC_MEMTYPE_OFFSET)
120
                   && 0x07 == MC_CSC_MEMTYPE_SYNC)
121
            {
122
              adjust_rw_delay (cur->mem, 2, 2);
123
            }
124
          return;
125
        }
126
      cur = cur->next;
127
    }
128
}
129
 
130
/* Set a specific MC register with value. */
131
void
132
mc_write_word (oraddr_t addr, uint32_t value, void *dat)
133
{
134
  struct mc *mc = dat;
135
  int chipsel;
136
 
137
  switch (addr)
138
    {
139
    case MC_CSR:
140
      mc->csr = value;
141
      break;
142
    case MC_POC:
143
      fprintf (stderr, "Warning: write to MC's POC register!");
144
      break;
145
    case MC_BA_MASK:
146
      mc->ba_mask = value & MC_BA_MASK_VALID;
147
      for (chipsel = 0; chipsel < N_CE; chipsel++)
148
        set_csc_tms (chipsel, mc->csc[chipsel], mc->tms[chipsel], mc);
149
      break;
150
    default:
151
      if (addr >= MC_CSC (0) && addr <= MC_TMS (N_CE - 1))
152
        {
153
          addr -= MC_CSC (0);
154
          if ((addr >> 2) & 1)
155
            mc->tms[addr >> 3] = value;
156
          else
157
            mc->csc[addr >> 3] = value;
158
 
159
          set_csc_tms (addr >> 3, mc->csc[addr >> 3], mc->tms[addr >> 3], mc);
160
          break;
161
        }
162
    }
163
}
164
 
165
/* Read a specific MC register. */
166
uint32_t
167
mc_read_word (oraddr_t addr, void *dat)
168
{
169
  struct mc *mc = dat;
170
  uint32_t value = 0;
171
 
172
  switch (addr)
173
    {
174
    case MC_CSR:
175
      value = mc->csr;
176
      break;
177
    case MC_POC:
178
      value = mc->poc;
179
      break;
180
    case MC_BA_MASK:
181
      value = mc->ba_mask;
182
      break;
183
    default:
184
      if (addr >= MC_CSC (0) && addr <= MC_TMS (N_CE - 1))
185
        {
186
          addr -= MC_CSC (0);
187
          if ((addr >> 2) & 1)
188
            value = mc->tms[addr >> 3];
189
          else
190
            value = mc->csc[addr >> 3];
191
        }
192
 
193
      break;
194
    }
195
  return value;
196
}
197
 
198
/* Read POC register and init memory controler regs. */
199
void
200
mc_reset (void *dat)
201
{
202
  struct mc *mc = dat;
203
  struct mc_area *cur, *prev, *tmp;
204
 
205
  PRINTF ("Resetting memory controller.\n");
206
 
207
  memset (mc->csc, 0, sizeof (mc->csc));
208
  memset (mc->tms, 0, sizeof (mc->tms));
209
 
210
  mc->csr = 0;
211
  mc->ba_mask = 0;
212
 
213
  /* Set CS0 */
214
  mc->csc[0] =
215
    (((mc->poc & 0x0c) >> 2) << MC_CSC_MEMTYPE_OFFSET) | ((mc->
216
                                                           poc & 0x03) <<
217
                                                          MC_CSC_BW_OFFSET) |
218
    1;
219
 
220
  if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC)
221
    {
222
      mc->tms[0] = MC_TMS_ASYNC_VALID;
223
    }
224
  else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET)
225
           && 0x07 == MC_CSC_MEMTYPE_SDRAM)
226
    {
227
      mc->tms[0] = MC_TMS_SDRAM_VALID;
228
    }
229
  else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET)
230
           && 0x07 == MC_CSC_MEMTYPE_SSRAM)
231
    {
232
      mc->tms[0] = MC_TMS_SSRAM_VALID;
233
    }
234
  else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET)
235
           && 0x07 == MC_CSC_MEMTYPE_SYNC)
236
    {
237
      mc->tms[0] = MC_TMS_SYNC_VALID;
238
    }
239
 
240
  /* Grab control over all the devices we are destined to control */
241
  cur = mc_areas;
242
  prev = NULL;
243
  while (cur)
244
    {
245
      if (cur->mc == mc->index)
246
        {
247
          if (prev)
248
            prev->next = cur->next;
249
          else
250
            mc_areas = cur->next;
251
          prev = cur;
252
          tmp = cur->next;
253
          cur->next = mc->mc_areas;
254
          mc->mc_areas = cur;
255
          cur = tmp;
256
        }
257
      else
258
        {
259
          prev = cur;
260
          cur = cur->next;
261
        }
262
    }
263
 
264
  for (cur = mc->mc_areas; cur; cur = cur->next)
265
    set_mem_valid (cur->mem, 0);
266
 
267
  set_csc_tms (0, mc->csc[0], mc->tms[0], mc);
268
}
269
 
270
/*---------------------------------------------------------------------------*/
271
/*!Free all allocated memory                                                 */
272
/*---------------------------------------------------------------------------*/
273
void
274
mc_done ()
275
{
276
  while (NULL != mc_areas)
277
    {
278
      struct mc_area *next = mc_areas->next;
279
 
280
      free (mc_areas);
281
      mc_areas = next;
282
    }
283
}       /* mc_done () */
284
 
285
 
286
void
287
mc_status (void *dat)
288
{
289
  struct mc *mc = dat;
290
  int i;
291
 
292
  PRINTF ("\nMemory Controller at 0x%" PRIxADDR ":\n", mc->baseaddr);
293
  PRINTF ("POC: 0x%" PRIx32 "\n", mc->poc);
294
  PRINTF ("BAS: 0x%" PRIx32 "\n", mc->ba_mask);
295
  PRINTF ("CSR: 0x%" PRIx32 "\n", mc->csr);
296
 
297
  for (i = 0; i < N_CE; i++)
298
    {
299
      PRINTF ("CE %02d -  CSC: 0x%" PRIx32 "  TMS: 0x%" PRIx32 "\n", i,
300
              mc->csc[i], mc->tms[i]);
301
    }
302
}
303
 
304
/*--------------------------------------------[ Peripheral<->MC interface ]---*/
305
/* Registers some memory to be under the memory controllers control */
306
void
307
mc_reg_mem_area (struct dev_memarea *mem, unsigned int cs, int mc)
308
{
309
  struct mc_area *new = malloc (sizeof (struct mc_area));
310
 
311
  if (NULL == new)
312
    {
313
      fprintf (stderr, "Out-of-memory\n");
314
      exit (-1);
315
    }
316
 
317
  new->cs   = cs;
318
  new->mem  = mem;
319
  new->mc   = mc;
320
 
321
  new->next = mc_areas;
322
 
323
  mc_areas  = new;
324
}
325
 
326
/*-----------------------------------------------------[ MC configuration ]---*/
327
static void
328
mc_enabled (union param_val val, void *dat)
329
{
330
  struct mc *mc = dat;
331
  mc->enabled = val.int_val;
332
}
333
 
334
static void
335
mc_baseaddr (union param_val val, void *dat)
336
{
337
  struct mc *mc = dat;
338
  mc->baseaddr = val.addr_val;
339
}
340
 
341
 
342
/*---------------------------------------------------------------------------*/
343
/*!Set the power on configuration state
344
 
345
   Only the bottom 4 bits are signficant. Other bits are truncated with a
346
   warning.
347
 
348
   @param[in] val  The value to use
349
   @param[in] dat  The config data structure                                 */
350
/*---------------------------------------------------------------------------*/
351
static void
352
mc_poc (union param_val  val,
353
        void            *dat)
354
{
355
  struct mc *mc = dat;
356
 
357
  if (val.int_val > 0xf)
358
    {
359
      fprintf (stderr, "Warning: memory controller PoC > 4 bits: truncated\n");
360
    }
361
 
362
  mc->poc = val.int_val & 0xf;
363
 
364
}       /* mc_poc() */
365
 
366
 
367
static void
368
mc_index (union param_val val, void *dat)
369
{
370
  struct mc *mc = dat;
371
  mc->index = val.int_val;
372
}
373
 
374
/*---------------------------------------------------------------------------*/
375
/*!Initialize a new memory controller configuration
376
 
377
   ALL parameters are set explicitly to default values.                      */
378
/*---------------------------------------------------------------------------*/
379
static void *
380
mc_sec_start ()
381
{
382
  struct mc *new = malloc (sizeof (struct mc));
383
 
384
  if (!new)
385
    {
386
      fprintf (stderr, "Peripheral MC: Run out of memory\n");
387
      exit (-1);
388
    }
389
 
390
  new->enabled  = 1;
391
  new->baseaddr = 0;
392
  new->poc      = 0;
393
  new->index    = 0;
394
 
395
  new->mc_areas = NULL;
396
 
397
  return new;
398
}
399
 
400
static void
401
mc_sec_end (void *dat)
402
{
403
  struct mc *mc = dat;
404
  struct mem_ops ops;
405
 
406
  if (!mc->enabled)
407
    {
408
      free (dat);
409
      return;
410
    }
411
 
412
  /* FIXME: Check to see that the index given to this mc is unique */
413
 
414
  mc->next = mcs;
415
  mcs = mc;
416
 
417
  memset (&ops, 0, sizeof (struct mem_ops));
418
 
419
  ops.readfunc32 = mc_read_word;
420
  ops.writefunc32 = mc_write_word;
421
  ops.write_dat32 = dat;
422
  ops.read_dat32 = dat;
423
 
424
  /* FIXME: Correct delays? */
425
  ops.delayr = 2;
426
  ops.delayw = 2;
427
 
428
  reg_mem_area (mc->baseaddr, MC_ADDR_SPACE, 1, &ops);
429
  reg_sim_reset (mc_reset, dat);
430
  reg_sim_stat (mc_status, dat);
431
}
432
 
433
void
434
reg_mc_sec (void)
435
{
436
  struct config_section *sec =
437
    reg_config_sec ("mc", mc_sec_start, mc_sec_end);
438
 
439 224 jeremybenn
  reg_config_param (sec, "enabled",  PARAMT_INT, mc_enabled);
440
  reg_config_param (sec, "baseaddr", PARAMT_ADDR, mc_baseaddr);
441
  reg_config_param (sec, "POC",      PARAMT_INT, mc_poc);
442
  reg_config_param (sec, "index",    PARAMT_INT, mc_index);
443 19 jeremybenn
}

powered by: WebSVN 2.1.0

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