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

Subversion Repositories openrisc

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

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

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

powered by: WebSVN 2.1.0

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