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

Subversion Repositories openrisc

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

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
#include "misc.h"
65
#include "argtable2.h"
66
 
67
 
68
struct config config;
69
struct runtime runtime;
70
 
71
struct config_section *cur_section;
72
 
73
struct config_section *sections = NULL;
74
 
75
/* Forward declarations */
76
static void read_script_file (const char *filename);
77
 
78
 
79
 
80
/*---------------------------------------------------------------------------*/
81
/*!Set default configuration parameters for fixed components
82
 
83
   These values are held in the global config variable. Parameter orders
84
   match the order in the corresponding section registration function and
85
   documentation.
86
 
87
   Also set some starting values for runtime elements.                       */
88
/*---------------------------------------------------------------------------*/
89
void
90
init_defconfig ()
91
{
92
  int  set_bits;                /* Temporaries for computing bit fields */
93
  int  way_bits;
94
 
95
  memset (&config, 0, sizeof (config));
96
 
97
  /* External linkage disabled here. */
98
  config.ext.class_ptr = NULL;
99
  config.ext.read_up   = NULL;
100
  config.ext.write_up  = NULL;
101
 
102
  /* Sim */
103
  config.sim.verbose        = 0;
104
  config.sim.debug          = 0;
105
  config.sim.profile        = 0;
106
  config.sim.prof_fn        = strdup ("sim.profile");
107
  config.sim.mprofile       = 0;
108
  config.sim.mprof_fn       = strdup ("sim.mprofile");
109
  config.sim.history        = 0;
110
  config.sim.exe_log        = 0;
111
  config.sim.exe_log_type   = EXE_LOG_HARDWARE;
112
  config.sim.exe_log_start  = 0;
113
  config.sim.exe_log_end    = 0;
114
  config.sim.exe_log_marker = 0;
115
  config.sim.exe_log_fn     = strdup ("executed.log");
116
  config.sim.clkcycle_ps    = 4000;     /* 4000 for 4ns (250MHz) */
117
 
118
  /* VAPI */
119
  config.vapi.enabled        = 0;
120
  config.vapi.server_port    = 50000;
121
  config.vapi.log_enabled    = 0;
122
  config.vapi.hide_device_id = 0;
123
  config.vapi.vapi_fn        = strdup ("vapi.log");
124
 
125
  /* CUC */
126
  config.cuc.calling_convention = 1;
127
  config.cuc.enable_bursts      = 1;
128
  config.cuc.no_multicycle      = 1;
129
  config.cuc.memory_order       = MO_STRONG;
130
  config.cuc.timings_fn         = strdup ("virtex.tim");
131
 
132
  /* CPU */
133
  cpu_state.sprs[SPR_VR]      = 0;
134
  cpu_state.sprs[SPR_UPR]     = SPR_UPR_UP | SPR_UPR_TTP;
135
  cpu_state.sprs[SPR_SR]      = SPR_SR_FO  | SPR_SR_SM;
136
  cpu_state.sprs[SPR_CPUCFGR] = SPR_CPUCFGR_OB32S;
137
  config.cpu.superscalar      = 0;
138
  config.cpu.hazards          = 0;
139
  config.cpu.dependstats      = 0;
140
  config.cpu.sbuf_len         = 0;
141
 
142
  /* Data cache (IC is set dynamically). Also set relevant SPR bits */
143
  config.dc.enabled         = 0;
144
  config.dc.nsets           = 1;
145
  config.dc.nways           = 1;
146
  config.dc.blocksize       = 1;
147
  config.dc.ustates         = 2;
148
  config.dc.load_hitdelay   = 2;
149
  config.dc.load_missdelay  = 2;
150
  config.dc.store_hitdelay  = 0;
151
  config.dc.store_missdelay = 0;
152
 
153
  if (config.dc.enabled)
154
    {
155
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DCP;
156
    }
157
  else
158
    {
159
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DCP;
160
    }
161
 
162
  set_bits = log2_int (config.dc.nsets);
163
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCS;
164
  cpu_state.sprs[SPR_DCCFGR] |= set_bits << SPR_DCCFGR_NCS_OFF;
165
 
166
  way_bits = log2_int (config.dc.nways);
167
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCW;
168
  cpu_state.sprs[SPR_DCCFGR] |= way_bits << SPR_DCCFGR_NCW_OFF;
169
 
170
  if (MIN_DC_BLOCK_SIZE == config.dc.blocksize)
171
    {
172
      cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_CBS;
173
    }
174
  else
175
    {
176
      cpu_state.sprs[SPR_DCCFGR] |= SPR_DCCFGR_CBS;
177
    }
178
 
179
  /* Power management */
180
  config.pm.enabled = 0;
181
 
182
  if (config.pm.enabled)
183
    {
184
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PMP;
185
    }
186
  else
187
    {
188
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PMP;
189
    }
190
 
191
  /* Programmable Interrupt Controller */
192
  config.pic.enabled      = 0;
193
  config.pic.edge_trigger = 1;
194
 
195
  if (config.pic.enabled)
196
    {
197
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PICP;
198
    }
199
  else
200
    {
201
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PICP;
202
    }
203
 
204
  /* Branch Prediction */
205
  config.bpb.enabled     = 0;
206
  config.bpb.btic        = 0;
207
  config.bpb.sbp_bnf_fwd = 0;
208
  config.bpb.sbp_bf_fwd  = 0;
209
  config.bpb.missdelay   = 0;
210
  config.bpb.hitdelay    = 0;
211
 
212
  /* Debug */
213
  config.debug.enabled     = 0;
214
  config.debug.gdb_enabled = 0;
215
  config.debug.rsp_enabled = 0;
216
  config.debug.server_port = 51000;
217
  config.debug.rsp_port    = 51000;
218
  config.debug.vapi_id     = 0;
219
 
220
  cpu_state.sprs[SPR_DCFGR] = SPR_DCFGR_WPCI |
221
                              MATCHPOINTS_TO_NDP (MAX_MATCHPOINTS);
222
 
223
  if (config.debug.enabled)
224
    {
225
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DUP;
226
    }
227
  else
228
    {
229
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DUP;
230
    }
231
 
232
  /* Configure runtime */
233
  memset (&runtime, 0, sizeof (runtime));
234
 
235
  /* Sim */
236
  runtime.sim.fexe_log              = NULL;
237
  runtime.sim.iprompt               = 0;
238
  runtime.sim.fprof                 = NULL;
239
  runtime.sim.fmprof                = NULL;
240
  runtime.sim.fout                  = stdout;
241
 
242
  /* NPC state. Set to 1 when NPC is changed while the processor is stalled. */
243
  cpu_state.npc_not_valid = 0;
244
 
245
  /* VAPI */
246
  runtime.vapi.vapi_file = NULL;
247
  runtime.vapi.enabled   = 0;
248
 
249
}       /* init_defconfig() */
250
 
251
 
252
/*---------------------------------------------------------------------------*/
253
/*! Parse the arguments for the standalone simulator
254
 
255
    Updated by Jeremy Bennett to use argtable2.
256
 
257
    @param[in] argc  Number of command args
258
    @param[in] argv  Vector of the command args
259
 
260
    @return  0 on success, 1 on failure                                      */
261
/*---------------------------------------------------------------------------*/
262
int
263
parse_args (int argc, char *argv[])
264
{
265
  struct arg_lit *vercop;
266
  struct arg_lit *help;
267
  struct arg_file *cfg_file;
268
  struct arg_lit *nosrv;
269
  struct arg_int *srv;
270
  struct arg_str *dbg;
271
  struct arg_lit *command;
272
  struct arg_lit *strict_npc;
273
  struct arg_lit *profile;
274
  struct arg_lit *mprofile;
275
  struct arg_file *load_file;
276
  struct arg_end *end;
277
 
278
  void *argtab[12];
279
  int nerrors;
280
 
281
  /* Specify each argument, with fall back values */
282
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
283
  help = arg_lit0 ("h", "help", "print this help message");
284
  cfg_file = arg_file0 ("f", "file", "<file>",
285
                        "config file (default \"sim.cfg\")");
286
  cfg_file->filename[0] = "sim.cfg";
287
  nosrv = arg_lit0 (NULL, "nosrv", "do not launch JTAG proxy server");
288
  srv = arg_int0 (NULL, "srv", "<n>", "port number (default random)");
289
  srv->ival[0] = rand () % (65536 - 49152) + 49152;
290
  srv->hdr.flag |= ARG_HASOPTVALUE;
291
  dbg = arg_str0 ("d", "debug-config", "<str>", "Debug config string");
292
  command = arg_lit0 ("i", "interactive", "launch interactive prompt");
293
  strict_npc = arg_lit0 (NULL, "strict-npc", "setting NPC flushes pipeline");
294
  profile = arg_lit0 (NULL, "enable-profile", "enable profiling");
295
  mprofile = arg_lit0 (NULL, "enable-mprofile", "enable memory profiling");
296
  load_file = arg_file0 (NULL, NULL, "<file>", "OR32 executable");
297
  end = arg_end (20);
298
 
299
  /* Set up the argument table */
300
  argtab[ 0] = vercop;
301
  argtab[ 1] = help;
302
  argtab[ 2] = cfg_file;
303
  argtab[ 3] = nosrv;
304
  argtab[ 4] = srv;
305
  argtab[ 5] = dbg;
306
  argtab[ 6] = command;
307
  argtab[ 7] = strict_npc;
308
  argtab[ 8] = profile;
309
  argtab[ 9] = mprofile;
310
  argtab[10] = load_file;
311
  argtab[11] = end;
312
 
313
  /* Parse */
314
  nerrors = arg_parse (argc, argv, argtab);
315
 
316
  /* Special case here is if help or version is specified, we ignore any other
317
     errors and just print the help or version information and then give up. */
318
  if (vercop->count > 0)
319
    {
320
      PRINTF ("OpenRISC 1000 Architectural Simulator, version %s\n",
321
              PACKAGE_VERSION);
322
 
323
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
324
      return 1;
325
    }
326
 
327
  if (help->count > 0)
328
    {
329
      printf ("Usage:\n  %s ", argv[0]);
330
      arg_print_syntax (stdout, argtab, "\n\n");
331
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
332
 
333
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
334
      return 1;
335
    }
336
 
337
  /* Deal with any errors */
338
  if (0 != nerrors)
339
    {
340
      arg_print_errors (stderr, end, "or1ksim");
341
      printf ("\nUsage:\n  %s ", argv[0]);
342
      arg_print_syntaxv (stderr, argtab, "\n");
343
 
344
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
345
      return 1;
346
    }
347
 
348
  /* Process config file next, so any other command args will override */
349
  if (0 == cfg_file->count)
350
    {
351
      fprintf (stderr,
352
               "Warning: No config file given, default configuration used\n");
353
    }
354
 
355
  read_script_file (cfg_file->filename[0]);
356
 
357
 
358
  /* Remote debug server */
359
  if (nosrv->count > 0)
360
    {
361
      if (srv->count > 0)
362
        {
363
          fprintf (stderr,
364
                   "%s: cannot specify --nosrv with --srv. Ignoring --nosrv\n",
365
                   argv[0]);
366
        }
367
      else
368
        {
369
          config.debug.enabled = 0;
370
          config.debug.gdb_enabled = 0;
371
        }
372
    }
373
 
374
  if (srv->count > 0)
375
    {
376
      config.debug.enabled = 1;
377
      config.debug.gdb_enabled = 1;
378
      config.debug.server_port = srv->ival[0];
379
    }
380
 
381
  /* Runtime debug messages */
382
  if (dbg->count > 0)
383
    {
384
      parse_dbchs (dbg->sval[0]);
385
    }
386
 
387
  /* Interactive operation */
388
  runtime.sim.iprompt = command->count;
389
 
390
  /* Request for strict NPC behavior (flush the pipeline on change) */
391
  config.sim.strict_npc = strict_npc->count;
392
 
393
  /* Profiling requests */
394
  config.sim.profile = profile->count;
395
  config.sim.mprofile = mprofile->count;
396
 
397
  /* Executable file */
398
  if (load_file->count > 0)
399
    {
400
      runtime.sim.filename = strdup (load_file->filename[0]);
401
    }
402
  else
403
    {
404
      runtime.sim.filename = NULL;
405
    }
406
 
407
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
408
  return 0;                      /* Success */
409
 
410
}       /* parse_args() */
411
 
412
 
413
/*---------------------------------------------------------------------------*/
414
/*!Print the current configuration                                           */
415
/*---------------------------------------------------------------------------*/
416
void
417
print_config ()
418
{
419
  if (config.sim.verbose)
420
    {
421
      char temp[20];
422
      PRINTF ("Verbose on, ");
423
      if (config.sim.debug)
424
        PRINTF ("simdebug on, ");
425
      else
426
        PRINTF ("simdebug off, ");
427
      if (runtime.sim.iprompt)
428
        PRINTF ("interactive prompt on\n");
429
      else
430
        PRINTF ("interactive prompt off\n");
431
 
432
      PRINTF ("Machine initialization...\n");
433
      generate_time_pretty (temp, config.sim.clkcycle_ps);
434
      PRINTF ("Clock cycle: %s\n", temp);
435
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_DCP)
436
        PRINTF ("Data cache present.\n");
437
      else
438
        PRINTF ("No data cache.\n");
439
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP)
440
        PRINTF ("Insn cache tag present.\n");
441
      else
442
        PRINTF ("No instruction cache.\n");
443
      if (config.bpb.enabled)
444
        PRINTF ("BPB simulation on.\n");
445
      else
446
        PRINTF ("BPB simulation off.\n");
447
      if (config.bpb.btic)
448
        PRINTF ("BTIC simulation on.\n");
449
      else
450
        PRINTF ("BTIC simulation off.\n");
451
    }
452
}
453
 
454
struct config_param
455
{
456
  char *name;
457
  enum param_t type;
458
  void (*func) (union param_val, void *dat);
459
  struct config_param *next;
460
};
461
 
462
void
463
base_include (union param_val val, void *dat)
464
{
465
  read_script_file (val.str_val);
466
  cur_section = NULL;
467
}
468
 
469
/*---------------------------------------------[ Simulator configuration ]---*/
470
 
471
 
472
void
473
sim_verbose (union param_val val, void *dat)
474
{
475
  config.sim.verbose = val.int_val;
476
}
477
 
478
 
479
/*---------------------------------------------------------------------------*/
480
/*!Set the simulator debug message level
481
 
482
   Value must be in the range 0 (no messages) to 9. Values outside this range
483
   are converted to the nearer end of the range with a warning.
484
 
485
   @param[in] val  The value to use
486
   @param[in] dat  The config data structure (not used here)                 */
487
/*---------------------------------------------------------------------------*/
488
void
489
sim_debug (union param_val  val,
490
           void            *dat)
491
{
492
  if (val.int_val < 0)
493
    {
494
      fprintf (stderr,
495
               "Warning: Config debug value negative: 0 substituted\n");
496
      config.sim.debug = 0;
497
    }
498
  else if (val.int_val > 9)
499
    {
500
      fprintf (stderr,
501
               "Warning: Config debug value too large: 9 substituted\n");
502
      config.sim.debug = 9;
503
    }
504
  else
505
    {
506
      config.sim.debug = val.int_val;
507
    }
508
}       /* sim_debug() */
509
 
510
 
511
void
512
sim_profile (union param_val val, void *dat)
513
{
514
  config.sim.profile = val.int_val;
515
}
516
 
517
void
518
sim_prof_fn (union param_val val, void *dat)
519
{
520
  if (NULL != config.sim.prof_fn)
521
    {
522
      free (config.sim.prof_fn);
523
    }
524
 
525
  config.sim.prof_fn = strdup(val.str_val);
526
}
527
 
528
void
529
sim_mprofile (union param_val val, void *dat)
530
{
531
  config.sim.mprofile = val.int_val;
532
}
533
 
534
void
535
sim_mprof_fn (union param_val val, void *dat)
536
{
537
  if (NULL != config.sim.mprof_fn)
538
    {
539
      free (config.sim.mprof_fn);
540
    }
541
 
542
  config.sim.mprof_fn = strdup (val.str_val);
543
}
544
 
545
void
546
sim_history (union param_val val, void *dat)
547
{
548
  config.sim.history = val.int_val;
549
}
550
 
551
void
552
sim_exe_log (union param_val val, void *dat)
553
{
554
  config.sim.exe_log = val.int_val;
555
}
556
 
557
/*---------------------------------------------------------------------------*/
558
/*!Set the execution log type
559
 
560
   Value must be one of default, hardware, simple or software. Invalid values
561
   are ignored with a warning.
562
 
563
   @param[in] val  The value to use
564
   @param[in] dat  The config data structure (not used here)                 */
565
/*---------------------------------------------------------------------------*/
566
void
567
sim_exe_log_type (union param_val  val,
568
                  void            *dat)
569
{
570
  if (strcasecmp (val.str_val, "default") == 0)
571
    {
572
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
573
    }
574
  else if (strcasecmp (val.str_val, "hardware") == 0)
575
    {
576
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
577
    }
578
  else if (strcasecmp (val.str_val, "simple") == 0)
579
    {
580
      config.sim.exe_log_type = EXE_LOG_SIMPLE;
581
    }
582
  else if (strcasecmp (val.str_val, "software") == 0)
583
    {
584
      config.sim.exe_log_type = EXE_LOG_SOFTWARE;
585
    }
586
  else
587
    {
588
      fprintf (stderr, "Warning: Execution log type %s invalid. Ignored",
589
               val.str_val);
590
    }
591
}       /* sim_exe_log_type() */
592
 
593
 
594
void
595
sim_exe_log_start (union param_val val, void *dat)
596
{
597
  config.sim.exe_log_start = val.longlong_val;
598
}
599
 
600
void
601
sim_exe_log_end (union param_val val, void *dat)
602
{
603
  config.sim.exe_log_end = val.longlong_val;
604
}
605
 
606
void
607
sim_exe_log_marker (union param_val val, void *dat)
608
{
609
  config.sim.exe_log_marker = val.int_val;
610
}
611
 
612
void
613
sim_exe_log_fn (union param_val val, void *dat)
614
{
615
  if (NULL != config.sim.exe_log_fn)
616
    {
617
      free (config.sim.exe_log_fn);
618
    }
619
 
620
  config.sim.exe_log_fn = strdup (val.str_val);
621
}
622
 
623
/*---------------------------------------------------------------------------*/
624
/*!Set the clock cycle time.
625
 
626
   Value must be an integer followed by one of ps, ns, us or ms.
627
 
628
   If a valid time is not presented, the value is unchanged.
629
 
630
   @param[in] val  The value to use
631
   @param[in] dat  The config data structure (not used here)                 */
632
/*---------------------------------------------------------------------------*/
633
void
634
sim_clkcycle (union param_val  val,
635
              void            *dat)
636
{
637
  int len = strlen (val.str_val);
638
  int pos = len - 1;
639
  long time;
640
  if ((len < 2) || (val.str_val[pos--] != 's'))
641
    {
642
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
643
               val.str_val);
644
      return;
645
    }
646
 
647
  switch (val.str_val[pos--])
648
    {
649
    case 'p':
650
      time = 1;
651
      break;
652
    case 'n':
653
      time = 1000;
654
      break;
655
    case 'u':
656
      time = 1000000;
657
      break;
658
    case 'm':
659
      time = 1000000000;
660
      break;
661
    default:
662
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
663
               val.str_val);
664
      return;
665
    }
666
 
667
  val.str_val[pos + 1] = 0;
668
  time = time * atol (val.str_val);
669
 
670
  if (0 == time)
671
    {
672
      fprintf (stderr, "Warning: Clock cycle time of zero invalid: ignored\n");
673
      return;
674
    }
675
 
676
  config.sim.clkcycle_ps = time;
677
 
678
}       /* sim_clkcycle() */
679
 
680
 
681
/*---------------------------------------------------------------------------*/
682
/*!Register the functions to handle a section sim
683
 
684
   This section does not allocate dynamically a data structure holding its
685
   config information. It's all in the global config.sim data
686
   structure. Therefore it does not need a start and end function to
687
   initialize default values (although it might be clearer to do so). The
688
   default values are set in init_defconfig().
689
 
690
   New preferred parameter names are introduced (_file for filenames), but
691
   the legacy names (_fn) are also present for backwards compatibility       */
692
/*---------------------------------------------------------------------------*/
693
static void
694
reg_sim_sec ()
695
{
696
  struct config_section *sec = reg_config_sec ("sim", NULL, NULL);
697
 
698
  reg_config_param (sec, "verbose",        paramt_int,      sim_verbose);
699
  reg_config_param (sec, "debug",          paramt_int,      sim_debug);
700
  reg_config_param (sec, "profile",        paramt_int,      sim_profile);
701
  reg_config_param (sec, "prof_file",      paramt_str,      sim_prof_fn);
702
  reg_config_param (sec, "prof_fn",        paramt_str,      sim_prof_fn);
703
  reg_config_param (sec, "mprofile",       paramt_int,      sim_mprofile);
704
  reg_config_param (sec, "mprof_file",     paramt_str,      sim_mprof_fn);
705
  reg_config_param (sec, "mprof_fn",       paramt_str,      sim_mprof_fn);
706
  reg_config_param (sec, "history",        paramt_int,      sim_history);
707
  reg_config_param (sec, "exe_log",        paramt_int,      sim_exe_log);
708
  reg_config_param (sec, "exe_log_type",   paramt_word,     sim_exe_log_type);
709
  reg_config_param (sec, "exe_log_start",  paramt_longlong, sim_exe_log_start);
710
  reg_config_param (sec, "exe_log_end",    paramt_longlong, sim_exe_log_end);
711
  reg_config_param (sec, "exe_log_marker", paramt_int,      sim_exe_log_marker);
712
  reg_config_param (sec, "exe_log_file",   paramt_str,      sim_exe_log_fn);
713
  reg_config_param (sec, "exe_log_fn",     paramt_str,      sim_exe_log_fn);
714
  reg_config_param (sec, "clkcycle",       paramt_word,     sim_clkcycle);
715
 
716
}       /* reg_sim_sec() */
717
 
718
 
719
void
720
reg_config_secs (void)
721
{
722
  reg_config_param (reg_config_sec ("base", NULL, NULL), "include",
723
                    paramt_str, base_include);
724
 
725
  reg_generic_sec ();           /* JPB */
726
  reg_sim_sec ();
727
  reg_cpu_sec ();
728
  reg_pic_sec ();
729
  reg_memory_sec ();
730
  reg_mc_sec ();
731
  reg_uart_sec ();
732
  reg_dma_sec ();
733
  reg_debug_sec ();
734
  reg_vapi_sec ();
735
  reg_ethernet_sec ();
736
  reg_immu_sec ();
737
  reg_dmmu_sec ();
738
  reg_ic_sec ();
739
  reg_dc_sec ();
740
  reg_gpio_sec ();
741
  reg_bpb_sec ();
742
  reg_pm_sec ();
743
  reg_vga_sec ();
744
  reg_fb_sec ();
745
  reg_kbd_sec ();
746
  reg_ata_sec ();
747
  reg_cuc_sec ();
748
}
749
 
750
void
751
reg_config_param (struct config_section *sec, const char *param,
752
                  enum param_t type,
753
                  void (*param_cb) (union param_val, void *))
754
{
755
  struct config_param *new = malloc (sizeof (struct config_param));
756
 
757
  if (!new)
758
    {
759
      fprintf (stderr, "Out-of-memory\n");
760
      exit (1);
761
    }
762
 
763
  if (!(new->name = strdup (param)))
764
    {
765
      fprintf (stderr, "Out-of-memory\n");
766
      exit (1);
767
    }
768
 
769
  new->func = param_cb;
770
  new->type = type;
771
 
772
  new->next = sec->params;
773
  sec->params = new;
774
}
775
 
776
struct config_section *
777
reg_config_sec (const char *section,
778
                void *(*sec_start) (void), void (*sec_end) (void *))
779
{
780
  struct config_section *new = malloc (sizeof (struct config_section));
781
 
782
  if (!new)
783
    {
784
      fprintf (stderr, "Out-of-memory\n");
785
      exit (1);
786
    }
787
 
788
  if (!(new->name = strdup (section)))
789
    {
790
      fprintf (stderr, "Out-of-memory\n");
791
      exit (1);
792
    }
793
 
794
  new->next = sections;
795
  new->sec_start = sec_start;
796
  new->sec_end = sec_end;
797
  new->params = NULL;
798
 
799
  sections = new;
800
 
801
  return new;
802
}
803
 
804
static void
805
switch_param (char *param, struct config_param *cur_param)
806
{
807
  char *end_p;
808
  union param_val val;
809
 
810
  /* Skip over an = sign if it exists */
811
  if (*param == '=')
812
    {
813
      param++;
814
      while (*param && isspace (*param))
815
        param++;
816
    }
817
 
818
  switch (cur_param->type)
819
    {
820
    case paramt_int:
821
      val.int_val = strtol (param, NULL, 0);
822
      break;
823
    case paramt_longlong:
824
      val.longlong_val = strtoll (param, NULL, 0);
825
      break;
826
    case paramt_addr:
827
      val.addr_val = strtoul (param, NULL, 0);
828
      break;
829
    case paramt_str:
830
      if (*param != '"')
831
        {
832
          fprintf (stderr,
833
                   "Warning: String value for parameter expected: ignored\n");
834
          return;
835
        }
836
 
837
      param++;
838
      end_p = param;
839
      while (*end_p && (*end_p != '"'))
840
        end_p++;
841
      *end_p = '\0';
842
      val.str_val = param;
843
      break;
844
    case paramt_word:
845
      end_p = param;
846
      while (*end_p && !isspace (*end_p))
847
        end_p++;
848
      *end_p = '\0';
849
      val.str_val = param;
850
      break;
851
    case paramt_none:
852
      break;
853
    }
854
 
855
  cur_param->func (val, cur_section->dat);
856
}
857
 
858
/* Read environment from a script file. Does not fail - assumes default configuration instead.
859
   The syntax of script file is:
860
   param = value
861
   section x
862
     data
863
     param = value
864
   end
865
 
866
   Example:
867
   section mc
868
     memory_table_file = sim.mem
869
     enable = 1
870
     POC = 0x47892344
871
   end
872
 
873
 */
874
 
875
static void
876
read_script_file (const char *filename)
877
{
878
  FILE *f;
879
  char *home = getenv ("HOME");
880
  char ctmp[STR_SIZE];
881
  int local = 1;
882
  cur_section = NULL;
883
 
884
  sprintf (ctmp, "%s/.or1k/%s", home, filename);
885
  if ((f = fopen (filename, "rt")) || (home && (f = fopen (ctmp, "rt"))))
886
    {
887
      if (config.sim.verbose)
888
        PRINTF ("Reading script file from '%s'...\n",
889
                local ? filename : ctmp);
890
 
891
      while (!feof (f))
892
        {
893
          char param[STR_SIZE];
894
          if (fscanf (f, "%s ", param) != 1)
895
            break;
896
          /* Is this a section? */
897
          if (strcmp (param, "section") == 0)
898
            {
899
              struct config_section *cur;
900
              cur_section = NULL;
901
              if (fscanf (f, "%s\n", param) != 1)
902
                {
903
                  fprintf (stderr, "%s: ERROR: Section name required.\n",
904
                           local ? filename : ctmp);
905
                  exit (1);
906
                }
907
              for (cur = sections; cur; cur = cur->next)
908
                if (strcmp (cur->name, param) == 0)
909
                  {
910
                    cur_section = cur;
911
                    break;
912
                  }
913
              if (!cur)
914
                {
915
                  fprintf (stderr,
916
                           "Warning: Unknown config section: %s; ignoring.\n",
917
                           param);
918
                  /* just skip section */
919
                  while (fscanf (f, "%s\n", param) == 1
920
                         && strcmp (param, "end"));
921
                }
922
              else
923
                {
924
                  cur->dat = NULL;
925
                  if (cur->sec_start)
926
                    cur->dat = cur->sec_start ();
927
                }
928
            }
929
          else if (strcmp (param, "end") == 0)
930
            {
931
              if (cur_section->sec_end)
932
                cur_section->sec_end (cur_section->dat);
933
              cur_section = NULL;
934
            }
935
          else if (strncmp (param, "/*", 2) == 0)
936
            {
937
              char c0 = 0, c1 = 0;
938
              while (c0 != '*' || c1 != '/')
939
                {
940
                  c0 = c1;
941
                  c1 = fgetc (f);
942
                  if (feof (f))
943
                    {
944
                      fprintf (stderr, "%s: ERROR: Comment reached EOF.\n",
945
                               local ? filename : ctmp);
946
                      exit (1);
947
                    }
948
                }
949
            }
950
          else
951
            {
952
              struct config_param *cur_param;
953
              char *cur_p;
954
              for (cur_param = cur_section->params; cur_param;
955
                   cur_param = cur_param->next)
956
                if (strcmp (cur_param->name, param) == 0)
957
                  {
958
                    break;
959
                  }
960
              if (!cur_param)
961
                {
962
                  fprintf (stderr, "Warning: Invalid parameter: %s; ignored\n",
963
                           param);
964
                  while (fgetc (f) != '\n' || feof (f));
965
                  continue;
966
                }
967
 
968
              if (cur_param->type == paramt_none)
969
                continue;
970
 
971
              /* Parse parameter value */
972
              cur_p = fgets (param, STR_SIZE, f);
973
 
974
              while (*cur_p && isspace (*cur_p))
975
                cur_p++;
976
 
977
              switch_param (cur_p, cur_param);
978
            }
979
        }
980
      fclose (f);
981
    }
982
  else if (config.sim.verbose)
983
    fprintf (stderr,
984
             "Warning: Cannot read script file from '%s' of '%s'.\n",
985
             filename, ctmp);
986
}
987
 
988
/* Utility for execution of set sim command.  */
989
static int
990
set_config (int argc, char **argv)
991
{
992
  struct config_section *cur;
993
  struct config_param *cur_param;
994
 
995
  if (argc < 2)
996
    return 1;
997
 
998
  PRINTF ("sec:%s\n", argv[1]);
999
  cur_section = NULL;
1000
  for (cur = sections; cur; cur = cur->next)
1001
    if (strcmp (cur->name, argv[1]) == 0)
1002
      {
1003
        cur_section = cur;
1004
        break;
1005
      }
1006
 
1007
  if (!cur_section)
1008
    return 1;
1009
 
1010
  if (argc < 3)
1011
    return 2;
1012
 
1013
  PRINTF ("item:%s\n", argv[2]);
1014
  {
1015
    for (cur_param = cur->params; cur_param; cur_param = cur_param->next)
1016
      if (strcmp (cur_param->name, argv[2]) == 0)
1017
        {
1018
          break;
1019
        }
1020
    if (!cur_param)
1021
      return 2;
1022
 
1023
    /* Parse parameter value */
1024
    if (cur_param->type)
1025
      {
1026
        if (argc < 4)
1027
          return 3;
1028
        PRINTF ("params:%s\n", argv[3]);
1029
      }
1030
 
1031
    switch_param (argv[3], cur_param);
1032
  }
1033
  return 0;
1034
}
1035
 
1036
/* Executes set sim command, displays error.  */
1037
void
1038
set_config_command (int argc, char **argv)
1039
{
1040
  struct config_section *cur;
1041
  struct config_param *cur_param;
1042
 
1043
  switch (set_config (argc, argv))
1044
    {
1045
    case 1:
1046
      PRINTF
1047
        ("Invalid or missing section name.  One of valid sections must be specified:\n");
1048
      for (cur = sections; cur; cur = cur->next)
1049
        PRINTF ("%s ", cur->name);
1050
      PRINTF ("\n");
1051
      break;
1052
    case 2:
1053
      PRINTF
1054
        ("Invalid or missing item name.  One of valid items must be specified:\n");
1055
      for (cur_param = cur_section->params; cur_param;
1056
           cur_param = cur_param->next)
1057
        PRINTF ("%s ", cur_param->name);
1058
      PRINTF ("\n");
1059
      break;
1060
    case 3:
1061
      PRINTF ("Invalid parameters specified.\n");
1062
      break;
1063
    }
1064
}

powered by: WebSVN 2.1.0

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