2 const char COPYRIGHT
[] =
3 "Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)";
6 * This source code is free software; you can redistribute it
7 * and/or modify it in source code form under the terms of the GNU
8 * General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
25 " This program is free software; you can redistribute it and/or modify\n"
26 " it under the terms of the GNU General Public License as published by\n"
27 " the Free Software Foundation; either version 2 of the License, or\n"
28 " (at your option) any later version.\n"
30 " This program is distributed in the hope that it will be useful,\n"
31 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
32 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
33 " GNU General Public License for more details.\n"
35 " You should have received a copy of the GNU General Public License\n"
36 " along with this program; if not, write to the Free Software\n"
37 " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
49 #if defined(HAVE_TIMES)
50 # include <sys/times.h>
52 #if defined(HAVE_GETOPT_H)
56 # include "parse_api.h"
59 # include "compiler.h"
60 # include "discipline.h"
62 #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
63 extern "C" int getopt(int argc
, char*argv
[], const char*fmt
);
64 extern "C" int optind
;
65 extern "C" const char*optarg
;
68 #if defined(__CYGWIN32__) && !defined(HAVE_GETOPT_H)
69 extern "C" int getopt(int argc
, char*argv
[], const char*fmt
);
70 extern "C" int optind
;
71 extern "C" const char*optarg
;
74 /* Count errors detected in flag processing. */
75 unsigned flag_errors
= 0;
77 const char VERSION
[] = "$Name: $";
79 const char*basedir
= ".";
81 const char*target
= "null";
84 * These are the language support control flags. These support which
85 * language features (the generation) to support. The generation_flag
86 * is a major mode, and the gn_* flags control specific sub-features.
88 generation_t generation_flag
= GN_DEFAULT
;
89 bool gn_icarus_misc_flag
= true;
90 bool gn_cadence_types_flag
= true;
91 bool gn_specify_blocks_flag
= true;
92 bool gn_io_range_error_flag
= true;
93 bool gn_verilog_ams_flag
= false;
95 map
<string
,const char*> flags
;
96 char*vpi_module_list
= 0;
98 map
<perm_string
,unsigned> missing_modules
;
99 map
<perm_string
,bool> library_file_map
;
101 list
<const char*> library_suff
;
103 list
<perm_string
> roots
;
105 char*ivlpp_string
= 0;
107 char* depfile_name
= NULL
;
108 FILE *depend_file
= NULL
;
111 * These are the warning enable flags.
113 bool warn_implicit
= false;
114 bool warn_timescale
= false;
115 bool warn_portbinding
= false;
116 bool warn_inf_loop
= false;
118 bool error_implicit
= false;
121 * Debug message class flags.
123 bool debug_scopes
= false;
124 bool debug_eval_tree
= false;
125 bool debug_elaborate
= false;
126 bool debug_synth2
= false;
127 bool debug_optimizer
= false;
130 * Verbose messages enabled.
132 bool verbose_flag
= false;
134 unsigned integer_width
= 32;
137 * Keep a heap of identifier strings that I encounter. This is a more
138 * efficient way to allocate those strings.
140 StringHeapLex lex_strings
;
142 StringHeapLex filename_strings
;
145 * In library searches, Windows file names are never case sensitive.
147 #if defined(__MINGW32__)
148 const bool CASE_SENSITIVE
= false;
150 const bool CASE_SENSITIVE
= true;
154 * Are we doing synthesis?
156 bool synthesis
= false;
158 extern void cprop(Design
*des
);
159 extern void synth(Design
*des
);
160 extern void synth2(Design
*des
);
161 extern void syn_rules(Design
*des
);
162 extern void nodangle(Design
*des
);
164 extern void xnfio(Design
*des
);
167 typedef void (*net_func
)(Design
*);
168 static struct net_func_map
{
170 void (*func
)(Design
*);
173 { "nodangle",&nodangle
},
175 { "synth2", &synth2
},
176 { "syn-rules", &syn_rules
},
183 queue
<net_func
> net_func_queue
;
185 net_func
name_to_net_func(const string
&name
)
187 for (unsigned idx
= 0 ; func_table
[idx
].name
; idx
+= 1)
188 if (name
== func_table
[idx
].name
)
189 return func_table
[idx
].func
;
194 const char *net_func_to_name(const net_func func
)
196 for (unsigned idx
= 0 ; func_table
[idx
].name
; idx
+= 1)
197 if (func
== func_table
[idx
].func
)
198 return func_table
[idx
].name
;
200 return "This cannot happen";
203 static void process_generation_flag(const char*gen
)
205 if (strcmp(gen
,"1") == 0) { // FIXME: Deprecated for 1995
206 generation_flag
= GN_VER1995
;
208 } else if (strcmp(gen
,"2") == 0) { // FIXME: Deprecated for 2001
209 generation_flag
= GN_VER2001
;
211 } else if (strcmp(gen
,"2x") == 0) { // FIXME: Deprecated for 2001
212 generation_flag
= GN_VER2001
;
213 gn_icarus_misc_flag
= true;
215 } else if (strcmp(gen
,"1995") == 0) {
216 generation_flag
= GN_VER1995
;
218 } else if (strcmp(gen
,"2001") == 0) {
219 generation_flag
= GN_VER2001
;
221 } else if (strcmp(gen
,"2005") == 0) {
222 generation_flag
= GN_VER2005
;
224 } else if (strcmp(gen
,"icarus-misc") == 0) {
225 gn_icarus_misc_flag
= true;
227 } else if (strcmp(gen
,"no-icarus-misc") == 0) {
228 gn_icarus_misc_flag
= false;
230 } else if (strcmp(gen
,"xtypes") == 0) {
231 gn_cadence_types_flag
= true;
233 } else if (strcmp(gen
,"no-xtypes") == 0) {
234 gn_cadence_types_flag
= false;
236 } else if (strcmp(gen
,"specify") == 0) {
237 gn_specify_blocks_flag
= true;
239 } else if (strcmp(gen
,"no-specify") == 0) {
240 gn_specify_blocks_flag
= false;
242 } else if (strcmp(gen
,"verilog-ams") == 0) {
243 gn_verilog_ams_flag
= true;
245 } else if (strcmp(gen
,"no-verilog-ams") == 0) {
246 gn_verilog_ams_flag
= false;
248 } else if (strcmp(gen
,"io-range-error") == 0) {
249 gn_io_range_error_flag
= true;
251 } else if (strcmp(gen
,"no-io-range-error") == 0) {
252 gn_io_range_error_flag
= false;
258 static void parm_to_flagmap(const string
&flag
)
262 unsigned off
= flag
.find('=');
263 if (off
> flag
.size()) {
268 key
= flag
.substr(0, off
);
269 value
= strdup(flag
.substr(off
+1).c_str());
276 * Read the contents of a config file. This file is a temporary
277 * configuration file made by the compiler driver to carry the bulky
278 * flags generated from the user. This reduces the size of the command
279 * line needed to invoke ivl.
281 * Each line of the iconfig file has the format:
285 * The <value> is all the text after the ':' and up to but not
286 * including the end of the line. Thus, white spaces and ':'
287 * characters may appear here.
289 * The valid keys are:
296 * Select which expression to use.
302 * Location to look for installed sub-components
305 * Activate a class of debug messages.
308 * Give the path to an output dependency file.
310 * flag:<name>=<string>
311 * Generic compiler flag strings.
314 * Append a named functor to the processing path.
316 * generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
317 * This is the generation flag
319 * ivlpp:<preprocessor command>
320 * This specifies the ivlpp command line used to process
321 * library modules as I read them in.
324 * This specifies the width of integer variables. (that is,
325 * variables declared using the "integer" keyword.)
327 * library_file:<path>
328 * This marks that a source file with the given path is a
329 * library. Any modules in that file are marked as library
336 * Path to the output file.
339 * Path to a system functions descriptor table
342 * Specify a root module. There may be multiple of this.
345 * Warning flag letters.
347 static void read_iconfig_file(const char*ipath
)
351 FILE*ifile
= fopen(ipath
, "r");
353 cerr
<< "ERROR: Unable to read config file: " << ipath
<< endl
;
357 while (fgets(buf
, sizeof buf
, ifile
) != 0) {
360 char*cp
= strchr(buf
, ':');
365 char*ep
= cp
+ strlen(cp
);
380 if (strcmp(buf
, "basedir") == 0) {
381 basedir
= strdup(cp
);
383 } else if (strcmp(buf
, "debug") == 0) {
384 if (strcmp(cp
, "scopes") == 0) {
386 cerr
<< "debug: Enable scopes debug" << endl
;
387 } else if (strcmp(cp
,"eval_tree") == 0) {
388 debug_eval_tree
= true;
389 cerr
<< "debug: Enable eval_tree debug" << endl
;
390 } else if (strcmp(cp
,"elaborate") == 0) {
391 debug_elaborate
= true;
392 cerr
<< "debug: Enable elaborate debug" << endl
;
393 } else if (strcmp(cp
,"synth2") == 0) {
395 cerr
<< "debug: Enable synth2 debug" << endl
;
396 } else if (strcmp(cp
,"optimizer") == 0) {
397 debug_optimizer
= true;
398 cerr
<< "debug: Enable optimizer debug" << endl
;
402 } else if (strcmp(buf
, "depfile") == 0) {
403 depfile_name
= strdup(cp
);
405 } else if (strcmp(buf
, "flag") == 0) {
407 parm_to_flagmap(parm
);
409 } else if (strcmp(buf
,"functor") == 0) {
410 if (strncmp(cp
, "synth", 5) == 0) {
411 synthesis
= true; // We are doing synthesis.
413 net_func tmp
= name_to_net_func(cp
);
415 cerr
<< "No such design transform function ``"
416 << cp
<< "''." << endl
;
420 net_func_queue
.push(tmp
);
422 } else if (strcmp(buf
, "generation") == 0) {
423 process_generation_flag(cp
);
425 } else if (strcmp(buf
, "ivlpp") == 0) {
426 ivlpp_string
= strdup(cp
);
428 } else if (strcmp(buf
, "iwidth") == 0) {
429 integer_width
= strtoul(cp
,0,10);
431 } else if (strcmp(buf
, "library_file") == 0) {
432 perm_string path
= filename_strings
.make(cp
);
433 library_file_map
[path
] = true;
435 } else if (strcmp(buf
,"module") == 0) {
436 if (vpi_module_list
== 0) {
437 vpi_module_list
= strdup(cp
);
440 char*tmp
= (char*)realloc(vpi_module_list
,
441 strlen(vpi_module_list
)
446 vpi_module_list
= tmp
;
448 flags
["VPI_MODULE_LIST"] = vpi_module_list
;
450 } else if (strcmp(buf
, "out") == 0) {
451 flags
["-o"] = strdup(cp
);
453 } else if (strcmp(buf
, "sys_func") == 0) {
454 load_sys_func_table(cp
);
456 } else if (strcmp(buf
, "root") == 0) {
457 roots
.push_back(lex_strings
.make(cp
));
459 } else if (strcmp(buf
,"warnings") == 0) {
460 /* Scan the warnings enable string for warning flags. */
461 for ( ; *cp
; cp
+= 1) switch (*cp
) {
463 warn_implicit
= true;
466 warn_inf_loop
= true;
469 warn_portbinding
= true;
472 warn_timescale
= true;
478 } else if (strcmp(buf
, "-y") == 0) {
479 build_library_index(cp
, CASE_SENSITIVE
);
481 } else if (strcmp(buf
, "-yl") == 0) {
482 build_library_index(cp
, false);
484 } else if (strcmp(buf
, "-Y") == 0) {
485 library_suff
.push_back(strdup(cp
));
487 } else if (strcmp(buf
,"-t") == 0) {
490 } else if (strcmp(buf
,"-T") == 0) {
491 if (strcmp(cp
,"min") == 0) {
492 min_typ_max_flag
= MIN
;
493 min_typ_max_warn
= 0;
494 } else if (strcmp(cp
,"typ") == 0) {
495 min_typ_max_flag
= TYP
;
496 min_typ_max_warn
= 0;
497 } else if (strcmp(cp
,"max") == 0) {
498 min_typ_max_flag
= MAX
;
499 min_typ_max_warn
= 0;
501 cerr
<< "Invalid argument (" << optarg
<< ") to -T flag."
510 extern Design
* elaborate(list
<perm_string
> root
);
512 #if defined(HAVE_TIMES)
513 static double cycles_diff(struct tms
*a
, struct tms
*b
)
515 clock_t aa
= a
->tms_utime
520 clock_t bb
= b
->tms_utime
525 return (aa
-bb
)/(double)sysconf(_SC_CLK_TCK
);
527 #else // ! defined(HAVE_TIMES)
529 struct tms
{ int x
; };
530 inline static void times(struct tms
*) { }
531 inline static double cycles_diff(struct tms
*a
, struct tms
*b
) { return 0; }
532 #endif // ! defined(HAVE_TIMES)
534 int main(int argc
, char*argv
[])
536 bool help_flag
= false;
537 bool times_flag
= false;
539 const char* net_path
= 0;
540 const char* pf_path
= 0;
543 struct tms cycles
[5];
545 library_suff
.push_back(".v");
547 vpi_module_list
= strdup("system");
548 flags
["VPI_MODULE_LIST"] = vpi_module_list
;
549 flags
["-o"] = "a.out";
550 min_typ_max_flag
= TYP
;
551 min_typ_max_warn
= 10;
553 while ((opt
= getopt(argc
, argv
, "C:f:hN:P:p:Vv")) != EOF
) switch (opt
) {
556 read_iconfig_file(optarg
);
560 parm_to_flagmap(optarg
);
572 parm_to_flagmap(optarg
);
576 # if defined(HAVE_TIMES)
581 cout
<< "Icarus Verilog version " << VERSION
<< endl
;
582 cout
<< COPYRIGHT
<< endl
;
583 cout
<< endl
<< NOTICE
<< endl
;
594 cout
<< "Icarus Verilog version " << VERSION
<< endl
<<
595 "usage: ivl <options> <file>\n"
597 "\t-C <name> Config file from driver.\n"
598 "\t-h Print usage information, and exit.\n"
599 "\t-N <file> Dump the elaborated netlist to <file>.\n"
600 "\t-P <file> Write the parsed input to <file>.\n"
601 "\t-p <assign> Set a parameter value.\n"
602 "\t-v Print progress indications"
603 #if defined(HAVE_TIMES)
604 " and execution times"
607 "\t-V Print version and copyright information, and exit.\n"
613 if (optind
== argc
) {
614 cerr
<< "No input files." << endl
;
619 depend_file
= fopen(depfile_name
, "a");
621 perror(depfile_name
);
625 lexor_keyword_mask
= 0;
626 switch (generation_flag
) {
628 lexor_keyword_mask
|= GN_KEYWORDS_1364_1995
;
631 lexor_keyword_mask
|= GN_KEYWORDS_1364_1995
;
632 lexor_keyword_mask
|= GN_KEYWORDS_1364_2001
;
633 lexor_keyword_mask
|= GN_KEYWORDS_1364_2001_CONFIG
;
636 lexor_keyword_mask
|= GN_KEYWORDS_1364_1995
;
637 lexor_keyword_mask
|= GN_KEYWORDS_1364_2001
;
638 lexor_keyword_mask
|= GN_KEYWORDS_1364_2001_CONFIG
;
639 lexor_keyword_mask
|= GN_KEYWORDS_1364_2005
;
643 if (gn_cadence_types_flag
)
644 lexor_keyword_mask
|= GN_KEYWORDS_ICARUS
;
646 if (gn_verilog_ams_flag
)
647 lexor_keyword_mask
|= GN_KEYWORDS_VAMS_2_3
;
653 cout
<< "Using language generation: ";
654 switch (generation_flag
) {
656 cout
<< "IEEE1364-1995";
659 cout
<< "IEEE1364-2001";
662 cout
<< "IEEE1364-2005";
666 if (gn_verilog_ams_flag
)
667 cout
<< ",verilog-ams";
669 if (gn_specify_blocks_flag
)
672 cout
<< ",no-specify";
674 if (gn_cadence_types_flag
)
677 cout
<< ",no-xtypes";
679 if (gn_icarus_misc_flag
)
680 cout
<< ",icarus-misc";
682 cout
<< ",no-icarus-misc";
684 cout
<< endl
<< "PARSING INPUT" << endl
;
687 /* Parse the input. Make the pform. */
688 int rc
= pform_parse(argv
[optind
]);
691 ofstream
out (pf_path
);
692 out
<< "PFORM DUMP NATURES:" << endl
;
693 for (map
<perm_string
,nature_t
*>::iterator cur
= natures
.begin()
694 ; cur
!= natures
.end() ; cur
++ ) {
695 pform_dump(out
, (*cur
).second
);
697 out
<< "PFORM DUMP DISCIPLINES:" << endl
;
698 for (map
<perm_string
,discipline_t
*>::iterator cur
= disciplines
.begin()
699 ; cur
!= disciplines
.end() ; cur
++ ) {
700 pform_dump(out
, (*cur
).second
);
702 out
<< "PFORM DUMP MODULES:" << endl
;
703 for (map
<perm_string
,Module
*>::iterator mod
= pform_modules
.begin()
704 ; mod
!= pform_modules
.end()
706 pform_dump(out
, (*mod
).second
);
708 out
<< "PFORM DUMP PRIMITIVES:" << endl
;
709 for (map
<perm_string
,PUdp
*>::iterator idx
= pform_primitives
.begin()
710 ; idx
!= pform_primitives
.end()
712 (*idx
).second
->dump(out
);
721 /* If the user did not give specific module(s) to start with,
722 then look for modules that are not instantiated anywhere. */
725 map
<perm_string
,bool> mentioned_p
;
726 map
<perm_string
,Module
*>::iterator mod
;
728 cout
<< "LOCATING TOP-LEVEL MODULES" << endl
<< " ";
729 for (mod
= pform_modules
.begin()
730 ; mod
!= pform_modules
.end()
732 list
<PGate
*> gates
= (*mod
).second
->get_gates();
733 list
<PGate
*>::const_iterator gate
;
734 for (gate
= gates
.begin(); gate
!= gates
.end(); gate
++) {
735 PGModule
*mod
= dynamic_cast<PGModule
*>(*gate
);
737 // Note that this module has been instantiated
738 mentioned_p
[mod
->get_type()] = true;
743 for (mod
= pform_modules
.begin()
744 ; mod
!= pform_modules
.end()
747 /* Don't choose library modules. */
748 if ((*mod
).second
->library_flag
)
751 /* Don't choose modules instantiated in other
753 if (mentioned_p
[(*mod
).second
->mod_name()])
756 /* What's left might as well be chosen as a root. */
758 cout
<< " " << (*mod
).second
->mod_name();
759 roots
.push_back((*mod
).second
->mod_name());
765 /* If there is *still* no guess for the root module, then give
766 up completely, and complain. */
769 cerr
<< "No top level modules, and no -s option." << endl
;
778 <<cycles_diff(cycles
+1, cycles
+0)<<" seconds."<<endl
;
780 cout
<< "ELABORATING DESIGN" << endl
;
783 /* On with the process of elaborating the module. */
784 Design
*des
= elaborate(roots
);
786 if ((des
== 0) || (des
->errors
> 0)) {
789 << " error(s) during elaboration." << endl
;
791 ofstream
out (net_path
);
795 cerr
<< "Elaboration failed" << endl
;
801 des
->set_flags(flags
);
803 /* Done with all the pform data. Delete the modules. */
804 for (map
<perm_string
,Module
*>::iterator idx
= pform_modules
.begin()
805 ; idx
!= pform_modules
.end() ; idx
++) {
807 delete (*idx
).second
;
815 <<cycles_diff(cycles
+2, cycles
+1)<<" seconds."<<endl
;
817 cout
<< "RUNNING FUNCTORS" << endl
;
820 while (!net_func_queue
.empty()) {
821 net_func func
= net_func_queue
.front();
822 net_func_queue
.pop();
824 cerr
<<" -F "<<net_func_to_name(func
)<< " ..." <<endl
;
830 cerr
<<" dumping netlist to " <<net_path
<< "..." <<endl
;
832 ofstream
out (net_path
);
838 << " error(s) in post-elaboration processing." <<
847 <<cycles_diff(cycles
+3, cycles
+2)<<" seconds."<<endl
;
852 cout
<< "CODE GENERATION -t "<<target
<< endl
;
856 emit_rc
= emit(des
, target
);
858 cerr
<< "error: Code generation had "
859 << emit_rc
<< " errors."
864 cerr
<< "error: Code generator failure: " << emit_rc
<< endl
;
872 <<cycles_diff(cycles
+4, cycles
+3)<<" seconds."<<endl
;
874 cout
<< "DONE." << endl
;
879 cout
<< "STATISTICS" << endl
;
880 cout
<< "lex_string:"
881 << " add_count=" << lex_strings
.add_count()
882 << " hit_count=" << lex_strings
.add_hit_count()
889 if (missing_modules
.size() > 0) {
890 cerr
<< "*** These modules were missing:" << endl
;
892 map
<perm_string
,unsigned>::const_iterator idx
;
893 for (idx
= missing_modules
.begin()
894 ; idx
!= missing_modules
.end()
896 cerr
<< " " << (*idx
).first
897 << " referenced " << (*idx
).second
900 cerr
<< "***" << endl
;
903 return des
? des
->errors
: 1;