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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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