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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc2/] [or1ksim/] [cpu/] [common/] [abstract.c] - Blame information for rev 1743

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

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

powered by: WebSVN 2.1.0

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