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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [sim-config.c] - Blame information for rev 666

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

Line No. Rev Author Line
1 19 jeremybenn
/* sim-config.c -- Simulator configuration
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
/* Simulator configuration. Eventually this one will be a lot bigger. Updated
27
   to use argtable2 for argument parsing. */
28
 
29
 
30
/* Autoconf and/or portability configuration */
31
#include "config.h"
32
#include "port.h"
33
 
34
/* System includes */
35
#include <stdlib.h>
36
 
37
/* Package includes */
38
#include "sim-config.h"
39
#include "vapi.h"
40
#include "cuc.h"
41
#include "cpu-config.h"
42
#include "memory.h"
43
#include "dmmu.h"
44
#include "immu.h"
45
#include "dcache-model.h"
46
#include "icache-model.h"
47
#include "pic.h"
48
#include "pm.h"
49 556 julius
#include "pcu.h"
50 19 jeremybenn
#include "branch-predict.h"
51
#include "debug-unit.h"
52
#include "mc.h"
53
#include "16450.h"
54
#include "dma.h"
55
#include "eth.h"
56
#include "gpio.h"
57
#include "vga.h"
58
#include "fb.h"
59
#include "ps2kbd.h"
60
#include "atahost.h"
61
#include "generic.h"
62
#include "execute.h"
63
#include "spr-defs.h"
64
#include "debug.h"
65 82 jeremybenn
#include "jtag.h"
66 19 jeremybenn
#include "misc.h"
67
#include "argtable2.h"
68
 
69
 
70 224 jeremybenn
/*! A structure used to represent possible parameters in a section. */
71
struct config_param
72
{
73
  char                 *name;                           /* param name */
74
  enum param_t          type;                           /* param type */
75
  void                (*func) (union param_val  val,    /* Setter function */
76
                               void            *dat);
77
  struct config_param  *next;                           /* Next param in list */
78
 
79
};      /* struct config_param */
80
 
81
 
82
/*! Config file line count */
83
static int  line_number;
84
 
85
/*! The global configuration data structure */
86 19 jeremybenn
struct config config;
87 224 jeremybenn
 
88
/*! The global runtime status data structure */
89 19 jeremybenn
struct runtime runtime;
90
 
91 224 jeremybenn
/*! Master list of sections it is possible to configure. */
92
static struct config_section *section_master_list = NULL;
93 19 jeremybenn
 
94
 
95 224 jeremybenn
/* -------------------------------------------------------------------------- */
96
/*!Register a parameter for a section
97 19 jeremybenn
 
98 224 jeremybenn
   Add a new parameter to the list of parameters that may be set for a given
99
   section.
100 19 jeremybenn
 
101 224 jeremybenn
   @param[in] sec       The section containing the parameter.
102
   @param[in] param     Name of the parameter
103
   @param[in] type      Type of the parameter
104
   @param[in] param_cb  Call back function to set this parameter.             */
105
/* -------------------------------------------------------------------------- */
106
void
107
reg_config_param (struct config_section  *sec,
108
                  const char             *param,
109
                  enum param_t            type,
110
                  void                  (*param_cb) (union param_val,
111
                                                     void *))
112
{
113
  struct config_param *new = malloc (sizeof (struct config_param));
114 19 jeremybenn
 
115 224 jeremybenn
  if (!new)
116
    {
117
      fprintf (stderr, "ERROR: Out-of-memory allocating parameter: exiting,\n");
118
      exit (1);
119
    }
120
 
121
  if (!(new->name = strdup (param)))
122
    {
123
      fprintf (stderr, "ERROR: Out-of-memory allocating parameter name: "
124
               "exiting,\n");
125
      exit (1);
126
    }
127
 
128
  /* Set up the parameter */
129
  new->func = param_cb;
130
  new->type = type;
131
 
132
  /* Insert on head of list */
133
  new->next = sec->params;
134
  sec->params = new;
135
 
136
}       /* reg_config_param () */
137
 
138
 
139
/* -------------------------------------------------------------------------- */
140
/*!Register a new section.
141
 
142
   Add a new section to the list of sections that may be found in a config
143
   file.
144
 
145
   @param[in] section    The name of the new section.
146
   @param[in] sec_start  Function to call at start of section configuration
147
                         (or NULL if none)
148
   @param[in] sec_end    Function to call at end of section configuration
149
                         (or NULL if none). Returns pointer to an arbitrary
150
                         data structure.
151
 
152
   @return  A pointer to the section data structure for the new section.      */
153
/* -------------------------------------------------------------------------- */
154
struct config_section *
155
reg_config_sec (const char   *section,
156
                void       *(*sec_start) (void),
157
                void        (*sec_end) (void *))
158
{
159
  struct config_section *new = malloc (sizeof (struct config_section));
160
 
161
  if (!new)
162
    {
163
      fprintf (stderr, "ERROR: Out-of-memory allocating section: exiting,\n");
164
      exit (1);
165
    }
166
 
167
  if (!(new->name = strdup (section)))
168
    {
169
      fprintf (stderr, "ERROR: Out-of-memory allocating section name: "
170
               "exiting,\n");
171
      exit (1);
172
    }
173
 
174
  /* Set up the section */
175
  new->next      = section_master_list;
176
  new->sec_start = sec_start;
177
  new->sec_end   = sec_end;
178
  new->params    = NULL;
179
 
180
  /* Insert the section */
181
  section_master_list = new;
182
 
183
  return new;
184
 
185
}       /* reg_config_sec () */
186
 
187
 
188
/* -------------------------------------------------------------------------- */
189
/*!Look up a section
190
 
191
   Given a section name, return the data structure describing that section.
192
 
193
   @param[in] name  The section to look for.
194
 
195
   @return  A pointer to the section config data structure, or NULL if the
196
            section is not found                                              */
197
/* -------------------------------------------------------------------------- */
198
static struct config_section *
199
lookup_section (char *name)
200
{
201
  struct config_section *cur = NULL;
202
 
203
  for (cur = section_master_list; NULL != cur; cur = cur->next)
204
    {
205
      if (strcmp (cur->name, name) == 0)
206
        {
207
          break;
208
        }
209
    }
210
 
211
  return  cur;
212
 
213
}       /* lookup_section () */
214
 
215
 
216
/* -------------------------------------------------------------------------- */
217
/*!Look up a parameter for a section
218
 
219
   Given a parameter name and a section data structure, return the data
220
   structure describing that parameter
221
 
222
   @param[in] name  The parameter to look for.
223
   @param[in] sec   The section containing the parameter.
224
 
225
   @return  A pointer to the parameter config data structure, or NULL if the
226
            parameter is not found                                            */
227
/* -------------------------------------------------------------------------- */
228
static struct config_param *
229
lookup_param (char                  *name,
230
              struct config_section *sec)
231
{
232
  struct config_param *param = NULL;
233
 
234
  for (param = sec->params; NULL != param; param = param->next)
235
    {
236
      if (strcmp (param->name, name) == 0)
237
        {
238
          break;
239
        }
240
    }
241
 
242
  return  param;
243
 
244
}       /* lookup_param () */
245
 
246
 
247
/* -------------------------------------------------------------------------- */
248 19 jeremybenn
/*!Set default configuration parameters for fixed components
249
 
250
   These values are held in the global config variable. Parameter orders
251
   match the order in the corresponding section registration function and
252
   documentation.
253
 
254 224 jeremybenn
   Also set some starting values for runtime elements.                        */
255
/* -------------------------------------------------------------------------- */
256 19 jeremybenn
void
257
init_defconfig ()
258
{
259
  int  set_bits;                /* Temporaries for computing bit fields */
260
  int  way_bits;
261
 
262
  memset (&config, 0, sizeof (config));
263
 
264
  /* External linkage disabled here. */
265
  config.ext.class_ptr = NULL;
266
  config.ext.read_up   = NULL;
267
  config.ext.write_up  = NULL;
268
 
269
  /* Sim */
270 202 julius
  config.sim.is_library          = 0;    /* Not library operation */
271
  config.sim.verbose             = 0;
272
  config.sim.debug               = 0;
273
  config.sim.profile             = 0;
274
  config.sim.prof_fn             = strdup ("sim.profile");
275
  config.sim.mprofile            = 0;
276
  config.sim.mprof_fn            = strdup ("sim.mprofile");
277
  config.sim.history             = 0;
278
  config.sim.exe_log             = 0;
279
  config.sim.exe_log_type        = EXE_LOG_HARDWARE;
280
  config.sim.exe_log_start       = 0;
281
  config.sim.exe_log_end         = 0;
282
  config.sim.exe_log_marker      = 0;
283
  config.sim.exe_log_fn          = strdup ("executed.log");
284
  config.sim.exe_bin_insn_log    = 0;
285
  config.sim.exe_bin_insn_log_fn = strdup ("exe-insn.bin");
286
  config.sim.clkcycle_ps         = 4000;        /* 4000 for 4ns (250MHz) */
287 19 jeremybenn
 
288 82 jeremybenn
  /* Debug */
289
  config.debug.jtagcycle_ps = 40000;    /* 40000 for 40ns (25MHz) */
290
 
291 19 jeremybenn
  /* VAPI */
292
  config.vapi.enabled        = 0;
293 346 jeremybenn
  config.vapi.server_port    = 50000;
294 19 jeremybenn
  config.vapi.log_enabled    = 0;
295
  config.vapi.hide_device_id = 0;
296
  config.vapi.vapi_fn        = strdup ("vapi.log");
297
 
298
  /* CUC */
299
  config.cuc.calling_convention = 1;
300
  config.cuc.enable_bursts      = 1;
301
  config.cuc.no_multicycle      = 1;
302
  config.cuc.memory_order       = MO_STRONG;
303
  config.cuc.timings_fn         = strdup ("virtex.tim");
304
 
305
  /* CPU */
306
  cpu_state.sprs[SPR_VR]      = 0;
307
  cpu_state.sprs[SPR_UPR]     = SPR_UPR_UP | SPR_UPR_TTP;
308
  cpu_state.sprs[SPR_SR]      = SPR_SR_FO  | SPR_SR_SM;
309
  cpu_state.sprs[SPR_CPUCFGR] = SPR_CPUCFGR_OB32S;
310
  config.cpu.superscalar      = 0;
311
  config.cpu.hazards          = 0;
312
  config.cpu.dependstats      = 0;
313
  config.cpu.sbuf_len         = 0;
314 100 julius
  config.cpu.hardfloat        = 0;
315 19 jeremybenn
 
316
  /* Data cache (IC is set dynamically). Also set relevant SPR bits */
317
  config.dc.enabled         = 0;
318
  config.dc.nsets           = 1;
319
  config.dc.nways           = 1;
320
  config.dc.blocksize       = 1;
321
  config.dc.ustates         = 2;
322
  config.dc.load_hitdelay   = 2;
323
  config.dc.load_missdelay  = 2;
324
  config.dc.store_hitdelay  = 0;
325
  config.dc.store_missdelay = 0;
326
 
327
  if (config.dc.enabled)
328
    {
329
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DCP;
330
    }
331
  else
332
    {
333
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DCP;
334
    }
335
 
336
  set_bits = log2_int (config.dc.nsets);
337
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCS;
338
  cpu_state.sprs[SPR_DCCFGR] |= set_bits << SPR_DCCFGR_NCS_OFF;
339
 
340
  way_bits = log2_int (config.dc.nways);
341
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCW;
342
  cpu_state.sprs[SPR_DCCFGR] |= way_bits << SPR_DCCFGR_NCW_OFF;
343
 
344
  if (MIN_DC_BLOCK_SIZE == config.dc.blocksize)
345
    {
346
      cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_CBS;
347
    }
348
  else
349
    {
350
      cpu_state.sprs[SPR_DCCFGR] |= SPR_DCCFGR_CBS;
351
    }
352
 
353
  /* Power management */
354
  config.pm.enabled = 0;
355
 
356
  if (config.pm.enabled)
357
    {
358
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PMP;
359
    }
360
  else
361
    {
362
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PMP;
363
    }
364
 
365
  /* Programmable Interrupt Controller */
366
  config.pic.enabled      = 0;
367
  config.pic.edge_trigger = 1;
368 432 jeremybenn
  config.pic.use_nmi      = 1;
369 19 jeremybenn
 
370
  if (config.pic.enabled)
371
    {
372
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PICP;
373
    }
374
  else
375
    {
376
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PICP;
377
    }
378
 
379 556 julius
  /* Performance Counters Unit */
380
  config.pcu.enabled     = 0;
381
 
382 19 jeremybenn
  /* Branch Prediction */
383
  config.bpb.enabled     = 0;
384
  config.bpb.btic        = 0;
385
  config.bpb.sbp_bnf_fwd = 0;
386
  config.bpb.sbp_bf_fwd  = 0;
387
  config.bpb.missdelay   = 0;
388
  config.bpb.hitdelay    = 0;
389
 
390
  /* Debug */
391
  config.debug.enabled     = 0;
392
  config.debug.rsp_enabled = 0;
393
  config.debug.rsp_port    = 51000;
394
  config.debug.vapi_id     = 0;
395
 
396
  cpu_state.sprs[SPR_DCFGR] = SPR_DCFGR_WPCI |
397
                              MATCHPOINTS_TO_NDP (MAX_MATCHPOINTS);
398
 
399
  if (config.debug.enabled)
400
    {
401
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DUP;
402
    }
403
  else
404
    {
405
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DUP;
406
    }
407
 
408
  /* Configure runtime */
409
  memset (&runtime, 0, sizeof (runtime));
410
 
411
  /* Sim */
412
  runtime.sim.fexe_log              = NULL;
413
  runtime.sim.iprompt               = 0;
414
  runtime.sim.fprof                 = NULL;
415
  runtime.sim.fmprof                = NULL;
416
  runtime.sim.fout                  = stdout;
417
 
418 82 jeremybenn
  /* Debug */
419
  runtime.debug.instr           = JI_UNDEFINED;
420
  runtime.debug.mod_id          = JM_UNDEFINED;
421
  runtime.debug.write_defined_p = 0;             /* No WRITE_COMMAND yet */
422
 
423 19 jeremybenn
  /* NPC state. Set to 1 when NPC is changed while the processor is stalled. */
424
  cpu_state.npc_not_valid = 0;
425
 
426
  /* VAPI */
427
  runtime.vapi.vapi_file = NULL;
428
  runtime.vapi.enabled   = 0;
429
 
430
}       /* init_defconfig() */
431
 
432
 
433 224 jeremybenn
/* -------------------------------------------------------------------------- */
434
/*!Set a configuration parameter.
435
 
436
   We have a string representing the value, and a data structure representing
437
   the particular parameter. Break out the value and call the setter function
438
   to set its value in the section.
439
 
440
   The value text is guaranteed to have no leading or trailing whitespace.
441
 
442
   @param[in] cur_section  Spec of the section currently being configured.
443
   @param[in] param        Spec of the parameter we are setting.
444
   @param[in] val_text     The parameter value text                           */
445
/* -------------------------------------------------------------------------- */
446
static void
447
set_config_param (struct config_section *cur_section,
448
                  struct config_param   *param,
449
                  char                  *val_text)
450
{
451
  union param_val  val;
452
 
453
  /* Break out the different parameter types */
454
  switch (param->type)
455
    {
456
    case PARAMT_NONE:
457
      break;
458
 
459
    case PARAMT_INT:
460
      val.int_val = strtol (val_text, NULL, 0);
461
      break;
462
 
463
    case PARAMT_LONGLONG:
464
      val.longlong_val = strtoll (val_text, NULL, 0);
465
      break;
466
 
467
    case PARAMT_ADDR:
468
      val.addr_val = strtoul (val_text, NULL, 0);
469
      break;
470
 
471
    case PARAMT_WORD:
472
    case PARAMT_STR:
473
      /* Word and string are the same thing by now. */
474
      val.str_val = val_text;
475
      break;
476
    }
477
 
478
  /* Call the setter function */
479
  param->func (val, cur_section->dat);
480
 
481
}       /* set_config_param () */
482
 
483
 
484
/* -------------------------------------------------------------------------- */
485
/*!Scan the next word, skipping any preceding space.
486
 
487
   A word is anything that is not white space, except where the white space is
488
   within quotation marks. Return the number of newlines we have to skip.
489
 
490
   @param[in] f     The file handle to read from
491
   @param[in] word  A buffer in which to store the word.
492
 
493
   @return  The text of the next entity or NULL at end of file. Note strings
494
            have their quotation marks removed.                               */
495
/* -------------------------------------------------------------------------- */
496
static char *
497
next_word (FILE *f,
498
           char  word[])
499
{
500
  int  c;
501
  int  i;
502
 
503
  /* Skip the whitespace */
504
  do
505
    {
506
      c = fgetc (f);
507
 
508
      line_number += ('\n' == c) ? 1: 0;
509
    }
510
  while ((EOF != c) && isspace (c));
511
 
512
  /* Get the word> Special treatment if it is a string. */
513
  if ('"' == c)
514
    {
515
      /* We have a string. Skip the opening quote. */
516
      c = fgetc (f);
517
 
518
      for (i = 0; i < (STR_SIZE - 1); i++)
519
        {
520
          if ('"' == c)
521
            {
522
              c = fgetc (f);            /* So ungetc works */
523
              break;                    /* End of the string */
524
            }
525
          else if ('\n' == c)
526
            {
527
              line_number++;
528
            }
529
          else if (EOF == c)
530
            {
531
              fprintf (stderr, "ERROR: EOF in middle of string: exiting.\n");
532
              exit (1);
533
            }
534
 
535
          word[i] = c;
536
          c = fgetc (f);
537
        }
538
 
539
      /* Skip the closing quote */
540
      c = fgetc (f);
541
    }
542
  else
543
    {
544
      /* We have a space delimited word */
545
      for (i = 0; i < (STR_SIZE - 1); i++)
546
        {
547
          if ((EOF == c) || isspace (c))
548
            {
549
              break;                    /* End of the word */
550
            }
551
 
552
          word[i] = c;
553
          c = fgetc (f);
554
        }
555
    }
556
 
557
  word[i] = '\0';                       /* Terminate the word */
558
 
559
  if ((STR_SIZE - 1) == i)
560
    {
561
      word[10]= '\0';
562
      fprintf (stderr,
563
               "ERROR: Symbol beginning %s on line %d too long: exiting.\n",
564
               word, line_number);
565
      exit (1);
566
    }
567
 
568
  ungetc (c, f);                        /* Ready for next time */
569
 
570
  return  (0 == i) ? NULL : word;
571
 
572
}       /* next_word () */
573
 
574
 
575
/* -------------------------------------------------------------------------- */
576
/*!Read the next lexeme from the a config file.
577
 
578
   At this stage we are just breaking things out into space delimited
579
   entities, stripping out comments.
580
 
581
   @param[in] f       The file handle to read from
582
   @param[in] lexeme  A buffer in which to store the lexeme.
583
 
584
   @return  The text of the next entity or NULL at end of file.               */
585
/* -------------------------------------------------------------------------- */
586
static char *
587
next_lexeme (FILE *f,
588
             char  lexeme[])
589
{
590
  if (NULL == next_word (f, lexeme))
591
    {
592
      return  NULL;
593
    }
594
 
595
  /* Skip any comments */
596
  while (0 ==strncmp (lexeme, "/*", 2))
597
    {
598
      /* Look for the closing '*' and '/'. */
599
      char  c0 = '\0';
600
      char  c1 = '\0';
601
 
602
      while (('*' != c0) || ('/' != c1))
603
        {
604
          c0 = c1;
605
          c1 = fgetc (f);
606
 
607
          line_number += ('\n' == c1) ? 1 : 0;
608
 
609
          /* We assume if we hit EOF we have a serious problem and die. */
610
          if (feof (f))
611
            {
612
              fprintf (stderr, "ERROR: Comment reached EOF.\n");
613
              exit (1);
614
            }
615
        }
616
 
617
      /* Get the next lexeme */
618
      if (NULL == next_word (f, lexeme))
619
        {
620
          return  NULL;
621
        }
622
    }
623
 
624
  return  lexeme;
625
 
626
}       /* next_lexeme () */
627
 
628
 
629
/* -------------------------------------------------------------------------- */
630
/*!Read configuration from a script file.
631
 
632
   The syntax of script file is:
633
 
634
     [section x
635
       [param [=] value]+
636
     end]*
637
 
638
   Example:
639
 
640
     section mc
641
       enabled = 1
642
       POC     = 0x47892344
643
     end
644
 
645
   The config file is searched for first in the local directory, then in
646
   ${HOME}/.or1ksim, then (for backwards compatibility) in ${HOME}/.or1ksim.
647
 
648
   If the file is not found, then a rude message is printed. The system will
649
   just use default values.
650
 
651
   @param[in] filename  The configuration file to use.                        */
652
/* -------------------------------------------------------------------------- */
653
static void
654
read_script_file (const char *filename)
655
{
656
  FILE *f;
657
  char *home = getenv ("HOME");
658
  char  ctmp1[STR_SIZE];
659
  char  ctmp2[STR_SIZE];
660
  char *dir;
661
 
662
  /* Attempt to open the config file. If we fail, give up with a rude
663
     message. */
664
  sprintf (ctmp1, "%s/.or1ksim/%s", home, filename);
665
  sprintf (ctmp2, "%s/.or1k/%s", home, filename);
666
 
667
  if (NULL != (f = fopen (filename, "r")))
668
    {
669
      dir = ".";
670
    }
671
  else if (home && (NULL != (f = fopen (ctmp1, "r"))))
672
    {
673
      dir = ctmp1;
674
    }
675
  else if (home && (NULL != (f = fopen (ctmp2, "r"))))
676
    {
677
      dir = ctmp2;
678
    }
679
  else
680
    {
681
      fprintf (stderr, "Warning: Failed to open script file \"%s\". Ignored.\n",
682
               filename);
683
      return;
684
    }
685
 
686
  /* Log the config file we have just opened if required. */
687
  if (config.sim.verbose)
688
    {
689
      PRINTF ("Reading script file from \"%s/%s\"...\n", dir, filename);
690
    }
691
 
692
  /* Process the config file. */
693
  char lexeme[STR_SIZE];                /* Next entity from the input */
694
  int  in_section_p = 0;         /* Are we processing a section */
695
 
696
  struct config_section *cur_section = NULL;    /* Section being processed */
697
 
698
  line_number = 1;
699
 
700
  while (NULL != next_lexeme (f, lexeme))
701
    {
702
      /* Get the next symbol. Four possibilities.
703
 
704
         1. It's "section". Only if we are not currently in a section. Process
705
            the start of a section.
706
 
707
         2. It's "end". Only if we are currently in a section. Process the end
708
            of a section.
709
 
710
         3. Anything else while we are in a section. Assume it is a parameter
711
            for the current section.
712
 
713
         4. Anything else. An error.
714
      */
715
      if (!in_section_p && (0 == strcmp (lexeme, "section")))
716
        {
717
          /* We have the start of a section */
718
          if (NULL == next_lexeme (f, lexeme))
719
            {
720
              fprintf (stderr, "ERROR: %s/%s: Section name required at line "
721
                       "%d. Exiting\n", dir, filename, line_number);
722
              exit (1);
723
            }
724
 
725
          cur_section = lookup_section (lexeme);
726
 
727
          if (NULL != cur_section)
728
            {
729
              /* Valid section, run its startup code, with any data saved. */
730
              cur_section->dat = NULL;
731
 
732
              if (cur_section->sec_start)
733
                {
734
                  cur_section->dat = cur_section->sec_start ();
735
                }
736
 
737
              in_section_p = 1;         /* Now in a section */
738
            }
739
          else
740
            {
741
              /* Skip an unrecognized section with a warning. */
742
              fprintf (stderr, "Warning: %s/%s: Unrecognized section: %s at "
743
                       "line %d: ignoring.\n", dir, filename, lexeme,
744
                       line_number);
745
 
746
              /* just skip section */
747
              while (NULL != next_lexeme (f, lexeme))
748
                {
749
                  if (strcmp (lexeme, "end"))
750
                    {
751
                      break;
752
                    }
753
                }
754
            }
755
        }
756
      else if (in_section_p && strcmp (lexeme, "end") == 0)
757
        {
758
          /* End of section. Run the end of section code */
759
          if (cur_section->sec_end)
760
            {
761
              cur_section->sec_end (cur_section->dat);
762
            }
763
 
764
          in_section_p = 0;              /* Not in a section any more */
765
        }
766
      else if (in_section_p)
767
        {
768
          /* We're in a section, so this must be a parameter. */
769
          struct config_param *param;
770
          char                *param_val;
771
 
772
          param = lookup_param (lexeme, cur_section);
773
 
774
          /* If we didn't recognize, then warn and skip to end of line/file) */
775
          if (NULL == param)
776
            {
777
              fprintf (stderr, "Warning: %s/%s: Unrecognized parameter: %s at "
778
                       "line %d; ignored.\n", dir, filename, lexeme,
779
                       line_number);
780
 
781
              /* Skip to end of line */
782
              while (( '\n' != fgetc (f)) || feof (f))
783
                ;
784
 
785
              line_number++;
786
              continue;                 /* Start looking again */
787
            }
788
 
789
          /* Get the argument if one is expected. */
790
          if (PARAMT_NONE != param->type)
791
            {
792
              param_val = next_lexeme (f, lexeme);
793
 
794
              if (NULL == param_val)
795
                {
796
                  fprintf (stderr, "Warning: %s/%s: No argument to parameter "
797
                           "%s at line %d; ignored.\n", dir, filename,
798
                           param->name, line_number);
799
 
800
                  /* Skip to end of line */
801
                  while (( '\n' != fgetc (f)) || feof (f))
802
                    ;
803
 
804
                  line_number++;
805
                  continue;                     /* Start looking again */
806
                }
807
 
808
              /* We allow an optional '=' */
809
              if (0 == strcmp (lexeme, "="))
810
                {
811
                  param_val = next_lexeme (f, lexeme);
812
 
813
                  if (NULL == param_val)
814
                    {
815
                      fprintf (stderr, "Warning: %s/%s: No argument to "
816
                               "parameter %s at line %d; ignored.\n", dir,
817
                               filename, param->name, line_number);
818
 
819
                      /* Skip to end of line */
820
                      while (( '\n' != fgetc (f)) || feof (f))
821
                        ;
822
 
823
                      line_number++;
824
                      continue;                 /* Start looking again */
825
                    }
826
                }
827
            }
828
          else
829
            {
830
              /* No argument */
831
              param_val = NULL;
832
            }
833
 
834
          /* Apply the parameter */
835
          set_config_param (cur_section, param, param_val);
836
        }
837
      else
838
        {
839
          /* We're not in a section, so we don't know what we have */
840
          fprintf (stderr, "Warning: %s/%s: Unrecognized config file contents "
841
                   " at line %d: ignored.\n", dir, filename, line_number);
842
 
843
          /* Skip to end of line */
844
          while (( '\n' != fgetc (f)) || feof (f))
845
            ;
846
 
847
          line_number++;
848
          continue;                     /* Start looking again */
849
        }
850
    }
851
 
852
  fclose (f);           /* All done */
853
 
854
}       /* read_script_file () */
855
 
856
 
857 19 jeremybenn
/*---------------------------------------------------------------------------*/
858 224 jeremybenn
/*!Allocate a memory block
859
 
860
   We can request a block of memory be allocated from the command line, rather
861
   than in a configuration file. It will be allocated, starting at address
862
   zero.
863
 
864
   The memory size may be presented in any format recognized by strtol,
865
   optionally followed by "G" or "g", "M" or "m" or "K" or "k" for giga, mega
866
   and kilo bytes respectively, and leading to mutliplcation by 2^30, 2^20 and
867
   2^10 respectively.
868
 
869
   This is intended for simple use of the simulator in tool chain
870
   verification, where the detailed memory behavior does not matter.
871
 
872
   @param[in] size  Memory size.                                             */
873
/*---------------------------------------------------------------------------*/
874
static void
875
alloc_memory_block (const char *size)
876
{
877
  /* Sort out the memory size. */
878
  unsigned long int  multiplier;
879
  int                last_ch = strlen (size) - 1;
880
 
881
  switch (size[last_ch])
882
    {
883
    case 'G': case 'g': multiplier = 0x40000000UL; break;
884
    case 'M': case 'm': multiplier =   0x100000UL; break;
885
    case 'K': case 'k': multiplier =      0x400UL; break;
886
    default:            multiplier =        0x1UL; break;
887
    }
888 346 jeremybenn
 
889 224 jeremybenn
  unsigned long int  mem_size = strtoul (size, NULL, 0) * multiplier;
890
 
891
  if (0 == mem_size)
892
    {
893
      fprintf (stderr, "Warning: Memory size %s not recognized: ignored.\n",
894
               size);
895
      return;
896
    }
897
 
898
  if (mem_size > 0xffffffff)
899
    {
900
      fprintf (stderr, "Warning: Memory size %s too large: ignored.\n",
901
               size);
902
      return;
903
    }
904
 
905
  /* Turn the memory size back into a decimal string and allocate it */
906
  char str_size[11];
907
  sprintf (str_size, "%lu\n", mem_size);
908
 
909
  struct config_section *sec = lookup_section ("memory");
910
 
911
  sec->dat = sec->sec_start ();
912
 
913
  set_config_param (sec, lookup_param ("name", sec),     "Default RAM");
914
  set_config_param (sec, lookup_param ("type", sec),     "unknown");
915
  set_config_param (sec, lookup_param ("baseaddr", sec), "0");
916
  set_config_param (sec, lookup_param ("size", sec),     str_size);
917
 
918
  sec->sec_end (sec->dat);
919 346 jeremybenn
 
920
  if (config.sim.verbose)
921
    {
922
      PRINTF ("Memory block of 0x%lx bytes allocated\n", mem_size);
923
    }
924 224 jeremybenn
}       /* alloc_memory_block () */
925
 
926
 
927
/*---------------------------------------------------------------------------*/
928 19 jeremybenn
/*! Parse the arguments for the standalone simulator
929
 
930
    Updated by Jeremy Bennett to use argtable2.
931
 
932
    @param[in] argc  Number of command args
933
    @param[in] argv  Vector of the command args
934
 
935
    @return  0 on success, 1 on failure                                      */
936
/*---------------------------------------------------------------------------*/
937
int
938
parse_args (int argc, char *argv[])
939
{
940 224 jeremybenn
  struct arg_lit  *vercop;
941
  struct arg_lit  *help;
942 19 jeremybenn
  struct arg_file *cfg_file;
943 224 jeremybenn
  struct arg_lit  *nosrv;
944
  struct arg_int  *srv;
945
  struct arg_str  *mem;
946
  struct arg_str  *dbg;
947
  struct arg_lit  *command;
948
  struct arg_lit  *quiet;
949
  struct arg_lit  *verbose;
950 385 jeremybenn
  struct arg_lit  *trace;
951 472 jeremybenn
  struct arg_lit  *trace_phy;
952
  struct arg_lit  *trace_virt;
953 224 jeremybenn
  struct arg_lit  *report_mem_errs;
954
  struct arg_lit  *strict_npc;
955
  struct arg_lit  *profile;
956
  struct arg_lit  *mprofile;
957 19 jeremybenn
  struct arg_file *load_file;
958 224 jeremybenn
  struct arg_end  *end;
959 19 jeremybenn
 
960
  /* Specify each argument, with fall back values */
961
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
962
  help = arg_lit0 ("h", "help", "print this help message");
963
  cfg_file = arg_file0 ("f", "file", "<file>",
964
                        "config file (default \"sim.cfg\")");
965
  cfg_file->filename[0] = "sim.cfg";
966 385 jeremybenn
  nosrv = arg_lit0 (NULL, "nosrv", "do not launch debug server");
967
  srv = arg_int0 (NULL, "srv", "<n>",
968
                  "launch debug server on port (default random)");
969 483 jeremybenn
  srv->ival[0] = random () % (65536 - 49152) + 49152;
970 19 jeremybenn
  srv->hdr.flag |= ARG_HASOPTVALUE;
971 224 jeremybenn
  mem = arg_str0 ("m", "memory", "<n>", "add memory block of <n> bytes");
972 19 jeremybenn
  dbg = arg_str0 ("d", "debug-config", "<str>", "Debug config string");
973
  command = arg_lit0 ("i", "interactive", "launch interactive prompt");
974 220 jeremybenn
  quiet = arg_lit0 ("q", "quiet", "minimal message output");
975 224 jeremybenn
  verbose = arg_lit0 ("V", "verbose", "verbose message output");
976 385 jeremybenn
  trace = arg_lit0 ("t", "trace", "trace each instruction");
977 472 jeremybenn
  trace_phy = arg_lit0 (NULL, "trace-physical",
978
                        "show physical instruction address when tracing");
979
  trace_virt = arg_lit0 (NULL, "trace-virtual",
980
                        "show virtual instruction address when tracing");
981 220 jeremybenn
  report_mem_errs = arg_lit0 (NULL, "report-memory-errors",
982
                              "Report out of memory accesses");
983 19 jeremybenn
  strict_npc = arg_lit0 (NULL, "strict-npc", "setting NPC flushes pipeline");
984
  profile = arg_lit0 (NULL, "enable-profile", "enable profiling");
985
  mprofile = arg_lit0 (NULL, "enable-mprofile", "enable memory profiling");
986
  load_file = arg_file0 (NULL, NULL, "<file>", "OR32 executable");
987
  end = arg_end (20);
988
 
989 224 jeremybenn
  /* The argument table */
990
  void *argtab[] = {
991
    vercop,
992
    help,
993
    cfg_file,
994
    nosrv,
995
    srv,
996
    mem,
997
    dbg,
998
    command,
999
    quiet,
1000
    verbose,
1001 385 jeremybenn
    trace,
1002 472 jeremybenn
    trace_phy,
1003
    trace_virt,
1004 224 jeremybenn
    report_mem_errs,
1005
    strict_npc,
1006
    profile,
1007
    mprofile,
1008
    load_file,
1009
    end };
1010 19 jeremybenn
 
1011
  /* Parse */
1012 224 jeremybenn
  int  nerrors = arg_parse (argc, argv, argtab);
1013 19 jeremybenn
 
1014
  /* Special case here is if help or version is specified, we ignore any other
1015
     errors and just print the help or version information and then give up. */
1016
  if (vercop->count > 0)
1017
    {
1018
      PRINTF ("OpenRISC 1000 Architectural Simulator, version %s\n",
1019
              PACKAGE_VERSION);
1020
 
1021
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1022
      return 1;
1023
    }
1024
 
1025
  if (help->count > 0)
1026
    {
1027
      printf ("Usage:\n  %s ", argv[0]);
1028
      arg_print_syntax (stdout, argtab, "\n\n");
1029
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
1030
 
1031
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1032
      return 1;
1033
    }
1034
 
1035
  /* Deal with any errors */
1036
  if (0 != nerrors)
1037
    {
1038
      arg_print_errors (stderr, end, "or1ksim");
1039
      printf ("\nUsage:\n  %s ", argv[0]);
1040
      arg_print_syntaxv (stderr, argtab, "\n");
1041
 
1042
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1043
      return 1;
1044
    }
1045
 
1046 224 jeremybenn
  /* Request for quiet running */
1047
  config.sim.quiet = quiet->count;
1048
 
1049
  /* Request for verbose running. Not sensible to use with quiet as well. */
1050
  if (quiet->count && verbose->count)
1051
    {
1052
      fprintf (stderr, "Warning: Cannot specify both --verbose and --quiet: "
1053
               "--vervose ignored.\n");
1054
      config.sim.verbose = 0;
1055
    }
1056
  else
1057
    {
1058
      config.sim.verbose = verbose->count;
1059
    }
1060
 
1061 472 jeremybenn
  /* Request for tracing. We may ask for instructions to be recorded with
1062
     either the physical or virtual address. */
1063
  runtime.sim.hush       = trace->count ? 0 : 1;
1064
  runtime.sim.trace_phy  = trace_phy->count  ? 1 : 0;
1065
  runtime.sim.trace_virt = trace_virt->count ? 1 : 0;
1066 385 jeremybenn
 
1067 472 jeremybenn
  /* Ensure we have a least one address type in use. */
1068
  if (!runtime.sim.trace_phy && !runtime.sim.trace_virt)
1069
    {
1070
      runtime.sim.trace_virt = 1;
1071
    }
1072
 
1073 224 jeremybenn
  /* Request for memory errors */
1074
  config.sim.report_mem_errs = report_mem_errs->count;
1075
 
1076
  /* Process config file next (if given), so any other command args will
1077
     override */
1078 19 jeremybenn
  if (0 == cfg_file->count)
1079
    {
1080 224 jeremybenn
      if (config.sim.verbose)
1081
        {
1082
          fprintf (stderr, "Default configuration used\n");
1083
        }
1084 19 jeremybenn
    }
1085 224 jeremybenn
  else
1086
    {
1087
      read_script_file (cfg_file->filename[0]);
1088
    }
1089 19 jeremybenn
 
1090 224 jeremybenn
  /* Allocate a memory block */
1091
  if (mem->count > 0)
1092
    {
1093
      alloc_memory_block (mem->sval[0]);
1094
    }
1095 19 jeremybenn
 
1096
  /* Remote debug server */
1097
  if (nosrv->count > 0)
1098
    {
1099
      if (srv->count > 0)
1100
        {
1101
          fprintf (stderr,
1102
                   "%s: cannot specify --nosrv with --srv. Ignoring --nosrv\n",
1103
                   argv[0]);
1104
        }
1105
      else
1106
        {
1107
          config.debug.enabled = 0;
1108 235 jeremybenn
          config.debug.rsp_enabled = 0;
1109 19 jeremybenn
        }
1110
    }
1111
 
1112
  if (srv->count > 0)
1113
    {
1114 235 jeremybenn
      config.debug.enabled     = 1;
1115
      config.debug.rsp_enabled = 1;
1116
      config.debug.rsp_port    = srv->ival[0];
1117 19 jeremybenn
    }
1118
 
1119
  /* Runtime debug messages */
1120
  if (dbg->count > 0)
1121
    {
1122
      parse_dbchs (dbg->sval[0]);
1123
    }
1124
 
1125
  /* Interactive operation */
1126
  runtime.sim.iprompt = command->count;
1127
 
1128
  /* Request for strict NPC behavior (flush the pipeline on change) */
1129
  config.sim.strict_npc = strict_npc->count;
1130
 
1131
  /* Profiling requests */
1132
  config.sim.profile = profile->count;
1133
  config.sim.mprofile = mprofile->count;
1134
 
1135
  /* Executable file */
1136
  if (load_file->count > 0)
1137
    {
1138
      runtime.sim.filename = strdup (load_file->filename[0]);
1139
    }
1140
  else
1141
    {
1142
      runtime.sim.filename = NULL;
1143
    }
1144
 
1145
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1146
  return 0;                      /* Success */
1147
 
1148
}       /* parse_args() */
1149
 
1150
 
1151
/*---------------------------------------------------------------------------*/
1152
/*!Print the current configuration                                           */
1153
/*---------------------------------------------------------------------------*/
1154
void
1155
print_config ()
1156
{
1157
  if (config.sim.verbose)
1158
    {
1159
      char temp[20];
1160
      PRINTF ("Verbose on, ");
1161
      if (config.sim.debug)
1162
        PRINTF ("simdebug on, ");
1163
      else
1164
        PRINTF ("simdebug off, ");
1165
      if (runtime.sim.iprompt)
1166
        PRINTF ("interactive prompt on\n");
1167
      else
1168
        PRINTF ("interactive prompt off\n");
1169
 
1170
      PRINTF ("Machine initialization...\n");
1171
      generate_time_pretty (temp, config.sim.clkcycle_ps);
1172
      PRINTF ("Clock cycle: %s\n", temp);
1173
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_DCP)
1174
        PRINTF ("Data cache present.\n");
1175
      else
1176
        PRINTF ("No data cache.\n");
1177
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP)
1178
        PRINTF ("Insn cache tag present.\n");
1179
      else
1180
        PRINTF ("No instruction cache.\n");
1181
      if (config.bpb.enabled)
1182
        PRINTF ("BPB simulation on.\n");
1183
      else
1184
        PRINTF ("BPB simulation off.\n");
1185
      if (config.bpb.btic)
1186
        PRINTF ("BTIC simulation on.\n");
1187
      else
1188
        PRINTF ("BTIC simulation off.\n");
1189
    }
1190
}
1191
 
1192 224 jeremybenn
/* Simulator configuration */
1193 19 jeremybenn
 
1194
 
1195 224 jeremybenn
/*---------------------------------------------------------------------------*/
1196
/*!Turn on verbose messages.
1197 19 jeremybenn
 
1198 224 jeremybenn
   @param[in] val  Non-zero (TRUE) to turn on verbose messages, zero (FALSE)
1199
                   otherwise.
1200
   @param[in] dat  The config data structure (not used here)                 */
1201
/*---------------------------------------------------------------------------*/
1202
static void
1203
sim_verbose (union param_val  val,
1204
             void            *dat)
1205 19 jeremybenn
{
1206
  config.sim.verbose = val.int_val;
1207
 
1208 224 jeremybenn
}       /* sim_verbose () */
1209 19 jeremybenn
 
1210 224 jeremybenn
 
1211 19 jeremybenn
/*---------------------------------------------------------------------------*/
1212
/*!Set the simulator debug message level
1213
 
1214
   Value must be in the range 0 (no messages) to 9. Values outside this range
1215
   are converted to the nearer end of the range with a warning.
1216
 
1217
   @param[in] val  The value to use
1218
   @param[in] dat  The config data structure (not used here)                 */
1219
/*---------------------------------------------------------------------------*/
1220 224 jeremybenn
static void
1221 19 jeremybenn
sim_debug (union param_val  val,
1222
           void            *dat)
1223
{
1224
  if (val.int_val < 0)
1225
    {
1226
      fprintf (stderr,
1227
               "Warning: Config debug value negative: 0 substituted\n");
1228
      config.sim.debug = 0;
1229
    }
1230
  else if (val.int_val > 9)
1231
    {
1232
      fprintf (stderr,
1233
               "Warning: Config debug value too large: 9 substituted\n");
1234
      config.sim.debug = 9;
1235
    }
1236
  else
1237
    {
1238
      config.sim.debug = val.int_val;
1239
    }
1240
}       /* sim_debug() */
1241
 
1242
 
1243 224 jeremybenn
/*---------------------------------------------------------------------------*/
1244
/*!Turn on profiling
1245
 
1246
   @param[in] val  Non-zero (TRUE) to turn on profiling, zero (FALSE) otherwise.
1247
   @param[in] dat  The config data structure (not used here)                 */
1248
/*---------------------------------------------------------------------------*/
1249
static void
1250
sim_profile (union param_val  val,
1251
             void            *dat)
1252 19 jeremybenn
{
1253
  config.sim.profile = val.int_val;
1254
 
1255 224 jeremybenn
}       /* sim_profile () */
1256
 
1257
 
1258
/*---------------------------------------------------------------------------*/
1259
/*!Specify the profiling file name.
1260
 
1261
   @param[in] val  The profiling file name
1262
   @param[in] dat  The config data structure (not used here)                 */
1263
/*---------------------------------------------------------------------------*/
1264
static void
1265
sim_prof_fn (union param_val  val,
1266
             void            *dat)
1267 19 jeremybenn
{
1268
  if (NULL != config.sim.prof_fn)
1269
    {
1270
      free (config.sim.prof_fn);
1271
    }
1272
 
1273
  config.sim.prof_fn = strdup(val.str_val);
1274
 
1275 224 jeremybenn
}       /* sim_prof_fn () */
1276
 
1277
 
1278
/*---------------------------------------------------------------------------*/
1279
/*!Turn on memory profiling
1280
 
1281
   @param[in] val  Non-zero (TRUE) to turn on memory profiling, zero (FALSE)
1282
                   otherwise.
1283
   @param[in] dat  The config data structure (not used here)                 */
1284
/*---------------------------------------------------------------------------*/
1285
static void
1286
sim_mprofile (union param_val  val,
1287
              void            *dat)
1288 19 jeremybenn
{
1289
  config.sim.mprofile = val.int_val;
1290
 
1291 224 jeremybenn
}       /* sim_mprofile () */
1292
 
1293
 
1294
/*---------------------------------------------------------------------------*/
1295
/*!Specify the memory profiling file name.
1296
 
1297
   @param[in] val  The memory profiling file name
1298
   @param[in] dat  The config data structure (not used here)                 */
1299
/*---------------------------------------------------------------------------*/
1300
static void
1301 19 jeremybenn
sim_mprof_fn (union param_val val, void *dat)
1302
{
1303
  if (NULL != config.sim.mprof_fn)
1304
    {
1305
      free (config.sim.mprof_fn);
1306
    }
1307
 
1308
  config.sim.mprof_fn = strdup (val.str_val);
1309
 
1310 224 jeremybenn
}       /* sim_mprof_fn () */
1311
 
1312
 
1313
/*---------------------------------------------------------------------------*/
1314
/*!Turn on execution tracking.
1315
 
1316
   @param[in] val  Non-zero (TRUE) to turn on tracking, zero (FALSE) otherwise.
1317
   @param[in] dat  The config data structure (not used here)                 */
1318
/*---------------------------------------------------------------------------*/
1319
static void
1320
sim_history (union param_val  val,
1321
             void            *dat)
1322 19 jeremybenn
{
1323
  config.sim.history = val.int_val;
1324
}
1325
 
1326 224 jeremybenn
 
1327
/*---------------------------------------------------------------------------*/
1328
/*!Record an execution log
1329
 
1330
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
1331
   @param[in] dat  The config data structure (not used here)                 */
1332
/*---------------------------------------------------------------------------*/
1333
static void
1334
sim_exe_log (union param_val  val,
1335
             void            *dat)
1336 19 jeremybenn
{
1337
  config.sim.exe_log = val.int_val;
1338
 
1339 224 jeremybenn
}       /* sim_exe_log () */
1340
 
1341 19 jeremybenn
/*---------------------------------------------------------------------------*/
1342
/*!Set the execution log type
1343
 
1344
   Value must be one of default, hardware, simple or software. Invalid values
1345
   are ignored with a warning.
1346
 
1347
   @param[in] val  The value to use
1348
   @param[in] dat  The config data structure (not used here)                 */
1349
/*---------------------------------------------------------------------------*/
1350 224 jeremybenn
static void
1351 19 jeremybenn
sim_exe_log_type (union param_val  val,
1352
                  void            *dat)
1353
{
1354
  if (strcasecmp (val.str_val, "default") == 0)
1355
    {
1356
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
1357
    }
1358
  else if (strcasecmp (val.str_val, "hardware") == 0)
1359
    {
1360
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
1361
    }
1362
  else if (strcasecmp (val.str_val, "simple") == 0)
1363
    {
1364
      config.sim.exe_log_type = EXE_LOG_SIMPLE;
1365
    }
1366
  else if (strcasecmp (val.str_val, "software") == 0)
1367
    {
1368
      config.sim.exe_log_type = EXE_LOG_SOFTWARE;
1369
    }
1370
  else
1371
    {
1372
      fprintf (stderr, "Warning: Execution log type %s invalid. Ignored",
1373
               val.str_val);
1374
    }
1375
}       /* sim_exe_log_type() */
1376
 
1377
 
1378 224 jeremybenn
/*---------------------------------------------------------------------------*/
1379
/*!Set the execution log start address
1380
 
1381
   Address at which to start logging.
1382
 
1383
   @param[in] val  The value to use
1384
   @param[in] dat  The config data structure (not used here)                 */
1385
/*---------------------------------------------------------------------------*/
1386
static void
1387
sim_exe_log_start (union param_val  val,
1388
                   void            *dat)
1389 19 jeremybenn
{
1390
  config.sim.exe_log_start = val.longlong_val;
1391
 
1392 224 jeremybenn
}       /* sim_exe_log_start () */
1393
 
1394
 
1395
/*---------------------------------------------------------------------------*/
1396
/*!Set the execution log end address
1397
 
1398
   Address at which to end logging.
1399
 
1400
   @param[in] val  The value to use
1401
   @param[in] dat  The config data structure (not used here)                 */
1402
/*---------------------------------------------------------------------------*/
1403
static void
1404
sim_exe_log_end (union param_val  val,
1405
                 void            *dat)
1406 19 jeremybenn
{
1407
  config.sim.exe_log_end = val.longlong_val;
1408
 
1409 224 jeremybenn
}       /* sim_exe_log_end () */
1410
 
1411
 
1412
/*---------------------------------------------------------------------------*/
1413
/*!Specify number of instruction between printing horizontal markers
1414
 
1415
   Control of log format
1416
 
1417
   @param[in] val  The value to use
1418
   @param[in] dat  The config data structure (not used here)                 */
1419
/*---------------------------------------------------------------------------*/
1420
static void
1421
sim_exe_log_marker (union param_val  val,
1422
                    void            *dat)
1423 19 jeremybenn
{
1424
  config.sim.exe_log_marker = val.int_val;
1425
 
1426 224 jeremybenn
}       /* sim_exe_log_marker () */
1427
 
1428
 
1429
/*---------------------------------------------------------------------------*/
1430
/*!Specify the execution log file name.
1431
 
1432
   @param[in] val  The execution log file name
1433
   @param[in] dat  The config data structure (not used here)                 */
1434
/*---------------------------------------------------------------------------*/
1435
static void
1436 19 jeremybenn
sim_exe_log_fn (union param_val val, void *dat)
1437
{
1438
  if (NULL != config.sim.exe_log_fn)
1439
    {
1440
      free (config.sim.exe_log_fn);
1441
    }
1442
 
1443
  config.sim.exe_log_fn = strdup (val.str_val);
1444
 
1445 224 jeremybenn
}       /* sim_exe_log_fn () */
1446
 
1447
 
1448
/*---------------------------------------------------------------------------*/
1449
/*!Turn on binary instruction logging
1450
 
1451
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
1452
   @param[in] dat  The config data structure (not used here)                 */
1453
/*---------------------------------------------------------------------------*/
1454
static void
1455 202 julius
sim_exe_bin_insn_log (union param_val val, void *dat)
1456
{
1457
  config.sim.exe_bin_insn_log = val.int_val;
1458
 
1459 224 jeremybenn
}       /* sim_exe_bin_insn_log () */
1460
 
1461
 
1462
/*---------------------------------------------------------------------------*/
1463
/*!Specify the binary instruction log file name.
1464
 
1465
   @param[in] val  The binary instruction log file name
1466
   @param[in] dat  The config data structure (not used here)                 */
1467
/*---------------------------------------------------------------------------*/
1468
static void
1469 202 julius
sim_exe_bin_insn_log_fn (union param_val val, void *dat)
1470
{
1471
  if (NULL != config.sim.exe_bin_insn_log_fn)
1472
    {
1473
      free (config.sim.exe_bin_insn_log_fn);
1474
    }
1475
 
1476
  config.sim.exe_bin_insn_log_fn = strdup (val.str_val);
1477
 
1478 224 jeremybenn
}       /* sim_exe_bin_insn_log_fn () */
1479 202 julius
 
1480
 
1481 19 jeremybenn
/*---------------------------------------------------------------------------*/
1482
/*!Set the clock cycle time.
1483
 
1484
   Value must be an integer followed by one of ps, ns, us or ms.
1485
 
1486
   If a valid time is not presented, the value is unchanged.
1487
 
1488
   @param[in] val  The value to use
1489
   @param[in] dat  The config data structure (not used here)                 */
1490
/*---------------------------------------------------------------------------*/
1491
void
1492
sim_clkcycle (union param_val  val,
1493
              void            *dat)
1494
{
1495
  int len = strlen (val.str_val);
1496
  int pos = len - 1;
1497
  long time;
1498
  if ((len < 2) || (val.str_val[pos--] != 's'))
1499
    {
1500
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
1501
               val.str_val);
1502
      return;
1503
    }
1504
 
1505
  switch (val.str_val[pos--])
1506
    {
1507
    case 'p':
1508
      time = 1;
1509
      break;
1510
    case 'n':
1511
      time = 1000;
1512
      break;
1513
    case 'u':
1514
      time = 1000000;
1515
      break;
1516
    case 'm':
1517
      time = 1000000000;
1518
      break;
1519
    default:
1520
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
1521
               val.str_val);
1522
      return;
1523
    }
1524
 
1525
  val.str_val[pos + 1] = 0;
1526
  time = time * atol (val.str_val);
1527
 
1528
  if (0 == time)
1529
    {
1530
      fprintf (stderr, "Warning: Clock cycle time of zero invalid: ignored\n");
1531
      return;
1532
    }
1533
 
1534
  config.sim.clkcycle_ps = time;
1535
 
1536
}       /* sim_clkcycle() */
1537
 
1538
 
1539
/*---------------------------------------------------------------------------*/
1540
/*!Register the functions to handle a section sim
1541
 
1542
   This section does not allocate dynamically a data structure holding its
1543
   config information. It's all in the global config.sim data
1544
   structure. Therefore it does not need a start and end function to
1545
   initialize default values (although it might be clearer to do so). The
1546
   default values are set in init_defconfig().
1547
 
1548
   New preferred parameter names are introduced (_file for filenames), but
1549
   the legacy names (_fn) are also present for backwards compatibility       */
1550
/*---------------------------------------------------------------------------*/
1551
static void
1552
reg_sim_sec ()
1553
{
1554
  struct config_section *sec = reg_config_sec ("sim", NULL, NULL);
1555
 
1556 224 jeremybenn
  reg_config_param (sec, "verbose",        PARAMT_INT,      sim_verbose);
1557
  reg_config_param (sec, "debug",          PARAMT_INT,      sim_debug);
1558
  reg_config_param (sec, "profile",        PARAMT_INT,      sim_profile);
1559
  reg_config_param (sec, "prof_file",      PARAMT_STR,      sim_prof_fn);
1560
  reg_config_param (sec, "prof_fn",        PARAMT_STR,      sim_prof_fn);
1561
  reg_config_param (sec, "mprofile",       PARAMT_INT,      sim_mprofile);
1562
  reg_config_param (sec, "mprof_file",     PARAMT_STR,      sim_mprof_fn);
1563
  reg_config_param (sec, "mprof_fn",       PARAMT_STR,      sim_mprof_fn);
1564
  reg_config_param (sec, "history",        PARAMT_INT,      sim_history);
1565
  reg_config_param (sec, "exe_log",        PARAMT_INT,      sim_exe_log);
1566
  reg_config_param (sec, "exe_log_type",   PARAMT_WORD,     sim_exe_log_type);
1567
  reg_config_param (sec, "exe_log_start",  PARAMT_LONGLONG, sim_exe_log_start);
1568
  reg_config_param (sec, "exe_log_end",    PARAMT_LONGLONG, sim_exe_log_end);
1569
  reg_config_param (sec, "exe_log_marker", PARAMT_INT,      sim_exe_log_marker);
1570
  reg_config_param (sec, "exe_log_file",   PARAMT_STR,      sim_exe_log_fn);
1571
  reg_config_param (sec, "exe_log_fn",     PARAMT_STR,      sim_exe_log_fn);
1572 19 jeremybenn
 
1573 224 jeremybenn
  reg_config_param (sec, "exe_bin_insn_log",      PARAMT_INT,
1574
                    sim_exe_bin_insn_log);
1575
  reg_config_param (sec, "exe_bin_insn_log_fn",   PARAMT_STR,
1576
                    sim_exe_bin_insn_log_fn);
1577
  reg_config_param (sec, "exe_bin_insn_log_file", PARAMT_STR,
1578
                    sim_exe_bin_insn_log_fn);
1579
 
1580
  reg_config_param (sec, "clkcycle",       PARAMT_WORD,     sim_clkcycle);
1581
 
1582 19 jeremybenn
}       /* reg_sim_sec() */
1583
 
1584
 
1585 224 jeremybenn
/*---------------------------------------------------------------------------*/
1586
/*!Register all the possible sections which we support.
1587
 
1588
   Each section type provides a registration function. This returns a struct
1589
   config_section, which in turn contains a list of config_params.           */
1590
/*---------------------------------------------------------------------------*/
1591 19 jeremybenn
void
1592 224 jeremybenn
reg_config_secs ()
1593 19 jeremybenn
{
1594
  reg_generic_sec ();           /* JPB */
1595
  reg_sim_sec ();
1596
  reg_cpu_sec ();
1597
  reg_pic_sec ();
1598
  reg_memory_sec ();
1599
  reg_mc_sec ();
1600
  reg_uart_sec ();
1601
  reg_dma_sec ();
1602
  reg_debug_sec ();
1603
  reg_vapi_sec ();
1604
  reg_ethernet_sec ();
1605
  reg_immu_sec ();
1606
  reg_dmmu_sec ();
1607
  reg_ic_sec ();
1608
  reg_dc_sec ();
1609
  reg_gpio_sec ();
1610
  reg_bpb_sec ();
1611
  reg_pm_sec ();
1612 556 julius
  reg_pcu_sec ();
1613 19 jeremybenn
  reg_vga_sec ();
1614
  reg_fb_sec ();
1615
  reg_kbd_sec ();
1616
  reg_ata_sec ();
1617
  reg_cuc_sec ();
1618
}
1619
 
1620
/* Utility for execution of set sim command.  */
1621
static int
1622
set_config (int argc, char **argv)
1623
{
1624 224 jeremybenn
  struct config_section *cur_section;
1625
  struct config_param *param;
1626 19 jeremybenn
 
1627
  if (argc < 2)
1628
    return 1;
1629
 
1630
  PRINTF ("sec:%s\n", argv[1]);
1631 224 jeremybenn
  cur_section = lookup_section (argv[1]);
1632 19 jeremybenn
 
1633 224 jeremybenn
  if (NULL == cur_section)
1634 19 jeremybenn
    return 1;
1635
 
1636
  if (argc < 3)
1637
    return 2;
1638
 
1639
  PRINTF ("item:%s\n", argv[2]);
1640
  {
1641 224 jeremybenn
    for (param = cur_section->params; param; param = param->next)
1642
      if (strcmp (param->name, argv[2]) == 0)
1643 19 jeremybenn
        {
1644
          break;
1645
        }
1646 224 jeremybenn
    if (!param)
1647 19 jeremybenn
      return 2;
1648
 
1649
    /* Parse parameter value */
1650 224 jeremybenn
    if (param->type)
1651 19 jeremybenn
      {
1652
        if (argc < 4)
1653
          return 3;
1654
        PRINTF ("params:%s\n", argv[3]);
1655
      }
1656
 
1657 224 jeremybenn
    set_config_param (cur_section, param, argv[3]);
1658 19 jeremybenn
  }
1659
  return 0;
1660
}
1661
 
1662
/* Executes set sim command, displays error.  */
1663
void
1664
set_config_command (int argc, char **argv)
1665
{
1666
  struct config_section *cur;
1667 224 jeremybenn
  struct config_param *param;
1668 19 jeremybenn
 
1669
  switch (set_config (argc, argv))
1670
    {
1671
    case 1:
1672
      PRINTF
1673
        ("Invalid or missing section name.  One of valid sections must be specified:\n");
1674 224 jeremybenn
      for (cur = section_master_list; cur; cur = cur->next)
1675 19 jeremybenn
        PRINTF ("%s ", cur->name);
1676
      PRINTF ("\n");
1677
      break;
1678
    case 2:
1679 224 jeremybenn
      cur = lookup_section (argv[1]);
1680 19 jeremybenn
      PRINTF
1681
        ("Invalid or missing item name.  One of valid items must be specified:\n");
1682 224 jeremybenn
      for (param = cur->params; param;
1683
           param = param->next)
1684
        PRINTF ("%s ", param->name);
1685 19 jeremybenn
      PRINTF ("\n");
1686
      break;
1687
    case 3:
1688
      PRINTF ("Invalid parameters specified.\n");
1689
      break;
1690
    }
1691
}

powered by: WebSVN 2.1.0

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