[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;