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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [cpu/] [common/] [abstract.c] - Blame information for rev 1319

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

Line No. Rev Author Line
1 2 cvs
/* abstract.c -- Abstract entities
2
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20 66 lampret
/* Abstract memory and routines that go with this. I need to
21 2 cvs
add all sorts of other abstract entities. Currently we have
22
only memory. */
23
 
24 221 markom
#include <stdlib.h>
25 2 cvs
#include <stdio.h>
26
#include <ctype.h>
27
#include <string.h>
28
 
29 6 lampret
#include "config.h"
30 7 jrydberg
#include "sim-config.h"
31 6 lampret
 
32 2 cvs
#include "parse.h"
33
#include "abstract.h"
34 261 markom
#include "labels.h"
35 2 cvs
#include "arch.h"
36
#include "execute.h"
37 32 lampret
#include "sprs.h"
38 35 lampret
#include "stats.h"
39 32 lampret
#include "except.h"
40 123 markom
#include "debug_unit.h"
41 134 markom
#include "opcode/or32.h"
42 547 markom
#include "support/profile.h"
43 1308 phoenix
#include "dmmu.h"
44
#include "dcache_model.h"
45
#include "icache_model.h"
46
#include "debug.h"
47 2 cvs
 
48
extern unsigned long reg[];
49 138 markom
extern char *disassembled;
50 2 cvs
 
51 28 lampret
/* This is an abstract+physical memory array rather than only physical
52
   memory array */
53 538 markom
static unsigned long *simmem32;
54 2 cvs
 
55 30 lampret
/* Pointer to memory area descriptions that are assigned to individual
56
   peripheral devices. */
57
struct dev_memarea *dev_list;
58
 
59 221 markom
/* Temporary variable to increase speed.  */
60
struct dev_memarea *cur_area;
61
 
62 970 simons
/* Pointer to memory controller device descriptor.  */
63
struct dev_memarea *mc_area = (struct dev_memarea *)0;
64
 
65 638 simons
/* These are set by mmu if cache inhibit bit is set for current acces.  */
66
int data_ci, insn_ci;
67
 
68 525 simons
/* Virtual address of current access. */
69
unsigned long cur_vadd;
70
 
71 261 markom
/* Calculates bit mask to fit the data */
72
unsigned long bit_mask (unsigned long data) {
73
  int i = 0;
74
  data--;
75 382 markom
  while (data >> i)
76 261 markom
    data |= 1 << i++;
77
  return data;
78
}
79
 
80
/* Register read and write function for a memory area.
81
   addr is inside the area, if addr & addr_mask == addr_compare
82
   (used also by peripheral devices like 16450 UART etc.) */
83
void register_memoryarea_mask(unsigned long addr_mask, unsigned long addr_compare,
84 970 simons
                         unsigned long size, unsigned granularity, unsigned mc_dev,
85 239 markom
                         unsigned long (readfunc)(unsigned long),
86 261 markom
                         void (writefunc)(unsigned long, unsigned long))
87 30 lampret
{
88 239 markom
  struct dev_memarea **pptmp;
89 261 markom
  unsigned long size_mask = bit_mask (size);
90
  int found_error = 0;
91
  addr_compare &= addr_mask;
92 221 markom
 
93 382 markom
  debug(5, "addr & %08x == %08x to %08x, size %08x, gran %iB\n", addr_mask, addr_compare, addr_compare | bit_mask (size), size, granularity);
94 239 markom
  /* Go to the end of the list. */
95 261 markom
  for(pptmp = &dev_list; *pptmp; pptmp = &(*pptmp)->next)
96
    if ((addr_compare >= (*pptmp)->addr_compare) && (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size)
97
     || (addr_compare + size > (*pptmp)->addr_compare) && (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size)) {
98 262 markom
      if (!found_error) {
99 261 markom
        fprintf (stderr, "ERROR: Overlapping memory area(s):\n");
100 1308 phoenix
        fprintf (stderr, "\taddr & %08lx == %08lx to %08lx, size %08lx, gran %iB\n",
101
                 addr_mask, addr_compare, addr_compare | bit_mask (size), size,
102
                 granularity);
103 262 markom
      }
104 261 markom
      found_error = 1;
105 1308 phoenix
      fprintf (stderr, "and\taddr & %08lx == %08lx to %08lx, size %08lx, gran %liB\n",
106
               (*pptmp)->addr_mask, (*pptmp)->addr_compare,
107
               (*pptmp)->addr_compare | (*pptmp)->size_mask,
108
               (*pptmp)->size, (*pptmp)->granularity);
109 261 markom
    }
110
 
111
  if (found_error)
112
    exit (-1);
113 537 markom
 
114 239 markom
  cur_area = *pptmp = (struct dev_memarea *)malloc(sizeof(struct dev_memarea));
115 970 simons
 
116
  if (mc_dev)
117
    mc_area = *pptmp;
118
 
119 261 markom
  (*pptmp)->addr_mask = addr_mask;
120
  (*pptmp)->addr_compare = addr_compare;
121 239 markom
  (*pptmp)->size = size;
122 261 markom
  (*pptmp)->size_mask = size_mask;
123 239 markom
  (*pptmp)->granularity = granularity;
124
  (*pptmp)->readfunc = readfunc;
125
  (*pptmp)->writefunc = writefunc;
126 479 markom
  (*pptmp)->log = 0;
127 882 simons
  (*pptmp)->delayr = 2;
128
  (*pptmp)->delayw = 2;
129 239 markom
  (*pptmp)->next = NULL;
130 261 markom
}
131 221 markom
 
132 261 markom
/* Register read and write function for a memory area.
133
   Memory areas should be aligned. Memory area is rounded up to
134
   fit the nearest 2^n aligment.
135 970 simons
   (used also by peripheral devices like 16450 UART etc.)
136
   If mc_dev is 1, this means that this device will be checked first for match
137
   and will be accessed in case in overlaping memory spaces.
138
   Only one device can have this set to 1 (used for memory controller) */
139 261 markom
void register_memoryarea(unsigned long addr,
140 970 simons
                         unsigned long size, unsigned granularity, unsigned mc_dev,
141 261 markom
                         unsigned long (readfunc)(unsigned long),
142
                         void (writefunc)(unsigned long, unsigned long))
143
{
144
  unsigned long size_mask = bit_mask (size);
145
  unsigned long addr_mask = ~size_mask;
146
  register_memoryarea_mask (addr_mask, addr & addr_mask,
147 970 simons
                      size_mask + 1, granularity, mc_dev,
148 261 markom
                      readfunc, writefunc);
149 30 lampret
}
150
 
151 261 markom
 
152 30 lampret
/* Check if access is to registered area of memory. */
153 560 markom
inline struct dev_memarea *verify_memoryarea(unsigned long addr)
154 30 lampret
{
155 239 markom
  struct dev_memarea *ptmp;
156 221 markom
 
157 970 simons
  /* Check memory controller space first */
158
  if (mc_area && (addr & mc_area->addr_mask) == (mc_area->addr_compare & mc_area->addr_mask))
159
    return cur_area = mc_area;
160
 
161
  /* Check cached value */
162 560 markom
  if (cur_area && (addr & cur_area->addr_mask) == (cur_area->addr_compare & cur_area->addr_mask))
163
    return cur_area;
164
 
165
  /* When mc is enabled, we must check valid also, otherwise we assume it is nonzero */
166
  IFF (config.mc.enabled) {
167
    /* Check list of registered devices. */
168
    for(ptmp = dev_list; ptmp; ptmp = ptmp->next)
169
      if ((addr & ptmp->addr_mask) == (ptmp->addr_compare & ptmp->addr_mask) && ptmp->valid)
170
        return cur_area = ptmp;
171
  } else {
172
    /* Check list of registered devices. */
173
    for(ptmp = dev_list; ptmp; ptmp = ptmp->next)
174
      if ((addr & ptmp->addr_mask) == (ptmp->addr_compare & ptmp->addr_mask))
175
        return cur_area = ptmp;
176
  }
177 239 markom
  return cur_area = NULL;
178 30 lampret
}
179
 
180 882 simons
/* Finds the memory area for the address and adjust the read and write delays for it. */
181
void adjust_rw_delay(unsigned long memaddr, unsigned long delayr, unsigned long delayw)
182
{
183
  if (verify_memoryarea(memaddr)) {
184
    cur_area->delayr = delayr;
185
    cur_area->delayw = delayw;
186
  }
187
}
188
 
189 1319 phoenix
/* for cpu accesses
190
 *
191
 * STATISTICS: check cpu/common/parse.c
192
 */
193 560 markom
inline unsigned long evalsim_mem32(unsigned long memaddr)
194
{
195 1319 phoenix
        return(evalsim_mem32_atomic(memaddr, 1));
196
}
197 560 markom
 
198 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do */
199
inline unsigned long evalsim_mem32_void(unsigned long memaddr)
200
{
201
        return(evalsim_mem32_atomic(memaddr, 0));
202
}
203
 
204
unsigned long evalsim_mem32_atomic(unsigned long memaddr, int cpu_access)
205
{
206
  unsigned long temp = 0;
207
 
208 560 markom
  if (verify_memoryarea(memaddr)) {
209
    switch(cur_area->granularity) {
210
    case 4:
211
      temp = cur_area->readfunc(memaddr);
212
      break;
213
    case 1:
214
      temp = cur_area->readfunc(memaddr) << 24;
215
      temp |= cur_area->readfunc(memaddr + 1) << 16;
216
      temp |= cur_area->readfunc(memaddr + 2) << 8;
217
      temp |= cur_area->readfunc(memaddr + 3);
218
      break;
219
    case 2:
220
      temp = cur_area->readfunc(memaddr) << 16;
221
      temp |= cur_area->readfunc(memaddr + 2);
222
      break;
223 1319 phoenix
    default:
224
      /* if you add new memory granularity be sure to check the formula
225
       * below for the read delay and fix it if necessery
226
       */
227
      PRINTF("unknown/unhandled memory granularuty\n");
228
      exit(-1);
229 560 markom
    }
230 1319 phoenix
    if (cpu_access)
231
      runtime.sim.mem_cycles += cur_area->delayr * (4 / cur_area->granularity);
232 560 markom
  }
233
  return temp;
234
}
235
 
236 1319 phoenix
/* for cpu accesses */
237
inline unsigned short evalsim_mem16(unsigned long memaddr)
238 560 markom
{
239 1319 phoenix
        return(evalsim_mem16_atomic(memaddr, 1));
240
}
241 560 markom
 
242 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do */
243
inline unsigned short evalsim_mem16_void(unsigned long memaddr)
244
{
245
        return(evalsim_mem16_atomic(memaddr, 0));
246
}
247
 
248
unsigned short evalsim_mem16_atomic(unsigned long memaddr, int cpu_access)
249
{
250
  unsigned long temp = 0;
251
 
252 560 markom
  if (verify_memoryarea(memaddr)) {
253
    switch(cur_area->granularity) {
254
    case 1:
255
      temp = cur_area->readfunc(memaddr) << 8;
256
      temp |= cur_area->readfunc(memaddr + 1);
257 1319 phoenix
      if (cpu_access)
258
        runtime.sim.mem_cycles += cur_area->delayr * 2;
259 560 markom
      break;
260
    case 2:
261
      temp = cur_area->readfunc(memaddr);
262 1319 phoenix
      if (cpu_access)
263
        runtime.sim.mem_cycles += cur_area->delayr;
264 560 markom
      break;
265
    case 4:
266 1319 phoenix
      temp = evalsim_mem32_atomic (memaddr & ~3ul, cpu_access);
267 560 markom
      if (memaddr & 2)
268
        temp &= 0xffff;
269
      else
270
        temp >>= 16;
271
      break;
272 1319 phoenix
    default:
273
      /* if you add new memory granularity be sure to check the formula
274
       * below for the read delay and fix it if necessery
275
       */
276
      PRINTF("unknown/unhandled memory granularuty\n");
277
      exit(-1);
278 560 markom
    }
279
  }
280
  return temp;
281
}
282
 
283 1319 phoenix
/* for cpu accesses */
284
inline unsigned char evalsim_mem8(unsigned long memaddr)
285 560 markom
{
286 1319 phoenix
        return(evalsim_mem8_atomic(memaddr, 1));
287
}
288 560 markom
 
289 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do */
290
inline unsigned char evalsim_mem8_void(unsigned long memaddr)
291
{
292
        return(evalsim_mem8_atomic(memaddr, 0));
293
}
294
 
295
unsigned char evalsim_mem8_atomic(unsigned long memaddr, int cpu_access)
296
{
297
  unsigned long temp = 0;
298
 
299 560 markom
  if (verify_memoryarea(memaddr)) {
300
    switch(cur_area->granularity) {
301
    case 1:
302
      temp = cur_area->readfunc(memaddr);
303 1319 phoenix
      if (cpu_access)
304
        runtime.sim.mem_cycles += cur_area->delayr;
305 560 markom
      break;
306
    case 2:
307 1319 phoenix
      temp = evalsim_mem16_atomic (memaddr & ~1ul, cpu_access);
308 560 markom
      if (memaddr & 1)
309
        temp &= 0xff;
310
      else
311
        temp >>= 8;
312
      break;
313
    case 4:
314 1319 phoenix
      temp = evalsim_mem32_atomic (memaddr & ~3ul, cpu_access);
315 560 markom
      temp >>= 8 * (3 - (memaddr & 3));
316
      temp &= 0xff;
317
      break;
318 1319 phoenix
    default:
319
      /* if you add new memory granularity be sure to check the formula
320
       * below for the read delay and fix it if necessery
321
       */
322
      PRINTF("unknown/unhandled memory granularuty\n");
323
      exit(-1);
324 560 markom
    }
325
  }
326
  return temp;
327
}
328
 
329 1319 phoenix
/* Returns 32-bit values from mem array. Big endian version.
330
 *
331
 * this function is only used in dump_memory() below, so it's
332
 * safe to asume it's for simulator purposes access only,
333
 * hence the use of eval_mem32_void()
334
 *
335
 * STATISTICS OK.
336
 */
337 349 simons
unsigned long read_mem(unsigned long memaddr,int* breakpoint)
338
{
339
  unsigned long temp;
340
 
341 525 simons
  cur_vadd = memaddr;
342 550 markom
  if (config.debug.enabled)
343 349 simons
    *breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
344 1319 phoenix
  temp = evalsim_mem32_void(memaddr);
345 611 simons
  if (!cur_area) {
346 997 markom
    PRINTF("EXCEPTION: read out of memory (16-bit access to %.8lx)\n", memaddr);
347 611 simons
    except_handle(EXCEPT_BUSERR, cur_vadd);
348
    temp = 0;
349
  }
350
 
351 599 simons
  if (!pending.valid && cur_area->log)
352 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> read %08lx\n", memaddr, temp);
353 550 markom
  if (config.debug.enabled)
354 349 simons
    *breakpoint += CheckDebugUnit(DebugLoadData,temp);  /* MM170901 */
355
  return temp;
356 537 markom
}
357 349 simons
 
358 1319 phoenix
/* Returns 32-bit values from mem array. Big endian version.
359
 *
360
 * STATISTICS OK (only used for cpu_access, that is architectural access)
361
 */
362 123 markom
unsigned long eval_mem32(unsigned long memaddr,int* breakpoint)
363 2 cvs
{
364 239 markom
  unsigned long temp;
365 123 markom
 
366 547 markom
  if (config.sim.mprofile)
367
    mprofile (memaddr, MPROF_32 | MPROF_READ);
368
 
369 538 markom
  if (memaddr & 3) {
370
    except_handle (EXCEPT_ALIGN, memaddr);
371
    return 0;
372
  }
373 557 markom
 
374 631 simons
  if (config.debug.enabled)
375
    *breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
376
 
377 574 markom
  cur_vadd = memaddr;
378 631 simons
 
379
  memaddr = dmmu_translate(memaddr, 0);
380 574 markom
  if (pending.valid)
381
    return 0;
382
 
383 992 simons
  if (config.dc.enabled)
384
    temp = dc_simulate_read(memaddr, 4);
385
  else {
386
    temp = evalsim_mem32(memaddr);
387
    if (!cur_area) {
388 997 markom
      PRINTF("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", memaddr);
389 992 simons
      except_handle(EXCEPT_BUSERR, cur_vadd);
390
      temp = 0;
391
    }
392 611 simons
  }
393
 
394 550 markom
  if (config.debug.enabled)
395 270 markom
    *breakpoint += CheckDebugUnit(DebugLoadData,temp);  /* MM170901 */
396 239 markom
  return temp;
397 66 lampret
}
398
 
399 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do
400
 *
401
 * STATISTICS OK
402
 */
403 1240 phoenix
unsigned long eval_direct32(unsigned long memaddr, int *breakpoint,
404
                            int through_mmu, int through_dc)
405
{
406
  unsigned long temp;
407
 
408
  if (memaddr & 3) {
409
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
410
      return 0;
411
  }
412
 
413
  cur_vadd = memaddr;
414
 
415
  if (through_mmu)
416
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
417
 
418
  if (through_dc)
419
    temp = dc_simulate_read(memaddr, 4);
420
  else {
421 1319 phoenix
    temp = evalsim_mem32_void(memaddr);
422 1240 phoenix
    if (!cur_area) {
423
      PRINTF("EXCEPTION: read out of memory (32-bit access to %.8lx) in eval_direct32()\n", memaddr);
424
      except_handle(EXCEPT_BUSERR, cur_vadd);
425
      temp = 0;
426
    }
427
  }
428
 
429
  return temp;
430
}
431
 
432
 
433 1319 phoenix
/* Returns 32-bit values from mem array. Big endian version.
434
 *
435
 * STATISTICS OK (only used for cpu_access, that is architectural access)
436
 */
437 349 simons
unsigned long eval_insn(unsigned long memaddr,int* breakpoint)
438
{
439
  unsigned long temp;
440
 
441 547 markom
  if (config.sim.mprofile)
442
    mprofile (memaddr, MPROF_32 | MPROF_FETCH);
443 532 markom
//  memaddr = simulate_ic_mmu_fetch(memaddr);
444 525 simons
  cur_vadd = pc;
445 1244 hpanther
 
446
  // I think this does not belong into eval_insn() 2004-01-30 HP
447
//  if (config.debug.enabled)
448
//    *breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
449
 
450
  // We could place the CheckDebugUnit(DebugInstructionFetch) here, but it is currently done
451
  // in decode_execute_wrapper, so I leave it like this. 2004-01-30 HP
452
 
453 631 simons
  if (config.ic.enabled)
454
    temp = ic_simulate_fetch(memaddr);
455 992 simons
  else {
456 631 simons
    temp = evalsim_mem32(memaddr);
457 992 simons
    if (!cur_area) {
458 997 markom
      PRINTF("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", memaddr);
459 992 simons
      except_handle(EXCEPT_BUSERR, cur_vadd);
460
      temp = 0;
461
    }
462 611 simons
  }
463
 
464 1244 hpanther
  // I think this does not belong into eval_insn() 2004-01-30 HP
465
//  if (config.debug.enabled)
466
//    *breakpoint += CheckDebugUnit(DebugLoadData,temp);  /* MM170901 */
467 349 simons
  return temp;
468
}
469
 
470 1319 phoenix
/* Returns 16-bit values from mem array. Big endian version.
471
 *
472
 * STATISTICS OK (only used for cpu_access, that is architectural access)
473
 */
474 123 markom
unsigned short eval_mem16(unsigned long memaddr,int* breakpoint)
475 2 cvs
{
476 239 markom
  unsigned short temp;
477 547 markom
 
478
  if (config.sim.mprofile)
479
    mprofile (memaddr, MPROF_16 | MPROF_READ);
480
 
481 538 markom
  if (memaddr & 1) {
482
    except_handle (EXCEPT_ALIGN, memaddr);
483
    return 0;
484
  }
485 574 markom
 
486 631 simons
  if (config.debug.enabled)
487
    *breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
488
 
489 574 markom
  cur_vadd = memaddr;
490 631 simons
 
491
  memaddr = dmmu_translate(memaddr, 0);
492 574 markom
  if (pending.valid)
493
    return 0;
494 66 lampret
 
495 992 simons
  if (config.dc.enabled)
496
    temp = (unsigned short)dc_simulate_read(memaddr, 2);
497
  else {
498
    temp = evalsim_mem16(memaddr);
499
    if (!cur_area) {
500 997 markom
      PRINTF("EXCEPTION: read out of memory (16-bit access to %.8lx)\n", memaddr);
501 992 simons
      except_handle(EXCEPT_BUSERR, cur_vadd);
502
      temp = 0;
503
    }
504 611 simons
  }
505
 
506 550 markom
  if (config.debug.enabled)
507 270 markom
    *breakpoint += CheckDebugUnit(DebugLoadData,temp);  /* MM170901 */
508 239 markom
  return temp;
509 66 lampret
}
510
 
511 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do
512
 *
513
 * STATISTICS OK.
514
 */
515 1240 phoenix
unsigned short eval_direct16(unsigned long memaddr, int *breakpoint,
516
                             int through_mmu, int through_dc)
517
{
518
  unsigned long temp;
519
 
520
  if (memaddr & 3) {
521
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
522
      return 0;
523
  }
524
 
525
  cur_vadd = memaddr;
526
 
527
  if (through_mmu)
528
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
529
 
530
  if (through_dc)
531
    temp = dc_simulate_read(memaddr, 2);
532
  else {
533 1319 phoenix
    temp = evalsim_mem16_void(memaddr);
534 1240 phoenix
    if (!cur_area) {
535
      PRINTF("EXCEPTION: read out of memory (16-bit access to %.8lx) in eval_direct16()\n", memaddr);
536
      except_handle(EXCEPT_BUSERR, cur_vadd);
537
      temp = 0;
538
    }
539
  }
540
 
541
  return temp;
542
}
543
 
544
 
545 1319 phoenix
/* Returns 8-bit values from mem array.
546
 *
547
 * STATISTICS OK (only used for cpu_access, that is architectural access)
548
 */
549 123 markom
unsigned char eval_mem8(unsigned long memaddr,int* breakpoint)
550 221 markom
{
551 631 simons
  unsigned char temp;
552 547 markom
 
553
  if (config.sim.mprofile)
554
    mprofile (memaddr, MPROF_8 | MPROF_READ);
555
 
556 631 simons
  if (config.debug.enabled)
557
    *breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr);  /* 28/05/01 CZ */
558
 
559 525 simons
  cur_vadd = memaddr;
560 631 simons
 
561
  memaddr = dmmu_translate(memaddr, 0);
562 458 simons
  if (pending.valid)
563
    return 0;
564 6 lampret
 
565 992 simons
  if (config.dc.enabled)
566
    temp = (unsigned char)dc_simulate_read(memaddr, 1);
567
  else {
568
    temp = evalsim_mem8(memaddr);
569
    if (!cur_area) {
570 997 markom
      PRINTF("EXCEPTION: read out of memory (8-bit access to %.8lx)\n", memaddr);
571 992 simons
      except_handle(EXCEPT_BUSERR, cur_vadd);
572
      temp = 0;
573
    }
574 611 simons
  }
575
 
576 550 markom
  if (config.debug.enabled)
577 270 markom
    *breakpoint += CheckDebugUnit(DebugLoadData,temp);  /* MM170901 */
578 239 markom
  return temp;
579 66 lampret
}
580
 
581 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do
582
 *
583
 * STATISTICS OK.
584
 */
585 1240 phoenix
unsigned char eval_direct8(unsigned long memaddr, int *breakpoint,
586
                           int through_mmu, int through_dc)
587
{
588
  unsigned char temp;
589
 
590
  if (memaddr & 3) {
591
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
592
    return 0;
593
  }
594
 
595
  cur_vadd = memaddr;
596
 
597
  if (through_mmu)
598
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
599
 
600
  if (through_dc)
601
    temp = (unsigned char)dc_simulate_read(memaddr, 1);
602
  else {
603 1319 phoenix
    temp = evalsim_mem8_void(memaddr);
604 1240 phoenix
    if (!cur_area) {
605
      PRINTF("EXCEPTION: read out of memory (8-bit access to %.8lx) in eval_direct8()\n", memaddr);
606
      except_handle(EXCEPT_BUSERR, cur_vadd);
607
      temp = 0;
608
    }
609
  }
610 1308 phoenix
  return temp;
611 1240 phoenix
}
612
 
613 1319 phoenix
/* for cpu accesses */
614
inline void setsim_mem32(unsigned long memaddr, unsigned long value)
615
{
616
  return(setsim_mem32_atomic(memaddr, value, 1));
617
}
618 1240 phoenix
 
619 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do */
620
inline void setsim_mem32_void(unsigned long memaddr, unsigned long value)
621 66 lampret
{
622 1319 phoenix
  return(setsim_mem32_atomic(memaddr, value, 0));
623
}
624
 
625
void setsim_mem32_atomic(unsigned long memaddr, unsigned long value, int cpu_access)
626
{
627 239 markom
  if (verify_memoryarea(memaddr)) {
628
    switch(cur_area->granularity) {
629 538 markom
    case 4:
630
      cur_area->writefunc(memaddr, value);
631 1319 phoenix
      if (cpu_access)
632
        runtime.sim.mem_cycles += cur_area->delayw;
633 538 markom
      break;
634 239 markom
    case 1:
635 251 erez
      cur_area->writefunc(memaddr    , (value >> 24) & 0xFF);
636 239 markom
      cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF);
637 251 erez
      cur_area->writefunc(memaddr + 2, (value >>  8) & 0xFF);
638
      cur_area->writefunc(memaddr + 3, (value      ) & 0xFF);
639 1319 phoenix
      if (cpu_access)
640
        runtime.sim.mem_cycles += cur_area->delayw * 4;
641 239 markom
      break;
642
    case 2:
643
      cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF);
644
      cur_area->writefunc(memaddr + 2, value & 0xFFFF);
645 1319 phoenix
      if (cpu_access)
646
        runtime.sim.mem_cycles += cur_area->delayw * 2;
647 239 markom
      break;
648 1319 phoenix
    default:
649
      /* if you add new memory granularity be sure to check the formula
650
       * below for the read delay and fix it if necessery
651
       */
652
      PRINTF("unknown/unhandled memory granularuty\n");
653
      exit(-1);
654 242 markom
    }
655 239 markom
  } else {
656 997 markom
    PRINTF("EXCEPTION: write out of memory (32-bit access to %.8lx)\n", memaddr);
657 525 simons
    except_handle(EXCEPT_BUSERR, cur_vadd);
658 239 markom
  }
659 2 cvs
}
660
 
661 1319 phoenix
/* for cpu accesses */
662
inline void setsim_mem16(unsigned long memaddr, unsigned short value)
663 66 lampret
{
664 1319 phoenix
  return(setsim_mem16_atomic(memaddr, value, 1));
665
}
666
 
667
/* for simulator accesses, the ones that cpu wouldn't do */
668
inline void setsim_mem16_void(unsigned long memaddr, unsigned short value)
669
{
670
  return(setsim_mem16_atomic(memaddr, value, 0));
671
}
672
 
673
void setsim_mem16_atomic(unsigned long memaddr, unsigned short value, int cpu_access)
674
{
675 538 markom
  unsigned long temp;
676 239 markom
  if (verify_memoryarea(memaddr)) {
677
    switch(cur_area->granularity) {
678
    case 1:
679
      cur_area->writefunc(memaddr, (value >> 8) & 0xFF);
680
      cur_area->writefunc(memaddr + 1, value & 0xFF);
681 1319 phoenix
      if (cpu_access)
682
        runtime.sim.mem_cycles += cur_area->delayw * 2;
683 239 markom
      break;
684
    case 2:
685 251 erez
      cur_area->writefunc(memaddr, value & 0xFFFF);
686 1319 phoenix
      if (cpu_access)
687
        runtime.sim.mem_cycles += cur_area->delayw;
688 239 markom
      break;
689
    case 4:
690 1319 phoenix
      temp = evalsim_mem32_void(memaddr & ~3ul);
691 546 simons
      temp &= 0xffff << ((memaddr & 2) ? 16 : 0);
692
      temp |= (unsigned long)(value & 0xffff) << ((memaddr & 2) ? 0 : 16);
693 1319 phoenix
      setsim_mem32_atomic(memaddr & ~3ul, temp, cpu_access);
694 239 markom
      break;
695 1319 phoenix
    default:
696
      /* if you add new memory granularity be sure to check the formula
697
       * below for the read delay and fix it if necessery
698
       */
699
      PRINTF("unknown/unhandled memory granularuty\n");
700
      exit(-1);
701 239 markom
    }
702
  } else {
703 997 markom
    PRINTF("EXCEPTION: write out of memory (16-bit access to %.8lx)\n", memaddr);
704 525 simons
    except_handle(EXCEPT_BUSERR, cur_vadd);
705 239 markom
  }
706 2 cvs
}
707
 
708 1319 phoenix
/* for cpu accesses */
709
inline void setsim_mem8(unsigned long memaddr, unsigned char value)
710 66 lampret
{
711 1319 phoenix
  return(setsim_mem8_atomic(memaddr, value, 1));
712
}
713
 
714
/* for simulator accesses, the ones that cpu wouldn't do */
715
inline void setsim_mem8_void(unsigned long memaddr, unsigned char value)
716
{
717
  return(setsim_mem8_atomic(memaddr, value, 0));
718
}
719
 
720
void setsim_mem8_atomic(unsigned long memaddr, unsigned char value, int cpu_access)
721
{
722 538 markom
  unsigned long temp;
723 239 markom
  if (verify_memoryarea(memaddr)) {
724 538 markom
    switch (cur_area->granularity) {
725
    case 1:
726 239 markom
      cur_area->writefunc(memaddr, value);
727 1319 phoenix
      if (cpu_access)
728
        runtime.sim.mem_cycles += cur_area->delayw;
729 538 markom
      break;
730
    case 2:
731 1319 phoenix
      temp = evalsim_mem16_void (memaddr & ~1ul);
732 546 simons
      temp &= 0xff << ((memaddr & 1) ? 8 : 0);
733
      temp |= (unsigned short)(value & 0xff) << ((memaddr & 1) ? 0 : 8);
734 1319 phoenix
      setsim_mem16_atomic (memaddr & ~1ul, temp, cpu_access);
735 538 markom
      break;
736
    case 4:
737 1319 phoenix
      temp = evalsim_mem32_void (memaddr & ~3ul);
738 538 markom
      temp &= ~(0xff << (8 * (3 - (memaddr & 3))));
739
      temp |= (unsigned long)(value & 0xff) << (8 * (3 - (memaddr & 3)));
740 1319 phoenix
      setsim_mem32_atomic (memaddr & ~3ul, temp, cpu_access);
741 538 markom
      break;
742 239 markom
    }
743
  } else {
744 997 markom
    PRINTF("EXCEPTION: write out of memory (8-bit access to %.8lx)\n", memaddr);
745 525 simons
    except_handle(EXCEPT_BUSERR, cur_vadd);
746 239 markom
  }
747 2 cvs
}
748 30 lampret
 
749 1319 phoenix
/* Set mem, 32-bit. Big endian version.
750
 *
751
 * STATISTICS OK. (the only suspicious usage is in toplevel.c,
752
 *                 where this instruction is used for patching memory,
753
 *                 wether this is cpu or architectual access is yet to
754
 *                 be decided)
755
 */
756 587 markom
void set_mem32(unsigned long memaddr, unsigned long value,int* breakpoint)
757
{
758
  if (config.sim.mprofile)
759
    mprofile (memaddr, MPROF_32 | MPROF_WRITE);
760
 
761
  if (memaddr & 3) {
762
    except_handle (EXCEPT_ALIGN, memaddr);
763
    return;
764
  }
765
 
766
  cur_vadd = memaddr;
767 631 simons
  memaddr = dmmu_translate(memaddr, 1);;
768 587 markom
  /* If we produced exception don't set anything */
769
  if (pending.valid)
770
    return;
771
 
772
  if (config.debug.enabled) {
773
    *breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);  /* 28/05/01 CZ */
774
    *breakpoint += CheckDebugUnit(DebugStoreData,value);
775
  }
776
 
777 992 simons
  dc_simulate_write(memaddr, value, 4);
778
 
779 1218 phoenix
  if (cur_area && cur_area->log)
780 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08lx\n", memaddr, value);
781 587 markom
}
782
 
783 1319 phoenix
/*
784
 * STATISTICS NOT OK.
785
 */
786 1240 phoenix
void set_direct32(unsigned long memaddr, unsigned long value,int* breakpoint,
787
                  int through_mmu, int through_dc)
788
{
789
 
790
  if (memaddr & 3) {
791
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
792
    return;
793
  }
794
 
795
  cur_vadd = memaddr;
796
 
797
  if (through_mmu) {
798
    /* 0 - no write access, we do not want a DPF exception do we ;)
799
     */
800
    memaddr = peek_into_dtlb(memaddr, 1, through_dc);
801
  }
802
 
803
 
804 1319 phoenix
  /* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
805
   *                and possibly also memory access times.
806 1240 phoenix
   */
807 1319 phoenix
  if (!through_dc)
808
    PRINTF("WARNING: statistics might not be OK\n");
809 1240 phoenix
  dc_simulate_write(memaddr, value, 4);
810
 
811
  if (cur_area && cur_area->log)
812 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08lx\n", memaddr, value);
813 1240 phoenix
}
814
 
815
 
816 587 markom
/* Set mem, 16-bit. Big endian version. */
817
 
818 1240 phoenix
void set_mem16(unsigned long memaddr, unsigned short value, int* breakpoint)
819 587 markom
{
820
  if (config.sim.mprofile)
821
    mprofile (memaddr, MPROF_16 | MPROF_WRITE);
822
 
823
  if (memaddr & 1) {
824
    except_handle (EXCEPT_ALIGN, memaddr);
825
    return;
826
  }
827
 
828
  cur_vadd = memaddr;
829 631 simons
  memaddr = dmmu_translate(memaddr, 1);;
830 587 markom
  /* If we produced exception don't set anything */
831
  if (pending.valid)
832
    return;
833
 
834
  if (config.debug.enabled) {
835
    *breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);  /* 28/05/01 CZ */
836
    *breakpoint += CheckDebugUnit(DebugStoreData,value);
837
  }
838
 
839 992 simons
  dc_simulate_write(memaddr, (unsigned long)value, 2);
840
 
841 1218 phoenix
  if (cur_area && cur_area->log)
842 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08x\n", memaddr, value);
843 587 markom
}
844
 
845 1319 phoenix
/*
846
 * STATISTICS NOT OK.
847
 */
848 1240 phoenix
void set_direct16(unsigned long memaddr, unsigned short value, int* breakpoint,
849
                  int through_mmu, int through_dc)
850
{
851
 
852
  if (memaddr & 3) {
853
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
854
    return;
855
  }
856
 
857
  cur_vadd = memaddr;
858
 
859
  if (through_mmu) {
860
    /* 0 - no write access, we do not want a DPF exception do we ;)
861
     */
862
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
863
  }
864
 
865 1319 phoenix
  /* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
866
   *                and possibly also memory access times.
867 1240 phoenix
   */
868 1319 phoenix
  if (!through_dc)
869
    PRINTF("WARNING: statistics might not be OK\n");
870 1240 phoenix
  dc_simulate_write(memaddr, value, 2);
871
 
872
  if (cur_area && cur_area->log)
873 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08x\n", memaddr, value);
874 1240 phoenix
}
875
 
876 587 markom
/* Set mem, 8-bit. */
877
 
878 1240 phoenix
void set_mem8(unsigned long memaddr, unsigned char value, int* breakpoint)
879 587 markom
{
880
  if (config.sim.mprofile)
881
    mprofile (memaddr, MPROF_8 | MPROF_WRITE);
882
 
883
  cur_vadd = memaddr;
884 631 simons
  memaddr = dmmu_translate(memaddr, 1);;
885 587 markom
  /* If we produced exception don't set anything */
886
  if (pending.valid) return;
887
 
888
  if (config.debug.enabled) {
889
    *breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);  /* 28/05/01 CZ */
890
    *breakpoint += CheckDebugUnit(DebugStoreData,value);
891
  }
892
 
893 992 simons
  dc_simulate_write(memaddr, (unsigned long)value, 1);
894
 
895 1218 phoenix
  if (cur_area && cur_area->log)
896 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08x\n", memaddr, value);
897 587 markom
}
898
 
899 1319 phoenix
/*
900
 * STATISTICS NOT OK.
901
 */
902 1240 phoenix
void set_direct8(unsigned long memaddr, unsigned char value, int* breakpoint,
903
                 int through_mmu, int through_dc)
904
{
905
 
906
  if (memaddr & 3) {
907
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
908
    return;
909
  }
910
 
911
  cur_vadd = memaddr;
912
 
913
  if (through_mmu) {
914
    /* 0 - no write access, we do not want a DPF exception do we ;)
915
     */
916
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
917
  }
918
 
919 1319 phoenix
  /* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
920
   *                and possibly also memory access times.
921 1240 phoenix
   */
922 1319 phoenix
  if (!through_dc)
923
    PRINTF("WARNING: statistics might not be OK\n");
924 1240 phoenix
  dc_simulate_write(memaddr, value, 1);
925
 
926
  if (cur_area && cur_area->log)
927
    fprintf (cur_area->log, "[%08x] -> write %08x\n", memaddr, value);
928
}
929
 
930
 
931 361 markom
void dumpmemory(unsigned int from, unsigned int to, int disasm, int nl)
932
{
933
  unsigned int i, j;
934
  struct label_entry *tmp;
935
  int ilen = disasm ? 4 : 16;
936
 
937
  for(i = from; i < to; i += ilen) {
938 997 markom
    PRINTF("%.8x: ", i);
939 361 markom
    for (j = 0; j < ilen;) {
940
      int data = -1;
941
      if (!disasm) {
942
        tmp = NULL;
943
        if (verify_memoryarea(i+j)) {
944
          struct label_entry *entry;
945
          entry = get_label(i + j);
946
          if (entry)
947 997 markom
            PRINTF("(%s)", entry->name);
948
          PRINTF("%02x ", data = evalsim_mem8(i+j));
949
        } else PRINTF("XX ");
950 361 markom
        j++;
951
      } else {
952
        int breakpoint;
953
        unsigned int _insn = read_mem(i, &breakpoint);
954
        int index = insn_decode (_insn);
955
        int len = insn_len (index);
956
 
957
        tmp = NULL;
958
        if (verify_memoryarea(i+j)) {
959
          struct label_entry *entry;
960
          entry = get_label(i + j);
961
          if (entry)
962 997 markom
            PRINTF("(%s)", entry->name);
963 361 markom
 
964 1308 phoenix
          PRINTF(": %08lx ", (unsigned long)_insn);
965 361 markom
          if (index >= 0) {
966
            disassemble_insn (_insn);
967 997 markom
            PRINTF(" %s", disassembled);
968 361 markom
          } else
969 997 markom
            PRINTF("<invalid>");
970
        } else PRINTF("XXXXXXXX");
971 361 markom
        j += len;
972
      }
973
    }
974
    if (nl)
975 997 markom
      PRINTF ("\n");
976 361 markom
  }
977
}
978
 
979 538 markom
unsigned long simmem_read_word(unsigned long addr) {
980
  return simmem32[(cur_area->misc + (addr & cur_area->size_mask)) >> 2];
981 221 markom
}
982
 
983 538 markom
void simmem_write_word(unsigned long addr, unsigned long value) {
984
  simmem32[(cur_area->misc + (addr & cur_area->size_mask)) >> 2] = value;
985 221 markom
}
986
 
987 424 markom
unsigned long simmem_read_zero(unsigned long addr) {
988
  if (config.sim.verbose)
989
    fprintf (stderr, "WARNING: memory read from non-read memory area 0x%08x.\n", addr);
990
  return 0;
991
}
992
 
993
void simmem_write_null(unsigned long addr, unsigned long value) {
994
  if (config.sim.verbose)
995 1308 phoenix
    fprintf (stderr, "WARNING: memory write to 0x%08lx, non-write memory area (value 0x%08lx).\n", addr, value);
996 424 markom
}
997
 
998
/* Initialize memory table from a config struct */
999
 
1000
void init_memory_table ()
1001 221 markom
{
1002 239 markom
  unsigned long memory_needed = 0;
1003 426 markom
 
1004 424 markom
  /* If nothing was defined, use default memory block */
1005
  if (config.memory.nmemories) {
1006
    int i;
1007
    for (i = 0; i < config.memory.nmemories; i++) {
1008
      unsigned long start = config.memory.table[i].baseaddr;
1009
      unsigned long length = config.memory.table[i].size;
1010
      char *type = config.memory.table[i].name;
1011
      int rd = config.memory.table[i].delayr;
1012
      int wd = config.memory.table[i].delayw;
1013
      int ce = config.memory.table[i].ce;
1014
      if (config.sim.verbose)
1015
        debug (1, "%08X %08X (%i KB): %s (activated by CE%i; read delay = %icyc, write delay = %icyc)\n",
1016
          start, length, length >> 10, type, ce, rd, wd);
1017 970 simons
      register_memoryarea(start, length, 4, 0, &simmem_read_word, &simmem_write_word);
1018 239 markom
      cur_area->misc = memory_needed;
1019 540 simons
      cur_area->chip_select = ce;
1020 543 simons
      cur_area->valid = 1;
1021 424 markom
      cur_area->delayw = wd;
1022
      cur_area->delayr = rd;
1023 426 markom
      if (config.memory.table[i].log[0] != '\0') {
1024
        if ((cur_area->log = fopen (config.memory.table[i].log, "wt+")) == NULL)
1025
          fprintf (stderr, "WARNING: Cannot open '%s'.\n", config.memory.table[i].log);
1026
      } else
1027 554 markom
        cur_area->log = NULL;
1028 261 markom
      memory_needed += cur_area->size;
1029 239 markom
    }
1030 997 markom
    PRINTF ("\n");
1031 239 markom
  } else {
1032 308 markom
    if (config.sim.verbose)
1033 424 markom
      fprintf (stderr, "WARNING: Memory not defined, assuming standard configuration.\n");
1034 970 simons
    register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 4, 0, &simmem_read_word, &simmem_write_word);
1035 554 markom
    cur_area->misc = memory_needed;
1036
    cur_area->chip_select = 0;
1037
    cur_area->valid = 1;
1038
    cur_area->delayw = 1;
1039
    cur_area->delayr = 1;
1040
    cur_area->log = NULL;
1041 261 markom
    memory_needed += cur_area->size;
1042 239 markom
  }
1043 424 markom
 
1044 538 markom
  simmem32 = (unsigned long *) malloc (sizeof (unsigned long) * ((memory_needed + 3) / 4));
1045
  if (!simmem32) {
1046 239 markom
    fprintf (stderr, "Failed to allocate sim memory. Aborting\n");
1047
    exit (-1);
1048
  }
1049 221 markom
}
1050 424 markom
 
1051
/* Changes read/write memory in read/write only */
1052
 
1053
void lock_memory_table ()
1054
{
1055
  struct dev_memarea *ptmp;
1056
 
1057
  /* Check list of registered devices. */
1058
  for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
1059 538 markom
    if (ptmp->delayr < 0 && ptmp->readfunc == &simmem_read_word)
1060 424 markom
      ptmp->readfunc = &simmem_read_zero;
1061 538 markom
    if (ptmp->delayw < 0 && ptmp->writefunc == &simmem_write_word)
1062 424 markom
      ptmp->writefunc = &simmem_write_null;
1063 543 simons
 
1064
    /* If this mem area is not for memory chip under MC control
1065
       then this area is valid all the time */
1066
    if (ptmp->readfunc != &simmem_read_word) {
1067
      ptmp->valid = 1;
1068
      ptmp->chip_select = -1;
1069
    }
1070 424 markom
  }
1071
}
1072 426 markom
 
1073
/* Closes files, etc. */
1074
 
1075
void done_memory_table ()
1076
{
1077
  struct dev_memarea *ptmp;
1078
 
1079
  /* Check list of registered devices. */
1080
  for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
1081
    if (ptmp->log)
1082
      fclose (ptmp->log);
1083
  }
1084
}
1085 427 markom
 
1086
/* Displays current memory configuration */
1087
 
1088
void memory_table_status ()
1089
{
1090
  struct dev_memarea *ptmp;
1091
 
1092
  /* Check list of registered devices. */
1093
  for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
1094 1308 phoenix
    PRINTF ("addr & %08lx == %08lx to %08lx, size %08lx, gran %liB\n",
1095 427 markom
      ptmp->addr_mask, ptmp->addr_compare, ptmp->addr_compare | bit_mask (ptmp->size),
1096
      ptmp->size, ptmp->granularity);
1097 997 markom
    PRINTF ("\t");
1098 427 markom
    if (ptmp->delayr >= 0)
1099 997 markom
      PRINTF ("read delay = %i cycles, ", ptmp->delayr);
1100 427 markom
    else
1101 997 markom
      PRINTF ("reads not possible, ");
1102 427 markom
 
1103
    if (ptmp->delayw >= 0)
1104 997 markom
      PRINTF ("write delay = %i cycles", ptmp->delayw);
1105 427 markom
    else
1106 997 markom
      PRINTF ("writes not possible");
1107 427 markom
 
1108
    if (ptmp->log)
1109 997 markom
      PRINTF (", (logged)\n");
1110 427 markom
    else
1111 997 markom
      PRINTF ("\n");
1112 427 markom
  }
1113
}
1114 433 markom
 
1115
/* Outputs time in pretty form to dest string */
1116
 
1117 897 markom
char *generate_time_pretty (char *dest, long time_ps)
1118 433 markom
{
1119
  int exp3 = 0;
1120
  if (time_ps) {
1121
    while ((time_ps % 1000) == 0) {
1122
      time_ps /= 1000;
1123
      exp3++;
1124
    }
1125
  }
1126 1308 phoenix
  sprintf (dest, "%li%cs", time_ps, "pnum"[exp3]);
1127 897 markom
  return dest;
1128 433 markom
}

powered by: WebSVN 2.1.0

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