1999-06-19 05:46:42 +02:00
|
|
|
|
|
|
|
|
const char COPYRIGHT[] =
|
2003-06-20 02:53:19 +02:00
|
|
|
"Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com)";
|
1999-06-19 05:46:42 +02:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
2002-08-12 03:34:58 +02:00
|
|
|
#ifdef HAVE_CVS_IDENT
|
2003-11-01 05:22:30 +01:00
|
|
|
#ident "$Id: main.cc,v 1.74 2003/11/01 04:22:30 steve Exp $"
|
1998-11-04 00:28:49 +01:00
|
|
|
#endif
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
1999-06-19 05:46:42 +02:00
|
|
|
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"
|
|
|
|
|
;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
# include <stdio.h>
|
2002-06-06 20:57:18 +02:00
|
|
|
# include <iostream>
|
1998-11-04 00:28:49 +01:00
|
|
|
# include <fstream>
|
1998-11-13 07:23:17 +01:00
|
|
|
# include <queue>
|
2001-10-19 23:53:24 +02:00
|
|
|
# include <list>
|
1998-11-18 05:25:22 +01:00
|
|
|
# include <map>
|
1998-11-04 00:28:49 +01:00
|
|
|
# include <unistd.h>
|
2001-06-23 20:41:02 +02:00
|
|
|
# include <stdlib.h>
|
2001-07-03 06:09:24 +02:00
|
|
|
#if defined(HAVE_TIMES)
|
|
|
|
|
# include <sys/times.h>
|
|
|
|
|
#endif
|
1999-11-29 18:02:21 +01:00
|
|
|
#if defined(HAVE_GETOPT_H)
|
|
|
|
|
# include <getopt.h>
|
|
|
|
|
#endif
|
1998-11-04 00:28:49 +01:00
|
|
|
# include "pform.h"
|
2001-10-21 01:02:39 +02:00
|
|
|
# include "parse_api.h"
|
1998-11-04 00:28:49 +01:00
|
|
|
# include "netlist.h"
|
|
|
|
|
# include "target.h"
|
2000-03-17 22:50:25 +01:00
|
|
|
# include "compiler.h"
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2001-05-20 19:34:53 +02:00
|
|
|
#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
|
|
|
|
|
|
2001-07-30 04:44:05 +02:00
|
|
|
#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
|
|
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
/* Count errors detected in flag processing. */
|
|
|
|
|
unsigned flag_errors = 0;
|
|
|
|
|
|
2003-10-26 23:43:42 +01:00
|
|
|
const char VERSION[] = "$Name: $";
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-01-24 02:35:08 +01:00
|
|
|
const char*target = "null";
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2002-05-24 03:13:00 +02:00
|
|
|
generation_t generation_flag = GN_DEFAULT;
|
|
|
|
|
|
1998-11-18 05:25:22 +01:00
|
|
|
map<string,string> flags;
|
|
|
|
|
|
2003-09-25 02:25:14 +02:00
|
|
|
map<string,unsigned> missing_modules;
|
|
|
|
|
|
2001-11-16 06:07:19 +01:00
|
|
|
list<const char*> library_suff;
|
2001-10-21 01:02:39 +02:00
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
list<const char*> roots;
|
|
|
|
|
|
2002-05-28 02:50:39 +02:00
|
|
|
char*ivlpp_string = 0;
|
|
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
char* depfile_name = NULL;
|
2002-04-04 07:26:13 +02:00
|
|
|
FILE *depend_file = NULL;
|
2003-09-22 03:12:08 +02:00
|
|
|
|
2000-03-17 22:50:25 +01:00
|
|
|
/*
|
|
|
|
|
* These are the warning enable flags.
|
|
|
|
|
*/
|
2002-04-15 02:04:22 +02:00
|
|
|
bool warn_implicit = false;
|
|
|
|
|
bool warn_timescale = false;
|
2003-02-22 05:12:49 +01:00
|
|
|
bool warn_portbinding = false;
|
2002-04-22 02:53:39 +02:00
|
|
|
|
|
|
|
|
bool error_implicit = false;
|
|
|
|
|
|
2001-10-21 01:02:39 +02:00
|
|
|
/*
|
|
|
|
|
* Verbose messages enabled.
|
|
|
|
|
*/
|
|
|
|
|
bool verbose_flag = false;
|
|
|
|
|
|
2003-03-01 07:25:30 +01:00
|
|
|
/*
|
|
|
|
|
* Keep a heap of identifier strings that I encounter. This is a more
|
|
|
|
|
* efficient way to allocate those strings.
|
|
|
|
|
*/
|
|
|
|
|
StringHeapLex lex_strings;
|
|
|
|
|
|
2002-05-28 22:40:37 +02:00
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
|
2003-11-01 05:22:30 +01:00
|
|
|
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);
|
|
|
|
|
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 },
|
|
|
|
|
{ "synth2", &synth2 },
|
|
|
|
|
{ "syn-rules", &syn_rules },
|
|
|
|
|
{ "xnfio", &xnfio },
|
|
|
|
|
{ 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";
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
static void process_generation_flag(const char*gen)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(gen,"1") == 0)
|
|
|
|
|
generation_flag = GN_VER1995;
|
|
|
|
|
|
|
|
|
|
else if (strcmp(gen,"2") == 0)
|
|
|
|
|
generation_flag = GN_VER2001;
|
|
|
|
|
|
|
|
|
|
else if (strcmp(gen,"3.0") == 0)
|
|
|
|
|
generation_flag = GN_SYSVER30;
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
generation_flag = GN_DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-28 04:25:03 +02:00
|
|
|
/*
|
|
|
|
|
* 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
|
2003-09-22 03:12:08 +02:00
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* depfile:<path>
|
|
|
|
|
* Give the path to an output dependency file.
|
|
|
|
|
*
|
2003-11-01 05:22:30 +01:00
|
|
|
* functor:<name>
|
|
|
|
|
* Append a named functor to the processing path.
|
|
|
|
|
*
|
2003-09-22 03:12:08 +02:00
|
|
|
* generation:<1|2|3.0>
|
|
|
|
|
* This is the generation flag
|
|
|
|
|
*
|
|
|
|
|
* ivlpp:<preprocessor command>
|
|
|
|
|
* This specifies the ivlpp command line used to process
|
|
|
|
|
* library modules as I read them in.
|
|
|
|
|
*
|
2003-09-23 07:57:15 +02:00
|
|
|
* module:<name>
|
|
|
|
|
* Load a VPI module.
|
|
|
|
|
*
|
2003-09-22 03:12:08 +02:00
|
|
|
* out:<path>
|
|
|
|
|
* Path to the output file.
|
|
|
|
|
*
|
|
|
|
|
* root:<name>
|
|
|
|
|
* Specify a root module. There may be multiple of this.
|
|
|
|
|
*
|
|
|
|
|
* warnings:<string>
|
|
|
|
|
* Warning flag letters.
|
2002-05-28 04:25:03 +02:00
|
|
|
*/
|
2002-05-28 02:50:39 +02:00
|
|
|
static void read_iconfig_file(const char*ipath)
|
|
|
|
|
{
|
|
|
|
|
char buf[8*1024];
|
|
|
|
|
|
|
|
|
|
FILE*ifile = fopen(ipath, "r");
|
2003-11-01 05:22:30 +01:00
|
|
|
if (ifile == 0) {
|
|
|
|
|
cerr << "ERROR: Unable to read config file: " << ipath << endl;
|
2002-05-28 02:50:39 +02:00
|
|
|
return;
|
2003-11-01 05:22:30 +01:00
|
|
|
}
|
2002-05-28 02:50:39 +02:00
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof buf, ifile) != 0) {
|
2003-11-01 05:22:30 +01:00
|
|
|
if (buf[0] == '#')
|
|
|
|
|
continue;
|
2002-05-28 02:50:39 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
if (strcmp(buf, "depfile") == 0) {
|
|
|
|
|
depfile_name = strdup(cp);
|
|
|
|
|
|
2003-11-01 05:22:30 +01:00
|
|
|
} else if (strcmp(buf,"functor") == 0) {
|
|
|
|
|
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);
|
|
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
} else if (strcmp(buf, "generation") == 0) {
|
|
|
|
|
process_generation_flag(cp);
|
|
|
|
|
|
|
|
|
|
} else if (strcmp(buf, "ivlpp") == 0) {
|
2002-05-28 02:50:39 +02:00
|
|
|
ivlpp_string = strdup(cp);
|
2002-05-28 04:25:03 +02:00
|
|
|
|
2003-09-23 07:57:15 +02:00
|
|
|
} else if (strcmp(buf,"module") == 0) {
|
|
|
|
|
flags["VPI_MODULE_LIST"] = flags["VPI_MODULE_LIST"]+","+cp;
|
|
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
} else if (strcmp(buf, "out") == 0) {
|
|
|
|
|
flags["-o"] = cp;
|
|
|
|
|
|
|
|
|
|
} else if (strcmp(buf, "root") == 0) {
|
|
|
|
|
roots.push_back(strdup(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 'p':
|
|
|
|
|
warn_portbinding = true;
|
|
|
|
|
break;
|
|
|
|
|
case 't':
|
|
|
|
|
warn_timescale = true;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-28 04:25:03 +02:00
|
|
|
} else if (strcmp(buf, "-y") == 0) {
|
2002-05-28 22:40:37 +02:00
|
|
|
build_library_index(cp, CASE_SENSITIVE);
|
|
|
|
|
|
|
|
|
|
} else if (strcmp(buf, "-yl") == 0) {
|
|
|
|
|
build_library_index(cp, false);
|
2002-05-28 04:25:03 +02:00
|
|
|
|
|
|
|
|
} else if (strcmp(buf, "-Y") == 0) {
|
|
|
|
|
library_suff.push_back(strdup(cp));
|
|
|
|
|
|
2003-09-22 03:12:08 +02:00
|
|
|
} 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;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-28 02:50:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-03-17 22:50:25 +01:00
|
|
|
|
1998-11-18 05:25:22 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-21 01:02:39 +02:00
|
|
|
extern Design* elaborate(list <const char*>root);
|
1998-11-13 07:23:17 +01:00
|
|
|
|
2001-07-03 06:09:24 +02:00
|
|
|
#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)
|
1998-11-13 07:23:17 +01:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
int main(int argc, char*argv[])
|
|
|
|
|
{
|
1998-11-16 06:03:52 +01:00
|
|
|
bool help_flag = false;
|
2001-07-03 06:09:24 +02:00
|
|
|
bool times_flag = false;
|
|
|
|
|
|
1999-04-23 06:34:32 +02:00
|
|
|
const char* net_path = 0;
|
|
|
|
|
const char* pf_path = 0;
|
1998-11-04 00:28:49 +01:00
|
|
|
int opt;
|
|
|
|
|
|
2001-07-03 06:09:24 +02:00
|
|
|
struct tms cycles[5];
|
|
|
|
|
|
2002-05-28 22:40:37 +02:00
|
|
|
library_suff.push_back(".v");
|
|
|
|
|
|
2000-01-13 06:11:24 +01:00
|
|
|
flags["VPI_MODULE_LIST"] = "system";
|
2000-08-09 05:43:45 +02:00
|
|
|
flags["-o"] = "a.out";
|
2000-07-29 19:58:20 +02:00
|
|
|
min_typ_max_flag = TYP;
|
|
|
|
|
min_typ_max_warn = 10;
|
2000-01-13 06:11:24 +01:00
|
|
|
|
2003-09-23 07:57:15 +02:00
|
|
|
while ((opt = getopt(argc, argv, "C:F:f:hN:P:p:t:Vv")) != EOF) switch (opt) {
|
2002-05-28 02:50:39 +02:00
|
|
|
|
|
|
|
|
case 'C':
|
|
|
|
|
read_iconfig_file(optarg);
|
|
|
|
|
break;
|
|
|
|
|
|
1998-11-13 07:23:17 +01:00
|
|
|
case 'F': {
|
|
|
|
|
net_func tmp = name_to_net_func(optarg);
|
|
|
|
|
if (tmp == 0) {
|
|
|
|
|
cerr << "No such design transform function ``"
|
|
|
|
|
<< optarg << "''." << endl;
|
1998-11-18 05:25:22 +01:00
|
|
|
flag_errors += 1;
|
1998-11-13 07:23:17 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
net_func_queue.push(tmp);
|
|
|
|
|
break;
|
|
|
|
|
}
|
1998-11-18 05:25:22 +01:00
|
|
|
case 'f':
|
|
|
|
|
parm_to_flagmap(optarg);
|
|
|
|
|
break;
|
1998-11-16 06:03:52 +01:00
|
|
|
case 'h':
|
|
|
|
|
help_flag = true;
|
|
|
|
|
break;
|
1999-04-23 06:34:32 +02:00
|
|
|
case 'N':
|
|
|
|
|
net_path = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'P':
|
|
|
|
|
pf_path = optarg;
|
|
|
|
|
break;
|
2001-01-20 20:02:04 +01:00
|
|
|
case 'p':
|
|
|
|
|
parm_to_flagmap(optarg);
|
|
|
|
|
break;
|
1998-11-04 00:28:49 +01:00
|
|
|
case 't':
|
|
|
|
|
target = optarg;
|
|
|
|
|
break;
|
2001-07-03 06:09:24 +02:00
|
|
|
case 'v':
|
2001-07-02 03:57:27 +02:00
|
|
|
verbose_flag = true;
|
2001-07-03 06:09:24 +02:00
|
|
|
# if defined(HAVE_TIMES)
|
|
|
|
|
times_flag = true;
|
|
|
|
|
# endif
|
2001-07-02 03:57:27 +02:00
|
|
|
break;
|
2001-07-03 06:09:24 +02:00
|
|
|
case 'V':
|
1999-06-19 05:46:42 +02:00
|
|
|
cout << "Icarus Verilog version " << VERSION << endl;
|
|
|
|
|
cout << COPYRIGHT << endl;
|
|
|
|
|
cout << endl << NOTICE << endl;
|
|
|
|
|
return 0;
|
1998-11-04 00:28:49 +01:00
|
|
|
default:
|
|
|
|
|
flag_errors += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flag_errors)
|
|
|
|
|
return flag_errors;
|
|
|
|
|
|
1998-11-16 06:03:52 +01:00
|
|
|
if (help_flag) {
|
2001-07-16 20:14:56 +02:00
|
|
|
cout << "Icarus Verilog version " << VERSION << endl <<
|
|
|
|
|
"usage: ivl <options> <file>\n"
|
|
|
|
|
"options:\n"
|
2002-05-28 22:40:37 +02:00
|
|
|
"\t-C <name> Config file from driver.\n"
|
2001-07-16 20:14:56 +02:00
|
|
|
"\t-F <name> Apply netlist function <name>.\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-t <name> Select target <name>.\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"
|
|
|
|
|
|
|
|
|
|
;
|
1998-11-16 06:03:52 +01:00
|
|
|
cout << "Netlist functions:" << endl;
|
|
|
|
|
for (unsigned idx = 0 ; func_table[idx].name ; idx += 1)
|
2001-07-16 20:14:56 +02:00
|
|
|
cout << "\t-F " << func_table[idx].name << endl;
|
1998-11-16 06:03:52 +01:00
|
|
|
cout << "Target types:" << endl;
|
|
|
|
|
for (unsigned idx = 0 ; target_table[idx] ; idx += 1)
|
2001-07-16 20:14:56 +02:00
|
|
|
cout << "\t-t " << target_table[idx]->name << endl;
|
1998-11-16 06:03:52 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
if (optind == argc) {
|
|
|
|
|
cerr << "No input files." << endl;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-04 07:26:13 +02:00
|
|
|
if( depfile_name ) {
|
|
|
|
|
depend_file = fopen(depfile_name, "a");
|
|
|
|
|
if(! depend_file) {
|
|
|
|
|
perror(depfile_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-07-02 03:57:27 +02:00
|
|
|
if (verbose_flag) {
|
2001-07-03 06:09:24 +02:00
|
|
|
if (times_flag)
|
|
|
|
|
times(cycles+0);
|
2002-05-24 03:13:00 +02:00
|
|
|
|
|
|
|
|
cout << "Using language generation: ";
|
|
|
|
|
switch (generation_flag) {
|
|
|
|
|
case GN_VER1995:
|
|
|
|
|
cout << "IEEE1364-1995";
|
|
|
|
|
break;
|
|
|
|
|
case GN_VER2001:
|
|
|
|
|
cout << "IEEE1364-2001";
|
|
|
|
|
break;
|
|
|
|
|
case GN_SYSVER30:
|
|
|
|
|
cout << "SystemVerilog 3.0";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-24 18:21:52 +02:00
|
|
|
cout << endl << "PARSING INPUT" << endl;
|
2001-07-02 03:57:27 +02:00
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
/* Parse the input. Make the pform. */
|
2001-10-21 01:02:39 +02:00
|
|
|
int rc = pform_parse(argv[optind]);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-04-23 06:34:32 +02:00
|
|
|
if (pf_path) {
|
|
|
|
|
ofstream out (pf_path);
|
1998-11-25 03:35:53 +01:00
|
|
|
out << "PFORM DUMP MODULES:" << endl;
|
2001-10-21 01:02:39 +02:00
|
|
|
for (map<string,Module*>::iterator mod = pform_modules.begin()
|
|
|
|
|
; mod != pform_modules.end()
|
1998-11-04 00:28:49 +01:00
|
|
|
; mod ++ ) {
|
1998-12-01 01:42:13 +01:00
|
|
|
pform_dump(out, (*mod).second);
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
1998-11-25 03:35:53 +01:00
|
|
|
out << "PFORM DUMP PRIMITIVES:" << endl;
|
2001-10-21 01:02:39 +02:00
|
|
|
for (map<string,PUdp*>::iterator idx = pform_primitives.begin()
|
|
|
|
|
; idx != pform_primitives.end()
|
1998-11-25 03:35:53 +01:00
|
|
|
; idx ++ ) {
|
|
|
|
|
(*idx).second->dump(out);
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
|
1999-07-11 01:29:21 +02:00
|
|
|
if (rc) {
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-22 21:48:32 +01:00
|
|
|
|
2001-10-19 23:53:24 +02:00
|
|
|
/* If the user did not give specific module(s) to start with,
|
|
|
|
|
then look for modules that are not instantiated anywhere. */
|
2000-11-22 21:48:32 +01:00
|
|
|
|
2001-10-19 23:53:24 +02:00
|
|
|
if (roots.empty()) {
|
|
|
|
|
map<string,bool> mentioned_p;
|
|
|
|
|
map<string,Module*>::iterator mod;
|
|
|
|
|
if (verbose_flag)
|
2002-07-24 18:21:52 +02:00
|
|
|
cout << "LOCATING TOP-LEVEL MODULES" << endl << " ";
|
2001-10-21 01:02:39 +02:00
|
|
|
for (mod = pform_modules.begin()
|
|
|
|
|
; mod != pform_modules.end()
|
|
|
|
|
; mod++) {
|
2001-10-19 23:53:24 +02:00
|
|
|
list<PGate*> gates = (*mod).second->get_gates();
|
|
|
|
|
list<PGate*>::const_iterator gate;
|
|
|
|
|
for (gate = gates.begin(); gate != gates.end(); gate++) {
|
|
|
|
|
PGModule *mod = dynamic_cast<PGModule*>(*gate);
|
|
|
|
|
if (mod) {
|
|
|
|
|
// Note that this module has been instantiated
|
|
|
|
|
mentioned_p[mod->get_type()] = true;
|
1999-05-05 05:27:14 +02:00
|
|
|
}
|
2001-10-19 23:53:24 +02:00
|
|
|
}
|
1999-05-05 05:27:14 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2001-10-21 01:02:39 +02:00
|
|
|
for (mod = pform_modules.begin()
|
|
|
|
|
; mod != pform_modules.end()
|
|
|
|
|
; mod++) {
|
2001-10-20 07:21:51 +02:00
|
|
|
if (mentioned_p[(*mod).second->mod_name()] == false) {
|
2001-10-19 23:53:24 +02:00
|
|
|
if (verbose_flag)
|
2001-10-20 07:21:51 +02:00
|
|
|
cout << " " << (*mod).second->mod_name();
|
|
|
|
|
roots.push_back((*mod).second->mod_name());
|
2001-10-19 23:53:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (verbose_flag)
|
|
|
|
|
cout << endl;
|
2000-11-22 21:48:32 +01:00
|
|
|
}
|
2001-10-19 23:53:24 +02:00
|
|
|
|
2000-11-22 21:48:32 +01:00
|
|
|
/* If there is *still* no guess for the root module, then give
|
|
|
|
|
up completely, and complain. */
|
|
|
|
|
|
2001-10-19 23:53:24 +02:00
|
|
|
if (roots.empty()) {
|
1999-05-05 05:27:14 +02:00
|
|
|
cerr << "No top level modules, and no -s option." << endl;
|
|
|
|
|
return 1;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
|
2000-11-22 21:48:32 +01:00
|
|
|
|
2001-07-02 03:57:27 +02:00
|
|
|
if (verbose_flag) {
|
2001-07-03 06:09:24 +02:00
|
|
|
if (times_flag) {
|
|
|
|
|
times(cycles+1);
|
|
|
|
|
cerr<<" ... done, "
|
|
|
|
|
<<cycles_diff(cycles+1, cycles+0)<<" seconds."<<endl;
|
|
|
|
|
}
|
2001-10-19 23:53:24 +02:00
|
|
|
cout << "ELABORATING DESIGN" << endl;
|
2001-07-02 03:57:27 +02:00
|
|
|
}
|
|
|
|
|
|
2000-11-22 21:48:32 +01:00
|
|
|
/* On with the process of elaborating the module. */
|
2001-10-21 01:02:39 +02:00
|
|
|
Design*des = elaborate(roots);
|
2000-11-22 21:48:32 +01:00
|
|
|
|
2003-09-25 02:25:14 +02:00
|
|
|
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;
|
2003-04-24 07:25:27 +02:00
|
|
|
}
|
2003-09-25 02:25:14 +02:00
|
|
|
|
|
|
|
|
goto errors_summary;
|
1999-02-01 01:26:48 +01:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1998-11-18 05:25:22 +01:00
|
|
|
des->set_flags(flags);
|
|
|
|
|
|
2003-09-26 04:17:14 +02:00
|
|
|
/* Done iwth all the pform data. Delete the modules. */
|
|
|
|
|
for (map<string,Module*>::iterator idx = pform_modules.begin()
|
|
|
|
|
; idx != pform_modules.end() ; idx ++) {
|
|
|
|
|
|
|
|
|
|
delete (*idx).second;
|
|
|
|
|
(*idx).second = 0;
|
|
|
|
|
}
|
1998-11-18 05:25:22 +01:00
|
|
|
|
2001-07-02 03:57:27 +02:00
|
|
|
if (verbose_flag) {
|
2001-07-03 06:09:24 +02:00
|
|
|
if (times_flag) {
|
|
|
|
|
times(cycles+2);
|
|
|
|
|
cerr<<" ... done, "
|
|
|
|
|
<<cycles_diff(cycles+2, cycles+1)<<" seconds."<<endl;
|
|
|
|
|
}
|
2002-07-24 18:21:52 +02:00
|
|
|
cout << "RUNNING FUNCTORS" << endl;
|
2001-07-02 03:57:27 +02:00
|
|
|
}
|
|
|
|
|
|
1998-11-13 07:23:17 +01:00
|
|
|
while (!net_func_queue.empty()) {
|
|
|
|
|
net_func func = net_func_queue.front();
|
|
|
|
|
net_func_queue.pop();
|
2001-07-03 06:09:24 +02:00
|
|
|
if (verbose_flag)
|
2002-07-24 18:21:52 +02:00
|
|
|
cerr<<" -F "<<net_func_to_name(func)<< " ..." <<endl;
|
1998-11-13 07:23:17 +01:00
|
|
|
func(des);
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
|
1999-04-23 06:34:32 +02:00
|
|
|
if (net_path) {
|
2002-06-24 03:49:38 +02:00
|
|
|
if (verbose_flag)
|
|
|
|
|
cerr<<" dumping netlist to " <<net_path<< "..." <<endl;
|
|
|
|
|
|
1999-04-23 06:34:32 +02:00
|
|
|
ofstream out (net_path);
|
1998-11-04 00:28:49 +01:00
|
|
|
des->dump(out);
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-19 00:06:29 +02:00
|
|
|
if (des->errors) {
|
|
|
|
|
cerr << des->errors
|
|
|
|
|
<< " error(s) in post-elaboration processing." <<
|
|
|
|
|
endl;
|
|
|
|
|
return des->errors;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2001-07-02 03:57:27 +02:00
|
|
|
if (verbose_flag) {
|
2001-07-03 06:09:24 +02:00
|
|
|
if (times_flag) {
|
|
|
|
|
times(cycles+3);
|
|
|
|
|
cerr<<" ... done, "
|
|
|
|
|
<<cycles_diff(cycles+3, cycles+2)<<" seconds."<<endl;
|
|
|
|
|
}
|
2002-08-19 00:06:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (verbose_flag) {
|
2002-07-24 18:21:52 +02:00
|
|
|
cout << "CODE GENERATION -t "<<target<< endl;
|
2001-07-02 03:57:27 +02:00
|
|
|
}
|
|
|
|
|
|
2003-09-25 02:25:14 +02:00
|
|
|
bool emit_rc;
|
|
|
|
|
emit_rc = emit(des, target);
|
1999-09-22 18:57:23 +02:00
|
|
|
if (!emit_rc) {
|
2000-08-09 05:43:45 +02:00
|
|
|
cerr << "error: Code generation had errors." << endl;
|
1999-09-22 18:57:23 +02:00
|
|
|
return 1;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
|
2001-07-02 03:57:27 +02:00
|
|
|
if (verbose_flag) {
|
2001-07-03 06:09:24 +02:00
|
|
|
if (times_flag) {
|
|
|
|
|
times(cycles+4);
|
|
|
|
|
cerr<<" ... done, "
|
|
|
|
|
<<cycles_diff(cycles+4, cycles+3)<<" seconds."<<endl;
|
2003-03-01 07:25:30 +01:00
|
|
|
} else {
|
2001-07-03 06:09:24 +02:00
|
|
|
cout << "DONE." << endl;
|
2003-03-01 07:25:30 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (verbose_flag) {
|
|
|
|
|
cout << "STATISTICS" << endl;
|
|
|
|
|
cout << "lex_string:"
|
|
|
|
|
<< " add_count=" << lex_strings.add_count()
|
|
|
|
|
<< " hit_count=" << lex_strings.add_hit_count()
|
|
|
|
|
<< endl;
|
2001-07-02 03:57:27 +02:00
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
return 0;
|
2003-09-25 02:25:14 +02:00
|
|
|
|
|
|
|
|
errors_summary:
|
|
|
|
|
if (missing_modules.size() > 0) {
|
|
|
|
|
cerr << "*** These modules were missing:" << endl;
|
|
|
|
|
|
|
|
|
|
map<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->errors;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* $Log: main.cc,v $
|
2003-11-01 05:22:30 +01:00
|
|
|
* Revision 1.74 2003/11/01 04:22:30 steve
|
|
|
|
|
* Accept functors in the config file.
|
|
|
|
|
*
|
2003-10-26 23:43:42 +01:00
|
|
|
* Revision 1.73 2003/10/26 22:43:42 steve
|
|
|
|
|
* Improve -V messages,
|
|
|
|
|
*
|
2003-09-26 04:17:14 +02:00
|
|
|
* Revision 1.72 2003/09/26 02:17:14 steve
|
|
|
|
|
* Delete pform when done with it.
|
|
|
|
|
*
|
2003-09-25 02:25:14 +02:00
|
|
|
* Revision 1.71 2003/09/25 00:25:14 steve
|
|
|
|
|
* Summary list of missing modules.
|
|
|
|
|
*
|
2003-09-23 07:57:15 +02:00
|
|
|
* Revision 1.70 2003/09/23 05:57:36 steve
|
|
|
|
|
* Pass -m flag from driver via iconfig file.
|
|
|
|
|
*
|
2003-09-22 03:12:08 +02:00
|
|
|
* Revision 1.69 2003/09/22 01:12:08 steve
|
|
|
|
|
* Pass more ivl arguments through the iconfig file.
|
|
|
|
|
*
|
2003-06-20 02:53:19 +02:00
|
|
|
* Revision 1.68 2003/06/20 00:53:19 steve
|
|
|
|
|
* Module attributes from the parser
|
|
|
|
|
* through to elaborated form.
|
|
|
|
|
*
|
2003-04-24 07:25:27 +02:00
|
|
|
* Revision 1.67 2003/04/24 05:25:27 steve
|
|
|
|
|
* Dump design even on errors.
|
|
|
|
|
*
|
2003-03-01 07:25:30 +01:00
|
|
|
* Revision 1.66 2003/03/01 06:25:30 steve
|
|
|
|
|
* Add the lex_strings string handler, and put
|
|
|
|
|
* scope names and system task/function names
|
|
|
|
|
* into this table. Also, permallocate event
|
|
|
|
|
* names from the beginning.
|
1998-11-04 00:28:49 +01:00
|
|
|
*/
|
|
|
|
|
|