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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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