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 335

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 235 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
  unsigned long int  mem_size = strtoul (size, NULL, 0) * multiplier;
884
 
885
  if (0 == mem_size)
886
    {
887
      fprintf (stderr, "Warning: Memory size %s not recognized: ignored.\n",
888
               size);
889
      return;
890
    }
891
 
892
  if (mem_size > 0xffffffff)
893
    {
894
      fprintf (stderr, "Warning: Memory size %s too large: ignored.\n",
895
               size);
896
      return;
897
    }
898
 
899
  /* Turn the memory size back into a decimal string and allocate it */
900
  char str_size[11];
901
  sprintf (str_size, "%lu\n", mem_size);
902
 
903
  struct config_section *sec = lookup_section ("memory");
904
 
905
  sec->dat = sec->sec_start ();
906
 
907
  set_config_param (sec, lookup_param ("name", sec),     "Default RAM");
908
  set_config_param (sec, lookup_param ("type", sec),     "unknown");
909
  set_config_param (sec, lookup_param ("baseaddr", sec), "0");
910
  set_config_param (sec, lookup_param ("size", sec),     str_size);
911
 
912
  sec->sec_end (sec->dat);
913
 
914
}       /* alloc_memory_block () */
915
 
916
 
917
/*---------------------------------------------------------------------------*/
918 19 jeremybenn
/*! Parse the arguments for the standalone simulator
919
 
920
    Updated by Jeremy Bennett to use argtable2.
921
 
922
    @param[in] argc  Number of command args
923
    @param[in] argv  Vector of the command args
924
 
925
    @return  0 on success, 1 on failure                                      */
926
/*---------------------------------------------------------------------------*/
927
int
928
parse_args (int argc, char *argv[])
929
{
930 224 jeremybenn
  struct arg_lit  *vercop;
931
  struct arg_lit  *help;
932 19 jeremybenn
  struct arg_file *cfg_file;
933 224 jeremybenn
  struct arg_lit  *nosrv;
934
  struct arg_int  *srv;
935
  struct arg_str  *mem;
936
  struct arg_str  *dbg;
937
  struct arg_lit  *command;
938
  struct arg_lit  *quiet;
939
  struct arg_lit  *verbose;
940
  struct arg_lit  *report_mem_errs;
941
  struct arg_lit  *strict_npc;
942
  struct arg_lit  *profile;
943
  struct arg_lit  *mprofile;
944 19 jeremybenn
  struct arg_file *load_file;
945 224 jeremybenn
  struct arg_end  *end;
946 19 jeremybenn
 
947
  /* Specify each argument, with fall back values */
948
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
949
  help = arg_lit0 ("h", "help", "print this help message");
950
  cfg_file = arg_file0 ("f", "file", "<file>",
951
                        "config file (default \"sim.cfg\")");
952
  cfg_file->filename[0] = "sim.cfg";
953
  nosrv = arg_lit0 (NULL, "nosrv", "do not launch JTAG proxy server");
954
  srv = arg_int0 (NULL, "srv", "<n>", "port number (default random)");
955
  srv->ival[0] = rand () % (65536 - 49152) + 49152;
956
  srv->hdr.flag |= ARG_HASOPTVALUE;
957 224 jeremybenn
  mem = arg_str0 ("m", "memory", "<n>", "add memory block of <n> bytes");
958 19 jeremybenn
  dbg = arg_str0 ("d", "debug-config", "<str>", "Debug config string");
959
  command = arg_lit0 ("i", "interactive", "launch interactive prompt");
960 220 jeremybenn
  quiet = arg_lit0 ("q", "quiet", "minimal message output");
961 224 jeremybenn
  verbose = arg_lit0 ("V", "verbose", "verbose message output");
962 220 jeremybenn
  report_mem_errs = arg_lit0 (NULL, "report-memory-errors",
963
                              "Report out of memory accesses");
964 19 jeremybenn
  strict_npc = arg_lit0 (NULL, "strict-npc", "setting NPC flushes pipeline");
965
  profile = arg_lit0 (NULL, "enable-profile", "enable profiling");
966
  mprofile = arg_lit0 (NULL, "enable-mprofile", "enable memory profiling");
967
  load_file = arg_file0 (NULL, NULL, "<file>", "OR32 executable");
968
  end = arg_end (20);
969
 
970 224 jeremybenn
  /* The argument table */
971
  void *argtab[] = {
972
    vercop,
973
    help,
974
    cfg_file,
975
    nosrv,
976
    srv,
977
    mem,
978
    dbg,
979
    command,
980
    quiet,
981
    verbose,
982
    report_mem_errs,
983
    strict_npc,
984
    profile,
985
    mprofile,
986
    load_file,
987
    end };
988 19 jeremybenn
 
989
  /* Parse */
990 224 jeremybenn
  int  nerrors = arg_parse (argc, argv, argtab);
991 19 jeremybenn
 
992
  /* Special case here is if help or version is specified, we ignore any other
993
     errors and just print the help or version information and then give up. */
994
  if (vercop->count > 0)
995
    {
996
      PRINTF ("OpenRISC 1000 Architectural Simulator, version %s\n",
997
              PACKAGE_VERSION);
998
 
999
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1000
      return 1;
1001
    }
1002
 
1003
  if (help->count > 0)
1004
    {
1005
      printf ("Usage:\n  %s ", argv[0]);
1006
      arg_print_syntax (stdout, argtab, "\n\n");
1007
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
1008
 
1009
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1010
      return 1;
1011
    }
1012
 
1013
  /* Deal with any errors */
1014
  if (0 != nerrors)
1015
    {
1016
      arg_print_errors (stderr, end, "or1ksim");
1017
      printf ("\nUsage:\n  %s ", argv[0]);
1018
      arg_print_syntaxv (stderr, argtab, "\n");
1019
 
1020
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1021
      return 1;
1022
    }
1023
 
1024 224 jeremybenn
  /* Request for quiet running */
1025
  config.sim.quiet = quiet->count;
1026
 
1027
  /* Request for verbose running. Not sensible to use with quiet as well. */
1028
  if (quiet->count && verbose->count)
1029
    {
1030
      fprintf (stderr, "Warning: Cannot specify both --verbose and --quiet: "
1031
               "--vervose ignored.\n");
1032
      config.sim.verbose = 0;
1033
    }
1034
  else
1035
    {
1036
      config.sim.verbose = verbose->count;
1037
    }
1038
 
1039
  /* Request for memory errors */
1040
  config.sim.report_mem_errs = report_mem_errs->count;
1041
 
1042
  /* Process config file next (if given), so any other command args will
1043
     override */
1044 19 jeremybenn
  if (0 == cfg_file->count)
1045
    {
1046 224 jeremybenn
      if (config.sim.verbose)
1047
        {
1048
          fprintf (stderr, "Default configuration used\n");
1049
        }
1050 19 jeremybenn
    }
1051 224 jeremybenn
  else
1052
    {
1053
      read_script_file (cfg_file->filename[0]);
1054
    }
1055 19 jeremybenn
 
1056 224 jeremybenn
  /* Allocate a memory block */
1057
  if (mem->count > 0)
1058
    {
1059
      alloc_memory_block (mem->sval[0]);
1060
    }
1061 19 jeremybenn
 
1062
  /* Remote debug server */
1063
  if (nosrv->count > 0)
1064
    {
1065
      if (srv->count > 0)
1066
        {
1067
          fprintf (stderr,
1068
                   "%s: cannot specify --nosrv with --srv. Ignoring --nosrv\n",
1069
                   argv[0]);
1070
        }
1071
      else
1072
        {
1073
          config.debug.enabled = 0;
1074 235 jeremybenn
          config.debug.rsp_enabled = 0;
1075 19 jeremybenn
        }
1076
    }
1077
 
1078
  if (srv->count > 0)
1079
    {
1080 235 jeremybenn
      config.debug.enabled     = 1;
1081
      config.debug.rsp_enabled = 1;
1082
      config.debug.rsp_port    = srv->ival[0];
1083 19 jeremybenn
    }
1084
 
1085
  /* Runtime debug messages */
1086
  if (dbg->count > 0)
1087
    {
1088
      parse_dbchs (dbg->sval[0]);
1089
    }
1090
 
1091
  /* Interactive operation */
1092
  runtime.sim.iprompt = command->count;
1093
 
1094
  /* Request for strict NPC behavior (flush the pipeline on change) */
1095
  config.sim.strict_npc = strict_npc->count;
1096
 
1097
  /* Profiling requests */
1098
  config.sim.profile = profile->count;
1099
  config.sim.mprofile = mprofile->count;
1100
 
1101
  /* Executable file */
1102
  if (load_file->count > 0)
1103
    {
1104
      runtime.sim.filename = strdup (load_file->filename[0]);
1105
    }
1106
  else
1107
    {
1108
      runtime.sim.filename = NULL;
1109
    }
1110
 
1111
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
1112
  return 0;                      /* Success */
1113
 
1114
}       /* parse_args() */
1115
 
1116
 
1117
/*---------------------------------------------------------------------------*/
1118
/*!Print the current configuration                                           */
1119
/*---------------------------------------------------------------------------*/
1120
void
1121
print_config ()
1122
{
1123
  if (config.sim.verbose)
1124
    {
1125
      char temp[20];
1126
      PRINTF ("Verbose on, ");
1127
      if (config.sim.debug)
1128
        PRINTF ("simdebug on, ");
1129
      else
1130
        PRINTF ("simdebug off, ");
1131
      if (runtime.sim.iprompt)
1132
        PRINTF ("interactive prompt on\n");
1133
      else
1134
        PRINTF ("interactive prompt off\n");
1135
 
1136
      PRINTF ("Machine initialization...\n");
1137
      generate_time_pretty (temp, config.sim.clkcycle_ps);
1138
      PRINTF ("Clock cycle: %s\n", temp);
1139
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_DCP)
1140
        PRINTF ("Data cache present.\n");
1141
      else
1142
        PRINTF ("No data cache.\n");
1143
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP)
1144
        PRINTF ("Insn cache tag present.\n");
1145
      else
1146
        PRINTF ("No instruction cache.\n");
1147
      if (config.bpb.enabled)
1148
        PRINTF ("BPB simulation on.\n");
1149
      else
1150
        PRINTF ("BPB simulation off.\n");
1151
      if (config.bpb.btic)
1152
        PRINTF ("BTIC simulation on.\n");
1153
      else
1154
        PRINTF ("BTIC simulation off.\n");
1155
    }
1156
}
1157
 
1158 224 jeremybenn
/* Simulator configuration */
1159 19 jeremybenn
 
1160
 
1161 224 jeremybenn
/*---------------------------------------------------------------------------*/
1162
/*!Turn on verbose messages.
1163 19 jeremybenn
 
1164 224 jeremybenn
   @param[in] val  Non-zero (TRUE) to turn on verbose messages, zero (FALSE)
1165
                   otherwise.
1166
   @param[in] dat  The config data structure (not used here)                 */
1167
/*---------------------------------------------------------------------------*/
1168
static void
1169
sim_verbose (union param_val  val,
1170
             void            *dat)
1171 19 jeremybenn
{
1172
  config.sim.verbose = val.int_val;
1173
 
1174 224 jeremybenn
}       /* sim_verbose () */
1175 19 jeremybenn
 
1176 224 jeremybenn
 
1177 19 jeremybenn
/*---------------------------------------------------------------------------*/
1178
/*!Set the simulator debug message level
1179
 
1180
   Value must be in the range 0 (no messages) to 9. Values outside this range
1181
   are converted to the nearer end of the range with a warning.
1182
 
1183
   @param[in] val  The value to use
1184
   @param[in] dat  The config data structure (not used here)                 */
1185
/*---------------------------------------------------------------------------*/
1186 224 jeremybenn
static void
1187 19 jeremybenn
sim_debug (union param_val  val,
1188
           void            *dat)
1189
{
1190
  if (val.int_val < 0)
1191
    {
1192
      fprintf (stderr,
1193
               "Warning: Config debug value negative: 0 substituted\n");
1194
      config.sim.debug = 0;
1195
    }
1196
  else if (val.int_val > 9)
1197
    {
1198
      fprintf (stderr,
1199
               "Warning: Config debug value too large: 9 substituted\n");
1200
      config.sim.debug = 9;
1201
    }
1202
  else
1203
    {
1204
      config.sim.debug = val.int_val;
1205
    }
1206
}       /* sim_debug() */
1207
 
1208
 
1209 224 jeremybenn
/*---------------------------------------------------------------------------*/
1210
/*!Turn on profiling
1211
 
1212
   @param[in] val  Non-zero (TRUE) to turn on profiling, zero (FALSE) otherwise.
1213
   @param[in] dat  The config data structure (not used here)                 */
1214
/*---------------------------------------------------------------------------*/
1215
static void
1216
sim_profile (union param_val  val,
1217
             void            *dat)
1218 19 jeremybenn
{
1219
  config.sim.profile = val.int_val;
1220
 
1221 224 jeremybenn
}       /* sim_profile () */
1222
 
1223
 
1224
/*---------------------------------------------------------------------------*/
1225
/*!Specify the profiling file name.
1226
 
1227
   @param[in] val  The profiling file name
1228
   @param[in] dat  The config data structure (not used here)                 */
1229
/*---------------------------------------------------------------------------*/
1230
static void
1231
sim_prof_fn (union param_val  val,
1232
             void            *dat)
1233 19 jeremybenn
{
1234
  if (NULL != config.sim.prof_fn)
1235
    {
1236
      free (config.sim.prof_fn);
1237
    }
1238
 
1239
  config.sim.prof_fn = strdup(val.str_val);
1240
 
1241 224 jeremybenn
}       /* sim_prof_fn () */
1242
 
1243
 
1244
/*---------------------------------------------------------------------------*/
1245
/*!Turn on memory profiling
1246
 
1247
   @param[in] val  Non-zero (TRUE) to turn on memory profiling, zero (FALSE)
1248
                   otherwise.
1249
   @param[in] dat  The config data structure (not used here)                 */
1250
/*---------------------------------------------------------------------------*/
1251
static void
1252
sim_mprofile (union param_val  val,
1253
              void            *dat)
1254 19 jeremybenn
{
1255
  config.sim.mprofile = val.int_val;
1256
 
1257 224 jeremybenn
}       /* sim_mprofile () */
1258
 
1259
 
1260
/*---------------------------------------------------------------------------*/
1261
/*!Specify the memory profiling file name.
1262
 
1263
   @param[in] val  The memory profiling file name
1264
   @param[in] dat  The config data structure (not used here)                 */
1265
/*---------------------------------------------------------------------------*/
1266
static void
1267 19 jeremybenn
sim_mprof_fn (union param_val val, void *dat)
1268
{
1269
  if (NULL != config.sim.mprof_fn)
1270
    {
1271
      free (config.sim.mprof_fn);
1272
    }
1273
 
1274
  config.sim.mprof_fn = strdup (val.str_val);
1275
 
1276 224 jeremybenn
}       /* sim_mprof_fn () */
1277
 
1278
 
1279
/*---------------------------------------------------------------------------*/
1280
/*!Turn on execution tracking.
1281
 
1282
   @param[in] val  Non-zero (TRUE) to turn on tracking, zero (FALSE) otherwise.
1283
   @param[in] dat  The config data structure (not used here)                 */
1284
/*---------------------------------------------------------------------------*/
1285
static void
1286
sim_history (union param_val  val,
1287
             void            *dat)
1288 19 jeremybenn
{
1289
  config.sim.history = val.int_val;
1290
}
1291
 
1292 224 jeremybenn
 
1293
/*---------------------------------------------------------------------------*/
1294
/*!Record an execution log
1295
 
1296
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
1297
   @param[in] dat  The config data structure (not used here)                 */
1298
/*---------------------------------------------------------------------------*/
1299
static void
1300
sim_exe_log (union param_val  val,
1301
             void            *dat)
1302 19 jeremybenn
{
1303
  config.sim.exe_log = val.int_val;
1304
 
1305 224 jeremybenn
}       /* sim_exe_log () */
1306
 
1307 19 jeremybenn
/*---------------------------------------------------------------------------*/
1308
/*!Set the execution log type
1309
 
1310
   Value must be one of default, hardware, simple or software. Invalid values
1311
   are ignored with a warning.
1312
 
1313
   @param[in] val  The value to use
1314
   @param[in] dat  The config data structure (not used here)                 */
1315
/*---------------------------------------------------------------------------*/
1316 224 jeremybenn
static void
1317 19 jeremybenn
sim_exe_log_type (union param_val  val,
1318
                  void            *dat)
1319
{
1320
  if (strcasecmp (val.str_val, "default") == 0)
1321
    {
1322
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
1323
    }
1324
  else if (strcasecmp (val.str_val, "hardware") == 0)
1325
    {
1326
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
1327
    }
1328
  else if (strcasecmp (val.str_val, "simple") == 0)
1329
    {
1330
      config.sim.exe_log_type = EXE_LOG_SIMPLE;
1331
    }
1332
  else if (strcasecmp (val.str_val, "software") == 0)
1333
    {
1334
      config.sim.exe_log_type = EXE_LOG_SOFTWARE;
1335
    }
1336
  else
1337
    {
1338
      fprintf (stderr, "Warning: Execution log type %s invalid. Ignored",
1339
               val.str_val);
1340
    }
1341
}       /* sim_exe_log_type() */
1342
 
1343
 
1344 224 jeremybenn
/*---------------------------------------------------------------------------*/
1345
/*!Set the execution log start address
1346
 
1347
   Address at which to start logging.
1348
 
1349
   @param[in] val  The value to use
1350
   @param[in] dat  The config data structure (not used here)                 */
1351
/*---------------------------------------------------------------------------*/
1352
static void
1353
sim_exe_log_start (union param_val  val,
1354
                   void            *dat)
1355 19 jeremybenn
{
1356
  config.sim.exe_log_start = val.longlong_val;
1357
 
1358 224 jeremybenn
}       /* sim_exe_log_start () */
1359
 
1360
 
1361
/*---------------------------------------------------------------------------*/
1362
/*!Set the execution log end address
1363
 
1364
   Address at which to end logging.
1365
 
1366
   @param[in] val  The value to use
1367
   @param[in] dat  The config data structure (not used here)                 */
1368
/*---------------------------------------------------------------------------*/
1369
static void
1370
sim_exe_log_end (union param_val  val,
1371
                 void            *dat)
1372 19 jeremybenn
{
1373
  config.sim.exe_log_end = val.longlong_val;
1374
 
1375 224 jeremybenn
}       /* sim_exe_log_end () */
1376
 
1377
 
1378
/*---------------------------------------------------------------------------*/
1379
/*!Specify number of instruction between printing horizontal markers
1380
 
1381
   Control of log format
1382
 
1383
   @param[in] val  The value to use
1384
   @param[in] dat  The config data structure (not used here)                 */
1385
/*---------------------------------------------------------------------------*/
1386
static void
1387
sim_exe_log_marker (union param_val  val,
1388
                    void            *dat)
1389 19 jeremybenn
{
1390
  config.sim.exe_log_marker = val.int_val;
1391
 
1392 224 jeremybenn
}       /* sim_exe_log_marker () */
1393
 
1394
 
1395
/*---------------------------------------------------------------------------*/
1396
/*!Specify the execution log file name.
1397
 
1398
   @param[in] val  The execution log file name
1399
   @param[in] dat  The config data structure (not used here)                 */
1400
/*---------------------------------------------------------------------------*/
1401
static void
1402 19 jeremybenn
sim_exe_log_fn (union param_val val, void *dat)
1403
{
1404
  if (NULL != config.sim.exe_log_fn)
1405
    {
1406
      free (config.sim.exe_log_fn);
1407
    }
1408
 
1409
  config.sim.exe_log_fn = strdup (val.str_val);
1410
 
1411 224 jeremybenn
}       /* sim_exe_log_fn () */
1412
 
1413
 
1414
/*---------------------------------------------------------------------------*/
1415
/*!Turn on binary instruction logging
1416
 
1417
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
1418
   @param[in] dat  The config data structure (not used here)                 */
1419
/*---------------------------------------------------------------------------*/
1420
static void
1421 202 julius
sim_exe_bin_insn_log (union param_val val, void *dat)
1422
{
1423
  config.sim.exe_bin_insn_log = val.int_val;
1424
 
1425 224 jeremybenn
}       /* sim_exe_bin_insn_log () */
1426
 
1427
 
1428
/*---------------------------------------------------------------------------*/
1429
/*!Specify the binary instruction log file name.
1430
 
1431
   @param[in] val  The binary instruction log file name
1432
   @param[in] dat  The config data structure (not used here)                 */
1433
/*---------------------------------------------------------------------------*/
1434
static void
1435 202 julius
sim_exe_bin_insn_log_fn (union param_val val, void *dat)
1436
{
1437
  if (NULL != config.sim.exe_bin_insn_log_fn)
1438
    {
1439
      free (config.sim.exe_bin_insn_log_fn);
1440
    }
1441
 
1442
  config.sim.exe_bin_insn_log_fn = strdup (val.str_val);
1443
 
1444 224 jeremybenn
}       /* sim_exe_bin_insn_log_fn () */
1445 202 julius
 
1446
 
1447 19 jeremybenn
/*---------------------------------------------------------------------------*/
1448
/*!Set the clock cycle time.
1449
 
1450
   Value must be an integer followed by one of ps, ns, us or ms.
1451
 
1452
   If a valid time is not presented, the value is unchanged.
1453
 
1454
   @param[in] val  The value to use
1455
   @param[in] dat  The config data structure (not used here)                 */
1456
/*---------------------------------------------------------------------------*/
1457
void
1458
sim_clkcycle (union param_val  val,
1459
              void            *dat)
1460
{
1461
  int len = strlen (val.str_val);
1462
  int pos = len - 1;
1463
  long time;
1464
  if ((len < 2) || (val.str_val[pos--] != 's'))
1465
    {
1466
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
1467
               val.str_val);
1468
      return;
1469
    }
1470
 
1471
  switch (val.str_val[pos--])
1472
    {
1473
    case 'p':
1474
      time = 1;
1475
      break;
1476
    case 'n':
1477
      time = 1000;
1478
      break;
1479
    case 'u':
1480
      time = 1000000;
1481
      break;
1482
    case 'm':
1483
      time = 1000000000;
1484
      break;
1485
    default:
1486
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
1487
               val.str_val);
1488
      return;
1489
    }
1490
 
1491
  val.str_val[pos + 1] = 0;
1492
  time = time * atol (val.str_val);
1493
 
1494
  if (0 == time)
1495
    {
1496
      fprintf (stderr, "Warning: Clock cycle time of zero invalid: ignored\n");
1497
      return;
1498
    }
1499
 
1500
  config.sim.clkcycle_ps = time;
1501
 
1502
}       /* sim_clkcycle() */
1503
 
1504
 
1505
/*---------------------------------------------------------------------------*/
1506
/*!Register the functions to handle a section sim
1507
 
1508
   This section does not allocate dynamically a data structure holding its
1509
   config information. It's all in the global config.sim data
1510
   structure. Therefore it does not need a start and end function to
1511
   initialize default values (although it might be clearer to do so). The
1512
   default values are set in init_defconfig().
1513
 
1514
   New preferred parameter names are introduced (_file for filenames), but
1515
   the legacy names (_fn) are also present for backwards compatibility       */
1516
/*---------------------------------------------------------------------------*/
1517
static void
1518
reg_sim_sec ()
1519
{
1520
  struct config_section *sec = reg_config_sec ("sim", NULL, NULL);
1521
 
1522 224 jeremybenn
  reg_config_param (sec, "verbose",        PARAMT_INT,      sim_verbose);
1523
  reg_config_param (sec, "debug",          PARAMT_INT,      sim_debug);
1524
  reg_config_param (sec, "profile",        PARAMT_INT,      sim_profile);
1525
  reg_config_param (sec, "prof_file",      PARAMT_STR,      sim_prof_fn);
1526
  reg_config_param (sec, "prof_fn",        PARAMT_STR,      sim_prof_fn);
1527
  reg_config_param (sec, "mprofile",       PARAMT_INT,      sim_mprofile);
1528
  reg_config_param (sec, "mprof_file",     PARAMT_STR,      sim_mprof_fn);
1529
  reg_config_param (sec, "mprof_fn",       PARAMT_STR,      sim_mprof_fn);
1530
  reg_config_param (sec, "history",        PARAMT_INT,      sim_history);
1531
  reg_config_param (sec, "exe_log",        PARAMT_INT,      sim_exe_log);
1532
  reg_config_param (sec, "exe_log_type",   PARAMT_WORD,     sim_exe_log_type);
1533
  reg_config_param (sec, "exe_log_start",  PARAMT_LONGLONG, sim_exe_log_start);
1534
  reg_config_param (sec, "exe_log_end",    PARAMT_LONGLONG, sim_exe_log_end);
1535
  reg_config_param (sec, "exe_log_marker", PARAMT_INT,      sim_exe_log_marker);
1536
  reg_config_param (sec, "exe_log_file",   PARAMT_STR,      sim_exe_log_fn);
1537
  reg_config_param (sec, "exe_log_fn",     PARAMT_STR,      sim_exe_log_fn);
1538 19 jeremybenn
 
1539 224 jeremybenn
  reg_config_param (sec, "exe_bin_insn_log",      PARAMT_INT,
1540
                    sim_exe_bin_insn_log);
1541
  reg_config_param (sec, "exe_bin_insn_log_fn",   PARAMT_STR,
1542
                    sim_exe_bin_insn_log_fn);
1543
  reg_config_param (sec, "exe_bin_insn_log_file", PARAMT_STR,
1544
                    sim_exe_bin_insn_log_fn);
1545
 
1546
  reg_config_param (sec, "clkcycle",       PARAMT_WORD,     sim_clkcycle);
1547
 
1548 19 jeremybenn
}       /* reg_sim_sec() */
1549
 
1550
 
1551 224 jeremybenn
/*---------------------------------------------------------------------------*/
1552
/*!Register all the possible sections which we support.
1553
 
1554
   Each section type provides a registration function. This returns a struct
1555
   config_section, which in turn contains a list of config_params.           */
1556
/*---------------------------------------------------------------------------*/
1557 19 jeremybenn
void
1558 224 jeremybenn
reg_config_secs ()
1559 19 jeremybenn
{
1560
  reg_generic_sec ();           /* JPB */
1561
  reg_sim_sec ();
1562
  reg_cpu_sec ();
1563
  reg_pic_sec ();
1564
  reg_memory_sec ();
1565
  reg_mc_sec ();
1566
  reg_uart_sec ();
1567
  reg_dma_sec ();
1568
  reg_debug_sec ();
1569
  reg_vapi_sec ();
1570
  reg_ethernet_sec ();
1571
  reg_immu_sec ();
1572
  reg_dmmu_sec ();
1573
  reg_ic_sec ();
1574
  reg_dc_sec ();
1575
  reg_gpio_sec ();
1576
  reg_bpb_sec ();
1577
  reg_pm_sec ();
1578
  reg_vga_sec ();
1579
  reg_fb_sec ();
1580
  reg_kbd_sec ();
1581
  reg_ata_sec ();
1582
  reg_cuc_sec ();
1583
}
1584
 
1585
/* Utility for execution of set sim command.  */
1586
static int
1587
set_config (int argc, char **argv)
1588
{
1589 224 jeremybenn
  struct config_section *cur_section;
1590
  struct config_param *param;
1591 19 jeremybenn
 
1592
  if (argc < 2)
1593
    return 1;
1594
 
1595
  PRINTF ("sec:%s\n", argv[1]);
1596 224 jeremybenn
  cur_section = lookup_section (argv[1]);
1597 19 jeremybenn
 
1598 224 jeremybenn
  if (NULL == cur_section)
1599 19 jeremybenn
    return 1;
1600
 
1601
  if (argc < 3)
1602
    return 2;
1603
 
1604
  PRINTF ("item:%s\n", argv[2]);
1605
  {
1606 224 jeremybenn
    for (param = cur_section->params; param; param = param->next)
1607
      if (strcmp (param->name, argv[2]) == 0)
1608 19 jeremybenn
        {
1609
          break;
1610
        }
1611 224 jeremybenn
    if (!param)
1612 19 jeremybenn
      return 2;
1613
 
1614
    /* Parse parameter value */
1615 224 jeremybenn
    if (param->type)
1616 19 jeremybenn
      {
1617
        if (argc < 4)
1618
          return 3;
1619
        PRINTF ("params:%s\n", argv[3]);
1620
      }
1621
 
1622 224 jeremybenn
    set_config_param (cur_section, param, argv[3]);
1623 19 jeremybenn
  }
1624
  return 0;
1625
}
1626
 
1627
/* Executes set sim command, displays error.  */
1628
void
1629
set_config_command (int argc, char **argv)
1630
{
1631
  struct config_section *cur;
1632 224 jeremybenn
  struct config_param *param;
1633 19 jeremybenn
 
1634
  switch (set_config (argc, argv))
1635
    {
1636
    case 1:
1637
      PRINTF
1638
        ("Invalid or missing section name.  One of valid sections must be specified:\n");
1639 224 jeremybenn
      for (cur = section_master_list; cur; cur = cur->next)
1640 19 jeremybenn
        PRINTF ("%s ", cur->name);
1641
      PRINTF ("\n");
1642
      break;
1643
    case 2:
1644 224 jeremybenn
      cur = lookup_section (argv[1]);
1645 19 jeremybenn
      PRINTF
1646
        ("Invalid or missing item name.  One of valid items must be specified:\n");
1647 224 jeremybenn
      for (param = cur->params; param;
1648
           param = param->next)
1649
        PRINTF ("%s ", param->name);
1650 19 jeremybenn
      PRINTF ("\n");
1651
      break;
1652
    case 3:
1653
      PRINTF ("Invalid parameters specified.\n");
1654
      break;
1655
    }
1656
}

powered by: WebSVN 2.1.0

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