[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: gEDA: `include dependendencies in iverilog
On Mon, 25 Mar 2002, Stephen Williams wrote:
> tell@telltronics.org said:
> > proposal: new option -M <filename> added to both ivlpp and the
> > iverilog. driver. If present, dependencies are written to the
> > indicated file, but verilog processing is not otherwise affected.
>
> Sounds fine. I suggest simplifying the overall problem by having
> the generated dependency file contain a simple list of files. This
> list can be easily formed into any convenient form using simple
> scripts or make rules. This side-steps the whole issue of what to
> put to the left of the :.
>
> At first blush one might guess that this whole thing can be done
> within iverilog and ivlpp, but then modules brought in by the -y
> flag will get missed. So you might choose to eventually continue
> the support into the ivl core.
In my application I ran into complications requiring post-processing the
dependencies anyway, so I went ahead and rewrote things as you suggest. I
also did dependencies for the -y part inside iverilog, which was trivial
except for the driver/build_string stuff related to iverilog.conf.
While inside ivlpp, I ran into somthing else I needed that was missing:
`include `FILENAME_IN_MACRO
Whether this is standard verilog or just somthing that all of the cadence
verilogs support, I'm not sure. Anyway, it was a one-line addition, and
fits well with the nested expansion applied to other ` macros. This is a
great way to get a makefile to insert several different "intitial" blocks
as testcases into a single testbench module.
I also found a potential ivlpp core-dump bug present in 20020317:
`define A nestedmacro();
`define B C
`B
Patch appended.
I've got a short tarfile of test cases that I'll send you and Steve Wilson
seperately.
--
Steve Tell tell@telltronics.org
--- verilog-20020317-orig/load_module.cc Tue Nov 20 18:36:34 2001
+++ verilog-20020317-sgt/load_module.cc Mon Apr 1 22:58:23 2002
@@ -28,6 +28,7 @@
const char dir_character = '/';
+extern FILE *depend_file;
bool load_module(const char*type)
{
@@ -45,7 +46,10 @@
FILE*file = fopen(path, "r");
if (file == 0)
continue;
-
+ if(depend_file) {
+ fprintf(depend_file, "%s\n", path);
+ }
+
if (verbose_flag) {
cerr << "Loading library file " << path << "." << endl;
}
--- verilog-20020317-orig/main.cc Fri Nov 16 00:07:19 2001
+++ verilog-20020317-sgt/main.cc Mon Apr 1 22:58:23 2002
@@ -81,6 +81,7 @@
list<const char*> library_dirs;
list<const char*> library_suff;
+FILE *depend_file = NULL;
/*
* These are the warning enable flags.
*/
@@ -182,6 +183,7 @@
unsigned flag_errors = 0;
queue<net_func> net_func_queue;
list<const char*> roots;
+ const char* depfile_name = NULL;
struct tms cycles[5];
@@ -190,7 +192,7 @@
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:y:")) != EOF) switch (opt) {
+ while ((opt = getopt(argc, argv, "F:f:hm:M:N:o:P:p:s:T:t:VvW:Y:y:")) != EOF) switch (opt) {
case 'F': {
net_func tmp = name_to_net_func(optarg);
if (tmp == 0) {
@@ -211,6 +213,9 @@
case 'm':
flags["VPI_MODULE_LIST"] = flags["VPI_MODULE_LIST"]+","+optarg;
break;
+ case 'M':
+ depfile_name = optarg;
+ break;
case 'N':
net_path = optarg;
break;
@@ -311,6 +316,14 @@
return 1;
}
+ if( depfile_name ) {
+ depend_file = fopen(depfile_name, "a");
+ if(! depend_file) {
+ perror(depfile_name);
+ }
+ }
+
+
/* If there were no -Y flags, then create a minimal library
suffix search list. */
if (library_suff.empty()) {
--- verilog-20020317-orig/iverilog.conf Sat Mar 9 17:31:48 2002
+++ verilog-20020317-sgt/iverilog.conf Mon Apr 1 23:55:19 2002
@@ -32,6 +32,8 @@
#
# %s Substitute the start module (-s flag) from the user.
#
+# %M Substitute the value of the -M<depfile> flag.
+#
# %N Substitute the value of the -N<path> flag.
#
# %o Substitute the value of the -o<path> flag, or the default
@@ -59,20 +61,20 @@
# be useful and interesting if the -N flag is included.
[-tnull -S]
-<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -Fsynth -Fsyn-rules -- -
+<ivl>%B/ivl %[v-v] %y %Y %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -Fsynth -Fsyn-rules -- -
[-tnull]
-<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -- -
+<ivl>%B/ivl %[v-v] %y %Y %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -- -
# --
# The vvp target generates code that the vvp simulation engine can execute.
# These rules support synthesized and non-synthesized variants.
[-tvvp -S]
-<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fsynth -Fsyn-rules -Fcprop -Fnodangle %f %m -o%o -- -
+<ivl>%B/ivl %[v-v] %y %Y %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fsynth -Fsyn-rules -Fcprop -Fnodangle %f %m -o%o -- -
[-tvvp]
-<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fcprop -Fnodangle %f %m -o%o -- -
+<ivl>%B/ivl %[v-v] %y %Y %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fcprop -Fnodangle %f %m -o%o -- -
# --
# The vvm target uses the <ivl> string to take the preprocessed code from
@@ -87,14 +89,14 @@
# This is the XNF code generator.
[-txnf]
-<ivl>%B/ivl %y %Y %[v-v] %s %[N-N%N] %[T-T%T] -txnf -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
+<ivl>%B/ivl %y %Y %[v-v] %s %[M-M%M] %[N-N%N] %[T-T%T] -txnf -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
# And this is another XNF code generator, under development.
[-tfpga]
-<ivl>%B/ivl %y %Y %[v-v] %s %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/fpga.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
+<ivl>%B/ivl %y %Y %[v-v] %s %[M-M%M] %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/fpga.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
# --
# This is the pal code generator. The target module requires the -fpart=<type>
# flag to specify the part type.
[-tpal]
-<ivl>%B/ivl %y %Y %[v-v] %s %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/pal.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
+<ivl>%B/ivl %y %Y %[v-v] %s %[M-M%M] %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/pal.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
--- verilog-20020317-orig/ivlpp/main.c Tue Nov 20 21:59:27 2001
+++ verilog-20020317-sgt/ivlpp/main.c Mon Apr 1 22:58:23 2002
@@ -86,6 +86,7 @@
int line_direct_flag = 0;
unsigned error_count = 0;
+FILE *depend_file = NULL;
/*
* This function reads from a file a list of file names. Each name
@@ -125,6 +126,7 @@
const char*flist_path = 0;
unsigned flag_errors = 0;
char*out_path = 0;
+ char *dep_path = NULL;
FILE*out;
/* Define preprocessor keywords that I plan to just pass. */
@@ -150,7 +152,7 @@
include_dir[0] = strdup(".");
include_cnt = 1;
- while ((opt = getopt(argc, argv, "D:f:I:K:Lo:v")) != EOF) switch (opt) {
+ while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) {
case 'D': {
char*tmp = strdup(optarg);
@@ -192,6 +194,14 @@
line_direct_flag = 1;
break;
+ case 'M':
+ if (dep_path) {
+ fprintf(stderr, "duplicate -M flag.\n");
+ } else {
+ dep_path = optarg;
+ }
+ break;
+
case 'o':
if (out_path) {
fprintf(stderr, "duplicate -o flag.\n");
@@ -219,6 +229,7 @@
" -I<dir> - Add an include file search directory\n"
" -K<def> - Define a keyword macro that I just pass\n"
" -L - Emit line number directives\n"
+ " -M<fil> - Write dependencies to <fil>\n"
" -o<fil> - Send the output to <fil>\n"
" -v - Print version information\n",
argv[0]);
@@ -250,6 +261,14 @@
out = stdout;
}
+ if(dep_path) {
+ depend_file = fopen(dep_path, "w");
+ if (depend_file == 0) {
+ perror(dep_path);
+ exit(1);
+ }
+ }
+
if (source_cnt == 0) {
fprintf(stderr, "%s: No input files given.\n", argv[0]);
return 1;
@@ -260,6 +279,10 @@
reset_lexor(out, source_list);
if (yyparse()) return -1;
+ if(depend_file) {
+ fclose(depend_file);
+ }
+
return error_count;
}
--- verilog-20020317-orig/ivlpp/lexor.lex Sat Mar 9 01:37:49 2002
+++ verilog-20020317-sgt/ivlpp/lexor.lex Mon Apr 1 22:58:23 2002
@@ -67,6 +67,8 @@
struct include_stack_t*next;
};
+static void emit_pathline(struct include_stack_t *isp);
+
static struct include_stack_t*file_queue = 0;
static struct include_stack_t*istack = 0;
static struct include_stack_t*standby = 0;
@@ -135,6 +137,7 @@
^{W}?`include { yy_push_state(PPINCLUDE); }
+<PPINCLUDE>`[a-zA-Z][a-zA-Z0-9_]* { def_match(); }
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
<PPINCLUDE>[ \t\b\f] { ; }
@@ -156,9 +159,9 @@
/* Anything that is not matched by the above is an error of some
sort. Print and error message and absorb the rest of the line. */
<PPINCLUDE>. {
- fprintf(stderr, "%s:%u: error: malformed `include directive."
- " Did you quote the file name?\n", istack->path,
- istack->lineno+1);
+ emit_pathline(istack);
+ fprintf(stderr, "error: malformed `include directive."
+ " Did you quote the file name?\n");
error_count += 1;
BEGIN(ERROR_LINE); }
@@ -319,9 +322,9 @@
yy_switch_to_buffer(yy_new_buffer(istack->file, YY_BUF_SIZE));
} else {
- fprintf(stderr, "%s:%u: warning: macro %s undefined "
- "(and assumed null) at this point.\n",
- istack->path, istack->lineno, yytext);
+ emit_pathline(istack);
+ fprintf(stderr, "warning: macro %s undefined "
+ "(and assumed null) at this point.\n", yytext);
}
}
@@ -580,7 +583,11 @@
static void include_filename()
{
- assert(standby == 0);
+ if(standby) {
+ emit_pathline(istack);
+ fprintf(stderr, "error: malformed `include directive. Extra junk on line?\n");
+ exit(1);
+ }
standby = malloc(sizeof(struct include_stack_t));
standby->path = strdup(yytext+1);
standby->path[strlen(standby->path)-1] = 0;
@@ -592,7 +599,9 @@
if (standby->path[0] == '/') {
standby->file = fopen(standby->path, "r");
-
+ if(depend_file && standby->file) {
+ fprintf(depend_file, "%s\n", istack->path);
+ }
} else {
unsigned idx = 0;
standby->file = 0;
@@ -600,9 +609,12 @@
char path[4096];
sprintf(path, "%s/%s", include_dir[idx], standby->path);
standby->file = fopen(path, "r");
- if (standby->file)
+ if (standby->file) {
+ if(depend_file) {
+ fprintf(depend_file, "%s\n", path);
+ }
break;
-
+ }
}
}
@@ -624,6 +636,22 @@
istack->lineno+1, istack->path);
}
+/* walk the include stack until we find an entry with a valid pathname,
+ * and print the file and line from that entry for use in an error message.
+ * The istack entries created by def_match() for macro expansions do not
+ * contain pathnames. This finds instead the real file in which the outermost
+ * macro was used.
+ */
+static void emit_pathline(struct include_stack_t*isp)
+{
+ while(isp && (isp->path == NULL)) {
+ isp = isp->next;
+ }
+ assert(isp);
+ fprintf(stderr, "%s:%u: ",
+ isp->path, isp->lineno+1);
+}
+
/*
* The lexical analyzer calls this function when the current file
* ends. Here I pop the include stack and resume the previous file. If
@@ -674,6 +702,9 @@
if (line_direct_flag)
fprintf(yyout, "\n`line 1 \"%s\" 0\n", istack->path);
+ if(depend_file) {
+ fprintf(depend_file, "%s\n", istack->path);
+ }
yyrestart(istack->file);
return 0;
@@ -709,6 +740,9 @@
perror(paths[0]);
exit(1);
}
+ if(depend_file) {
+ fprintf(depend_file, "%s\n", paths[0]);
+ }
yyout = out;
--- verilog-20020317-orig/ivlpp/globals.h Wed Sep 13 18:33:13 2000
+++ verilog-20020317-sgt/ivlpp/globals.h Mon Apr 1 22:58:23 2002
@@ -37,6 +37,8 @@
extern unsigned error_count;
+extern FILE *depend_file;
+
/* This is the entry to the parser. */
extern int yyparse();
--- verilog-20020317-orig/driver/main.c Fri Mar 15 18:27:42 2002
+++ verilog-20020317-sgt/driver/main.c Mon Apr 1 22:58:23 2002
@@ -23,7 +23,7 @@
const char HELP[] =
"Usage: iverilog [-ESvV] [-B base] [-C path] [-c cmdfile]\n"
-" [-D macro[=defn]] [-I includedir] [-m module]\n"
+" [-D macro[=defn]] [-I includedir] [-M depfile] [-m module]\n"
" [-N file] [-o filename] [-p flag=value]\n"
" [-s topmodule] [-t target] [-T min|typ|max]\n"
" [-W class] [-y dir] [-Y suf] source_file(s)\n"
@@ -87,6 +87,7 @@
const char*opath = "a.out" EXEEXT;
const char*npath = 0;
const char*targ = "vvp";
+const char*depfile = 0;
char warning_flags[16] = "";
char *library_flags = 0;
@@ -399,7 +400,7 @@
return 1;
}
- while ((opt = getopt(argc, argv, "B:C:c:D:Ef:hI:m:N::o:p:Ss:T:t:vVW:y:")) != EOF) {
+ while ((opt = getopt(argc, argv, "B:C:c:D:Ef:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@@ -442,6 +443,10 @@
process_include_dir(optarg);
break;
+ case 'M':
+ depfile = optarg;
+ break;
+
case 'm':
if (mod_list == 0) {
mod_list = malloc(strlen(" -m")+strlen(optarg)+1);
@@ -601,6 +606,12 @@
ncmd += strlen(def_list);
}
+ if (depfile) {
+ cmd = realloc(cmd, ncmd + strlen(depfile) + 5);
+ strcat(cmd, " -M ");
+ strcat(cmd, depfile);
+ ncmd += strlen(depfile) + 4;
+ }
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
--- verilog-20020317-orig/driver/build_string.c Fri Nov 16 00:07:19 2001
+++ verilog-20020317-sgt/driver/build_string.c Mon Apr 1 22:58:23 2002
@@ -54,6 +54,7 @@
if (((*pattern == 's') && start)
|| ((*pattern == 'v') && verbose_flag)
+ || ((*pattern == 'M') && depfile)
|| ((*pattern == 'N') && npath)
|| ((*pattern == 'T') && mtm)) {
int rc = build_string(output, olen,
@@ -87,6 +88,14 @@
}
break;
+ case 'M':
+ if (depfile) {
+ strcpy(output, depfile);
+ output += strlen(depfile);
+ olen -= strlen(depfile);
+ }
+ break;
+
case 'N':
if (npath) {
strcpy(output, npath);
--- verilog-20020317-orig/driver/globals.h Fri Nov 16 00:07:19 2001
+++ verilog-20020317-sgt/driver/globals.h Mon Apr 1 23:02:23 2002
@@ -36,6 +36,9 @@
/* This is the optional -Tmin|typ|max setting. */
extern const char*mtm;
+ /* Ths is the optional -M<dependfile> value, if one was supplied. */
+extern const char*depfile;
+
/* Ths is the optional -N<path> value, if one was supplied. */
extern const char*npath;