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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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