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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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