const char COPYRIGHT[] = "Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)"; /* * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU * General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) #ident "$Id: main.cc,v 1.50 2001/10/20 23:02:40 steve Exp $" #endif # include "config.h" const char NOTICE[] = " This program is free software; you can redistribute it and/or modify\n" " it under the terms of the GNU General Public License as published by\n" " the Free Software Foundation; either version 2 of the License, or\n" " (at your option) any later version.\n" "\n" " This program is distributed in the hope that it will be useful,\n" " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" " GNU General Public License for more details.\n" "\n" " You should have received a copy of the GNU General Public License\n" " along with this program; if not, write to the Free Software\n" " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n" ; # include # include # include # include # include # include # include # include #if defined(HAVE_TIMES) # include #endif #if defined(HAVE_GETOPT_H) # include #endif # include "pform.h" # include "parse_api.h" # include "netlist.h" # include "target.h" # include "compiler.h" #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H) extern "C" int getopt(int argc, char*argv[], const char*fmt); extern "C" int optind; extern "C" const char*optarg; #endif #if defined(__CYGWIN32__) && !defined(HAVE_GETOPT_H) extern "C" int getopt(int argc, char*argv[], const char*fmt); extern "C" int optind; extern "C" const char*optarg; #endif const char VERSION[] = "$Name: $ $State: Exp $"; const char*target = "null"; map flags; list library_dirs; /* * These are the warning enable flags. */ bool warn_implicit = false; /* * Verbose messages enabled. */ bool verbose_flag = false; static void parm_to_flagmap(const string&flag) { string key, value; unsigned off = flag.find('='); if (off > flag.size()) { key = flag; value = ""; } else { key = flag.substr(0, off); value = flag.substr(off+1); } flags[key] = value; } extern Design* elaborate(list root); extern void cprop(Design*des); extern void synth(Design*des); extern void syn_rules(Design*des); extern void nodangle(Design*des); extern void xnfio(Design*des); typedef void (*net_func)(Design*); static struct net_func_map { const char*name; void (*func)(Design*); } func_table[] = { { "cprop", &cprop }, { "nodangle",&nodangle }, { "synth", &synth }, { "syn-rules", &syn_rules }, { "xnfio", &xnfio }, { 0, 0 } }; net_func name_to_net_func(const string&name) { for (unsigned idx = 0 ; func_table[idx].name ; idx += 1) if (name == func_table[idx].name) return func_table[idx].func; return 0; } const char *net_func_to_name(const net_func func) { for (unsigned idx = 0 ; func_table[idx].name ; idx += 1) if (func == func_table[idx].func) return func_table[idx].name; return "This cannot happen"; } #if defined(HAVE_TIMES) static double cycles_diff(struct tms *a, struct tms *b) { clock_t aa = a->tms_utime + a->tms_stime + a->tms_cutime + a->tms_cstime; clock_t bb = b->tms_utime + b->tms_stime + b->tms_cutime + b->tms_cstime; return (aa-bb)/(double)sysconf(_SC_CLK_TCK); } #else // ! defined(HAVE_TIMES) // Provide dummies struct tms { int x; }; inline static void times(struct tms *) { } inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; } #endif // ! defined(HAVE_TIMES) int main(int argc, char*argv[]) { bool help_flag = false; bool times_flag = false; const char* net_path = 0; const char* pf_path = 0; const char* warn_en = ""; int opt; unsigned flag_errors = 0; queue net_func_queue; list roots; struct tms cycles[5]; flags["VPI_MODULE_LIST"] = "system"; flags["-o"] = "a.out"; min_typ_max_flag = TYP; min_typ_max_warn = 10; while ((opt = getopt(argc, argv, "F:f:hm:N:o:P:p:s:T:t:VvW:y:")) != EOF) switch (opt) { case 'F': { net_func tmp = name_to_net_func(optarg); if (tmp == 0) { cerr << "No such design transform function ``" << optarg << "''." << endl; flag_errors += 1; break; } net_func_queue.push(tmp); break; } case 'f': parm_to_flagmap(optarg); break; case 'h': help_flag = true; break; case 'm': flags["VPI_MODULE_LIST"] = flags["VPI_MODULE_LIST"]+","+optarg; break; case 'N': net_path = optarg; break; case 'o': flags["-o"] = optarg; break; case 'P': pf_path = optarg; break; case 'p': parm_to_flagmap(optarg); break; case 's': roots.push_back(optarg); break; case 'T': if (strcmp(optarg,"min") == 0) { min_typ_max_flag = MIN; min_typ_max_warn = 0; } else if (strcmp(optarg,"typ") == 0) { min_typ_max_flag = TYP; min_typ_max_warn = 0; } else if (strcmp(optarg,"max") == 0) { min_typ_max_flag = MAX; min_typ_max_warn = 0; } else { cerr << "Invalid argument (" << optarg << ") to -T flag." << endl; flag_errors += 1; } break; case 't': target = optarg; break; case 'v': verbose_flag = true; # if defined(HAVE_TIMES) times_flag = true; # endif break; case 'V': cout << "Icarus Verilog version " << VERSION << endl; cout << COPYRIGHT << endl; cout << endl << NOTICE << endl; return 0; case 'W': warn_en = optarg; break; case 'y': library_dirs.push_back(optarg); break; default: flag_errors += 1; break; } if (flag_errors) return flag_errors; if (help_flag) { cout << "Icarus Verilog version " << VERSION << endl << "usage: ivl \n" "options:\n" "\t-F Apply netlist function .\n" "\t-h Print usage information, and exit.\n" "\t-m Load vpi module .\n" "\t-N Dump the elaborated netlist to .\n" "\t-o Write output to .\n" "\t-P Write the parsed input to .\n" "\t-p Set a parameter value.\n" "\t-s Select the top-level module.\n" "\t-T [min|typ|max] Select timing corner.\n" "\t-t Select target .\n" "\t-v Print progress indications" #if defined(HAVE_TIMES) " and execution times" #endif ".\n" "\t-V Print version and copyright information, and exit.\n" "\t-y Add directory to library search path.\n" ; cout << "Netlist functions:" << endl; for (unsigned idx = 0 ; func_table[idx].name ; idx += 1) cout << "\t-F " << func_table[idx].name << endl; cout << "Target types:" << endl; for (unsigned idx = 0 ; target_table[idx] ; idx += 1) cout << "\t-t " << target_table[idx]->name << endl; return 0; } if (optind == argc) { cerr << "No input files." << endl; return 1; } /* Scan the warnings enable string for warning flags. */ for (const char*cp = warn_en ; *cp ; cp += 1) switch (*cp) { case 'i': warn_implicit = true; break; default: break; } if (verbose_flag) { if (times_flag) times(cycles+0); cout << "PARSING INPUT ..." << endl; } /* Parse the input. Make the pform. */ int rc = pform_parse(argv[optind]); if (pf_path) { ofstream out (pf_path); out << "PFORM DUMP MODULES:" << endl; for (map::iterator mod = pform_modules.begin() ; mod != pform_modules.end() ; mod ++ ) { pform_dump(out, (*mod).second); } out << "PFORM DUMP PRIMITIVES:" << endl; for (map::iterator idx = pform_primitives.begin() ; idx != pform_primitives.end() ; idx ++ ) { (*idx).second->dump(out); } } if (rc) { return rc; } /* If the user did not give specific module(s) to start with, then look for modules that are not instantiated anywhere. */ if (roots.empty()) { map mentioned_p; map::iterator mod; if (verbose_flag) cout << "LOCATING TOP-LEVEL MODULES..." << endl << " "; for (mod = pform_modules.begin() ; mod != pform_modules.end() ; mod++) { list gates = (*mod).second->get_gates(); list::const_iterator gate; for (gate = gates.begin(); gate != gates.end(); gate++) { PGModule *mod = dynamic_cast(*gate); if (mod) { // Note that this module has been instantiated mentioned_p[mod->get_type()] = true; } } } for (mod = pform_modules.begin() ; mod != pform_modules.end() ; mod++) { if (mentioned_p[(*mod).second->mod_name()] == false) { if (verbose_flag) cout << " " << (*mod).second->mod_name(); roots.push_back((*mod).second->mod_name()); } } if (verbose_flag) cout << endl; } /* If there is *still* no guess for the root module, then give up completely, and complain. */ if (roots.empty()) { cerr << "No top level modules, and no -s option." << endl; return 1; } if (verbose_flag) { if (times_flag) { times(cycles+1); cerr<<" ... done, " <errors) { cerr << des->errors << " error(s) during elaboration." << endl; return des->errors; } des->set_flags(flags); if (verbose_flag) { if (times_flag) { times(cycles+2); cerr<<" ... done, " <dump(out); } if (verbose_flag) { if (times_flag) { times(cycles+3); cerr<<" ... done, " <