OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

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

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

powered by: WebSVN 2.1.0

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