2000-04-21 08:41:02 +02:00
|
|
|
/*
|
2001-06-30 02:59:24 +02:00
|
|
|
* Copyright (c) 2000-2001 Stephen Williams (steve@icarus.com)
|
2000-04-21 08:41:02 +02: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-04-15 02:04:22 +02:00
|
|
|
#ident "$Id: main.c,v 1.35 2002/04/15 00:04:23 steve Exp $"
|
2001-07-25 05:10:48 +02:00
|
|
|
|
|
|
|
|
# include "config.h"
|
2000-04-21 08:41:02 +02:00
|
|
|
|
2002-02-03 08:05:36 +01:00
|
|
|
|
2000-11-30 03:50:54 +01:00
|
|
|
const char HELP[] =
|
2002-02-03 08:05:36 +01:00
|
|
|
"Usage: iverilog [-ESvV] [-B base] [-C path] [-c cmdfile]\n"
|
2002-04-04 07:26:13 +02:00
|
|
|
" [-D macro[=defn]] [-I includedir] [-M depfile] [-m module]\n"
|
2001-07-25 05:10:48 +02:00
|
|
|
" [-N file] [-o filename] [-p flag=value]\n"
|
|
|
|
|
" [-s topmodule] [-t target] [-T min|typ|max]\n"
|
2001-11-16 06:07:19 +01:00
|
|
|
" [-W class] [-y dir] [-Y suf] source_file(s)\n"
|
2001-07-25 05:10:48 +02:00
|
|
|
"See man page for details.";
|
2000-11-30 03:50:54 +01:00
|
|
|
|
|
|
|
|
#define MAXSIZE 4096
|
|
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2000-10-09 00:36:55 +02:00
|
|
|
#include <assert.h>
|
2000-04-21 08:41:02 +02:00
|
|
|
|
2000-07-12 01:30:03 +02:00
|
|
|
#include <sys/types.h>
|
2001-05-20 20:06:57 +02:00
|
|
|
#ifdef HAVE_SYS_WAIT_H
|
2000-07-12 01:30:03 +02:00
|
|
|
#include <sys/wait.h>
|
2001-05-20 20:06:57 +02:00
|
|
|
#endif
|
2000-07-12 01:30:03 +02:00
|
|
|
|
2001-05-20 17:09:39 +02:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-09-30 05:20:47 +02:00
|
|
|
#if HAVE_GETOPT_H
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-05-20 20:06:57 +02:00
|
|
|
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
|
|
|
|
extern int getopt(int argc, char*argv[], const char*fmt);
|
|
|
|
|
extern int optind;
|
|
|
|
|
extern const char*optarg;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if !defined(WIFEXITED)
|
2001-05-20 20:22:02 +02:00
|
|
|
# define WIFEXITED(rc) ((rc&0x7f) == 0)
|
2001-05-20 20:06:57 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if !defined(WEXITSTATUS)
|
2001-05-20 20:22:02 +02:00
|
|
|
# define WEXITSTATUS(rc) (rc>>8)
|
2001-05-20 20:06:57 +02:00
|
|
|
#endif
|
|
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
#ifndef IVL_ROOT
|
|
|
|
|
# define IVL_ROOT "."
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-06-16 21:00:06 +02:00
|
|
|
#ifndef RDYNAMIC
|
|
|
|
|
# define RDYNAMIC "-rdynamic"
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-10-09 00:36:55 +02:00
|
|
|
# include "globals.h"
|
|
|
|
|
|
2001-05-20 17:09:39 +02:00
|
|
|
#ifdef __MINGW32__
|
2001-06-15 07:14:21 +02:00
|
|
|
const char sep = '\\';
|
2001-05-20 17:09:39 +02:00
|
|
|
#else
|
2001-06-15 07:14:21 +02:00
|
|
|
const char sep = '/';
|
2001-05-20 17:09:39 +02:00
|
|
|
#endif
|
|
|
|
|
|
2001-11-12 19:47:32 +01:00
|
|
|
extern void cfreset(FILE*fd, const char*path);
|
|
|
|
|
|
2001-06-30 02:59:24 +02:00
|
|
|
const char*base = 0;
|
2000-07-29 19:58:20 +02:00
|
|
|
const char*mtm = 0;
|
2001-05-20 17:09:39 +02:00
|
|
|
const char*opath = "a.out" EXEEXT;
|
2000-08-09 03:34:00 +02:00
|
|
|
const char*npath = 0;
|
2001-06-30 23:53:42 +02:00
|
|
|
const char*targ = "vvp";
|
2002-04-04 07:26:13 +02:00
|
|
|
const char*depfile = 0;
|
2000-04-23 23:14:32 +02:00
|
|
|
|
2000-05-04 00:14:31 +02:00
|
|
|
char warning_flags[16] = "";
|
2001-10-21 01:02:39 +02:00
|
|
|
char *library_flags = 0;
|
2001-11-16 06:07:19 +01:00
|
|
|
char *library_flags2 = 0;
|
2000-05-04 00:14:31 +02:00
|
|
|
|
2000-05-05 03:07:42 +02:00
|
|
|
char*inc_list = 0;
|
|
|
|
|
char*def_list = 0;
|
2000-05-17 05:53:29 +02:00
|
|
|
char*mod_list = 0;
|
2000-11-30 03:50:54 +01:00
|
|
|
char*command_filename = 0;
|
2001-10-23 02:37:29 +02:00
|
|
|
char*start = 0;
|
2000-05-05 03:07:42 +02:00
|
|
|
|
2000-04-29 03:20:14 +02:00
|
|
|
char*f_list = 0;
|
|
|
|
|
|
2001-11-21 03:20:34 +01:00
|
|
|
/* These are used to collect the list of file names that will be
|
|
|
|
|
passed to ivlpp. Keep the list in a file because it can be a long
|
|
|
|
|
list. */
|
|
|
|
|
char*source_path = 0;
|
|
|
|
|
FILE*source_file = 0;
|
|
|
|
|
unsigned source_count = 0;
|
|
|
|
|
|
2000-05-04 00:14:31 +02:00
|
|
|
int synth_flag = 0;
|
2000-04-21 08:41:02 +02:00
|
|
|
int verbose_flag = 0;
|
2000-11-30 03:50:54 +01:00
|
|
|
int command_file = 0;
|
|
|
|
|
|
|
|
|
|
FILE *fp;
|
2000-04-21 08:41:02 +02:00
|
|
|
|
2000-11-30 03:50:54 +01:00
|
|
|
char line[MAXSIZE];
|
|
|
|
|
char tmp[MAXSIZE];
|
2000-04-21 08:41:02 +02:00
|
|
|
|
2001-06-30 02:59:24 +02:00
|
|
|
static char ivl_root[MAXSIZE];
|
2001-06-12 05:53:10 +02:00
|
|
|
|
2000-10-09 00:36:55 +02:00
|
|
|
/*
|
|
|
|
|
* This is the default target type. It looks up the bits that are
|
|
|
|
|
* needed to run the command from the configuration file (which is
|
|
|
|
|
* already parsed for us) so we can handle must of the generic cases.
|
|
|
|
|
*/
|
|
|
|
|
static int t_default(char*cmd, unsigned ncmd)
|
2000-04-22 00:51:38 +02:00
|
|
|
{
|
|
|
|
|
int rc;
|
2000-10-09 00:36:55 +02:00
|
|
|
const char*pattern;
|
2000-04-22 00:51:38 +02:00
|
|
|
|
2000-10-09 00:36:55 +02:00
|
|
|
pattern = lookup_pattern("<ivl>");
|
|
|
|
|
if (pattern == 0) {
|
|
|
|
|
fprintf(stderr, "No such target: %s\n", targ);
|
|
|
|
|
return -1;
|
2000-04-26 05:33:32 +02:00
|
|
|
}
|
|
|
|
|
|
2000-10-09 00:36:55 +02:00
|
|
|
tmp[0] = ' ';
|
|
|
|
|
tmp[1] = '|';
|
|
|
|
|
tmp[2] = ' ';
|
|
|
|
|
rc = build_string(tmp+3, sizeof tmp - 3, pattern);
|
|
|
|
|
cmd = realloc(cmd, ncmd+3+rc+1);
|
2001-05-20 17:09:39 +02:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
|
{
|
|
|
|
|
char *t;
|
|
|
|
|
for (t = tmp; *t; t++)
|
|
|
|
|
{
|
|
|
|
|
if (*t == '/') *t = '\\';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-04-26 05:33:32 +02:00
|
|
|
strcpy(cmd+ncmd, tmp);
|
2000-10-09 00:36:55 +02:00
|
|
|
|
2000-04-22 00:51:38 +02:00
|
|
|
|
|
|
|
|
if (verbose_flag)
|
2000-04-26 05:33:32 +02:00
|
|
|
printf("translate: %s\n", cmd);
|
2000-04-22 00:51:38 +02:00
|
|
|
|
2000-11-30 03:50:54 +01:00
|
|
|
|
2000-04-26 05:33:32 +02:00
|
|
|
rc = system(cmd);
|
2001-11-21 03:20:34 +01:00
|
|
|
remove(source_path);
|
2000-07-12 01:30:03 +02:00
|
|
|
if (rc != 0) {
|
2001-10-11 02:12:49 +02:00
|
|
|
if (rc == 127) {
|
|
|
|
|
fprintf(stderr, "Failed to execute: %s\n", cmd);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-12 01:30:03 +02:00
|
|
|
if (WIFEXITED(rc))
|
|
|
|
|
return WEXITSTATUS(rc);
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "Command signaled: %s\n", cmd);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2000-04-22 00:51:38 +02:00
|
|
|
}
|
|
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
/*
|
|
|
|
|
* This function handles the vvm target. After preprocessing, run the
|
|
|
|
|
* ivl translator to get C++, then run g++ to make an executable
|
|
|
|
|
* program out of that.
|
|
|
|
|
*/
|
2000-04-26 05:33:32 +02:00
|
|
|
static int t_vvm(char*cmd, unsigned ncmd)
|
2000-04-21 08:41:02 +02:00
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
|
2000-10-28 05:45:47 +02:00
|
|
|
const char*pattern = lookup_pattern("<ivl>");
|
2000-10-28 05:45:47 +02:00
|
|
|
if (pattern == 0) {
|
|
|
|
|
fprintf(stderr, "No such target: %s\n", targ);
|
|
|
|
|
return -1;
|
2000-08-09 03:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
2000-10-28 05:45:47 +02:00
|
|
|
tmp[0] = ' ';
|
|
|
|
|
tmp[1] = '|';
|
|
|
|
|
tmp[2] = ' ';
|
|
|
|
|
rc = build_string(tmp+3, sizeof tmp - 3, pattern);
|
|
|
|
|
cmd = realloc(cmd, ncmd+3+rc+1);
|
2001-05-20 17:09:39 +02:00
|
|
|
|
|
|
|
|
#ifdef __MINGW32__
|
|
|
|
|
{
|
|
|
|
|
char *t;
|
|
|
|
|
for (t = tmp; *t; t++)
|
|
|
|
|
{
|
|
|
|
|
if (*t == '/') *t = '\\';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2000-04-26 05:33:32 +02:00
|
|
|
strcpy(cmd+ncmd, tmp);
|
|
|
|
|
|
2001-05-20 17:09:39 +02:00
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
if (verbose_flag)
|
2000-04-26 05:33:32 +02:00
|
|
|
printf("translate: %s\n", cmd);
|
2000-04-21 08:41:02 +02:00
|
|
|
|
2000-04-26 05:33:32 +02:00
|
|
|
rc = system(cmd);
|
2001-11-21 03:20:34 +01:00
|
|
|
remove(source_path);
|
2000-04-21 08:41:02 +02:00
|
|
|
if (rc != 0) {
|
2000-07-12 01:30:03 +02:00
|
|
|
if (WIFEXITED(rc)) {
|
|
|
|
|
fprintf(stderr, "errors translating Verilog program.\n");
|
|
|
|
|
return WEXITSTATUS(rc);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "Command signaled: %s\n", cmd);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2000-04-21 08:41:02 +02:00
|
|
|
}
|
|
|
|
|
|
2001-06-30 06:23:02 +02:00
|
|
|
#if defined(__MINGW32__)
|
|
|
|
|
/* In the Windows world, the path to headers and libraries
|
|
|
|
|
for vvm is relative the ivl_root, which is in something like:
|
|
|
|
|
|
|
|
|
|
d:\iverilog\lib\ivl <-- ivl_root
|
|
|
|
|
d:\iverilog\include <-- vvm headers
|
|
|
|
|
d:\iverilog\lib <-- vvm libraries
|
|
|
|
|
|
|
|
|
|
So we make up all the ugly references that are the g++
|
|
|
|
|
command line to compile a .cc file generated by vvm. */
|
|
|
|
|
sprintf(tmp, "%s " RDYNAMIC " -s -fno-exceptions -o %s "
|
|
|
|
|
"-I%s\\..\\..\\include -L%s\\.. %s.cc -lvvm -lvpip %s",
|
|
|
|
|
CXX, opath, ivl_root, ivl_root, opath, DLLIB);
|
|
|
|
|
#else
|
|
|
|
|
/* In the UNIX universe, life is easy. The configure script
|
|
|
|
|
has figured everything out and wrote it into the Makefile,
|
|
|
|
|
which passes it on as the IVL_INC and IVL_LIB defines. */
|
2001-06-27 04:22:26 +02:00
|
|
|
sprintf(tmp, "%s " RDYNAMIC " -s -fno-exceptions -o %s -I%s "
|
|
|
|
|
"-L%s %s.cc -lvvm -lvpip %s", CXX, opath, IVL_INC,
|
|
|
|
|
IVL_LIB, opath, DLLIB);
|
2001-06-30 06:23:02 +02:00
|
|
|
#endif
|
2000-04-21 08:41:02 +02:00
|
|
|
if (verbose_flag)
|
2000-04-26 05:33:32 +02:00
|
|
|
printf("compile: %s\n", tmp);
|
2000-04-21 08:41:02 +02:00
|
|
|
|
2000-04-26 05:33:32 +02:00
|
|
|
rc = system(tmp);
|
2000-04-21 08:41:02 +02:00
|
|
|
if (rc != 0) {
|
2000-07-12 01:30:03 +02:00
|
|
|
if (WIFEXITED(rc)) {
|
|
|
|
|
fprintf(stderr, "errors compiling translated program.\n");
|
|
|
|
|
return WEXITSTATUS(rc);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "Command signaled: %s\n", tmp);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2000-04-21 08:41:02 +02:00
|
|
|
}
|
|
|
|
|
|
2000-04-26 05:33:32 +02:00
|
|
|
sprintf(tmp, "%s.cc", opath);
|
|
|
|
|
unlink(tmp);
|
2000-04-21 08:41:02 +02:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-05-04 00:14:31 +02:00
|
|
|
static void process_warning_switch(const char*name)
|
|
|
|
|
{
|
|
|
|
|
if (warning_flags[0] == 0)
|
|
|
|
|
strcpy(warning_flags, "-W");
|
|
|
|
|
|
|
|
|
|
if (strcmp(name,"all") == 0) {
|
2002-04-15 02:04:22 +02:00
|
|
|
strcat(warning_flags, "it");
|
2000-05-04 00:14:31 +02:00
|
|
|
|
|
|
|
|
} else if (strcmp(name,"implicit") == 0) {
|
|
|
|
|
if (! strchr(warning_flags+2, 'i'))
|
|
|
|
|
strcat(warning_flags, "i");
|
2002-04-15 02:04:22 +02:00
|
|
|
}else if (strcmp(name,"timescale") == 0) {
|
|
|
|
|
if (! strchr(warning_flags+2, 't'))
|
|
|
|
|
strcat(warning_flags, "t");
|
2000-05-04 00:14:31 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
void process_library_switch(const char *name)
|
2001-10-21 01:02:39 +02:00
|
|
|
{
|
|
|
|
|
if (library_flags) {
|
|
|
|
|
library_flags = realloc(library_flags,
|
|
|
|
|
strlen(library_flags) + strlen(name) + 5);
|
|
|
|
|
strcat(library_flags, " -y ");
|
|
|
|
|
} else {
|
|
|
|
|
library_flags = malloc(strlen(name) + 4);
|
|
|
|
|
strcpy(library_flags, "-y ");
|
|
|
|
|
}
|
|
|
|
|
strcat(library_flags, name);
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-16 06:07:19 +01:00
|
|
|
void process_library2_switch(const char *name)
|
|
|
|
|
{
|
|
|
|
|
if (library_flags2) {
|
|
|
|
|
library_flags2 = realloc(library_flags2,
|
|
|
|
|
strlen(library_flags2) + strlen(name) + 5);
|
|
|
|
|
strcat(library_flags2, " -Y ");
|
|
|
|
|
} else {
|
|
|
|
|
library_flags2 = malloc(strlen(name) + 4);
|
|
|
|
|
strcpy(library_flags2, "-Y ");
|
|
|
|
|
}
|
|
|
|
|
strcat(library_flags2, name);
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-12 19:47:32 +01:00
|
|
|
void process_include_dir(const char *name)
|
|
|
|
|
{
|
|
|
|
|
if (inc_list == 0) {
|
|
|
|
|
inc_list = malloc(strlen(" -I")+strlen(name)+1);
|
|
|
|
|
strcpy(inc_list, " -I");
|
|
|
|
|
strcat(inc_list, name);
|
|
|
|
|
} else {
|
|
|
|
|
inc_list = realloc(inc_list, strlen(inc_list)
|
|
|
|
|
+ strlen(" -I")
|
|
|
|
|
+ strlen(name) + 1);
|
|
|
|
|
strcat(inc_list, " -I");
|
|
|
|
|
strcat(inc_list, name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-13 04:30:26 +01:00
|
|
|
void process_define(const char*name)
|
|
|
|
|
{
|
|
|
|
|
if (def_list == 0) {
|
|
|
|
|
def_list = malloc(strlen(" -D")+strlen(name)+1);
|
|
|
|
|
strcpy(def_list, " -D");
|
|
|
|
|
strcat(def_list, name);
|
|
|
|
|
} else {
|
|
|
|
|
def_list = realloc(def_list, strlen(def_list)
|
|
|
|
|
+ strlen(" -D")
|
|
|
|
|
+ strlen(name) + 1);
|
|
|
|
|
strcat(def_list, " -D");
|
|
|
|
|
strcat(def_list, name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
void process_file_name(const char*name)
|
|
|
|
|
{
|
2001-11-21 03:20:34 +01:00
|
|
|
fprintf(source_file, "%s\n", name);
|
|
|
|
|
source_count += 1;
|
2001-11-12 02:26:36 +01:00
|
|
|
}
|
|
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
|
{
|
2000-10-09 00:36:55 +02:00
|
|
|
const char*config_path = 0;
|
2000-04-26 05:33:32 +02:00
|
|
|
char*cmd;
|
|
|
|
|
unsigned ncmd;
|
2000-04-21 08:41:02 +02:00
|
|
|
int e_flag = 0;
|
2002-02-03 08:05:36 +01:00
|
|
|
int version_flag = 0;
|
2000-04-21 08:41:02 +02:00
|
|
|
int opt, idx;
|
|
|
|
|
char*cp;
|
|
|
|
|
|
2001-06-30 02:59:24 +02:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
|
{ char * s;
|
|
|
|
|
char basepath[1024];
|
|
|
|
|
GetModuleFileName(NULL,basepath,1024);
|
|
|
|
|
|
|
|
|
|
/* Calculate the ivl_root from the path to the command. This
|
|
|
|
|
is necessary because of the installation process in
|
|
|
|
|
Windows. Mostly, it is those darn drive letters, but oh
|
|
|
|
|
well. We know the command path is formed like this:
|
|
|
|
|
|
|
|
|
|
D:\iverilog\bin\iverilog.exe
|
|
|
|
|
|
|
|
|
|
The IVL_ROOT in a Windows installation is the path:
|
|
|
|
|
|
|
|
|
|
D:\iverilog\lib\ivl
|
|
|
|
|
|
|
|
|
|
so we chop the file name and the last directory by
|
|
|
|
|
turning the last two \ characters to null. Then we append
|
|
|
|
|
the lib\ivl to finish. */
|
|
|
|
|
|
|
|
|
|
strncpy(ivl_root, basepath, MAXSIZE);
|
|
|
|
|
s = strrchr(ivl_root, sep);
|
|
|
|
|
if (s) *s = 0;
|
|
|
|
|
s = strrchr(ivl_root, sep);
|
|
|
|
|
if (s) *s = 0;
|
|
|
|
|
strcat(ivl_root, "\\lib\\ivl");
|
|
|
|
|
|
|
|
|
|
base = ivl_root;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
/* In a UNIX environment, the IVL_ROOT from the Makefile is
|
|
|
|
|
dependable. It points to the $prefix/lib/ivl directory,
|
|
|
|
|
where the sub-parts are installed. */
|
|
|
|
|
strcpy(ivl_root, IVL_ROOT);
|
|
|
|
|
base = ivl_root;
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-03-16 00:27:42 +01:00
|
|
|
source_path = strdup(tempnam(NULL, "ivrlg"));
|
2001-11-21 03:20:34 +01:00
|
|
|
assert(source_path);
|
|
|
|
|
source_file = fopen(source_path, "w");
|
2002-03-16 00:27:42 +01:00
|
|
|
if (NULL == source_file) {
|
|
|
|
|
fprintf(stderr, "%s: Error opening temporary file %s\n",
|
|
|
|
|
argv[0], source_path);
|
|
|
|
|
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2001-11-21 03:20:34 +01:00
|
|
|
|
2002-04-04 07:26:13 +02:00
|
|
|
while ((opt = getopt(argc, argv, "B:C:c:D:Ef:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
2000-04-21 08:41:02 +02:00
|
|
|
|
|
|
|
|
switch (opt) {
|
|
|
|
|
case 'B':
|
|
|
|
|
base = optarg;
|
|
|
|
|
break;
|
2000-10-09 00:36:55 +02:00
|
|
|
case 'C':
|
|
|
|
|
config_path = optarg;
|
|
|
|
|
break;
|
2000-11-30 03:50:54 +01:00
|
|
|
case 'c':
|
|
|
|
|
command_filename = malloc(strlen(optarg)+1);
|
2001-10-20 01:10:08 +02:00
|
|
|
strcpy(command_filename, optarg);
|
2000-11-30 03:50:54 +01:00
|
|
|
break;
|
2000-05-05 03:07:42 +02:00
|
|
|
case 'D':
|
2001-11-13 04:30:26 +01:00
|
|
|
process_define(optarg);
|
2000-05-05 03:07:42 +02:00
|
|
|
break;
|
2000-04-21 08:41:02 +02:00
|
|
|
case 'E':
|
|
|
|
|
e_flag = 1;
|
|
|
|
|
break;
|
2000-04-29 03:20:14 +02:00
|
|
|
case 'f':
|
2001-01-20 20:02:04 +01:00
|
|
|
fprintf(stderr, "warning: The -f flag is moved to -p\n");
|
|
|
|
|
case 'p':
|
2000-04-29 03:20:14 +02:00
|
|
|
if (f_list == 0) {
|
2001-01-20 20:02:04 +01:00
|
|
|
f_list = malloc(strlen(" -p")+strlen(optarg)+1);
|
|
|
|
|
strcpy(f_list, " -p");
|
2000-04-29 03:20:14 +02:00
|
|
|
strcat(f_list, optarg);
|
|
|
|
|
} else {
|
|
|
|
|
f_list = realloc(f_list, strlen(f_list) +
|
2001-01-20 20:02:04 +01:00
|
|
|
strlen(" -p") +
|
2000-04-29 03:20:14 +02:00
|
|
|
strlen(optarg) + 1);
|
2001-01-20 20:02:04 +01:00
|
|
|
strcat(f_list, " -p");
|
2000-04-29 03:20:14 +02:00
|
|
|
strcat(f_list, optarg);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2000-11-30 03:50:54 +01:00
|
|
|
|
|
|
|
|
case 'h':
|
|
|
|
|
fprintf(stderr, "%s\n", HELP);
|
|
|
|
|
return 1;
|
|
|
|
|
|
2000-05-05 03:07:42 +02:00
|
|
|
case 'I':
|
2001-11-12 19:47:32 +01:00
|
|
|
process_include_dir(optarg);
|
2000-05-05 03:07:42 +02:00
|
|
|
break;
|
2001-11-12 19:47:32 +01:00
|
|
|
|
2002-04-04 07:26:13 +02:00
|
|
|
case 'M':
|
|
|
|
|
depfile = optarg;
|
|
|
|
|
break;
|
|
|
|
|
|
2000-05-17 05:53:29 +02:00
|
|
|
case 'm':
|
|
|
|
|
if (mod_list == 0) {
|
|
|
|
|
mod_list = malloc(strlen(" -m")+strlen(optarg)+1);
|
|
|
|
|
strcpy(mod_list, " -m");
|
|
|
|
|
strcat(mod_list, optarg);
|
|
|
|
|
} else {
|
|
|
|
|
mod_list = realloc(mod_list, strlen(mod_list)
|
|
|
|
|
+ strlen(" -m")
|
|
|
|
|
+ strlen(optarg) + 1);
|
|
|
|
|
strcat(mod_list, " -m");
|
|
|
|
|
strcat(mod_list, optarg);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2000-08-09 03:34:00 +02:00
|
|
|
|
|
|
|
|
case 'N':
|
|
|
|
|
npath = optarg;
|
|
|
|
|
break;
|
|
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
case 'o':
|
|
|
|
|
opath = optarg;
|
|
|
|
|
break;
|
2000-08-09 03:34:00 +02:00
|
|
|
|
2000-05-04 00:14:31 +02:00
|
|
|
case 'S':
|
|
|
|
|
synth_flag = 1;
|
|
|
|
|
break;
|
2000-04-23 23:14:32 +02:00
|
|
|
case 's':
|
2001-10-23 02:37:29 +02:00
|
|
|
if (start) {
|
|
|
|
|
static const char *s = " -s ";
|
|
|
|
|
size_t l = strlen(start);
|
|
|
|
|
start = realloc(start, l + strlen(optarg) + strlen(s) + 1);
|
|
|
|
|
strcpy(start + l, s);
|
|
|
|
|
strcpy(start + l + strlen(s), optarg);
|
|
|
|
|
} else {
|
|
|
|
|
static const char *s = "-s ";
|
|
|
|
|
start = malloc(strlen(optarg) + strlen(s) + 1);
|
|
|
|
|
strcpy(start, s);
|
|
|
|
|
strcpy(start + strlen(s), optarg);
|
|
|
|
|
}
|
2000-04-23 23:14:32 +02:00
|
|
|
break;
|
2000-07-29 19:58:20 +02:00
|
|
|
case 'T':
|
|
|
|
|
if (strcmp(optarg,"min") == 0) {
|
|
|
|
|
mtm = "min";
|
|
|
|
|
} else if (strcmp(optarg,"typ") == 0) {
|
|
|
|
|
mtm = "typ";
|
|
|
|
|
} else if (strcmp(optarg,"max") == 0) {
|
|
|
|
|
mtm = "max";
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "%s: invalid -T%s argument\n",
|
|
|
|
|
argv[0], optarg);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2000-04-21 08:41:02 +02:00
|
|
|
case 't':
|
|
|
|
|
targ = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'v':
|
|
|
|
|
verbose_flag = 1;
|
|
|
|
|
break;
|
2002-02-03 08:05:36 +01:00
|
|
|
case 'V':
|
|
|
|
|
version_flag = 1;
|
|
|
|
|
break;
|
2000-05-04 00:14:31 +02:00
|
|
|
case 'W':
|
|
|
|
|
process_warning_switch(optarg);
|
|
|
|
|
break;
|
2001-10-21 01:02:39 +02:00
|
|
|
case 'y':
|
|
|
|
|
process_library_switch(optarg);
|
|
|
|
|
break;
|
2001-11-16 06:07:19 +01:00
|
|
|
case 'Y':
|
|
|
|
|
process_library2_switch(optarg);
|
|
|
|
|
break;
|
2000-04-21 08:41:02 +02:00
|
|
|
case '?':
|
|
|
|
|
default:
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-03 08:05:36 +01:00
|
|
|
if (version_flag || verbose_flag) {
|
|
|
|
|
printf("Icarus Verilog version " VERSION "\n");
|
|
|
|
|
printf("Copyright 1998-2002 Stephen Williams\n");
|
|
|
|
|
printf("$Name: $\n");
|
|
|
|
|
|
|
|
|
|
if (version_flag)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
if (command_filename) {
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
if (( fp = fopen(command_filename, "r")) == NULL ) {
|
|
|
|
|
fprintf(stderr, "%s: Can't open %s\n",
|
|
|
|
|
argv[0], command_filename);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-12 19:47:32 +01:00
|
|
|
cfreset(fp, command_filename);
|
2001-11-12 02:26:36 +01:00
|
|
|
rc = cfparse();
|
2001-11-12 19:47:32 +01:00
|
|
|
if (rc != 0) {
|
|
|
|
|
fprintf(stderr, "%s: error reading command file\n",
|
|
|
|
|
command_filename);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2001-11-12 02:26:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Finally, process all the remaining words on the command
|
|
|
|
|
line as file names. */
|
|
|
|
|
for (idx = optind ; idx < argc ; idx += 1)
|
|
|
|
|
process_file_name(argv[idx]);
|
|
|
|
|
|
|
|
|
|
|
2001-11-21 03:20:34 +01:00
|
|
|
fclose(source_file);
|
|
|
|
|
source_file = 0;
|
|
|
|
|
|
|
|
|
|
if (source_count == 0) {
|
2000-04-23 23:14:32 +02:00
|
|
|
fprintf(stderr, "%s: No input files.\n", argv[0]);
|
2000-11-30 03:50:54 +01:00
|
|
|
fprintf(stderr, "%s\n", HELP);
|
2000-04-23 23:14:32 +02:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-09 00:36:55 +02:00
|
|
|
/* Load the iverilog.conf file to get our substitution
|
|
|
|
|
strings. */
|
2000-11-30 03:50:54 +01:00
|
|
|
|
2000-10-09 00:36:55 +02:00
|
|
|
{ char path[1024];
|
|
|
|
|
FILE*fd;
|
|
|
|
|
if (config_path) {
|
|
|
|
|
strcpy(path, config_path);
|
|
|
|
|
} else {
|
2001-06-15 07:14:21 +02:00
|
|
|
sprintf(path, "%s%civerilog.conf", base,sep);
|
2000-10-09 00:36:55 +02:00
|
|
|
}
|
|
|
|
|
fd = fopen(path, "r");
|
2001-04-26 18:04:39 +02:00
|
|
|
if (fd == 0) {
|
|
|
|
|
fprintf(stderr, "Config file \"%s\" not found\n",path);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2000-10-09 00:36:55 +02:00
|
|
|
reset_lexor(fd);
|
|
|
|
|
yyparse();
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-26 05:33:32 +02:00
|
|
|
/* Start building the preprocess command line. */
|
|
|
|
|
|
2001-11-21 03:20:34 +01:00
|
|
|
sprintf(tmp, "%s%civlpp %s%s -f%s ", base,sep,
|
2000-05-04 22:08:20 +02:00
|
|
|
verbose_flag?" -v":"",
|
2001-11-21 03:20:34 +01:00
|
|
|
e_flag?"":" -L", source_path);
|
2000-04-26 05:33:32 +02:00
|
|
|
|
|
|
|
|
ncmd = strlen(tmp);
|
|
|
|
|
cmd = malloc(ncmd + 1);
|
2000-04-26 23:11:41 +02:00
|
|
|
strcpy(cmd, tmp);
|
2000-04-26 05:33:32 +02:00
|
|
|
|
2000-05-05 03:07:42 +02:00
|
|
|
if (inc_list) {
|
|
|
|
|
cmd = realloc(cmd, ncmd + strlen(inc_list) + 1);
|
|
|
|
|
strcat(cmd, inc_list);
|
|
|
|
|
ncmd += strlen(inc_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (def_list) {
|
|
|
|
|
cmd = realloc(cmd, ncmd + strlen(def_list) + 1);
|
|
|
|
|
strcat(cmd, def_list);
|
|
|
|
|
ncmd += strlen(def_list);
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-04 07:26:13 +02:00
|
|
|
if (depfile) {
|
|
|
|
|
cmd = realloc(cmd, ncmd + strlen(depfile) + 5);
|
|
|
|
|
strcat(cmd, " -M ");
|
|
|
|
|
strcat(cmd, depfile);
|
|
|
|
|
ncmd += strlen(depfile) + 4;
|
|
|
|
|
}
|
2000-11-30 03:50:54 +01:00
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
/* If the -E flag was given on the command line, then all we
|
|
|
|
|
do is run the preprocessor and put the output where the
|
|
|
|
|
user wants it. */
|
|
|
|
|
if (e_flag) {
|
2000-07-12 01:30:03 +02:00
|
|
|
int rc;
|
2000-04-21 08:41:02 +02:00
|
|
|
if (strcmp(opath,"-") != 0) {
|
2000-04-26 05:33:32 +02:00
|
|
|
sprintf(tmp, " > %s", opath);
|
|
|
|
|
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
|
|
|
|
strcpy(cmd+ncmd, tmp);
|
|
|
|
|
ncmd += strlen(tmp);
|
2000-04-21 08:41:02 +02:00
|
|
|
}
|
2000-04-26 05:33:32 +02:00
|
|
|
|
2000-04-21 08:41:02 +02:00
|
|
|
if (verbose_flag)
|
2000-04-26 05:33:32 +02:00
|
|
|
printf("preprocess: %s\n", cmd);
|
2000-04-21 08:41:02 +02:00
|
|
|
|
2000-07-12 01:30:03 +02:00
|
|
|
rc = system(cmd);
|
2001-11-21 03:20:34 +01:00
|
|
|
remove(source_path);
|
2000-07-12 01:30:03 +02:00
|
|
|
if (rc != 0) {
|
|
|
|
|
if (WIFEXITED(rc)) {
|
|
|
|
|
fprintf(stderr, "errors preprocessing Verilog program.\n");
|
|
|
|
|
return WEXITSTATUS(rc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "Command signaled: %s\n", cmd);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2000-04-21 08:41:02 +02:00
|
|
|
}
|
|
|
|
|
|
2000-10-09 00:36:55 +02:00
|
|
|
if (strcmp(targ,"vvm") == 0)
|
2000-04-26 05:33:32 +02:00
|
|
|
return t_vvm(cmd, ncmd);
|
2000-04-21 08:41:02 +02:00
|
|
|
else {
|
2000-10-09 00:36:55 +02:00
|
|
|
return t_default(cmd, ncmd);
|
2000-04-21 08:41:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2000-10-09 00:36:55 +02:00
|
|
|
* $Log: main.c,v $
|
2002-04-15 02:04:22 +02:00
|
|
|
* Revision 1.35 2002/04/15 00:04:23 steve
|
|
|
|
|
* Timescale warnings.
|
|
|
|
|
*
|
2002-04-04 07:26:13 +02:00
|
|
|
* Revision 1.34 2002/04/04 05:26:13 steve
|
|
|
|
|
* Add dependency generation.
|
|
|
|
|
*
|
2002-03-16 00:27:42 +01:00
|
|
|
* Revision 1.33 2002/03/15 23:27:42 steve
|
|
|
|
|
* Patch to allow user to set place for temporary files.
|
|
|
|
|
*
|
2002-02-03 08:05:36 +01:00
|
|
|
* Revision 1.32 2002/02/03 07:05:37 steve
|
|
|
|
|
* Support print of version number.
|
|
|
|
|
*
|
2001-11-21 03:20:34 +01:00
|
|
|
* Revision 1.31 2001/11/21 02:20:34 steve
|
|
|
|
|
* Pass list of file to ivlpp via temporary file.
|
|
|
|
|
*
|
2001-11-16 06:07:19 +01:00
|
|
|
* Revision 1.30 2001/11/16 05:07:19 steve
|
|
|
|
|
* Add support for +libext+ in command files.
|
|
|
|
|
*
|
2001-11-13 04:30:26 +01:00
|
|
|
* Revision 1.29 2001/11/13 03:30:26 steve
|
|
|
|
|
* The +incdir+ plusarg can take multiple directores,
|
|
|
|
|
* and add initial support for +define+ in the command file.
|
|
|
|
|
*
|
2001-11-12 19:47:32 +01:00
|
|
|
* Revision 1.28 2001/11/12 18:47:32 steve
|
|
|
|
|
* Support +incdir in command files, and ignore other
|
|
|
|
|
* +args flags. Also ignore -a and -v flags.
|
|
|
|
|
*
|
2001-11-12 02:26:36 +01:00
|
|
|
* Revision 1.27 2001/11/12 01:26:36 steve
|
|
|
|
|
* More sophisticated command file parser.
|
|
|
|
|
*
|
2001-11-11 01:10:05 +01:00
|
|
|
* Revision 1.26 2001/11/11 00:10:05 steve
|
|
|
|
|
* Remov XNF dead wood.
|
|
|
|
|
*
|
2001-10-23 02:37:29 +02:00
|
|
|
* Revision 1.25 2001/10/23 00:37:30 steve
|
|
|
|
|
* The -s flag can now be repeated on the iverilog command.
|
|
|
|
|
*
|
2001-10-21 01:02:39 +02:00
|
|
|
* Revision 1.24 2001/10/20 23:02:40 steve
|
|
|
|
|
* Add automatic module libraries.
|
|
|
|
|
*
|
2001-10-20 01:10:08 +02:00
|
|
|
* Revision 1.23 2001/10/19 23:10:08 steve
|
|
|
|
|
* Fix memory fault with -c flag.
|
|
|
|
|
*
|
2001-10-11 02:12:49 +02:00
|
|
|
* Revision 1.22 2001/10/11 00:12:49 steve
|
|
|
|
|
* Detect execv failures.
|
|
|
|
|
*
|
2001-07-25 05:10:48 +02:00
|
|
|
* Revision 1.21 2001/07/25 03:10:50 steve
|
|
|
|
|
* Create a config.h.in file to hold all the config
|
|
|
|
|
* junk, and support gcc 3.0. (Stephan Boettcher)
|
|
|
|
|
*
|
2001-06-30 23:53:42 +02:00
|
|
|
* Revision 1.20 2001/06/30 21:53:42 steve
|
|
|
|
|
* Make the vvp target the default.
|
|
|
|
|
*
|
2001-06-30 06:23:02 +02:00
|
|
|
* Revision 1.19 2001/06/30 04:23:02 steve
|
|
|
|
|
* Get include and lib paths right for mingw and vvm.
|
|
|
|
|
*
|
2001-06-30 02:59:24 +02:00
|
|
|
* Revision 1.18 2001/06/30 00:59:24 steve
|
|
|
|
|
* Redo the ivl_root calculator for mingw.
|
|
|
|
|
*
|
2001-06-27 04:22:26 +02:00
|
|
|
* Revision 1.17 2001/06/27 02:22:26 steve
|
|
|
|
|
* Get include and lib paths from Makefile.
|
|
|
|
|
*
|
2001-06-20 04:25:40 +02:00
|
|
|
* Revision 1.16 2001/06/20 02:25:40 steve
|
|
|
|
|
* Edit ivl_install_dir only on mingw
|
|
|
|
|
*
|
2001-06-15 07:14:21 +02:00
|
|
|
* Revision 1.15 2001/06/15 05:14:21 steve
|
|
|
|
|
* Fix library path calculation on non Windows systems
|
|
|
|
|
* to include the install directories. (Brendan Simon)
|
|
|
|
|
*
|
2001-06-12 05:53:10 +02:00
|
|
|
* Revision 1.14 2001/06/12 03:53:10 steve
|
|
|
|
|
* Change the VPI call process so that loaded .vpi modules
|
|
|
|
|
* use a function table instead of implicit binding.
|
|
|
|
|
*
|
2001-05-20 20:22:02 +02:00
|
|
|
* Revision 1.13 2001/05/20 18:22:02 steve
|
|
|
|
|
* Fix WIFEXITED macro.
|
|
|
|
|
*
|
2001-05-20 20:06:57 +02:00
|
|
|
* Revision 1.12 2001/05/20 18:06:57 steve
|
|
|
|
|
* local declares if the header is missing.
|
|
|
|
|
*
|
2001-05-20 17:09:39 +02:00
|
|
|
* Revision 1.11 2001/05/20 15:09:40 steve
|
|
|
|
|
* Mingw32 support (Venkat Iyer)
|
|
|
|
|
*
|
2001-05-17 05:14:26 +02:00
|
|
|
* Revision 1.10 2001/05/17 03:14:26 steve
|
|
|
|
|
* Update help message.
|
|
|
|
|
*
|
2001-04-26 18:04:39 +02:00
|
|
|
* Revision 1.9 2001/04/26 16:04:39 steve
|
|
|
|
|
* Handle missing or uninstalled .conf files.
|
|
|
|
|
*
|
2001-02-01 18:12:22 +01:00
|
|
|
* Revision 1.8 2001/02/01 17:12:22 steve
|
|
|
|
|
* Forgot to actually allow the -p flag.
|
|
|
|
|
*
|
2001-01-20 20:02:04 +01:00
|
|
|
* Revision 1.7 2001/01/20 19:02:05 steve
|
|
|
|
|
* Switch hte -f flag to the -p flag.
|
2000-04-21 08:41:02 +02:00
|
|
|
*/
|
|
|
|
|
|