1 const char COPYRIGHT[] =
2           "Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)";
3 
4 /*
5  *    This source code is free software; you can redistribute it
6  *    and/or modify it in source code form under the terms of the GNU
7  *    General Public License as published by the Free Software
8  *    Foundation; either version 2 of the License, or (at your option)
9  *    any later version.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    GNU General Public License for more details.
15  *
16  *    You should have received a copy of the GNU General Public License
17  *    along with this program; if not, write to the Free Software
18  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 # include "config.h"
22 # include "version_base.h"
23 # include "version_tag.h"
24 
25 const char NOTICE[] =
26 "  This program is free software; you can redistribute it and/or modify\n"
27 "  it under the terms of the GNU General Public License as published by\n"
28 "  the Free Software Foundation; either version 2 of the License, or\n"
29 "  (at your option) any later version.\n"
30 "\n"
31 "  This program is distributed in the hope that it will be useful,\n"
32 "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
33 "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
34 "  GNU General Public License for more details.\n"
35 "\n"
36 "  You should have received a copy of the GNU General Public License along\n"
37 "  with this program; if not, write to the Free Software Foundation, Inc.,\n"
38 "  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
39 ;
40 
41 # include  <cstdio>
42 # include  <iostream>
43 # include  <fstream>
44 # include  <queue>
45 # include  <cstring>
46 # include  <list>
47 # include  <map>
48 # include  <unistd.h>
49 # include  <cstdlib>
50 #if defined(HAVE_TIMES)
51 # include  <sys/times.h>
52 #endif
53 #if defined(HAVE_GETOPT_H)
54 # include  <getopt.h>
55 #endif
56 # include  "pform.h"
57 # include  "parse_api.h"
58 # include  "PGenerate.h"
59 # include  "netlist.h"
60 # include  "target.h"
61 # include  "compiler.h"
62 # include  "discipline.h"
63 # include  "t-dll.h"
64 
65 #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
66 extern "C" int getopt(int argc, char*argv[], const char*fmt);
67 extern "C" int optind;
68 extern "C" const char*optarg;
69 #endif
70 
71 #if defined(__CYGWIN__) && !defined(HAVE_GETOPT_H)
72 extern "C" int getopt(int argc, char*argv[], const char*fmt);
73 extern "C" int optind;
74 extern "C" const char*optarg;
75 #endif
76 
77 #if defined(TRAP_SIGINT_FOR_DEBUG)
78 /*
79  * This is a debugging aid. Do not compile it in general, but leave it
80  * here for those days when I need the ability to cleanly exit on a
81  * signal interrupt.
82 */
83 # include  <csignal>
signals_handler(int sig)84 static void signals_handler(int sig)
85 {
86       fprintf(stderr, "Exit on signal %d\n", sig);
87       exit(1);
88 }
89 #endif
90 
91 # include  "ivl_alloc.h"
92 
93 /* Count errors detected in flag processing. */
94 unsigned flag_errors = 0;
95 
96 const char*basedir = strdup(".");
97 
98 /*
99  * These are the language support control flags. These support which
100  * language features (the generation) to support. The generation_flag
101  * is a major mode, and the gn_* flags control specific sub-features.
102  */
103 generation_t generation_flag = GN_DEFAULT;
104 bool gn_icarus_misc_flag = true;
105 bool gn_cadence_types_flag = true;
106 bool gn_specify_blocks_flag = true;
107 bool gn_supported_assertions_flag = true;
108 bool gn_unsupported_assertions_flag = true;
109 bool gn_io_range_error_flag = true;
110 bool gn_strict_ca_eval_flag = false;
111 bool gn_strict_expr_width_flag = false;
112 bool gn_shared_loop_index_flag = true;
113 bool gn_verilog_ams_flag = false;
114 
115 /*
116  * For some generations we allow a system function to be called
117  * as a task and only print a warning message. The default for
118  * this is that it is a run time error.
119  */
120 ivl_sfunc_as_task_t def_sfunc_as_task = IVL_SFUNC_AS_TASK_ERROR;
121 
122 map<string,const char*> flags;
123 char*vpi_module_list = 0;
add_vpi_module(const char * name)124 void add_vpi_module(const char*name)
125 {
126       if (vpi_module_list == 0) {
127 	    vpi_module_list = strdup(name);
128 
129       } else {
130 	    char*tmp = (char*)realloc(vpi_module_list,
131 				      strlen(vpi_module_list)
132 				      + strlen(name)
133 				      + 2);
134 	    strcat(tmp, ",");
135 	    strcat(tmp, name);
136 	    vpi_module_list = tmp;
137       }
138       flags["VPI_MODULE_LIST"] = vpi_module_list;
139       load_vpi_module(name);
140 }
141 
142 map<perm_string,unsigned> missing_modules;
143 map<perm_string,bool> library_file_map;
144 
145 vector<perm_string> source_files;
146 
147 list<const char*> library_suff;
148 
149 list<perm_string> roots;
150 
151 char*ivlpp_string = 0;
152 
153 char depfile_mode = 'a';
154 char* depfile_name = NULL;
155 FILE *depend_file = NULL;
156 
157 /*
158  * These are the warning enable flags.
159  */
160 bool warn_implicit  = false;
161 bool warn_implicit_dimensions = false;
162 bool warn_timescale = false;
163 bool warn_portbinding = false;
164 bool warn_inf_loop = false;
165 bool warn_ob_select = false;
166 bool warn_sens_entire_vec = false;
167 bool warn_sens_entire_arr = false;
168 bool warn_anachronisms = false;
169 bool warn_floating_nets = false;
170 
171 /*
172  * Ignore errors about missing modules
173  */
174 bool ignore_missing_modules = false;
175 
176 /*
177  * Debug message class flags.
178  */
179 bool debug_scopes = false;
180 bool debug_eval_tree = false;
181 bool debug_elaborate = false;
182 bool debug_emit = false;
183 bool debug_synth2 = false;
184 bool debug_optimizer = false;
185 
186 /*
187  * Compilation control flags.
188  */
189 bool separate_compilation = false;
190 
191 /*
192  * Optimization control flags.
193  */
194 unsigned opt_const_func = 0;
195 
196 /*
197  * Miscellaneous flags.
198  */
199 bool disable_virtual_pins = false;
200 unsigned long array_size_limit = 16777216;  // Minimum required by IEEE-1364?
201 unsigned recursive_mod_limit = 10;
202 bool disable_concatz_generation = false;
203 
204 /*
205  * Verbose messages enabled.
206  */
207 bool verbose_flag = false;
208 
209 unsigned integer_width = 32;
210 
211 /*
212  * Width limit for unsized expressions.
213  */
214 unsigned width_cap = 65536;
215 
216 int def_ts_units = 0;
217 int def_ts_prec = 0;
218 
219 /*
220  * Keep a heap of identifier strings that I encounter. This is a more
221  * efficient way to allocate those strings.
222  */
223 StringHeapLex lex_strings;
224 
225 StringHeapLex filename_strings;
226 
227 StringHeapLex bits_strings;
228 
229 /*
230  * In library searches, Windows file names are never case sensitive.
231  */
232 #if defined(__MINGW32__)
233 const bool CASE_SENSITIVE = false;
234 #else
235 const bool CASE_SENSITIVE = true;
236 #endif
237 
238 /*
239  * Are we doing synthesis?
240  */
241 bool synthesis = false;
242 
243 extern void cprop(Design*des);
244 extern void exposenodes(Design*des);
245 extern void synth(Design*des);
246 extern void synth2(Design*des);
247 extern void syn_rules(Design*des);
248 extern void nodangle(Design*des);
249 
250 typedef void (*net_func)(Design*);
251 static struct net_func_map {
252       const char*name;
253       void (*func)(Design*);
254 } func_table[] = {
255       { "cprop",       &cprop },
256       { "exposenodes", &exposenodes },
257       { "nodangle",    &nodangle },
258       { "synth",       &synth },
259       { "synth2",      &synth2 },
260       { "syn-rules",   &syn_rules },
261       { 0, 0 }
262 };
263 
264 queue<net_func> net_func_queue;
265 
name_to_net_func(const string & name)266 net_func name_to_net_func(const string&name)
267 {
268       for (unsigned idx = 0 ;  func_table[idx].name ;  idx += 1)
269 	    if (name == func_table[idx].name)
270 		  return func_table[idx].func;
271 
272       return 0;
273 }
274 
net_func_to_name(const net_func func)275 const char *net_func_to_name(const net_func func)
276 {
277       for (unsigned idx = 0 ;  func_table[idx].name ;  idx += 1)
278 	    if (func == func_table[idx].func)
279 		  return func_table[idx].name;
280 
281       return "This cannot happen";
282 }
283 
process_generation_flag(const char * gen)284 static void process_generation_flag(const char*gen)
285 {
286       if (strcmp(gen,"1") == 0) { // FIXME: Deprecated for 1995
287 	    generation_flag = GN_VER1995;
288 
289       } else if (strcmp(gen,"2") == 0) { // FIXME: Deprecated for 2001
290 	    generation_flag = GN_VER2001;
291 
292       } else if (strcmp(gen,"2x") == 0) { // FIXME: Deprecated for 2001
293 	    generation_flag = GN_VER2001;
294 	    gn_icarus_misc_flag = true;
295 
296       } else if (strcmp(gen,"1995") == 0) {
297 	    generation_flag = GN_VER1995;
298 
299       } else if (strcmp(gen,"2001") == 0) {
300 	    generation_flag = GN_VER2001;
301 
302       } else if (strcmp(gen,"2001-noconfig") == 0) {
303 	    generation_flag = GN_VER2001_NOCONFIG;
304 
305       } else if (strcmp(gen,"2005") == 0) {
306 	    generation_flag = GN_VER2005;
307 
308       } else if (strcmp(gen,"2005-sv") == 0) {
309 	    generation_flag = GN_VER2005_SV;
310 
311       } else if (strcmp(gen,"2009") == 0) {
312 	    generation_flag = GN_VER2009;
313 
314       } else if (strcmp(gen,"2012") == 0) {
315 	    generation_flag = GN_VER2012;
316 
317       } else if (strcmp(gen,"icarus-misc") == 0) {
318 	    gn_icarus_misc_flag = true;
319 
320       } else if (strcmp(gen,"no-icarus-misc") == 0) {
321 	    gn_icarus_misc_flag = false;
322 
323       } else if (strcmp(gen,"xtypes") == 0) {
324 	    gn_cadence_types_flag = true;
325 
326       } else if (strcmp(gen,"no-xtypes") == 0) {
327 	    gn_cadence_types_flag = false;
328 
329       } else if (strcmp(gen,"specify") == 0) {
330 	    gn_specify_blocks_flag = true;
331 
332       } else if (strcmp(gen,"no-specify") == 0) {
333 	    gn_specify_blocks_flag = false;
334 
335       } else if (strcmp(gen,"assertions") == 0) {
336 	    gn_supported_assertions_flag = true;
337 	    gn_unsupported_assertions_flag = true;
338 
339       } else if (strcmp(gen,"supported-assertions") == 0) {
340 	    gn_supported_assertions_flag = true;
341 	    gn_unsupported_assertions_flag = false;
342 
343       } else if (strcmp(gen,"no-assertions") == 0) {
344 	    gn_supported_assertions_flag = false;
345 	    gn_unsupported_assertions_flag = false;
346 
347       } else if (strcmp(gen,"verilog-ams") == 0) {
348 	    gn_verilog_ams_flag = true;
349 
350       } else if (strcmp(gen,"no-verilog-ams") == 0) {
351 	    gn_verilog_ams_flag = false;
352 
353       } else if (strcmp(gen,"io-range-error") == 0) {
354 	    gn_io_range_error_flag = true;
355 
356       } else if (strcmp(gen,"no-io-range-error") == 0) {
357 	    gn_io_range_error_flag = false;
358 
359       } else if (strcmp(gen,"strict-ca-eval") == 0) {
360 	    gn_strict_ca_eval_flag = true;
361 
362       } else if (strcmp(gen,"no-strict-ca-eval") == 0) {
363 	    gn_strict_ca_eval_flag = false;
364 
365       } else if (strcmp(gen,"strict-expr-width") == 0) {
366 	    gn_strict_expr_width_flag = true;
367 
368       } else if (strcmp(gen,"no-strict-expr-width") == 0) {
369 	    gn_strict_expr_width_flag = false;
370 
371       } else if (strcmp(gen,"shared-loop-index") == 0) {
372 	    gn_shared_loop_index_flag = true;
373 
374       } else if (strcmp(gen,"no-shared-loop-index") == 0) {
375 	    gn_shared_loop_index_flag = false;
376 
377 	  } else {
378       }
379 }
380 
parm_to_flagmap(const string & flag)381 static void parm_to_flagmap(const string&flag)
382 {
383       string key;
384       const char*value;
385       unsigned off = flag.find('=');
386       if (off > flag.size()) {
387 	    key = flag;
388 	    value = strdup("");
389 
390       } else {
391 	    key = flag.substr(0, off);
392 	    value = strdup(flag.substr(off+1).c_str());
393       }
394 
395       flags[key] = value;
396 }
397 
398 static void find_module_mention(map<perm_string,bool>&check_map, Module*m);
399 static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
400 
401 /*
402  * Convert a string to a time unit or precision.
403  *
404  * Returns true on failure.
405  */
get_ts_const(const char * & cp,int & res,bool is_units)406 static bool get_ts_const(const char*&cp, int&res, bool is_units)
407 {
408 	/* Check for the 1 digit. */
409       if (*cp != '1') {
410 	    if (is_units) {
411 		  cerr << "Error: Invalid +timescale units constant "
412 		          "(1st digit)." << endl;
413 	    } else {
414 		  cerr << "Error: Invalid +timescale precision constant "
415 		          "(1st digit)." << endl;
416 	    }
417 	    return true;
418       }
419       cp += 1;
420 
421 	/* Check the number of zeros after the 1. */
422       res = strspn(cp, "0");
423       if (res > 2) {
424 	    if (is_units) {
425 		  cerr << "Error: Invalid +timescale units constant "
426 		          "(number of zeros)." << endl;
427 	    } else {
428 		  cerr << "Error: Invalid +timescale precision constant "
429 		          "(number of zeros)." << endl;
430 	    }
431 	    return true;
432       }
433       cp += res;
434 
435 	/* Now process the scaling string. */
436       if (strncmp("s", cp, 1) == 0) {
437 	    res -= 0;
438 	    cp += 1;
439 	    return false;
440 
441       } else if (strncmp("ms", cp, 2) == 0) {
442 	    res -= 3;
443 	    cp += 2;
444 	    return false;
445 
446       } else if (strncmp("us", cp, 2) == 0) {
447 	    res -= 6;
448 	    cp += 2;
449 	    return false;
450 
451       } else if (strncmp("ns", cp, 2) == 0) {
452 	    res -= 9;
453 	    cp += 2;
454 	    return false;
455 
456       } else if (strncmp("ps", cp, 2) == 0) {
457 	    res -= 12;
458 	    cp += 2;
459 	    return false;
460 
461       } else if (strncmp("fs", cp, 2) == 0) {
462 	    res -= 15;
463 	    cp += 2;
464 	    return false;
465 
466       }
467 
468       if (is_units) {
469 	    cerr << "Error: Invalid +timescale units scale." << endl;
470       } else {
471 	    cerr << "Error: Invalid +timescale precision scale." << endl;
472       }
473       return true;
474 }
475 
476 /*
477  * Process a string with the following form (no space allowed):
478  *
479  *   num = < '1' | '10' | '100' >
480  *   scale = < 's' | 'ms' | 'us' | 'ns' | 'ps' | 'fs' >
481  *
482  *   "<num> <scale> '/' <num> <scale>
483  *
484  * and set the default time units and precision if successful.
485  *
486  * Return true if we have an error processing the timescale string.
487  */
set_default_timescale(const char * ts_string)488 static bool set_default_timescale(const char*ts_string)
489 {
490 	/* Because this came from a command file we can not have embedded
491 	 * space in this string. */
492       const char*cp = ts_string;
493       int units = 0;
494       int prec = 0;
495 
496 	/* Get the time units. */
497       if (get_ts_const(cp, units, true)) return true;
498 
499 	/* Skip the '/'. */
500       if (*cp != '/') {
501 	    cerr << "Error: +timescale separator '/' is missing." << endl;
502 	    return true;
503       }
504       cp += 1;
505 
506 	/* Get the time precision. */
507       if (get_ts_const(cp, prec, false)) return true;
508 
509 	/* The time unit must be greater than or equal to the precision. */
510       if (units < prec) {
511 	    cerr << "Error: +timescale unit must not be less than the "
512 	            "precision." << endl;
513 	    return true;
514       }
515 
516 	/* We have valid units and precision so set the global defaults. */
517       def_ts_units = units;
518       def_ts_prec = prec;
519       return false;
520 }
521 
522 /*
523  * Read the contents of a config file. This file is a temporary
524  * configuration file made by the compiler driver to carry the bulky
525  * flags generated from the user. This reduces the size of the command
526  * line needed to invoke ivl.
527  *
528  * Each line of the iconfig file has the format:
529  *
530  *      <keyword>:<value>
531  *
532  * The <value> is all the text after the ':' and up to but not
533  * including the end of the line. Thus, white spaces and ':'
534  * characters may appear here.
535  *
536  * The valid keys are:
537  *
538  *    -y:<dir>
539  *    -yl:<dir>
540  *    -Y:<string>
541  *
542  *    -T:<min/typ/max>
543  *        Select which expression to use.
544  *
545  *    -t:<target>    (obsolete)
546  *        Usually, "-t:dll"
547  *
548  *    basedir:<path>
549  *        Location to look for installed sub-components
550  *
551  *    debug:<name>
552  *        Activate a class of debug messages.
553  *
554  *    depfile:<path>
555  *        Give the path to an output dependency file.
556  *
557  *    flag:<name>=<string>
558  *        Generic compiler flag strings.
559  *
560  *    functor:<name>
561  *        Append a named functor to the processing path.
562  *
563  *    generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
564  *        This is the generation flag
565  *
566  *    ivlpp:<preprocessor command>
567  *        This specifies the ivlpp command line used to process
568  *        library modules as I read them in.
569  *
570  *    iwidth:<bits>
571  *        This specifies the width of integer variables. (that is,
572  *        variables declared using the "integer" keyword.)
573  *
574  *    library_file:<path>
575  *        This marks that a source file with the given path is a
576  *        library. Any modules in that file are marked as library
577  *        modules.
578  *
579  *    module:<name>
580  *        Load a VPI module.
581  *
582  *    out:<path>
583  *        Path to the output file.
584  *
585  *    sys_func:<path>
586  *        Path to a system functions descriptor table
587  *
588  *    root:<name>
589  *        Specify a root module. There may be multiple of this.
590  *
591  *    warnings:<string>
592  *        Warning flag letters.
593  *
594  *    ignore_missing_modules:<bool>
595  *        true to ignore errors about missing modules
596  */
597 bool had_timescale = false;
read_iconfig_file(const char * ipath)598 static void read_iconfig_file(const char*ipath)
599 {
600       char buf[8*1024];
601       vector<pair<char*,bool> > to_build_library_index;
602 
603       FILE*ifile = fopen(ipath, "r");
604       if (ifile == 0) {
605 	    cerr << "ERROR: Unable to read config file: " << ipath << endl;
606 	    return;
607       }
608 
609       while (fgets(buf, sizeof buf, ifile) != 0) {
610 	    assert(strlen(buf) < sizeof buf);
611 	    if ((strlen(buf) == ((sizeof buf) - 1))
612 		&& buf[sizeof buf -2] != '\n') {
613 		  cerr << "WARNING: Line buffer overflow reading iconfig file: "
614 		       << ipath
615 		       << "." << endl;
616 		  assert(0);
617 	    }
618 	    if (buf[0] == '#')
619 		  continue;
620 	    char*cp = strchr(buf, ':');
621 	    if (cp == 0)
622 		  continue;
623 
624 	    *cp++ = 0;
625 	    char*ep = cp + strlen(cp);
626 	    while (ep > cp) {
627 		  ep -= 1;
628 		  switch (*ep) {
629 		      case '\r':
630 		      case '\n':
631 		      case ' ':
632 		      case '\t':
633 			*ep = 0;
634 			break;
635 		      default:
636 			ep = cp;
637 		  }
638 	    }
639 
640 	    if (strcmp(buf, "basedir") == 0) {
641 		  free((void *)basedir);
642 		  basedir = strdup(cp);
643 
644 	    } else if (strcmp(buf, "debug") == 0) {
645 		  if (strcmp(cp, "scopes") == 0) {
646 			debug_scopes = true;
647 			cerr << "debug: Enable scopes debug" << endl;
648 		  } else if (strcmp(cp,"eval_tree") == 0) {
649 			debug_eval_tree = true;
650 			cerr << "debug: Enable eval_tree debug" << endl;
651 		  } else if (strcmp(cp,"elaborate") == 0) {
652 			debug_elaborate = true;
653 			cerr << "debug: Enable elaborate debug" << endl;
654 		  } else if (strcmp(cp,"emit") == 0) {
655 			debug_emit = true;
656 			cerr << "debug: Enable emit debug" << endl;
657 		  } else if (strcmp(cp,"synth2") == 0) {
658 			debug_synth2 = true;
659 			cerr << "debug: Enable synth2 debug" << endl;
660 		  } else if (strcmp(cp,"optimizer") == 0) {
661 			debug_optimizer = true;
662 			cerr << "debug: Enable optimizer debug" << endl;
663 		  } else {
664 		  }
665 
666 	    } else if (strcmp(buf, "depmode") == 0) {
667 		  depfile_mode = *cp;
668 
669 	    } else if (strcmp(buf, "depfile") == 0) {
670 		  depfile_name = strdup(cp);
671 
672 	    } else if (strcmp(buf, "flag") == 0) {
673 		  string parm = cp;
674 		  parm_to_flagmap(parm);
675 
676 	    } else if (strcmp(buf,"functor") == 0) {
677 		if (strncmp(cp, "synth", 5) == 0) {
678 		      synthesis = true;  // We are doing synthesis.
679 		}
680 		net_func tmp = name_to_net_func(cp);
681 		if (tmp == 0) {
682 		      cerr << "No such design transform function ``"
683 			   << cp << "''." << endl;
684 		      flag_errors += 1;
685 		      break;
686 		}
687 		net_func_queue.push(tmp);
688 
689 	    } else if (strcmp(buf, "generation") == 0) {
690 		  process_generation_flag(cp);
691 
692 	    } else if (strcmp(buf, "ivlpp") == 0) {
693 		  ivlpp_string = strdup(cp);
694 
695 	    } else if (strcmp(buf, "iwidth") == 0) {
696 		  integer_width = strtoul(cp,0,10);
697 
698 	    } else if (strcmp(buf, "widthcap") == 0) {
699 		  width_cap = strtoul(cp,0,10);
700 
701 	    } else if (strcmp(buf, "library_file") == 0) {
702 		  perm_string path = filename_strings.make(cp);
703 		  library_file_map[path] = true;
704 
705 	    } else if (strcmp(buf,"module") == 0) {
706 		  add_vpi_module(cp);
707 
708 	    } else if (strcmp(buf, "out") == 0) {
709 		  free((void *)flags["-o"]);
710 		  flags["-o"] = strdup(cp);
711 
712 	    } else if (strcmp(buf, "sys_func") == 0) {
713 		  load_sys_func_table(cp);
714 
715 	    } else if (strcmp(buf, "root") == 0) {
716 		  roots.push_back(lex_strings.make(cp));
717 
718 	    } else if (strcmp(buf,"warnings") == 0) {
719 		    /* Scan the warnings enable string for warning flags. */
720 		  for ( ;  *cp ;  cp += 1) switch (*cp) {
721 		      case 'f':
722 			warn_floating_nets = true;
723 			break;
724 		      case 'i':
725 			warn_implicit = true;
726 			break;
727 		      case 'd':
728 			warn_implicit_dimensions = true;
729 			break;
730 		      case 'l':
731 			warn_inf_loop = true;
732 			break;
733 		      case 's':
734 			warn_ob_select = true;
735 			break;
736 		      case 'p':
737 			warn_portbinding = true;
738 			break;
739 		      case 't':
740 			warn_timescale = true;
741 			break;
742 		      case 'v':
743 			warn_sens_entire_vec = true;
744 			break;
745 		      case 'a':
746 			warn_sens_entire_arr = true;
747 			break;
748 		      case 'n':
749 			warn_anachronisms = true;
750 			break;
751 		      default:
752 			break;
753 		  }
754 
755 	    } else if (strcmp(buf, "ignore_missing_modules") == 0) {
756 		  if (strcmp(cp, "true") == 0)
757 		    ignore_missing_modules = true;
758 
759 	    } else if (strcmp(buf, "-y") == 0) {
760 		  to_build_library_index.push_back(make_pair(strdup(cp), CASE_SENSITIVE));
761 
762 	    } else if (strcmp(buf, "-yl") == 0) {
763 		  to_build_library_index.push_back(make_pair(strdup(cp), false));
764 
765 	    } else if (strcmp(buf, "-Y") == 0) {
766 		  library_suff.push_back(strdup(cp));
767 
768 	    } else if (strcmp(buf,"-t") == 0) {
769 		    // NO LONGER USED
770 
771 	    } else if (strcmp(buf,"-T") == 0) {
772 		  if (strcmp(cp,"min") == 0) {
773 			min_typ_max_flag = MIN;
774 			min_typ_max_warn = 0;
775 		  } else if (strcmp(cp,"typ") == 0) {
776 			min_typ_max_flag = TYP;
777 			min_typ_max_warn = 0;
778 		  } else if (strcmp(cp,"max") == 0) {
779 			min_typ_max_flag = MAX;
780 			min_typ_max_warn = 0;
781 		  } else {
782 			cerr << "Invalid argument (" << optarg << ") to -T flag."
783 			     << endl;
784 			flag_errors += 1;
785 		  }
786 	    } else if (strcmp(buf,"defparam") == 0) {
787 		  parm_to_defparam_list(cp);
788 	    } else if (strcmp(buf,"timescale") == 0) {
789 		  if (had_timescale) {
790 			cerr << "Command File: Warning: default timescale "
791 			        "is being set multiple times." << endl;
792 			cerr << "                     : using the last valid "
793 			        "+timescale found." << endl;
794 		  }
795 		  if (set_default_timescale(cp)) {
796 			cerr << "     : with +timescale+" << cp << "+" << endl;
797 			flag_errors += 1;
798 		  } else had_timescale = true;
799 	    }
800       }
801       fclose(ifile);
802       for (vector<pair<char *, bool> >::iterator it = to_build_library_index.begin() ;
803 	   it != to_build_library_index.end() ; ++ it ) {
804 	    build_library_index(it->first, it->second);
805 	    free(it->first);
806       }
807 }
808 
809 /*
810  * This function reads a list of source file names. Each name starts
811  * with the first non-space character, and ends with the last non-space
812  * character. Spaces in the middle are OK.
813  */
read_sources_file(const char * path)814 static void read_sources_file(const char*path)
815 {
816       char line_buf[2048];
817 
818       FILE*fd = fopen(path, "r");
819       if (fd == 0) {
820 	    cerr << "ERROR: Unable to read source file list: " << path << endl;
821 	    return;
822       }
823 
824       while (fgets(line_buf, sizeof line_buf, fd) != 0) {
825 	      // assertion test that we are not overflowing the line
826 	      // buffer. Really should make this more robust, but
827 	      // better to assert then go weird.
828 	    assert(strlen(line_buf) < sizeof line_buf);
829 	    if ((strlen(line_buf) == ((sizeof line_buf) - 1))
830 		&& line_buf[sizeof line_buf -2] != '\n') {
831 		  cerr << "WARNING: Line buffer overflow reading sources file: "
832 		       << path
833 		       << "." << endl;
834 		  assert(0);
835 	    }
836 	    char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
837 	    char*tail = cp + strlen(cp);
838 	    while (tail > cp) {
839 		  if (! isspace((int)tail[-1]))
840 			break;
841 		  tail -= 1;
842 		  tail[0] = 0;
843 	    }
844 
845 	    if (cp < tail)
846 		  source_files.push_back(filename_strings.make(cp));
847       }
848 
849       fclose(fd);
850 }
851 
852 extern Design* elaborate(list <perm_string> root);
853 
854 #if defined(HAVE_TIMES)
cycles_diff(struct tms * a,struct tms * b)855 static double cycles_diff(struct tms *a, struct tms *b)
856 {
857       clock_t aa = a->tms_utime
858 	    +      a->tms_stime
859 	    +      a->tms_cutime
860 	    +      a->tms_cstime;
861 
862       clock_t bb = b->tms_utime
863 	    +      b->tms_stime
864 	    +      b->tms_cutime
865 	    +      b->tms_cstime;
866 
867       return (aa-bb)/(double)sysconf(_SC_CLK_TCK);
868 }
869 #else // ! defined(HAVE_TIMES)
870 // Provide dummies
871 struct tms { int x; };
times(struct tms *)872 inline static void times(struct tms *) { }
cycles_diff(struct tms *,struct tms *)873 inline static double cycles_diff(struct tms *, struct tms *) { return 0; }
874 #endif // ! defined(HAVE_TIMES)
875 
EOC_cleanup(void)876 static void EOC_cleanup(void)
877 {
878       cleanup_sys_func_table();
879 
880       for (list<const char*>::iterator suf = library_suff.begin() ;
881            suf != library_suff.end() ; ++ suf ) {
882 	    free((void *)*suf);
883       }
884       library_suff.clear();
885 
886       free((void *) basedir);
887       free(ivlpp_string);
888       free(depfile_name);
889 
890       for (map<string, const char*>::iterator flg = flags.begin() ;
891            flg != flags.end() ; ++ flg ) {
892 	    free((void *)flg->second);
893       }
894       flags.clear();
895 
896       lex_strings.cleanup();
897       bits_strings.cleanup();
898       filename_strings.cleanup();
899 }
900 
main(int argc,char * argv[])901 int main(int argc, char*argv[])
902 {
903       bool help_flag = false;
904       bool times_flag = false;
905       bool version_flag = false;
906 
907       const char* net_path = 0;
908       const char* pf_path = 0;
909       int opt;
910 
911       struct tms cycles[5];
912 
913 #if defined(TRAP_SIGINT_FOR_DEBUG)
914       signal(SIGINT, &signals_handler);
915 #endif
916       if( ::getenv("IVL_WAIT_FOR_DEBUGGER") != 0 ) {
917           fprintf( stderr, "Waiting for debugger...\n");
918           bool debugger_release = false;
919           while( !debugger_release )  {
920 #if defined(__MINGW32__)
921               Sleep(1000);
922 #else
923               sleep(1);
924 #endif
925         }
926       }
927       library_suff.push_back(strdup(".v"));
928 
929       flags["-o"] = strdup("a.out");
930       min_typ_max_flag = TYP;
931       min_typ_max_warn = 10;
932 
933       while ((opt = getopt(argc, argv, "C:F:f:hN:P:p:Vv")) != EOF) switch (opt) {
934 
935 	  case 'C':
936 	    read_iconfig_file(optarg);
937 	    break;
938 	  case 'F':
939 	    read_sources_file(optarg);
940 	    break;
941 	  case 'f':
942 	    parm_to_flagmap(optarg);
943 	    break;
944 	  case 'h':
945 	    help_flag = true;
946 	    break;
947 	  case 'N':
948 	    net_path = optarg;
949 	    break;
950 	  case 'P':
951 	    pf_path = optarg;
952 	    break;
953 	  case 'p':
954 	    parm_to_flagmap(optarg);
955 	    break;
956 	  case 'v':
957 	    verbose_flag = true;
958 #          if defined(HAVE_TIMES)
959 	    times_flag = true;
960 #          endif
961 	    flags["VVP_EXTRA_ARGS"] = strdup(" -v");
962 	    break;
963 	  case 'V':
964 	    version_flag = true;
965 	    break;
966 	  default:
967 	    flag_errors += 1;
968 	    break;
969       }
970 
971       if (flag_errors)
972 	    return flag_errors;
973 
974       if (version_flag) {
975 	    cout << "\nIcarus Verilog Parser/Elaborator version "
976 		 << VERSION << " (" << VERSION_TAG << ")" << endl << endl;
977 	    cout << COPYRIGHT << endl << endl;
978 	    cout << NOTICE << endl;
979 
980 	    cout << " FLAGS DLL " << flags["DLL"] << endl;
981 
982 	    dll_target_obj.test_version(flags["DLL"]);
983 
984 	    return 0;
985       }
986 
987       if (help_flag) {
988 	    cout << "Icarus Verilog Parser/Elaborator version "
989 		 << VERSION << " (" << VERSION_TAG << ")"  << endl <<
990 "usage: ivl <options> <file>\n"
991 "options:\n"
992 "\t-C <name>        Config file from driver.\n"
993 "\t-F <file>        List of source files from driver.\n"
994 "\t-h               Print usage information, and exit.\n"
995 "\t-N <file>        Dump the elaborated netlist to <file>.\n"
996 "\t-P <file>        Write the parsed input to <file>.\n"
997 "\t-p <assign>      Set a parameter value.\n"
998 "\t-v               Print progress indications"
999 #if defined(HAVE_TIMES)
1000                                            " and execution times"
1001 #endif
1002                                            ".\n"
1003 "\t-V               Print version and copyright information, and exit.\n"
1004 
1005 		  ;
1006 	    return 0;
1007       }
1008 
1009       int arg = optind;
1010       while (arg < argc) {
1011 	    perm_string path = filename_strings.make(argv[arg++]);
1012 	    source_files.push_back(path);
1013       }
1014 
1015       if (source_files.empty()) {
1016 	    cerr << "No input files." << endl;
1017 	    return 1;
1018       }
1019 
1020       separate_compilation = source_files.size() > 1;
1021 
1022       if( depfile_name ) {
1023 	      depend_file = fopen(depfile_name, "a");
1024 	      if(! depend_file) {
1025 		      perror(depfile_name);
1026 	      }
1027       }
1028 
1029       lexor_keyword_mask = 0;
1030       switch (generation_flag) {
1031         case GN_VER2012:
1032 	  lexor_keyword_mask |= GN_KEYWORDS_1800_2012;
1033 	  // fallthrough
1034         case GN_VER2009:
1035 	  lexor_keyword_mask |= GN_KEYWORDS_1800_2009;
1036 	  // fallthrough
1037         case GN_VER2005_SV:
1038 	  lexor_keyword_mask |= GN_KEYWORDS_1800_2005;
1039 	  // fallthrough
1040         case GN_VER2005:
1041 	  lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
1042 	  // fallthrough
1043         case GN_VER2001:
1044 	  lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
1045 	  // fallthrough
1046         case GN_VER2001_NOCONFIG:
1047 	  lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
1048 	  // fallthrough
1049         case GN_VER1995:
1050 	  lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
1051       }
1052 
1053       if (gn_cadence_types_flag)
1054 	    lexor_keyword_mask |= GN_KEYWORDS_ICARUS;
1055 
1056       if (gn_verilog_ams_flag)
1057 	    lexor_keyword_mask |= GN_KEYWORDS_VAMS_2_3;
1058 
1059       if (verbose_flag) {
1060 	    if (times_flag)
1061 		  times(cycles+0);
1062 
1063 	    cout << "Using language generation: ";
1064 	    switch (generation_flag) {
1065 		case GN_VER1995:
1066 		  cout << "IEEE1364-1995";
1067 		  break;
1068 		case GN_VER2001_NOCONFIG:
1069 		  cout << "IEEE1364-2001-noconfig";
1070 		  break;
1071 		case GN_VER2001:
1072 		  cout << "IEEE1364-2001";
1073 		  break;
1074 		case GN_VER2005:
1075 		  cout << "IEEE1364-2005";
1076 		  break;
1077 		case GN_VER2005_SV:
1078 		  cout << "IEEE1800-2005";
1079 		  break;
1080 		case GN_VER2009:
1081 		  cout << "IEEE1800-2009";
1082 		  break;
1083 		case GN_VER2012:
1084 		  cout << "IEEE1800-2012";
1085 		  break;
1086 	    }
1087 
1088 	    if (gn_verilog_ams_flag)
1089 		  cout << ",verilog-ams";
1090 
1091 	    if (gn_specify_blocks_flag)
1092 		  cout << ",specify";
1093 	    else
1094 		  cout << ",no-specify";
1095 
1096 	    if (gn_cadence_types_flag)
1097 		  cout << ",xtypes";
1098 	    else
1099 		  cout << ",no-xtypes";
1100 
1101 	    if (gn_icarus_misc_flag)
1102 		  cout << ",icarus-misc";
1103 	    else
1104 		  cout << ",no-icarus-misc";
1105 
1106 	    cout << endl << "PARSING INPUT" << endl;
1107       }
1108 
1109       const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"];
1110       if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0;
1111 
1112       flag_tmp = flags["ARRAY_SIZE_LIMIT"];
1113       if (flag_tmp) array_size_limit = strtoul(flag_tmp,NULL,0);
1114 
1115       flag_tmp = flags["RECURSIVE_MOD_LIMIT"];
1116       if (flag_tmp) recursive_mod_limit = strtoul(flag_tmp,NULL,0);
1117 
1118       flag_tmp = flags["DISABLE_CONCATZ_GENERATION"];
1119       if (flag_tmp) disable_concatz_generation = strcmp(flag_tmp,"true")==0;
1120 
1121 	/* Parse the input. Make the pform. */
1122       int rc = 0;
1123       for (unsigned idx = 0; idx < source_files.size(); idx += 1) {
1124 	    rc += pform_parse(source_files[idx]);
1125       }
1126 
1127       if (pf_path) {
1128 	    ofstream out (pf_path);
1129 	    out << "PFORM DUMP NATURES:" << endl;
1130 	    for (map<perm_string,ivl_nature_t>::iterator cur = natures.begin()
1131 		       ; cur != natures.end() ; ++ cur ) {
1132 		  pform_dump(out, (*cur).second);
1133 	    }
1134 	    out << "PFORM DUMP DISCIPLINES:" << endl;
1135 	    for (map<perm_string,ivl_discipline_t>::iterator cur = disciplines.begin()
1136 		       ; cur != disciplines.end() ; ++ cur ) {
1137 		  pform_dump(out, (*cur).second);
1138 	    }
1139 	    out << "PFORM DUMP COMPILATION UNITS:" << endl;
1140 	    for (vector<PPackage*>::iterator pac = pform_units.begin()
1141 		       ; pac != pform_units.end() ; ++ pac) {
1142 		  pform_dump(out, *pac);
1143 	    }
1144 	    out << "PFORM DUMP PACKAGES:" << endl;
1145 	    for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
1146 		       ; pac != pform_packages.end() ; ++ pac) {
1147 		  pform_dump(out, pac->second);
1148 	    }
1149 	    out << "PFORM DUMP MODULES:" << endl;
1150 	    for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
1151 		       ; mod != pform_modules.end() ; ++ mod ) {
1152 		  pform_dump(out, (*mod).second);
1153 	    }
1154 	    out << "PFORM DUMP PRIMITIVES:" << endl;
1155 	    for (map<perm_string,PUdp*>::iterator idx = pform_primitives.begin()
1156 		       ; idx != pform_primitives.end() ; ++ idx ) {
1157 		  (*idx).second->dump(out);
1158 	    }
1159       }
1160 
1161       if (rc) {
1162 	    return rc;
1163       }
1164 
1165 
1166 	/* If the user did not give specific module(s) to start with,
1167 	   then look for modules that are not instantiated anywhere.  */
1168 
1169       if (roots.empty()) {
1170 	    map<perm_string,bool> mentioned_p;
1171 	    map<perm_string,Module*>::iterator mod;
1172 	    if (verbose_flag)
1173 		  cout << "LOCATING TOP-LEVEL MODULES" << endl << "  ";
1174 	    for (mod = pform_modules.begin()
1175 		       ; mod != pform_modules.end() ; ++ mod ) {
1176 		  find_module_mention(mentioned_p, mod->second);
1177 	    }
1178 
1179 	    for (mod = pform_modules.begin()
1180 		       ; mod != pform_modules.end() ; ++ mod ) {
1181 
1182 		    /* Don't choose library modules. */
1183 		  if ((*mod).second->library_flag)
1184 			continue;
1185 
1186 		    /* Don't choose modules instantiated in other
1187 		       modules. */
1188 		  if (mentioned_p[(*mod).second->mod_name()])
1189 			continue;
1190 
1191 		    /* What's left might as well be chosen as a root. */
1192 		  if (verbose_flag)
1193 			cout << " " << (*mod).second->mod_name();
1194 		  roots.push_back((*mod).second->mod_name());
1195 	    }
1196 	    if (verbose_flag)
1197 		  cout << endl;
1198       }
1199 
1200 	/* If there is *still* no guess for the root module, then give
1201 	   up completely, and complain. */
1202 
1203       if (roots.empty()) {
1204 	    cerr << "No top level modules, and no -s option." << endl;
1205 	    return ignore_missing_modules ? 0 : 1;
1206       }
1207 
1208 
1209       if (verbose_flag) {
1210 	    if (times_flag) {
1211 		  times(cycles+1);
1212 		  cerr<<" ... done, "
1213 		      <<cycles_diff(cycles+1, cycles+0)<<" seconds."<<endl;
1214 	    }
1215 	    cout << "ELABORATING DESIGN" << endl;
1216       }
1217 
1218 	/* Decide if we are going to allow system functions to be called
1219 	 * as tasks. */
1220       if (gn_system_verilog()) {
1221 	    def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING;
1222       }
1223 
1224 	/* On with the process of elaborating the module. */
1225       Design*des = elaborate(roots);
1226 
1227       if ((des == 0) || (des->errors > 0)) {
1228 	    if (des != 0) {
1229 		  cerr << des->errors
1230 		       << " error(s) during elaboration." << endl;
1231 		  if (net_path) {
1232 			ofstream out (net_path);
1233 			des->dump(out);
1234 		  }
1235 	    } else {
1236 		  cerr << "Elaboration failed" << endl;
1237 	    }
1238 
1239 	    goto errors_summary;
1240       }
1241 
1242       des->set_flags(flags);
1243 
1244       switch(min_typ_max_flag) {
1245 	case MIN:
1246 	    des->set_delay_sel(Design::MIN);
1247 	    break;
1248 	case TYP:
1249 	    des->set_delay_sel(Design::TYP);
1250 	    break;
1251 	case MAX:
1252 	    des->set_delay_sel(Design::MAX);
1253 	    break;
1254 	default:
1255 	    assert(0);
1256       }
1257 
1258 	/* Done with all the pform data. Delete the modules. */
1259       for (map<perm_string,Module*>::iterator idx = pform_modules.begin()
1260 		 ; idx != pform_modules.end() ; ++ idx ) {
1261 
1262 	    delete (*idx).second;
1263 	    (*idx).second = 0;
1264       }
1265 
1266       if (verbose_flag) {
1267 	    if (times_flag) {
1268 		  times(cycles+2);
1269 		  cerr<<" ... done, "
1270 		      <<cycles_diff(cycles+2, cycles+1)<<" seconds."<<endl;
1271 	    }
1272 	    cout << "RUNNING FUNCTORS" << endl;
1273       }
1274 
1275       while (!net_func_queue.empty()) {
1276 	    net_func func = net_func_queue.front();
1277 	    net_func_queue.pop();
1278 	    if (verbose_flag)
1279 		  cerr<<" -F "<<net_func_to_name(func)<< " ..." <<endl;
1280 	    func(des);
1281       }
1282 
1283       if (verbose_flag) {
1284 	    cout << "CALCULATING ISLANDS" << endl;
1285       }
1286       des->join_islands();
1287 
1288       if (net_path) {
1289 	    if (verbose_flag)
1290 		  cerr<<" dumping netlist to " <<net_path<< "..." <<endl;
1291 
1292 	    ofstream out (net_path);
1293 	    des->dump(out);
1294       }
1295 
1296       if (des->errors) {
1297 	    cerr << des->errors
1298 		 << " error(s) in post-elaboration processing." <<
1299 		  endl;
1300 	    return des->errors;
1301       }
1302 
1303       if (verbose_flag) {
1304 	    if (times_flag) {
1305 		  times(cycles+3);
1306 		  cerr<<" ... done, "
1307 		      <<cycles_diff(cycles+3, cycles+2)<<" seconds."<<endl;
1308 	    }
1309       }
1310 
1311       if (verbose_flag) {
1312 	    cout << "CODE GENERATION" << endl;
1313       }
1314 
1315       if (int emit_rc = des->emit(&dll_target_obj)) {
1316 	    if (emit_rc > 0) {
1317 		  cerr << "error: Code generation had "
1318 		       << emit_rc << " error(s)."
1319 		       << endl;
1320 		  return 1;
1321 	    }
1322 	    if (emit_rc < 0) {
1323 		  cerr << "error: Code generator failure: " << emit_rc << endl;
1324 		  return -1;
1325 	    }
1326 	    assert(emit_rc);
1327       }
1328 
1329       if (verbose_flag) {
1330 	    if (times_flag) {
1331 		  times(cycles+4);
1332 		  cerr<<" ... done, "
1333 		      <<cycles_diff(cycles+4, cycles+3)<<" seconds."<<endl;
1334 	    } else {
1335 		  cout << "DONE." << endl;
1336 	    }
1337       }
1338 
1339       if (verbose_flag) {
1340 	    cout << "STATISTICS" << endl;
1341 	    cout << "lex_string:"
1342 		 << " add_count=" << lex_strings.add_count()
1343 		 << " hit_count=" << lex_strings.add_hit_count()
1344 		 << endl;
1345       }
1346 
1347       delete des;
1348       EOC_cleanup();
1349       return 0;
1350 
1351  errors_summary:
1352       if (! missing_modules.empty()) {
1353 	    cerr << "*** These modules were missing:" << endl;
1354 
1355 	    map<perm_string,unsigned>::const_iterator idx;
1356 	    for (idx = missing_modules.begin()
1357 		       ; idx != missing_modules.end() ; ++ idx )
1358 		  cerr << "        " << (*idx).first
1359 		       << " referenced " << (*idx).second
1360 		       << " times."<< endl;
1361 
1362 	    cerr << "***" << endl;
1363       }
1364 
1365       return des? des->errors : 1;
1366 }
1367 
find_module_mention(map<perm_string,bool> & check_map,Module * mod)1368 static void find_module_mention(map<perm_string,bool>&check_map, Module*mod)
1369 {
1370       list<PGate*> gates = mod->get_gates();
1371       list<PGate*>::const_iterator gate;
1372       for (gate = gates.begin(); gate != gates.end(); ++ gate ) {
1373 	    PGModule*tmp = dynamic_cast<PGModule*>(*gate);
1374 	    if (tmp) {
1375 		    // Note that this module has been instantiated
1376 		  check_map[tmp->get_type()] = true;
1377 	    }
1378       }
1379 
1380       list<PGenerate*>::const_iterator cur;
1381       for (cur = mod->generate_schemes.begin()
1382 		 ; cur != mod->generate_schemes.end() ; ++ cur ) {
1383 	    find_module_mention(check_map, *cur);
1384       }
1385 }
1386 
find_module_mention(map<perm_string,bool> & check_map,PGenerate * schm)1387 static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*schm)
1388 {
1389       list<PGate*>::const_iterator gate;
1390       for (gate = schm->gates.begin(); gate != schm->gates.end(); ++ gate ) {
1391 	    PGModule*tmp = dynamic_cast<PGModule*>(*gate);
1392 	    if (tmp) {
1393 		    // Note that this module has been instantiated
1394 		  check_map[tmp->get_type()] = true;
1395 	    }
1396       }
1397 
1398       list<PGenerate*>::const_iterator cur;
1399       for (cur = schm->generate_schemes.begin()
1400 		 ; cur != schm->generate_schemes.end() ; ++ cur ) {
1401 	    find_module_mention(check_map, *cur);
1402       }
1403 }
1404