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

Subversion Repositories or1k

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

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
#include "except.h"
39 123 markom
#include "debug_unit.h"
40 134 markom
#include "opcode/or32.h"
41 547 markom
#include "support/profile.h"
42 1308 phoenix
#include "dmmu.h"
43
#include "dcache_model.h"
44
#include "icache_model.h"
45
#include "debug.h"
46 1344 nogj
#include "stats.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 1324 phoenix
    PRINTF("EXCEPTION: read out of memory (32-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 1324 phoenix
  if (memaddr & 1) {
521 1240 phoenix
    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
  cur_vadd = memaddr;
591
 
592
  if (through_mmu)
593
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
594
 
595
  if (through_dc)
596
    temp = (unsigned char)dc_simulate_read(memaddr, 1);
597
  else {
598 1319 phoenix
    temp = evalsim_mem8_void(memaddr);
599 1240 phoenix
    if (!cur_area) {
600
      PRINTF("EXCEPTION: read out of memory (8-bit access to %.8lx) in eval_direct8()\n", memaddr);
601
      except_handle(EXCEPT_BUSERR, cur_vadd);
602
      temp = 0;
603
    }
604
  }
605 1308 phoenix
  return temp;
606 1240 phoenix
}
607
 
608 1319 phoenix
/* for cpu accesses */
609
inline void setsim_mem32(unsigned long memaddr, unsigned long value)
610
{
611
  return(setsim_mem32_atomic(memaddr, value, 1));
612
}
613 1240 phoenix
 
614 1319 phoenix
/* for simulator accesses, the ones that cpu wouldn't do */
615
inline void setsim_mem32_void(unsigned long memaddr, unsigned long value)
616 66 lampret
{
617 1319 phoenix
  return(setsim_mem32_atomic(memaddr, value, 0));
618
}
619
 
620
void setsim_mem32_atomic(unsigned long memaddr, unsigned long value, int cpu_access)
621
{
622 239 markom
  if (verify_memoryarea(memaddr)) {
623
    switch(cur_area->granularity) {
624 538 markom
    case 4:
625
      cur_area->writefunc(memaddr, value);
626 1319 phoenix
      if (cpu_access)
627
        runtime.sim.mem_cycles += cur_area->delayw;
628 538 markom
      break;
629 239 markom
    case 1:
630 251 erez
      cur_area->writefunc(memaddr    , (value >> 24) & 0xFF);
631 239 markom
      cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF);
632 251 erez
      cur_area->writefunc(memaddr + 2, (value >>  8) & 0xFF);
633
      cur_area->writefunc(memaddr + 3, (value      ) & 0xFF);
634 1319 phoenix
      if (cpu_access)
635
        runtime.sim.mem_cycles += cur_area->delayw * 4;
636 239 markom
      break;
637
    case 2:
638
      cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF);
639
      cur_area->writefunc(memaddr + 2, value & 0xFFFF);
640 1319 phoenix
      if (cpu_access)
641
        runtime.sim.mem_cycles += cur_area->delayw * 2;
642 239 markom
      break;
643 1319 phoenix
    default:
644
      /* if you add new memory granularity be sure to check the formula
645
       * below for the read delay and fix it if necessery
646
       */
647
      PRINTF("unknown/unhandled memory granularuty\n");
648
      exit(-1);
649 242 markom
    }
650 239 markom
  } else {
651 997 markom
    PRINTF("EXCEPTION: write out of memory (32-bit access to %.8lx)\n", memaddr);
652 525 simons
    except_handle(EXCEPT_BUSERR, cur_vadd);
653 239 markom
  }
654 2 cvs
}
655
 
656 1319 phoenix
/* for cpu accesses */
657
inline void setsim_mem16(unsigned long memaddr, unsigned short value)
658 66 lampret
{
659 1319 phoenix
  return(setsim_mem16_atomic(memaddr, value, 1));
660
}
661
 
662
/* for simulator accesses, the ones that cpu wouldn't do */
663
inline void setsim_mem16_void(unsigned long memaddr, unsigned short value)
664
{
665
  return(setsim_mem16_atomic(memaddr, value, 0));
666
}
667
 
668
void setsim_mem16_atomic(unsigned long memaddr, unsigned short value, int cpu_access)
669
{
670 538 markom
  unsigned long temp;
671 239 markom
  if (verify_memoryarea(memaddr)) {
672
    switch(cur_area->granularity) {
673
    case 1:
674
      cur_area->writefunc(memaddr, (value >> 8) & 0xFF);
675
      cur_area->writefunc(memaddr + 1, value & 0xFF);
676 1319 phoenix
      if (cpu_access)
677
        runtime.sim.mem_cycles += cur_area->delayw * 2;
678 239 markom
      break;
679
    case 2:
680 251 erez
      cur_area->writefunc(memaddr, value & 0xFFFF);
681 1319 phoenix
      if (cpu_access)
682
        runtime.sim.mem_cycles += cur_area->delayw;
683 239 markom
      break;
684
    case 4:
685 1319 phoenix
      temp = evalsim_mem32_void(memaddr & ~3ul);
686 546 simons
      temp &= 0xffff << ((memaddr & 2) ? 16 : 0);
687
      temp |= (unsigned long)(value & 0xffff) << ((memaddr & 2) ? 0 : 16);
688 1319 phoenix
      setsim_mem32_atomic(memaddr & ~3ul, temp, cpu_access);
689 239 markom
      break;
690 1319 phoenix
    default:
691
      /* if you add new memory granularity be sure to check the formula
692
       * below for the read delay and fix it if necessery
693
       */
694
      PRINTF("unknown/unhandled memory granularuty\n");
695
      exit(-1);
696 239 markom
    }
697
  } else {
698 997 markom
    PRINTF("EXCEPTION: write out of memory (16-bit access to %.8lx)\n", memaddr);
699 525 simons
    except_handle(EXCEPT_BUSERR, cur_vadd);
700 239 markom
  }
701 2 cvs
}
702
 
703 1319 phoenix
/* for cpu accesses */
704
inline void setsim_mem8(unsigned long memaddr, unsigned char value)
705 66 lampret
{
706 1319 phoenix
  return(setsim_mem8_atomic(memaddr, value, 1));
707
}
708
 
709
/* for simulator accesses, the ones that cpu wouldn't do */
710
inline void setsim_mem8_void(unsigned long memaddr, unsigned char value)
711
{
712
  return(setsim_mem8_atomic(memaddr, value, 0));
713
}
714
 
715
void setsim_mem8_atomic(unsigned long memaddr, unsigned char value, int cpu_access)
716
{
717 538 markom
  unsigned long temp;
718 239 markom
  if (verify_memoryarea(memaddr)) {
719 538 markom
    switch (cur_area->granularity) {
720
    case 1:
721 239 markom
      cur_area->writefunc(memaddr, value);
722 1319 phoenix
      if (cpu_access)
723
        runtime.sim.mem_cycles += cur_area->delayw;
724 538 markom
      break;
725
    case 2:
726 1319 phoenix
      temp = evalsim_mem16_void (memaddr & ~1ul);
727 546 simons
      temp &= 0xff << ((memaddr & 1) ? 8 : 0);
728
      temp |= (unsigned short)(value & 0xff) << ((memaddr & 1) ? 0 : 8);
729 1319 phoenix
      setsim_mem16_atomic (memaddr & ~1ul, temp, cpu_access);
730 538 markom
      break;
731
    case 4:
732 1319 phoenix
      temp = evalsim_mem32_void (memaddr & ~3ul);
733 538 markom
      temp &= ~(0xff << (8 * (3 - (memaddr & 3))));
734
      temp |= (unsigned long)(value & 0xff) << (8 * (3 - (memaddr & 3)));
735 1319 phoenix
      setsim_mem32_atomic (memaddr & ~3ul, temp, cpu_access);
736 538 markom
      break;
737 239 markom
    }
738
  } else {
739 997 markom
    PRINTF("EXCEPTION: write out of memory (8-bit access to %.8lx)\n", memaddr);
740 525 simons
    except_handle(EXCEPT_BUSERR, cur_vadd);
741 239 markom
  }
742 2 cvs
}
743 30 lampret
 
744 1319 phoenix
/* Set mem, 32-bit. Big endian version.
745
 *
746
 * STATISTICS OK. (the only suspicious usage is in toplevel.c,
747
 *                 where this instruction is used for patching memory,
748
 *                 wether this is cpu or architectual access is yet to
749
 *                 be decided)
750
 */
751 587 markom
void set_mem32(unsigned long memaddr, unsigned long value,int* breakpoint)
752
{
753
  if (config.sim.mprofile)
754
    mprofile (memaddr, MPROF_32 | MPROF_WRITE);
755
 
756
  if (memaddr & 3) {
757
    except_handle (EXCEPT_ALIGN, memaddr);
758
    return;
759
  }
760
 
761
  cur_vadd = memaddr;
762 631 simons
  memaddr = dmmu_translate(memaddr, 1);;
763 587 markom
  /* If we produced exception don't set anything */
764
  if (pending.valid)
765
    return;
766
 
767
  if (config.debug.enabled) {
768
    *breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);  /* 28/05/01 CZ */
769
    *breakpoint += CheckDebugUnit(DebugStoreData,value);
770
  }
771
 
772 992 simons
  dc_simulate_write(memaddr, value, 4);
773
 
774 1218 phoenix
  if (cur_area && cur_area->log)
775 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08lx\n", memaddr, value);
776 587 markom
}
777
 
778 1319 phoenix
/*
779
 * STATISTICS NOT OK.
780
 */
781 1240 phoenix
void set_direct32(unsigned long memaddr, unsigned long value,int* breakpoint,
782
                  int through_mmu, int through_dc)
783
{
784
 
785
  if (memaddr & 3) {
786
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
787
    return;
788
  }
789
 
790
  cur_vadd = memaddr;
791
 
792
  if (through_mmu) {
793
    /* 0 - no write access, we do not want a DPF exception do we ;)
794
     */
795
    memaddr = peek_into_dtlb(memaddr, 1, through_dc);
796
  }
797
 
798
 
799 1319 phoenix
  /* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
800
   *                and possibly also memory access times.
801 1240 phoenix
   */
802 1319 phoenix
  if (!through_dc)
803
    PRINTF("WARNING: statistics might not be OK\n");
804 1240 phoenix
  dc_simulate_write(memaddr, value, 4);
805
 
806
  if (cur_area && cur_area->log)
807 1324 phoenix
    fprintf (cur_area->log, "[%08lx] -> DIRECT write %08lx\n", memaddr, value);
808 1240 phoenix
}
809
 
810
 
811 587 markom
/* Set mem, 16-bit. Big endian version. */
812
 
813 1240 phoenix
void set_mem16(unsigned long memaddr, unsigned short value, int* breakpoint)
814 587 markom
{
815
  if (config.sim.mprofile)
816
    mprofile (memaddr, MPROF_16 | MPROF_WRITE);
817
 
818
  if (memaddr & 1) {
819
    except_handle (EXCEPT_ALIGN, memaddr);
820
    return;
821
  }
822
 
823
  cur_vadd = memaddr;
824 631 simons
  memaddr = dmmu_translate(memaddr, 1);;
825 587 markom
  /* If we produced exception don't set anything */
826
  if (pending.valid)
827
    return;
828
 
829
  if (config.debug.enabled) {
830
    *breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);  /* 28/05/01 CZ */
831
    *breakpoint += CheckDebugUnit(DebugStoreData,value);
832
  }
833
 
834 992 simons
  dc_simulate_write(memaddr, (unsigned long)value, 2);
835
 
836 1218 phoenix
  if (cur_area && cur_area->log)
837 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08x\n", memaddr, value);
838 587 markom
}
839
 
840 1319 phoenix
/*
841
 * STATISTICS NOT OK.
842
 */
843 1240 phoenix
void set_direct16(unsigned long memaddr, unsigned short value, int* breakpoint,
844
                  int through_mmu, int through_dc)
845
{
846
 
847 1324 phoenix
  if (memaddr & 1) {
848 1240 phoenix
    PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
849
    return;
850
  }
851
 
852
  cur_vadd = memaddr;
853
 
854
  if (through_mmu) {
855
    /* 0 - no write access, we do not want a DPF exception do we ;)
856
     */
857
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
858
  }
859
 
860 1319 phoenix
  /* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
861
   *                and possibly also memory access times.
862 1240 phoenix
   */
863 1319 phoenix
  if (!through_dc)
864
    PRINTF("WARNING: statistics might not be OK\n");
865 1240 phoenix
  dc_simulate_write(memaddr, value, 2);
866
 
867
  if (cur_area && cur_area->log)
868 1324 phoenix
    fprintf (cur_area->log, "[%08lx] -> DIRECT write %08x\n", memaddr, value);
869 1240 phoenix
}
870
 
871 587 markom
/* Set mem, 8-bit. */
872
 
873 1240 phoenix
void set_mem8(unsigned long memaddr, unsigned char value, int* breakpoint)
874 587 markom
{
875
  if (config.sim.mprofile)
876
    mprofile (memaddr, MPROF_8 | MPROF_WRITE);
877
 
878
  cur_vadd = memaddr;
879 631 simons
  memaddr = dmmu_translate(memaddr, 1);;
880 587 markom
  /* If we produced exception don't set anything */
881
  if (pending.valid) return;
882
 
883
  if (config.debug.enabled) {
884
    *breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr);  /* 28/05/01 CZ */
885
    *breakpoint += CheckDebugUnit(DebugStoreData,value);
886
  }
887
 
888 992 simons
  dc_simulate_write(memaddr, (unsigned long)value, 1);
889
 
890 1218 phoenix
  if (cur_area && cur_area->log)
891 1308 phoenix
    fprintf (cur_area->log, "[%08lx] -> write %08x\n", memaddr, value);
892 587 markom
}
893
 
894 1319 phoenix
/*
895
 * STATISTICS NOT OK.
896
 */
897 1240 phoenix
void set_direct8(unsigned long memaddr, unsigned char value, int* breakpoint,
898
                 int through_mmu, int through_dc)
899
{
900
 
901
  cur_vadd = memaddr;
902
 
903
  if (through_mmu) {
904
    /* 0 - no write access, we do not want a DPF exception do we ;)
905
     */
906
    memaddr = peek_into_dtlb(memaddr, 0, through_dc);
907
  }
908
 
909 1319 phoenix
  /* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
910
   *                and possibly also memory access times.
911 1240 phoenix
   */
912 1319 phoenix
  if (!through_dc)
913
    PRINTF("WARNING: statistics might not be OK\n");
914 1240 phoenix
  dc_simulate_write(memaddr, value, 1);
915
 
916
  if (cur_area && cur_area->log)
917 1324 phoenix
    fprintf (cur_area->log, "[%08x] -> DIRECT write %08x\n", memaddr, value);
918 1240 phoenix
}
919
 
920
 
921 361 markom
void dumpmemory(unsigned int from, unsigned int to, int disasm, int nl)
922
{
923
  unsigned int i, j;
924
  struct label_entry *tmp;
925
  int ilen = disasm ? 4 : 16;
926
 
927
  for(i = from; i < to; i += ilen) {
928 997 markom
    PRINTF("%.8x: ", i);
929 361 markom
    for (j = 0; j < ilen;) {
930
      int data = -1;
931
      if (!disasm) {
932
        tmp = NULL;
933
        if (verify_memoryarea(i+j)) {
934
          struct label_entry *entry;
935
          entry = get_label(i + j);
936
          if (entry)
937 997 markom
            PRINTF("(%s)", entry->name);
938
          PRINTF("%02x ", data = evalsim_mem8(i+j));
939
        } else PRINTF("XX ");
940 361 markom
        j++;
941
      } else {
942
        int breakpoint;
943
        unsigned int _insn = read_mem(i, &breakpoint);
944
        int index = insn_decode (_insn);
945
        int len = insn_len (index);
946
 
947
        tmp = NULL;
948
        if (verify_memoryarea(i+j)) {
949
          struct label_entry *entry;
950
          entry = get_label(i + j);
951
          if (entry)
952 997 markom
            PRINTF("(%s)", entry->name);
953 361 markom
 
954 1308 phoenix
          PRINTF(": %08lx ", (unsigned long)_insn);
955 361 markom
          if (index >= 0) {
956
            disassemble_insn (_insn);
957 997 markom
            PRINTF(" %s", disassembled);
958 361 markom
          } else
959 997 markom
            PRINTF("<invalid>");
960
        } else PRINTF("XXXXXXXX");
961 361 markom
        j += len;
962
      }
963
    }
964
    if (nl)
965 997 markom
      PRINTF ("\n");
966 361 markom
  }
967
}
968
 
969 538 markom
unsigned long simmem_read_word(unsigned long addr) {
970
  return simmem32[(cur_area->misc + (addr & cur_area->size_mask)) >> 2];
971 221 markom
}
972
 
973 538 markom
void simmem_write_word(unsigned long addr, unsigned long value) {
974
  simmem32[(cur_area->misc + (addr & cur_area->size_mask)) >> 2] = value;
975 221 markom
}
976
 
977 424 markom
unsigned long simmem_read_zero(unsigned long addr) {
978
  if (config.sim.verbose)
979
    fprintf (stderr, "WARNING: memory read from non-read memory area 0x%08x.\n", addr);
980
  return 0;
981
}
982
 
983
void simmem_write_null(unsigned long addr, unsigned long value) {
984
  if (config.sim.verbose)
985 1308 phoenix
    fprintf (stderr, "WARNING: memory write to 0x%08lx, non-write memory area (value 0x%08lx).\n", addr, value);
986 424 markom
}
987
 
988
/* Initialize memory table from a config struct */
989
 
990
void init_memory_table ()
991 221 markom
{
992 239 markom
  unsigned long memory_needed = 0;
993 426 markom
 
994 424 markom
  /* If nothing was defined, use default memory block */
995
  if (config.memory.nmemories) {
996
    int i;
997
    for (i = 0; i < config.memory.nmemories; i++) {
998
      unsigned long start = config.memory.table[i].baseaddr;
999
      unsigned long length = config.memory.table[i].size;
1000
      char *type = config.memory.table[i].name;
1001
      int rd = config.memory.table[i].delayr;
1002
      int wd = config.memory.table[i].delayw;
1003
      int ce = config.memory.table[i].ce;
1004
      if (config.sim.verbose)
1005
        debug (1, "%08X %08X (%i KB): %s (activated by CE%i; read delay = %icyc, write delay = %icyc)\n",
1006
          start, length, length >> 10, type, ce, rd, wd);
1007 970 simons
      register_memoryarea(start, length, 4, 0, &simmem_read_word, &simmem_write_word);
1008 239 markom
      cur_area->misc = memory_needed;
1009 540 simons
      cur_area->chip_select = ce;
1010 543 simons
      cur_area->valid = 1;
1011 424 markom
      cur_area->delayw = wd;
1012
      cur_area->delayr = rd;
1013 426 markom
      if (config.memory.table[i].log[0] != '\0') {
1014
        if ((cur_area->log = fopen (config.memory.table[i].log, "wt+")) == NULL)
1015
          fprintf (stderr, "WARNING: Cannot open '%s'.\n", config.memory.table[i].log);
1016
      } else
1017 554 markom
        cur_area->log = NULL;
1018 261 markom
      memory_needed += cur_area->size;
1019 239 markom
    }
1020 997 markom
    PRINTF ("\n");
1021 239 markom
  } else {
1022 308 markom
    if (config.sim.verbose)
1023 424 markom
      fprintf (stderr, "WARNING: Memory not defined, assuming standard configuration.\n");
1024 970 simons
    register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 4, 0, &simmem_read_word, &simmem_write_word);
1025 554 markom
    cur_area->misc = memory_needed;
1026
    cur_area->chip_select = 0;
1027
    cur_area->valid = 1;
1028
    cur_area->delayw = 1;
1029
    cur_area->delayr = 1;
1030
    cur_area->log = NULL;
1031 261 markom
    memory_needed += cur_area->size;
1032 239 markom
  }
1033 424 markom
 
1034 538 markom
  simmem32 = (unsigned long *) malloc (sizeof (unsigned long) * ((memory_needed + 3) / 4));
1035
  if (!simmem32) {
1036 239 markom
    fprintf (stderr, "Failed to allocate sim memory. Aborting\n");
1037
    exit (-1);
1038
  }
1039 221 markom
}
1040 424 markom
 
1041
/* Changes read/write memory in read/write only */
1042
 
1043
void lock_memory_table ()
1044
{
1045
  struct dev_memarea *ptmp;
1046
 
1047
  /* Check list of registered devices. */
1048
  for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
1049 538 markom
    if (ptmp->delayr < 0 && ptmp->readfunc == &simmem_read_word)
1050 424 markom
      ptmp->readfunc = &simmem_read_zero;
1051 538 markom
    if (ptmp->delayw < 0 && ptmp->writefunc == &simmem_write_word)
1052 424 markom
      ptmp->writefunc = &simmem_write_null;
1053 543 simons
 
1054
    /* If this mem area is not for memory chip under MC control
1055
       then this area is valid all the time */
1056
    if (ptmp->readfunc != &simmem_read_word) {
1057
      ptmp->valid = 1;
1058
      ptmp->chip_select = -1;
1059
    }
1060 424 markom
  }
1061
}
1062 426 markom
 
1063
/* Closes files, etc. */
1064
 
1065
void done_memory_table ()
1066
{
1067
  struct dev_memarea *ptmp;
1068
 
1069
  /* Check list of registered devices. */
1070
  for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
1071
    if (ptmp->log)
1072
      fclose (ptmp->log);
1073
  }
1074
}
1075 427 markom
 
1076
/* Displays current memory configuration */
1077
 
1078
void memory_table_status ()
1079
{
1080
  struct dev_memarea *ptmp;
1081
 
1082
  /* Check list of registered devices. */
1083
  for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
1084 1308 phoenix
    PRINTF ("addr & %08lx == %08lx to %08lx, size %08lx, gran %liB\n",
1085 427 markom
      ptmp->addr_mask, ptmp->addr_compare, ptmp->addr_compare | bit_mask (ptmp->size),
1086
      ptmp->size, ptmp->granularity);
1087 997 markom
    PRINTF ("\t");
1088 427 markom
    if (ptmp->delayr >= 0)
1089 997 markom
      PRINTF ("read delay = %i cycles, ", ptmp->delayr);
1090 427 markom
    else
1091 997 markom
      PRINTF ("reads not possible, ");
1092 427 markom
 
1093
    if (ptmp->delayw >= 0)
1094 997 markom
      PRINTF ("write delay = %i cycles", ptmp->delayw);
1095 427 markom
    else
1096 997 markom
      PRINTF ("writes not possible");
1097 427 markom
 
1098
    if (ptmp->log)
1099 997 markom
      PRINTF (", (logged)\n");
1100 427 markom
    else
1101 997 markom
      PRINTF ("\n");
1102 427 markom
  }
1103
}
1104 433 markom
 
1105
/* Outputs time in pretty form to dest string */
1106
 
1107 897 markom
char *generate_time_pretty (char *dest, long time_ps)
1108 433 markom
{
1109
  int exp3 = 0;
1110
  if (time_ps) {
1111
    while ((time_ps % 1000) == 0) {
1112
      time_ps /= 1000;
1113
      exp3++;
1114
    }
1115
  }
1116 1308 phoenix
  sprintf (dest, "%li%cs", time_ps, "pnum"[exp3]);
1117 897 markom
  return dest;
1118 433 markom
}

powered by: WebSVN 2.1.0

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