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

Subversion Repositories or1k

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

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

powered by: WebSVN 2.1.0

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