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

Subversion Repositories openrisc

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

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

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

powered by: WebSVN 2.1.0

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