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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [cpu/] [or32/] [execute.c] - Blame information for rev 472

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

Line No. Rev Author Line
1 19 jeremybenn
/* execute.c -- OR1K architecture dependent simulation
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
5
   Copyright (C) 2008 Embecosm Limited
6 233 julius
   Copyright (C) 2010 ORSoC AB
7 19 jeremybenn
 
8
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
9 233 julius
   Contributor Julius Baxter <julius.baxter@orsoc.se>
10 19 jeremybenn
 
11
   This file is part of OpenRISC 1000 Architectural Simulator.
12
 
13
   This program is free software; you can redistribute it and/or modify it
14
   under the terms of the GNU General Public License as published by the Free
15
   Software Foundation; either version 3 of the License, or (at your option)
16
   any later version.
17
 
18
   This program is distributed in the hope that it will be useful, but WITHOUT
19
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
21
   more details.
22
 
23
   You should have received a copy of the GNU General Public License along
24
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
25
 
26
/* This program is commented throughout in a fashion suitable for processing
27
   with Doxygen. */
28
 
29
 
30
/* Most of the OR1K simulation is done in here.
31
 
32
   When SIMPLE_EXECUTION is defined below a file insnset.c is included!
33
*/
34
 
35
/* Autoconf and/or portability configuration */
36
#include "config.h"
37
#include "port.h"
38
 
39
/* System includes */
40
#include <stdlib.h>
41
 
42
/* Package includes */
43
#include "execute.h"
44
#include "toplevel-support.h"
45
#include "except.h"
46
#include "labels.h"
47
#include "sched.h"
48
#include "stats.h"
49
#include "opcode/or32.h"
50
#include "dmmu.h"
51
#include "immu.h"
52
#include "sim-cmd.h"
53
#include "vapi.h"
54
#include "debug-unit.h"
55
#include "branch-predict.h"
56
#include "sprs.h"
57
#include "rsp-server.h"
58 233 julius
#include "softfloat.h"
59 19 jeremybenn
 
60
/* Includes and macros for simple execution */
61
#if SIMPLE_EXECUTION
62
 
63
#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn)
64
 
65
#define PARAM0 eval_operand(0, current->insn_index, current->insn)
66
#define PARAM1 eval_operand(1, current->insn_index, current->insn)
67
#define PARAM2 eval_operand(2, current->insn_index, current->insn)
68
 
69
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
70
 
71
#endif  /* SIMPLE_EXECUTION */
72
 
73
 
74
/*! Current cpu state. Globally available. */
75
struct cpu_state  cpu_state;
76
 
77
/*! Temporary program counter. Globally available */
78
oraddr_t  pcnext;
79
 
80
/*! Num cycles waiting for stores to complete. Globally available */
81
int  sbuf_wait_cyc = 0;
82
 
83
/*! Number of total store cycles. Globally available */
84
int  sbuf_total_cyc = 0;
85
 
86
/*! Whether we are doing statistical analysis. Globally available */
87
int  do_stats = 0;
88
 
89
/*! History of execution. Globally available */
90
struct hist_exec *hist_exec_tail = NULL;
91
 
92
/* Benchmark multi issue execution. This file only */
93
static int  multissue[20];
94
static int  issued_per_cycle = 4;
95
 
96
/* Store buffer analysis - stores are accumulated and commited when IO is
97
   idle. This file only */
98
static int  sbuf_head              = 0;
99
static int  sbuf_tail              = 0;
100
static int  sbuf_count             = 0;
101
#if !(DYNAMIC_EXECUTION)
102
static int  sbuf_buf[MAX_SBUF_LEN] = { 0 };
103
#endif
104
 
105
static int sbuf_prev_cycles = 0;
106
 
107
/* Variables used throughout this file to share information */
108
static int  breakpoint;
109
static int  next_delay_insn;
110
 
111
/* Forward declaration of static functions */
112
#if !(DYNAMIC_EXECUTION)
113
static void decode_execute (struct iqueue_entry *current);
114
#endif
115
 
116
/*---------------------------------------------------------------------------*/
117
/*!Get an actual value of a specific register
118
 
119
   Implementation specific. Abort if we are given a duff register. Only used
120 82 jeremybenn
   externally to support simprintf(), which is now obsolete.
121 19 jeremybenn
 
122
   @param[in] regno  The register of interest
123
 
124
   @return  The value of the register                                        */
125
/*---------------------------------------------------------------------------*/
126
uorreg_t
127
evalsim_reg (unsigned int  regno)
128
{
129
  if (regno < MAX_GPRS)
130
    {
131
#if RAW_RANGE_STATS
132
      int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
133
 
134
      if ((unsigned long) delta < (unsigned long) RAW_RANGE)
135
        {
136
          raw_stats.range[delta]++;
137
        }
138
#endif /* RAW_RANGE */
139
 
140
      return cpu_state.reg[regno];
141
    }
142
  else
143
    {
144
      PRINTF ("\nABORT: read out of registers\n");
145
      sim_done ();
146
      return 0;
147
    }
148
}       /* evalsim_reg() */
149
 
150
 
151
/*---------------------------------------------------------------------------*/
152
/*!Set a specific register with value
153
 
154
   Implementation specific. Abort if we are given a duff register.
155
 
156
   @param[in] regno  The register of interest
157
   @param[in] value  The value to be set                                     */
158
/*---------------------------------------------------------------------------*/
159
void
160
setsim_reg (unsigned int  regno,
161
            uorreg_t      value)
162
{
163
  if (regno == 0)                /* gpr0 is always zero */
164
    {
165
      value = 0;
166
    }
167
 
168
  if (regno < MAX_GPRS)
169
    {
170
      cpu_state.reg[regno] = value;
171
    }
172
  else
173
    {
174
      PRINTF ("\nABORT: write out of registers\n");
175
      sim_done ();
176
    }
177
 
178
#if RAW_RANGE_STATS
179
  raw_stats.reg[regno] = runtime.sim.cycles;
180
#endif /* RAW_RANGE */
181
 
182
}       /* setsim_reg() */
183
 
184
 
185
/*---------------------------------------------------------------------------*/
186
/*!Evaluates source operand operand
187
 
188
   Implementation specific. Declared global, although this is only actually
189
   required for DYNAMIC_EXECUTION,
190
 
191
   @param[in] insn  The instruction
192
   @param[in] opd   The operand
193
 
194
   @return  The value of the source operand                                  */
195
/*---------------------------------------------------------------------------*/
196
uorreg_t
197
eval_operand_val (uint32_t               insn,
198
                  struct insn_op_struct *opd)
199
{
200
  unsigned long  operand = 0;
201
  unsigned long  sbit;
202
  unsigned int   nbits = 0;
203
 
204
  while (1)
205
    {
206
      operand |=
207
        ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) <<
208
        nbits;
209
      nbits += opd->data;
210
 
211
      if (opd->type & OPTYPE_OP)
212
        {
213
          break;
214
        }
215
 
216
      opd++;
217
    }
218
 
219
  if (opd->type & OPTYPE_SIG)
220
    {
221
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
222
 
223
      if (operand & (1 << sbit))
224
        {
225
          operand |= ~REG_C (0) << sbit;
226
        }
227
    }
228
 
229
  return operand;
230
 
231
}       /* eval_operand_val() */
232
 
233
 
234
/*---------------------------------------------------------------------------*/
235
/*!Does source operand depend on computation of dest operand?
236
 
237
      Cycle t                 Cycle t+1
238
  dst: irrelevant         src: immediate                  always 0
239
  dst: reg1 direct        src: reg2 direct                0 if reg1 != reg2
240
  dst: reg1 disp          src: reg2 direct                always 0
241
  dst: reg1 direct        src: reg2 disp                  0 if reg1 != reg2
242
  dst: reg1 disp          src: reg2 disp                  always 1 (store must
243
                                                          finish before load)
244
  dst: flag               src: flag                       always 1
245
 
246
  @param[in] prev  Previous instruction
247
  @param[in] next  Next instruction
248
 
249
  @return  Non-zero if yes.                                                  */
250
/*---------------------------------------------------------------------------*/
251
static int
252
check_depend (struct iqueue_entry *prev,
253
              struct iqueue_entry *next)
254
{
255
  /* Find destination type. */
256
  unsigned long          type = 0;
257
  int                    prev_dis;
258
  int                    next_dis;
259
  orreg_t                prev_reg_val = 0;
260
  struct insn_op_struct *opd;
261
 
262 230 jeremybenn
  if (or1ksim_or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
263
      && or1ksim_or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
264 19 jeremybenn
    {
265
      return  1;
266
    }
267
 
268 230 jeremybenn
  opd      = or1ksim_op_start[prev->insn_index];
269 19 jeremybenn
  prev_dis = 0;
270
 
271
  while (1)
272
    {
273
      if (opd->type & OPTYPE_DIS)
274
        {
275
          prev_dis = 1;
276
        }
277
 
278
      if (opd->type & OPTYPE_DST)
279
        {
280
          type = opd->type;
281
 
282
          if (prev_dis)
283
            {
284
              type |= OPTYPE_DIS;
285
            }
286
 
287
          /* Destination is always a register */
288
          prev_reg_val = eval_operand_val (prev->insn, opd);
289
          break;
290
        }
291
 
292
      if (opd->type & OPTYPE_LAST)
293
        {
294
          return 0;              /* Doesn't have a destination operand */
295
        }
296
 
297
      if (opd->type & OPTYPE_OP)
298
        {
299
          prev_dis = 0;
300
        }
301
 
302
      opd++;
303
    }
304
 
305
  /* We search all source operands - if we find confict => return 1 */
306 230 jeremybenn
  opd      = or1ksim_op_start[next->insn_index];
307 19 jeremybenn
  next_dis = 0;
308
 
309
  while (1)
310
    {
311
      if (opd->type & OPTYPE_DIS)
312
        {
313
          next_dis = 1;
314
        }
315
 
316
      /* This instruction sequence also depends on order of execution:
317
           l.lw r1, k(r1)
318
           l.sw k(r1), r4
319
         Here r1 is a destination in l.sw */
320
 
321
      /* FIXME: This situation is not handeld here when r1 == r2:
322
           l.sw k(r1), r4
323
           l.lw r3, k(r2) */
324
      if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST)))
325
        {
326
          if (opd->type & OPTYPE_REG)
327
            {
328
              if (eval_operand_val (next->insn, opd) == prev_reg_val)
329
                {
330
                  return 1;
331
                }
332
            }
333
        }
334
 
335
      if (opd->type & OPTYPE_LAST)
336
        {
337
          break;
338
        }
339
 
340
      opd++;
341
    }
342
 
343
  return  0;
344
 
345
}       /* check_depend() */
346
 
347
 
348
/*---------------------------------------------------------------------------*/
349
/*!Should instruction NOT be executed?
350
 
351
   Modified by CZ 26/05/01 for new mode execution.
352
 
353
   @return  Nonzero if instruction should NOT be executed                    */
354
/*---------------------------------------------------------------------------*/
355
static int
356
fetch ()
357
{
358
  static int break_just_hit = 0;
359
 
360
  if (NULL != breakpoints)
361
    {
362
      /* MM: Check for breakpoint.  This has to be done in fetch cycle,
363
         because of peripheria.
364
         MM1709: if we cannot access the memory entry, we could not set the
365
         breakpoint earlier, so just check the breakpoint list.  */
366
      if (has_breakpoint (peek_into_itlb (cpu_state.pc)) && !break_just_hit)
367
        {
368
          break_just_hit = 1;
369
          return 1;             /* Breakpoint set. */
370
        }
371
      break_just_hit = 0;
372
    }
373
 
374
  breakpoint                 = 0;
375
  cpu_state.iqueue.insn_addr = cpu_state.pc;
376
  cpu_state.iqueue.insn      = eval_insn (cpu_state.pc, &breakpoint);
377
 
378
  /* Fetch instruction. */
379
  if (!except_pending)
380
    {
381
      runtime.cpu.instructions++;
382
    }
383
 
384
  /* update_pc will be called after execution */
385
  return 0;
386
 
387
}       /* fetch() */
388
 
389
 
390
/*---------------------------------------------------------------------------*/
391
/*!This code actually updates the PC value                                   */
392
/*---------------------------------------------------------------------------*/
393
static void
394
update_pc ()
395
{
396
  cpu_state.delay_insn    = next_delay_insn;
397
  cpu_state.sprs[SPR_PPC] = cpu_state.pc;       /* Store value for later */
398
  cpu_state.pc            = pcnext;
399
  pcnext                  = cpu_state.delay_insn ? cpu_state.pc_delay :
400
                                                   pcnext + 4;
401
}       /* update_pc() */
402
 
403
 
404
/*---------------------------------------------------------------------------*/
405
/*!Perform analysis of the instruction being executed
406
 
407
   This could be static for SIMPLE_EXECUTION, but made global for general use.
408
 
409
   @param[in] current  The instruction being executed                        */
410
/*---------------------------------------------------------------------------*/
411
void
412
analysis (struct iqueue_entry *current)
413
{
414
  if (config.cpu.dependstats)
415
    {
416
      /* Dynamic, dependency stats. */
417
      adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1,
418
                 check_depend (&cpu_state.icomplet, current));
419
 
420
      /* Dynamic, functional units stats. */
421 230 jeremybenn
      addfstats (or1ksim_or32_opcodes[cpu_state.icomplet.insn_index].func_unit,
422
                 or1ksim_or32_opcodes[current->insn_index].func_unit, 1,
423 19 jeremybenn
                 check_depend (&cpu_state.icomplet, current));
424
 
425
      /* Dynamic, single stats. */
426
      addsstats (current->insn_index, 1);
427
    }
428
 
429
  if (config.cpu.superscalar)
430
    {
431 230 jeremybenn
      if ((or1ksim_or32_opcodes[current->insn_index].func_unit == it_branch) ||
432
          (or1ksim_or32_opcodes[current->insn_index].func_unit == it_jump))
433 19 jeremybenn
        runtime.sim.storecycles += 0;
434
 
435 230 jeremybenn
      if (or1ksim_or32_opcodes[current->insn_index].func_unit == it_store)
436 19 jeremybenn
        runtime.sim.storecycles += 1;
437
 
438 230 jeremybenn
      if (or1ksim_or32_opcodes[current->insn_index].func_unit == it_load)
439 19 jeremybenn
        runtime.sim.loadcycles += 1;
440
 
441
      /* Pseudo multiple issue benchmark */
442 230 jeremybenn
      if ((multissue[or1ksim_or32_opcodes[current->insn_index].func_unit] < 1) ||
443 19 jeremybenn
          (check_depend (&cpu_state.icomplet, current))
444
          || (issued_per_cycle < 1))
445
        {
446
          int i;
447
          for (i = 0; i < 20; i++)
448
            multissue[i] = 2;
449
          issued_per_cycle = 2;
450
          runtime.cpu.supercycles++;
451
          if (check_depend (&cpu_state.icomplet, current))
452
            runtime.cpu.hazardwait++;
453
          multissue[it_unknown] = 2;
454
          multissue[it_shift] = 2;
455
          multissue[it_compare] = 1;
456
          multissue[it_branch] = 1;
457
          multissue[it_jump] = 1;
458
          multissue[it_extend] = 2;
459
          multissue[it_nop] = 2;
460
          multissue[it_move] = 2;
461
          multissue[it_movimm] = 2;
462
          multissue[it_arith] = 2;
463
          multissue[it_store] = 2;
464
          multissue[it_load] = 2;
465
        }
466 230 jeremybenn
      multissue[or1ksim_or32_opcodes[current->insn_index].func_unit]--;
467 19 jeremybenn
      issued_per_cycle--;
468
    }
469
 
470
  if (config.cpu.dependstats)
471
    /* Instruction waits in completition buffer until retired. */
472
    memcpy (&cpu_state.icomplet, current, sizeof (struct iqueue_entry));
473
 
474
  if (config.sim.history)
475
    {
476
      /* History of execution */
477
      hist_exec_tail = hist_exec_tail->next;
478
      hist_exec_tail->addr = cpu_state.icomplet.insn_addr;
479
    }
480
 
481
  if (config.sim.exe_log)
482
    dump_exe_log ();
483
 
484 202 julius
  if (config.sim.exe_bin_insn_log)
485
    dump_exe_bin_insn_log (current);
486
 
487 19 jeremybenn
}       /* analysis() */
488
 
489
 
490
#if !(DYNAMIC_EXECUTION)
491
 
492
/*---------------------------------------------------------------------------*/
493
/*!Store buffer analysis for store instructions
494
 
495
   Stores are accumulated and commited when IO is idle
496
 
497
   @param[in] cyc  Number of cycles being analysed                           */
498
/*---------------------------------------------------------------------------*/
499
static void
500
sbuf_store (int cyc)
501
{
502
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
503
 
504
  sbuf_total_cyc   += cyc;
505
  sbuf_prev_cycles  = runtime.sim.cycles;
506
 
507
  /* Take stores from buffer, that occured meanwhile */
508
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
509
    {
510
      delta     -= sbuf_buf[sbuf_tail];
511
      sbuf_tail  = (sbuf_tail + 1) % MAX_SBUF_LEN;
512
      sbuf_count--;
513
    }
514
 
515
  if (sbuf_count)
516
    {
517
      sbuf_buf[sbuf_tail] -= delta;
518
    }
519
 
520
  /* Store buffer is full, take one out */
521
  if (sbuf_count >= config.cpu.sbuf_len)
522
    {
523
      sbuf_wait_cyc          += sbuf_buf[sbuf_tail];
524
      runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
525
      sbuf_prev_cycles       += sbuf_buf[sbuf_tail];
526
      sbuf_tail               = (sbuf_tail + 1) % MAX_SBUF_LEN;
527
      sbuf_count--;
528
    }
529
 
530
  /* Put newest store in the buffer */
531
  sbuf_buf[sbuf_head] = cyc;
532
  sbuf_head           = (sbuf_head + 1) % MAX_SBUF_LEN;
533
  sbuf_count++;
534
 
535
}       /* sbuf_store() */
536
 
537
 
538
/*---------------------------------------------------------------------------*/
539
/*!Store buffer analysis for load instructions
540
 
541
   Previous stores should commit, before any load                            */
542
/*---------------------------------------------------------------------------*/
543
static void
544
sbuf_load ()
545
{
546
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
547
  sbuf_prev_cycles = runtime.sim.cycles;
548
 
549
  /* Take stores from buffer, that occured meanwhile */
550
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
551
    {
552
      delta     -= sbuf_buf[sbuf_tail];
553
      sbuf_tail  = (sbuf_tail + 1) % MAX_SBUF_LEN;
554
      sbuf_count--;
555
    }
556
 
557
  if (sbuf_count)
558
    {
559
      sbuf_buf[sbuf_tail] -= delta;
560
    }
561
 
562
  /* Wait for all stores to complete */
563
  while (sbuf_count > 0)
564
    {
565
      sbuf_wait_cyc          += sbuf_buf[sbuf_tail];
566
      runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
567
      sbuf_prev_cycles       += sbuf_buf[sbuf_tail];
568
      sbuf_tail               = (sbuf_tail + 1) % MAX_SBUF_LEN;
569
      sbuf_count--;
570
    }
571
}       /* sbuf_load() */
572
 
573
#endif  /* !DYNAMIC_EXECUTION */
574
 
575
 
576
/*---------------------------------------------------------------------------*/
577
/*!Outputs dissasembled instruction                                          */
578
/*---------------------------------------------------------------------------*/
579
void
580
dump_exe_log ()
581
{
582
  oraddr_t      insn_addr = cpu_state.iqueue.insn_addr;
583
  unsigned int  i;
584
  unsigned int  j;
585
  uorreg_t      operand;
586
 
587
  if (insn_addr == 0xffffffff)
588
    {
589
      return;
590
    }
591
 
592
  if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
593
      ((config.sim.exe_log_end <= 0) ||
594
       (runtime.cpu.instructions <= config.sim.exe_log_end)))
595
    {
596
      struct label_entry *entry;
597
 
598
      if (config.sim.exe_log_marker &&
599
          !(runtime.cpu.instructions % config.sim.exe_log_marker))
600
        {
601
          fprintf (runtime.sim.fexe_log,
602
                   "--------------------- %8lli instruction "
603
                   "---------------------\n",
604
                   runtime.cpu.instructions);
605
        }
606
 
607
      switch (config.sim.exe_log_type)
608
        {
609
        case EXE_LOG_HARDWARE:
610
          fprintf (runtime.sim.fexe_log,
611
                   "\nEXECUTED(%11llu): %" PRIxADDR ":  ",
612
                   runtime.cpu.instructions, insn_addr);
613
          fprintf (runtime.sim.fexe_log, "%.2x%.2x",
614
                   eval_direct8 (insn_addr, 0, 0),
615
                   eval_direct8 (insn_addr + 1, 0, 0));
616
          fprintf (runtime.sim.fexe_log, "%.2x%.2x",
617
                   eval_direct8 (insn_addr + 2, 0, 0),
618
                   eval_direct8 (insn_addr + 3, 0, 0));
619
 
620
          for (i = 0; i < MAX_GPRS; i++)
621
            {
622
              if (i % 4 == 0)
623
                {
624
                  fprintf (runtime.sim.fexe_log, "\n");
625
                }
626
 
627
              fprintf (runtime.sim.fexe_log, "GPR%2u: %" PRIxREG "  ", i,
628
                       cpu_state.reg[i]);
629
            }
630
 
631
          fprintf (runtime.sim.fexe_log, "\n");
632
          fprintf (runtime.sim.fexe_log, "SR   : %.8" PRIx32 "  ",
633
                   cpu_state.sprs[SPR_SR]);
634
          fprintf (runtime.sim.fexe_log, "EPCR0: %" PRIxADDR "  ",
635
                   cpu_state.sprs[SPR_EPCR_BASE]);
636
          fprintf (runtime.sim.fexe_log, "EEAR0: %" PRIxADDR "  ",
637
                   cpu_state.sprs[SPR_EEAR_BASE]);
638
          fprintf (runtime.sim.fexe_log, "ESR0 : %.8" PRIx32 "\n",
639
                   cpu_state.sprs[SPR_ESR_BASE]);
640
          break;
641
 
642
        case EXE_LOG_SIMPLE:
643
        case EXE_LOG_SOFTWARE:
644 230 jeremybenn
          or1ksim_disassemble_index (cpu_state.iqueue.insn,
645 19 jeremybenn
                             cpu_state.iqueue.insn_index);
646
 
647
          entry = get_label (insn_addr);
648
          if (entry)
649
            {
650
              fprintf (runtime.sim.fexe_log, "%s:\n", entry->name);
651
            }
652
 
653
          if (config.sim.exe_log_type == EXE_LOG_SOFTWARE)
654
            {
655
              struct insn_op_struct *opd =
656 230 jeremybenn
                or1ksim_op_start[cpu_state.iqueue.insn_index];
657 19 jeremybenn
 
658
              j = 0;
659
              while (1)
660
                {
661
                  operand = eval_operand_val (cpu_state.iqueue.insn, opd);
662
                  while (!(opd->type & OPTYPE_OP))
663
                    {
664
                      opd++;
665
                    }
666
                  if (opd->type & OPTYPE_DIS)
667
                    {
668
                      fprintf (runtime.sim.fexe_log,
669
                               "EA =%" PRIxADDR " PA =%" PRIxADDR " ",
670
                               cpu_state.insn_ea,
671
                               peek_into_dtlb (cpu_state.insn_ea, 0, 0));
672
                      opd++;    /* Skip of register operand */
673
                      j++;
674
                    }
675
                  else if ((opd->type & OPTYPE_REG) && operand)
676
                    {
677
                      fprintf (runtime.sim.fexe_log, "r%-2i=%" PRIxREG " ",
678
                               (int) operand, evalsim_reg (operand));
679
                    }
680
                  else
681
                    {
682
                      fprintf (runtime.sim.fexe_log, "             ");
683
                    }
684
                  j++;
685
                  if (opd->type & OPTYPE_LAST)
686
                    {
687
                      break;
688
                    }
689
                  opd++;
690
                }
691 230 jeremybenn
              if (or1ksim_or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG)
692 19 jeremybenn
                {
693
                  fprintf (runtime.sim.fexe_log, "SR =%" PRIxREG " ",
694
                           cpu_state.sprs[SPR_SR]);
695
                  j++;
696
                }
697
              while (j < 3)
698
                {
699
                  fprintf (runtime.sim.fexe_log, "             ");
700
                  j++;
701
                }
702
            }
703
          fprintf (runtime.sim.fexe_log, "%" PRIxADDR " ", insn_addr);
704 230 jeremybenn
          fprintf (runtime.sim.fexe_log, "%s\n", or1ksim_disassembled);
705 19 jeremybenn
        }
706
    }
707
}       /* dump_exe_log() */
708
 
709
 
710 202 julius
 
711 19 jeremybenn
/*---------------------------------------------------------------------------*/
712 202 julius
/*!Outputs binary copy of instruction to a file                              */
713
/*---------------------------------------------------------------------------*/
714
void
715
dump_exe_bin_insn_log (struct iqueue_entry *current)
716
{
717
  // Do endian swap before spitting out (will be kept in LE on a LE machine)
718
  // but more useful to see it in big endian format.
719
  // Should probably host htonl().
720
  uint32_t insn = (((current->insn & 0xff)<<24) |
721
                   ((current->insn & 0xff00)<<8) |
722
                   ((current->insn & 0xff0000)>>8) |
723
                   ((current->insn & 0xff000000)>>24));
724
 
725
  //for(i=0;i<4;i++) tmp_insn[i] = eval_direct8 (insn_addr+i, 0, 0);
726
 
727
  // Dump it into binary log file
728
  fwrite((void*)&insn, 4, 1, runtime.sim.fexe_bin_insn_log);
729
 
730
 
731
}       /* dump_exe_bin_insn_log() */
732
 
733
 
734
/*---------------------------------------------------------------------------*/
735 19 jeremybenn
/*!Dump registers
736
 
737
   Supports the CLI 'r' and 't' commands                                     */
738
/*---------------------------------------------------------------------------*/
739
void
740
dumpreg ()
741
{
742
  int       i;
743
  oraddr_t  physical_pc;
744
 
745
  if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr)))
746
    {
747
      disassemble_memory (physical_pc, physical_pc + 4, 0);
748
    }
749
  else
750
    {
751
      PRINTF ("INTERNAL SIMULATOR ERROR:\n");
752
      PRINTF ("no translation for currently executed instruction\n");
753
    }
754
 
755
  // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
756
  PRINTF (" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles,
757
          runtime.cpu.instructions);
758
  if (config.cpu.superscalar)
759
    {
760
      PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
761
    }
762
  if (config.cpu.hazards)
763
    {
764
      PRINTF ("  HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
765
    }
766
  else if (config.cpu.superscalar)
767
    {
768
      PRINTF ("\n");
769
    }
770
 
771
  if ((physical_pc = peek_into_itlb (cpu_state.pc)))
772
    {
773
      disassemble_memory (physical_pc, physical_pc + 4, 0);
774
    }
775
  else
776
    {
777
      PRINTF ("%" PRIxADDR ": : xxxxxxxx  ITLB miss follows", cpu_state.pc);
778
    }
779
 
780
  PRINTF (" (next insn) %s", (cpu_state.delay_insn ? "(delay insn)" : ""));
781
 
782
  for (i = 0; i < MAX_GPRS; i++)
783
    {
784
      if (i % 4 == 0)
785
        {
786
          PRINTF ("\n");
787
        }
788
 
789
      PRINTF ("GPR%.2u: %" PRIxREG "  ", i, evalsim_reg (i));
790
    }
791
 
792
  PRINTF ("flag: %u\n", cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0);
793
 
794
}       /* dumpreg() */
795
 
796
 
797
/*---------------------------------------------------------------------------*/
798 420 jeremybenn
/*!Trace an instruction
799
 
800
   Supports GDB tracing                                                      */
801
/*---------------------------------------------------------------------------*/
802
void
803
trace_instr ()
804
{
805
  oraddr_t  physical_pc;
806
 
807
  if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr)))
808
    {
809 472 jeremybenn
      disassemble_instr (physical_pc, cpu_state.iqueue.insn_addr,
810
                         cpu_state.iqueue.insn);
811 420 jeremybenn
    }
812
  else
813
    {
814 472 jeremybenn
      PRINTF ("Instruction address translation failed: no trace available\n");
815 420 jeremybenn
    }
816
}       /* trace_instr () */
817
 
818
 
819
/*---------------------------------------------------------------------------*/
820 19 jeremybenn
/*!Wrapper around real decode_execute function
821
 
822
   Some statistics here only
823
 
824
   @param[in] current  Instruction being executed                            */
825
/*---------------------------------------------------------------------------*/
826
static void
827
decode_execute_wrapper (struct iqueue_entry *current)
828
{
829
  breakpoint = 0;
830
 
831
#ifndef HAVE_EXECUTION
832
#error HAVE_EXECUTION has to be defined in order to execute programs.
833
#endif
834
 
835
  /* FIXME: Most of this file is not needed with DYNAMIC_EXECUTION */
836
#if !(DYNAMIC_EXECUTION)
837
  decode_execute (current);
838
#endif
839
 
840
  if (breakpoint)
841
    {
842
      except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
843
    }
844
}       /* decode_execute_wrapper() */
845
 
846
/*---------------------------------------------------------------------------*/
847
/*!Reset the CPU                                                             */
848
/*---------------------------------------------------------------------------*/
849
void
850
cpu_reset ()
851
{
852
  int               i;
853
  struct hist_exec *hist_exec_head = NULL;
854
  struct hist_exec *hist_exec_new;
855
 
856
  runtime.sim.cycles       = 0;
857
  runtime.sim.loadcycles   = 0;
858
  runtime.sim.storecycles  = 0;
859
  runtime.cpu.instructions = 0;
860
  runtime.cpu.supercycles  = 0;
861
  runtime.cpu.hazardwait   = 0;
862
 
863
  for (i = 0; i < MAX_GPRS; i++)
864
    {
865
      setsim_reg (i, 0);
866
    }
867
 
868
  memset (&cpu_state.iqueue,   0, sizeof (cpu_state.iqueue));
869
  memset (&cpu_state.icomplet, 0, sizeof (cpu_state.icomplet));
870
 
871
  sbuf_head        = 0;
872
  sbuf_tail        = 0;
873
  sbuf_count       = 0;
874
  sbuf_prev_cycles = 0;
875
 
876
  /* Initialise execution history circular buffer */
877
  for (i = 0; i < HISTEXEC_LEN; i++)
878
    {
879
      hist_exec_new = malloc (sizeof (struct hist_exec));
880
 
881
      if (!hist_exec_new)
882
        {
883
          fprintf (stderr, "Out-of-memory\n");
884
          exit (1);
885
        }
886
 
887
      if (!hist_exec_head)
888
        {
889
          hist_exec_head = hist_exec_new;
890
        }
891
      else
892
        {
893
          hist_exec_tail->next = hist_exec_new;
894
        }
895
 
896
      hist_exec_new->prev = hist_exec_tail;
897
      hist_exec_tail = hist_exec_new;
898
    }
899
 
900
  /* Make hist_exec_tail->next point to hist_exec_head */
901
  hist_exec_tail->next = hist_exec_head;
902
  hist_exec_head->prev = hist_exec_tail;
903
 
904
  /* MM1409: All progs should start at reset vector entry! This sorted out by
905
     setting the cpu_state.pc field below. Not clear this is very good code! */
906
 
907
  /* Patches suggested by Shinji Wakatsuki, so that the vector address takes
908
     notice of the Exception Prefix High bit of the Supervision register */
909
  pcnext = (cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? 0xf0000000 : 0x00000000);
910
 
911
  if (config.sim.verbose)
912
    {
913
      PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext);
914
    }
915
 
916
  cpu_state.pc  = pcnext;
917
  pcnext       += 4;
918
 
919
  /* MM1409: All programs should set their stack pointer!  */
920
#if !(DYNAMIC_EXECUTION)
921
  except_handle (EXCEPT_RESET, 0);
922
  update_pc ();
923
#endif
924
 
925
  except_pending = 0;
926
  cpu_state.pc   = cpu_state.sprs[SPR_SR] & SPR_SR_EPH ?
927
    0xf0000000 + EXCEPT_RESET : EXCEPT_RESET;
928
 
929
}       /* cpu_reset() */
930
 
931
 
932
/*---------------------------------------------------------------------------*/
933
/*!Simulates one CPU clock cycle
934
 
935
  @return  non-zero if a breakpoint is hit, zero otherwise.                  */
936
/*---------------------------------------------------------------------------*/
937
int
938
cpu_clock ()
939
{
940
  except_pending  = 0;
941
  next_delay_insn = 0;
942
 
943
  if (fetch ())
944
    {
945
      PRINTF ("Breakpoint hit.\n");
946
      return  1;
947
    }
948
 
949
  if (except_pending)
950
    {
951
      update_pc ();
952
      except_pending = 0;
953
      return  0;
954
    }
955
 
956
  if (breakpoint)
957
    {
958
      except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
959
      update_pc ();
960
      except_pending = 0;
961
      return  0;
962
    }
963
 
964
  decode_execute_wrapper (&cpu_state.iqueue);
965
  update_pc ();
966
  return  0;
967
 
968
}       /* cpu_clock() */
969
 
970
 
971
/*---------------------------------------------------------------------------*/
972
/*!If decoding cannot be found, call this function                           */
973
/*---------------------------------------------------------------------------*/
974
#if SIMPLE_EXECUTION
975
void
976
l_invalid (struct iqueue_entry *current)
977
{
978
#else
979
void
980
l_invalid ()
981
{
982
#endif
983
  except_handle (EXCEPT_ILLEGAL, cpu_state.iqueue.insn_addr);
984
 
985
}       /* l_invalid() */
986
 
987
 
988
/*---------------------------------------------------------------------------*/
989
/*!The main execution loop                                                   */
990
/*---------------------------------------------------------------------------*/
991
void
992
exec_main ()
993
{
994
  long long time_start;
995
 
996
  while (1)
997
    {
998
      time_start = runtime.sim.cycles;
999
      if (config.debug.enabled)
1000
        {
1001
          while (runtime.cpu.stalled)
1002
            {
1003
              if (config.debug.rsp_enabled)
1004
                {
1005
                  handle_rsp ();
1006
                }
1007
              else
1008
                {
1009
                  fprintf (stderr, "ERROR: CPU stalled and GDB connection not "
1010
                           "enabled: Invoking CLI and terminating.\n");
1011
                  /* Dump the user into interactive mode.  From there he or
1012
                     she can decide what to do. */
1013
                  handle_sim_command ();
1014
                  sim_done ();
1015
                }
1016
              if (runtime.sim.iprompt)
1017
                handle_sim_command ();
1018
            }
1019
        }
1020
 
1021
      /* Each cycle has counter of mem_cycles; this value is joined with cycles
1022
         at the end of the cycle; no sim originated memory accesses should be
1023
         performed inbetween. */
1024
      runtime.sim.mem_cycles = 0;
1025
 
1026
      if (!config.pm.enabled ||
1027
          !(config.pm.enabled &
1028
            (cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME))))
1029
        {
1030
          if (cpu_clock ())
1031
            {
1032
              /* A breakpoint has been hit, drop to interactive mode */
1033
              handle_sim_command ();
1034
            }
1035
        }
1036
 
1037 385 jeremybenn
      /* If we are tracing, dump after each instruction. */
1038
      if (!runtime.sim.hush)
1039
        {
1040 420 jeremybenn
          trace_instr ();
1041 385 jeremybenn
        }
1042
 
1043 19 jeremybenn
      if (config.vapi.enabled && runtime.vapi.enabled)
1044
        {
1045
          vapi_check ();
1046
        }
1047
 
1048
      if (config.debug.enabled)
1049
        {
1050
          if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST)
1051
            {
1052
              set_stall_state (1);
1053
 
1054
              if (config.debug.rsp_enabled)
1055
                {
1056
                  rsp_exception (EXCEPT_TRAP);
1057
                }
1058
            }
1059
        }
1060
 
1061
      runtime.sim.cycles        += runtime.sim.mem_cycles;
1062
      scheduler.job_queue->time -= runtime.sim.cycles - time_start;
1063
 
1064
      if (scheduler.job_queue->time <= 0)
1065
        {
1066
          do_scheduler ();
1067
        }
1068
    }
1069
}       /* exec_main() */
1070
 
1071 226 julius
/*---------------------------------------------------------------------------*/
1072 233 julius
/*!Update the rounding mode variable the softfloat library reads             */
1073 226 julius
/*---------------------------------------------------------------------------*/
1074 230 jeremybenn
static void
1075 233 julius
float_set_rm ()
1076
{
1077
  //
1078
  // float_rounding_mode is used by the softfloat library, it is declared in
1079
  // "softfloat.h"
1080
  //
1081
  switch(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_RM)
1082
    {
1083
    case FPCSR_RM_RN:
1084
      //printf("or1ksim <%s>: rounding mode RN\n",__FUNCTION__);
1085
      float_rounding_mode = float_round_nearest_even;
1086
      break;
1087
    case FPCSR_RM_RZ:
1088
      //printf("or1ksim <%s>: rounding mode RZ\n",__FUNCTION__);
1089
      float_rounding_mode = float_round_to_zero;
1090
      break;
1091
    case FPCSR_RM_RIP:
1092
      //printf("or1ksim <%s>: rounding mode R+\n",__FUNCTION__);
1093
      float_rounding_mode = float_round_up;
1094
      break;
1095
    case FPCSR_RM_RIN:
1096
      //printf("or1ksim <%s>: rounding mode R-\n",__FUNCTION__);
1097
      float_rounding_mode = float_round_down;
1098
      break;
1099
    }
1100
}
1101 226 julius
 
1102
/*---------------------------------------------------------------------------*/
1103 233 julius
/*!Update the OR1K's FPCSR after each floating point instruction             */
1104 226 julius
/*---------------------------------------------------------------------------*/
1105 230 jeremybenn
static void
1106 233 julius
float_set_flags ()
1107
{
1108
  // Get the flags from softfloat's variable and set the OR1K's FPCR values
1109
  // First clear all flags in OR1K FPCSR
1110
  cpu_state.sprs[SPR_FPCSR] &= ~SPR_FPCSR_ALLF;
1111
 
1112
  if (float_exception_flags & float_flag_invalid)
1113
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IVF;
1114
  if (float_exception_flags & float_flag_divbyzero)
1115
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_DZF;
1116
  if (float_exception_flags & float_flag_overflow)
1117
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_OVF;
1118
  if (float_exception_flags & float_flag_underflow)
1119
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_UNF;
1120
  if (float_exception_flags & float_flag_inexact)
1121
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IXF;
1122
  /*
1123
  printf("or1ksim: post-fp-op flags from softfloat: %x%x%x%x%x\n",
1124
         !!(float_exception_flags & float_flag_invalid),
1125
         !!(float_exception_flags & float_flag_divbyzero),
1126
         !!(float_exception_flags & float_flag_overflow),
1127
         !!(float_exception_flags & float_flag_underflow),
1128
         !!(float_exception_flags & float_flag_inexact));
1129
  */
1130
  // TODO: Call FP exception is FPEE set and any of the flags were set
1131
  /*
1132 226 julius
     if ((cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_FPEE) &
1133
     (|(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_ALLF)))
1134
     except_handle (EXCEPT_FPE, cpu_state.iqueue.insn_addr);
1135 233 julius
  */
1136
  // Now clear softfloat's flags:
1137
  float_exception_flags = 0;
1138
 
1139
}
1140 226 julius
 
1141 19 jeremybenn
#if COMPLEX_EXECUTION
1142
 
1143
/* Include generated/built in decode_execute function */
1144
#include "execgen.c"
1145
 
1146
#elif SIMPLE_EXECUTION
1147
 
1148
 
1149
/*---------------------------------------------------------------------------*/
1150
/*!Evaluates source operand
1151
 
1152
   Implementation specific.
1153
 
1154
   @param[in] op_no       The operand
1155
   @param[in] insn_index  Address of the instruction
1156
   @param[in] insn        The instruction
1157
 
1158
   @return  The value of the operand                                         */
1159
/*---------------------------------------------------------------------------*/
1160
static uorreg_t
1161
eval_operand (int            op_no,
1162
              unsigned long  insn_index,
1163
              uint32_t       insn)
1164
{
1165 230 jeremybenn
  struct insn_op_struct *opd = or1ksim_op_start[insn_index];
1166 19 jeremybenn
  uorreg_t               ret;
1167
 
1168
  while (op_no)
1169
    {
1170
      if (opd->type & OPTYPE_LAST)
1171
        {
1172
          fprintf (stderr,
1173
                   "Instruction requested more operands than it has\n");
1174
          exit (1);
1175
        }
1176
 
1177
      if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
1178
        {
1179
          op_no--;
1180
        }
1181
 
1182
      opd++;
1183
    }
1184
 
1185
  if (opd->type & OPTYPE_DIS)
1186
    {
1187
      ret = eval_operand_val (insn, opd);
1188
 
1189
      while (!(opd->type & OPTYPE_OP))
1190
        {
1191
          opd++;
1192
        }
1193
 
1194
      opd++;
1195
      ret               += evalsim_reg (eval_operand_val (insn, opd));
1196
      cpu_state.insn_ea  = ret;
1197
 
1198
      return  ret;
1199
    }
1200
 
1201
  if (opd->type & OPTYPE_REG)
1202
    {
1203
      return  evalsim_reg (eval_operand_val (insn, opd));
1204
    }
1205
 
1206
  return  eval_operand_val (insn, opd);
1207
 
1208
}       /* eval_operand() */
1209
 
1210
 
1211
/*---------------------------------------------------------------------------*/
1212
/*!Set destination operand (register direct) with value.
1213
 
1214
   Implementation specific.
1215
 
1216
   @param[in] op_no       The operand
1217
   @param[in] value       The value to set
1218
   @param[in] insn_index  Address of the instruction
1219
   @param[in] insn        The instruction                                    */
1220
/*---------------------------------------------------------------------------*/
1221
static void
1222
set_operand (int            op_no,
1223
             orreg_t        value,
1224
             unsigned long  insn_index,
1225
             uint32_t       insn)
1226
{
1227 230 jeremybenn
  struct insn_op_struct *opd = or1ksim_op_start[insn_index];
1228 19 jeremybenn
 
1229
  while (op_no)
1230
    {
1231
      if (opd->type & OPTYPE_LAST)
1232
        {
1233
          fprintf (stderr,
1234
                   "Instruction requested more operands than it has\n");
1235
          exit (1);
1236
        }
1237
 
1238
      if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
1239
        {
1240
          op_no--;
1241
        }
1242
 
1243
      opd++;
1244
    }
1245
 
1246
  if (!(opd->type & OPTYPE_REG))
1247
    {
1248
      fprintf (stderr, "Trying to set a non-register operand\n");
1249
      exit (1);
1250
    }
1251
 
1252
  setsim_reg (eval_operand_val (insn, opd), value);
1253
 
1254
}       /* set_operand() */
1255
 
1256
 
1257
/*---------------------------------------------------------------------------*/
1258
/*!Simple and rather slow decoding function
1259
 
1260
   Based on built automata.
1261
 
1262
   @param[in] current  The current instruction to execute                    */
1263
/*---------------------------------------------------------------------------*/
1264
static void
1265
decode_execute (struct iqueue_entry *current)
1266
{
1267
  int insn_index;
1268
 
1269 230 jeremybenn
  current->insn_index = insn_index = or1ksim_insn_decode (current->insn);
1270 19 jeremybenn
 
1271
  if (insn_index < 0)
1272
    {
1273
      l_invalid (current);
1274
    }
1275
  else
1276
    {
1277 230 jeremybenn
      or1ksim_or32_opcodes[insn_index].exec (current);
1278 19 jeremybenn
    }
1279
 
1280
  if (do_stats)
1281
    analysis (&cpu_state.iqueue);
1282
}
1283
 
1284
#include "insnset.c"
1285
 
1286
#elif defined(DYNAMIC_EXECUTION)
1287
 
1288
#else
1289
# error "Must define SIMPLE_EXECUTION, COMPLEX_EXECUTION or DYNAMIC_EXECUTION"
1290
#endif

powered by: WebSVN 2.1.0

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