Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1241 lines (1053 sloc) 32.228 kb
const char COPYRIGHT[] =
"Copyright (c) 1998-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include "version_base.h"
# include "version_tag.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 along\n"
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
;
# include <cstdio>
# include <iostream>
# include <fstream>
# include <queue>
# include <cstring>
# include <list>
# include <map>
# include <unistd.h>
# include <cstdlib>
#if defined(HAVE_TIMES)
# include <sys/times.h>
#endif
#if defined(HAVE_GETOPT_H)
# include <getopt.h>
#endif
# include "pform.h"
# include "parse_api.h"
# include "PGenerate.h"
# include "netlist.h"
# include "target.h"
# include "compiler.h"
# include "discipline.h"
# include "t-dll.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
#if defined(TRAP_SIGINT_FOR_DEBUG)
/*
* This is a debugging aid. Do not compile it in general, but leave it
* here for those days when I need the ability to cleanly exit on a
* signal interrupt.
*/
# include <csignal>
static void signals_handler(int sig)
{
fprintf(stderr, "Exit on signal %d\n", sig);
exit(1);
}
#endif
# include "ivl_alloc.h"
/* Count errors detected in flag processing. */
unsigned flag_errors = 0;
const char*basedir = strdup(".");
/*
* These are the language support control flags. These support which
* language features (the generation) to support. The generation_flag
* is a major mode, and the gn_* flags control specific sub-features.
*/
generation_t generation_flag = GN_DEFAULT;
bool gn_icarus_misc_flag = true;
bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
bool gn_io_range_error_flag = true;
bool gn_strict_ca_eval_flag = false;
bool gn_strict_expr_width_flag = false;
bool gn_verilog_ams_flag = false;
/*
* For some generations we allow a system function to be called
* as a task and only print a warning message. The default for
* this is that it is a run time error.
*/
ivl_sfunc_as_task_t def_sfunc_as_task = IVL_SFUNC_AS_TASK_ERROR;
map<string,const char*> flags;
char*vpi_module_list = 0;
void add_vpi_module(const char*name)
{
if (vpi_module_list == 0) {
vpi_module_list = strdup(name);
} else {
char*tmp = (char*)realloc(vpi_module_list,
strlen(vpi_module_list)
+ strlen(name)
+ 2);
strcat(tmp, ",");
strcat(tmp, name);
vpi_module_list = tmp;
}
flags["VPI_MODULE_LIST"] = vpi_module_list;
}
map<perm_string,unsigned> missing_modules;
map<perm_string,bool> library_file_map;
list<const char*> library_suff;
list<perm_string> roots;
char*ivlpp_string = 0;
char depfile_mode = 'a';
char* depfile_name = NULL;
FILE *depend_file = NULL;
/*
* These are the warning enable flags.
*/
bool warn_implicit = false;
bool warn_timescale = false;
bool warn_portbinding = false;
bool warn_inf_loop = false;
bool warn_ob_select = false;
bool warn_sens_entire_vec = false;
bool warn_sens_entire_arr = false;
bool warn_anachronisms = false;
/*
* Debug message class flags.
*/
bool debug_scopes = false;
bool debug_eval_tree = false;
bool debug_elaborate = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
/*
* Miscellaneous flags.
*/
bool disable_virtual_pins = false;
unsigned long array_size_limit = 16777216; // Minimum required by IEEE-1364?
unsigned recursive_mod_limit = 10;
/*
* Verbose messages enabled.
*/
bool verbose_flag = false;
unsigned integer_width = 32;
int def_ts_units = 0;
int def_ts_prec = 0;
/*
* Keep a heap of identifier strings that I encounter. This is a more
* efficient way to allocate those strings.
*/
StringHeapLex lex_strings;
StringHeapLex filename_strings;
StringHeapLex bits_strings;
/*
* In library searches, Windows file names are never case sensitive.
*/
#if defined(__MINGW32__)
const bool CASE_SENSITIVE = false;
#else
const bool CASE_SENSITIVE = true;
#endif
/*
* Are we doing synthesis?
*/
bool synthesis = false;
extern void cprop(Design*des);
extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
extern void nodangle(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 },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
{ 0, 0 }
};
queue<net_func> net_func_queue;
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";
}
static void process_generation_flag(const char*gen)
{
if (strcmp(gen,"1") == 0) { // FIXME: Deprecated for 1995
generation_flag = GN_VER1995;
} else if (strcmp(gen,"2") == 0) { // FIXME: Deprecated for 2001
generation_flag = GN_VER2001;
} else if (strcmp(gen,"2x") == 0) { // FIXME: Deprecated for 2001
generation_flag = GN_VER2001;
gn_icarus_misc_flag = true;
} else if (strcmp(gen,"1995") == 0) {
generation_flag = GN_VER1995;
} else if (strcmp(gen,"2001") == 0) {
generation_flag = GN_VER2001;
} else if (strcmp(gen,"2001-noconfig") == 0) {
generation_flag = GN_VER2001_NOCONFIG;
} else if (strcmp(gen,"2005") == 0) {
generation_flag = GN_VER2005;
} else if (strcmp(gen,"2005-sv") == 0) {
generation_flag = GN_VER2005_SV;
} else if (strcmp(gen,"2009") == 0) {
generation_flag = GN_VER2009;
} else if (strcmp(gen,"icarus-misc") == 0) {
gn_icarus_misc_flag = true;
} else if (strcmp(gen,"no-icarus-misc") == 0) {
gn_icarus_misc_flag = false;
} else if (strcmp(gen,"xtypes") == 0) {
gn_cadence_types_flag = true;
} else if (strcmp(gen,"no-xtypes") == 0) {
gn_cadence_types_flag = false;
} else if (strcmp(gen,"specify") == 0) {
gn_specify_blocks_flag = true;
} else if (strcmp(gen,"no-specify") == 0) {
gn_specify_blocks_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true;
} else if (strcmp(gen,"no-verilog-ams") == 0) {
gn_verilog_ams_flag = false;
} else if (strcmp(gen,"io-range-error") == 0) {
gn_io_range_error_flag = true;
} else if (strcmp(gen,"no-io-range-error") == 0) {
gn_io_range_error_flag = false;
} else if (strcmp(gen,"strict-ca-eval") == 0) {
gn_strict_ca_eval_flag = true;
} else if (strcmp(gen,"no-strict-ca-eval") == 0) {
gn_strict_ca_eval_flag = false;
} else if (strcmp(gen,"strict-expr-width") == 0) {
gn_strict_expr_width_flag = true;
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
gn_strict_expr_width_flag = false;
} else {
}
}
static void parm_to_flagmap(const string&flag)
{
string key;
const char*value;
unsigned off = flag.find('=');
if (off > flag.size()) {
key = flag;
value = strdup("");
} else {
key = flag.substr(0, off);
value = strdup(flag.substr(off+1).c_str());
}
flags[key] = value;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*m);
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
/*
* Convert a string to a time unit or precision.
*
* Returns true on failure.
*/
static bool get_ts_const(const char*&cp, int&res, bool is_units)
{
/* Check for the 1 digit. */
if (*cp != '1') {
if (is_units) {
cerr << "Error: Invalid +timescale units constant "
"(1st digit)." << endl;
} else {
cerr << "Error: Invalid +timescale precision constant "
"(1st digit)." << endl;
}
return true;
}
cp += 1;
/* Check the number of zeros after the 1. */
res = strspn(cp, "0");
if (res > 2) {
if (is_units) {
cerr << "Error: Invalid +timescale units constant "
"(number of zeros)." << endl;
} else {
cerr << "Error: Invalid +timescale precision constant "
"(number of zeros)." << endl;
}
return true;
}
cp += res;
/* Now process the scaling string. */
if (strncmp("s", cp, 1) == 0) {
res -= 0;
cp += 1;
return false;
} else if (strncmp("ms", cp, 2) == 0) {
res -= 3;
cp += 2;
return false;
} else if (strncmp("us", cp, 2) == 0) {
res -= 6;
cp += 2;
return false;
} else if (strncmp("ns", cp, 2) == 0) {
res -= 9;
cp += 2;
return false;
} else if (strncmp("ps", cp, 2) == 0) {
res -= 12;
cp += 2;
return false;
} else if (strncmp("fs", cp, 2) == 0) {
res -= 15;
cp += 2;
return false;
}
if (is_units) {
cerr << "Error: Invalid +timescale units scale." << endl;
} else {
cerr << "Error: Invalid +timescale precision scale." << endl;
}
return true;
}
/*
* Process a string with the following form (no space allowed):
*
* num = < '1' | '10' | '100' >
* scale = < 's' | 'ms' | 'us' | 'ns' | 'ps' | 'fs' >
*
* "<num> <scale> '/' <num> <scale>
*
* and set the default time units and precision if successful.
*
* Return true if we have an error processing the timescale string.
*/
static bool set_default_timescale(const char*ts_string)
{
/* Because this came from a command file we can not have embedded
* space in this string. */
const char*cp = ts_string;
int units = 0;
int prec = 0;
/* Get the time units. */
if (get_ts_const(cp, units, true)) return true;
/* Skip the '/'. */
if (*cp != '/') {
cerr << "Error: +timescale separator '/' is missing." << endl;
return true;
}
cp += 1;
/* Get the time precision. */
if (get_ts_const(cp, prec, false)) return true;
/* The time unit must be greater than or equal to the precision. */
if (units < prec) {
cerr << "Error: +timescale unit must not be less than the "
"precision." << endl;
return true;
}
/* We have valid units and precision so set the global defaults. */
def_ts_units = units;
def_ts_prec = prec;
return false;
}
/*
* Read the contents of a config file. This file is a temporary
* configuration file made by the compiler driver to carry the bulky
* flags generated from the user. This reduces the size of the command
* line needed to invoke ivl.
*
* Each line of the iconfig file has the format:
*
* <keyword>:<value>
*
* The <value> is all the text after the ':' and up to but not
* including the end of the line. Thus, white spaces and ':'
* characters may appear here.
*
* The valid keys are:
*
* -y:<dir>
* -yl:<dir>
* -Y:<string>
*
* -T:<min/typ/max>
* Select which expression to use.
*
* -t:<target> (obsolete)
* Usually, "-t:dll"
*
* basedir:<path>
* Location to look for installed sub-components
*
* debug:<name>
* Activate a class of debug messages.
*
* depfile:<path>
* Give the path to an output dependency file.
*
* flag:<name>=<string>
* Generic compiler flag strings.
*
* functor:<name>
* Append a named functor to the processing path.
*
* generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
* This is the generation flag
*
* ivlpp:<preprocessor command>
* This specifies the ivlpp command line used to process
* library modules as I read them in.
*
* iwidth:<bits>
* This specifies the width of integer variables. (that is,
* variables declared using the "integer" keyword.)
*
* library_file:<path>
* This marks that a source file with the given path is a
* library. Any modules in that file are marked as library
* modules.
*
* module:<name>
* Load a VPI module.
*
* out:<path>
* Path to the output file.
*
* sys_func:<path>
* Path to a system functions descriptor table
*
* root:<name>
* Specify a root module. There may be multiple of this.
*
* warnings:<string>
* Warning flag letters.
*/
bool had_timescale = false;
static void read_iconfig_file(const char*ipath)
{
char buf[8*1024];
FILE*ifile = fopen(ipath, "r");
if (ifile == 0) {
cerr << "ERROR: Unable to read config file: " << ipath << endl;
return;
}
while (fgets(buf, sizeof buf, ifile) != 0) {
if (buf[0] == '#')
continue;
char*cp = strchr(buf, ':');
if (cp == 0)
continue;
*cp++ = 0;
char*ep = cp + strlen(cp);
while (ep > cp) {
ep -= 1;
switch (*ep) {
case '\r':
case '\n':
case ' ':
case '\t':
*ep = 0;
break;
default:
ep = cp;
}
}
if (strcmp(buf, "basedir") == 0) {
free((void *)basedir);
basedir = strdup(cp);
} else if (strcmp(buf, "debug") == 0) {
if (strcmp(cp, "scopes") == 0) {
debug_scopes = true;
cerr << "debug: Enable scopes debug" << endl;
} else if (strcmp(cp,"eval_tree") == 0) {
debug_eval_tree = true;
cerr << "debug: Enable eval_tree debug" << endl;
} else if (strcmp(cp,"elaborate") == 0) {
debug_elaborate = true;
cerr << "debug: Enable elaborate debug" << endl;
} else if (strcmp(cp,"synth2") == 0) {
debug_synth2 = true;
cerr << "debug: Enable synth2 debug" << endl;
} else if (strcmp(cp,"optimizer") == 0) {
debug_optimizer = true;
cerr << "debug: Enable optimizer debug" << endl;
} else {
}
} else if (strcmp(buf, "depmode") == 0) {
depfile_mode = *cp;
} else if (strcmp(buf, "depfile") == 0) {
depfile_name = strdup(cp);
} else if (strcmp(buf, "flag") == 0) {
string parm = cp;
parm_to_flagmap(parm);
} else if (strcmp(buf,"functor") == 0) {
if (strncmp(cp, "synth", 5) == 0) {
synthesis = true; // We are doing synthesis.
}
net_func tmp = name_to_net_func(cp);
if (tmp == 0) {
cerr << "No such design transform function ``"
<< cp << "''." << endl;
flag_errors += 1;
break;
}
net_func_queue.push(tmp);
} else if (strcmp(buf, "generation") == 0) {
process_generation_flag(cp);
} else if (strcmp(buf, "ivlpp") == 0) {
ivlpp_string = strdup(cp);
} else if (strcmp(buf, "iwidth") == 0) {
integer_width = strtoul(cp,0,10);
} else if (strcmp(buf, "library_file") == 0) {
perm_string path = filename_strings.make(cp);
library_file_map[path] = true;
} else if (strcmp(buf,"module") == 0) {
add_vpi_module(cp);
} else if (strcmp(buf, "out") == 0) {
free((void *)flags["-o"]);
flags["-o"] = strdup(cp);
} else if (strcmp(buf, "sys_func") == 0) {
load_sys_func_table(cp);
} else if (strcmp(buf, "root") == 0) {
roots.push_back(lex_strings.make(cp));
} else if (strcmp(buf,"warnings") == 0) {
/* Scan the warnings enable string for warning flags. */
for ( ; *cp ; cp += 1) switch (*cp) {
case 'i':
warn_implicit = true;
break;
case 'l':
warn_inf_loop = true;
break;
case 's':
warn_ob_select = true;
break;
case 'p':
warn_portbinding = true;
break;
case 't':
warn_timescale = true;
break;
case 'v':
warn_sens_entire_vec = true;
break;
case 'a':
warn_sens_entire_arr = true;
break;
case 'n':
warn_anachronisms = true;
break;
default:
break;
}
} else if (strcmp(buf, "-y") == 0) {
build_library_index(cp, CASE_SENSITIVE);
} else if (strcmp(buf, "-yl") == 0) {
build_library_index(cp, false);
} else if (strcmp(buf, "-Y") == 0) {
library_suff.push_back(strdup(cp));
} else if (strcmp(buf,"-t") == 0) {
// NO LONGER USED
} else if (strcmp(buf,"-T") == 0) {
if (strcmp(cp,"min") == 0) {
min_typ_max_flag = MIN;
min_typ_max_warn = 0;
} else if (strcmp(cp,"typ") == 0) {
min_typ_max_flag = TYP;
min_typ_max_warn = 0;
} else if (strcmp(cp,"max") == 0) {
min_typ_max_flag = MAX;
min_typ_max_warn = 0;
} else {
cerr << "Invalid argument (" << optarg << ") to -T flag."
<< endl;
flag_errors += 1;
}
} else if (strcmp(buf,"defparam") == 0) {
parm_to_defparam_list(cp);
} else if (strcmp(buf,"timescale") == 0) {
if (had_timescale) {
cerr << "Command File: Warning: default timescale "
"is being set multiple times." << endl;
cerr << " : using the last valid "
"+timescale found." << endl;
}
if (set_default_timescale(cp)) {
cerr << " : with +timescale+" << cp << "+" << endl;
flag_errors += 1;
} else had_timescale = true;
}
}
fclose(ifile);
}
extern Design* elaborate(list <perm_string> root);
#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 *, struct tms *) { return 0; }
#endif // ! defined(HAVE_TIMES)
static void EOC_cleanup(void)
{
cleanup_sys_func_table();
for (list<const char*>::iterator suf = library_suff.begin() ;
suf != library_suff.end() ; ++ suf ) {
free((void *)*suf);
}
library_suff.clear();
free((void *) basedir);
free(ivlpp_string);
free(depfile_name);
for (map<string, const char*>::iterator flg = flags.begin() ;
flg != flags.end() ; ++ flg ) {
free((void *)flg->second);
}
flags.clear();
lex_strings.cleanup();
bits_strings.cleanup();
filename_strings.cleanup();
}
int main(int argc, char*argv[])
{
bool help_flag = false;
bool times_flag = false;
bool version_flag = false;
const char* net_path = 0;
const char* pf_path = 0;
int opt;
struct tms cycles[5];
#if defined(TRAP_SIGINT_FOR_DEBUG)
signal(SIGINT, &signals_handler);
#endif
if( ::getenv("IVL_WAIT_FOR_DEBUGGER") != 0 ) {
fprintf( stderr, "Waiting for debugger...\n");
bool debugger_release = false;
while( !debugger_release ) {
#if defined(__MINGW32__)
Sleep(1000);
#else
sleep(1);
#endif
}
}
library_suff.push_back(strdup(".v"));
// Start the module list with the base system module.
add_vpi_module("system");
add_vpi_module("vhdl_sys");
flags["-o"] = strdup("a.out");
min_typ_max_flag = TYP;
min_typ_max_warn = 10;
while ((opt = getopt(argc, argv, "C:f:hN:P:p:Vv")) != EOF) switch (opt) {
case 'C':
read_iconfig_file(optarg);
break;
case 'f':
parm_to_flagmap(optarg);
break;
case 'h':
help_flag = true;
break;
case 'N':
net_path = optarg;
break;
case 'P':
pf_path = optarg;
break;
case 'p':
parm_to_flagmap(optarg);
break;
case 'v':
verbose_flag = true;
# if defined(HAVE_TIMES)
times_flag = true;
# endif
break;
case 'V':
version_flag = true;
break;
default:
flag_errors += 1;
break;
}
if (flag_errors)
return flag_errors;
if (version_flag) {
cout << "\nIcarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl << endl;
cout << COPYRIGHT << endl << endl;
cout << NOTICE << endl;
cout << " FLAGS DLL " << flags["DLL"] << endl;
dll_target_obj.test_version(flags["DLL"]);
return 0;
}
if (help_flag) {
cout << "Icarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl <<
"usage: ivl <options> <file>\n"
"options:\n"
"\t-C <name> Config file from driver.\n"
"\t-h Print usage information, and exit.\n"
"\t-N <file> Dump the elaborated netlist to <file>.\n"
"\t-P <file> Write the parsed input to <file>.\n"
"\t-p <assign> Set a parameter value.\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"
;
return 0;
}
if (optind == argc) {
cerr << "No input files." << endl;
return 1;
}
if( depfile_name ) {
depend_file = fopen(depfile_name, "a");
if(! depend_file) {
perror(depfile_name);
}
}
lexor_keyword_mask = 0;
switch (generation_flag) {
case GN_VER2009:
lexor_keyword_mask |= GN_KEYWORDS_1800_2009;
case GN_VER2005_SV:
lexor_keyword_mask |= GN_KEYWORDS_1800_2005;
case GN_VER2005:
lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
case GN_VER2001:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
case GN_VER2001_NOCONFIG:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
case GN_VER1995:
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
}
if (gn_cadence_types_flag)
lexor_keyword_mask |= GN_KEYWORDS_ICARUS;
if (gn_verilog_ams_flag)
lexor_keyword_mask |= GN_KEYWORDS_VAMS_2_3;
if (verbose_flag) {
if (times_flag)
times(cycles+0);
cout << "Using language generation: ";
switch (generation_flag) {
case GN_VER1995:
cout << "IEEE1364-1995";
break;
case GN_VER2001_NOCONFIG:
cout << "IEEE1364-2001-noconfig";
break;
case GN_VER2001:
cout << "IEEE1364-2001";
break;
case GN_VER2005:
cout << "IEEE1364-2005";
break;
case GN_VER2005_SV:
cout << "IEEE1800-2005";
break;
case GN_VER2009:
cout << "IEEE1800-2009";
break;
}
if (gn_verilog_ams_flag)
cout << ",verilog-ams";
if (gn_specify_blocks_flag)
cout << ",specify";
else
cout << ",no-specify";
if (gn_cadence_types_flag)
cout << ",xtypes";
else
cout << ",no-xtypes";
if (gn_icarus_misc_flag)
cout << ",icarus-misc";
else
cout << ",no-icarus-misc";
cout << endl << "PARSING INPUT" << endl;
}
const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"];
if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0;
flag_tmp = flags["ARRAY_SIZE_LIMIT"];
if (flag_tmp) array_size_limit = strtoul(flag_tmp,NULL,0);
flag_tmp = flags["RECURSIVE_MOD_LIMIT"];
if (flag_tmp) recursive_mod_limit = strtoul(flag_tmp,NULL,0);
/* Parse the input. Make the pform. */
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
int rc = pform_parse(argv[optind]);
if (pf_path) {
ofstream out (pf_path);
out << "PFORM DUMP NATURES:" << endl;
for (map<perm_string,ivl_nature_t>::iterator cur = natures.begin()
; cur != natures.end() ; ++ cur ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP DISCIPLINES:" << endl;
for (map<perm_string,ivl_discipline_t>::iterator cur = disciplines.begin()
; cur != disciplines.end() ; ++ cur ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP MODULES:" << endl;
for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
; mod != pform_modules.end() ; ++ mod ) {
pform_dump(out, (*mod).second);
}
out << "PFORM DUMP PRIMITIVES:" << endl;
for (map<perm_string,PUdp*>::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<perm_string,bool> mentioned_p;
map<perm_string,Module*>::iterator mod;
if (verbose_flag)
cout << "LOCATING TOP-LEVEL MODULES" << endl << " ";
for (mod = pform_modules.begin()
; mod != pform_modules.end() ; ++ mod ) {
find_module_mention(mentioned_p, mod->second);
}
for (mod = pform_modules.begin()
; mod != pform_modules.end() ; ++ mod ) {
/* Don't choose library modules. */
if ((*mod).second->library_flag)
continue;
/* Don't choose modules instantiated in other
modules. */
if (mentioned_p[(*mod).second->mod_name()])
continue;
/* What's left might as well be chosen as a root. */
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, "
<<cycles_diff(cycles+1, cycles+0)<<" seconds."<<endl;
}
cout << "ELABORATING DESIGN" << endl;
}
/* Decide if we are going to allow system functions to be called
* as tasks. */
if (generation_flag >= GN_VER2005_SV) {
def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING;
}
/* On with the process of elaborating the module. */
Design*des = elaborate(roots);
if ((des == 0) || (des->errors > 0)) {
if (des != 0) {
cerr << des->errors
<< " error(s) during elaboration." << endl;
if (net_path) {
ofstream out (net_path);
des->dump(out);
}
} else {
cerr << "Elaboration failed" << endl;
}
goto errors_summary;
}
des->set_flags(flags);
switch(min_typ_max_flag) {
case MIN:
des->set_delay_sel(Design::MIN);
break;
case TYP:
des->set_delay_sel(Design::TYP);
break;
case MAX:
des->set_delay_sel(Design::MAX);
break;
default:
assert(0);
}
/* Done with all the pform data. Delete the modules. */
for (map<perm_string,Module*>::iterator idx = pform_modules.begin()
; idx != pform_modules.end() ; ++ idx ) {
delete (*idx).second;
(*idx).second = 0;
}
if (verbose_flag) {
if (times_flag) {
times(cycles+2);
cerr<<" ... done, "
<<cycles_diff(cycles+2, cycles+1)<<" seconds."<<endl;
}
cout << "RUNNING FUNCTORS" << endl;
}
while (!net_func_queue.empty()) {
net_func func = net_func_queue.front();
net_func_queue.pop();
if (verbose_flag)
cerr<<" -F "<<net_func_to_name(func)<< " ..." <<endl;
func(des);
}
if (verbose_flag) {
cout << "CALCULATING ISLANDS" << endl;
}
des->join_islands();
if (net_path) {
if (verbose_flag)
cerr<<" dumping netlist to " <<net_path<< "..." <<endl;
ofstream out (net_path);
des->dump(out);
}
if (des->errors) {
cerr << des->errors
<< " error(s) in post-elaboration processing." <<
endl;
return des->errors;
}
if (verbose_flag) {
if (times_flag) {
times(cycles+3);
cerr<<" ... done, "
<<cycles_diff(cycles+3, cycles+2)<<" seconds."<<endl;
}
}
if (verbose_flag) {
cout << "CODE GENERATION" << endl;
}
if (int emit_rc = des->emit(&dll_target_obj)) {
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " error(s)."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
assert(emit_rc);
}
if (verbose_flag) {
if (times_flag) {
times(cycles+4);
cerr<<" ... done, "
<<cycles_diff(cycles+4, cycles+3)<<" seconds."<<endl;
} else {
cout << "DONE." << endl;
}
}
if (verbose_flag) {
cout << "STATISTICS" << endl;
cout << "lex_string:"
<< " add_count=" << lex_strings.add_count()
<< " hit_count=" << lex_strings.add_hit_count()
<< endl;
}
delete des;
EOC_cleanup();
return 0;
errors_summary:
if (! missing_modules.empty()) {
cerr << "*** These modules were missing:" << endl;
map<perm_string,unsigned>::const_iterator idx;
for (idx = missing_modules.begin()
; idx != missing_modules.end() ; ++ idx )
cerr << " " << (*idx).first
<< " referenced " << (*idx).second
<< " times."<< endl;
cerr << "***" << endl;
}
return des? des->errors : 1;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*mod)
{
list<PGate*> gates = mod->get_gates();
list<PGate*>::const_iterator gate;
for (gate = gates.begin(); gate != gates.end(); ++ gate ) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = mod->generate_schemes.begin()
; cur != mod->generate_schemes.end() ; ++ cur ) {
find_module_mention(check_map, *cur);
}
}
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*schm)
{
list<PGate*>::const_iterator gate;
for (gate = schm->gates.begin(); gate != schm->gates.end(); ++ gate ) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = schm->generate_schemes.begin()
; cur != schm->generate_schemes.end() ; ++ cur ) {
find_module_mention(check_map, *cur);
}
}
Jump to Line
Something went wrong with that request. Please try again.