diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index 2fb6fe74a..190142d96 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -1,4 +1,4 @@ -.TH iverilog 1 "Oct 21st, 2019" "" "Version %M.%n%E" +.TH iverilog 1 "Oct 23rd, 2019" "" "Version %M.%n%E" .SH NAME iverilog - Icarus Verilog compiler @@ -583,6 +583,24 @@ This is always defined when compiling with Icarus Verilog. .B __VAMS_ENABLE__ = 1 This is defined if Verilog\-AMS is enabled. +.SH ENVIRONMENT +.PP +\fIiverilog\fP also accepts some environment variables that control +its behavior. These can be used to make semi-permanent changes. + +.TP 8 +.B IVERILOG_ICONFIG=\fIfile-name\fP +This sets the name used for the temporary file that passes parameters +to the compiler proper, and prevents that file being deleted after the +compiler has exited. + +.TP 8 +.B IVERILOG_VPI_MODULE_PATH=\fI/some/path:/some/other/path\fP +This adds additional components to the VPI module search path. Paths +specified in this way are searched after paths specified with \fB-L\fP, +but before the default search path. Multiple paths can be separated with +colons (semicolons if using Windows). + .SH EXAMPLES These examples assume that you have a Verilog source file called hello.v in the current directory diff --git a/driver/main.c b/driver/main.c index c30e309ed..97917bd67 100644 --- a/driver/main.c +++ b/driver/main.c @@ -99,8 +99,10 @@ extern const char*optarg; #ifdef __MINGW32__ const char sep = '\\'; +const char path_sep = ';'; #else const char sep = '/'; +const char path_sep = ':'; #endif extern void cfreset(FILE*fd, const char*path); @@ -173,6 +175,9 @@ static char iconfig_common_path[4096] = ""; static const char**vpi_path_list = 0; static unsigned vpi_path_list_size = 0; +static const char**env_vpi_path_list = 0; +static unsigned env_vpi_path_list_size = 0; + int synth_flag = 0; int verbose_flag = 0; @@ -865,6 +870,71 @@ static int process_depfile(const char*name) return 0; } +static void add_env_vpi_module_path(const char*path) +{ + env_vpi_path_list_size += 1; + env_vpi_path_list = (const char**)realloc(env_vpi_path_list, + env_vpi_path_list_size*sizeof(char*)); + env_vpi_path_list[env_vpi_path_list_size-1] = path; +} + +static void get_env_vpi_module_paths(void) +{ + char *var = getenv("IVERILOG_VPI_MODULE_PATH"); + char *ptr, *end; + + if (!var) + return; + + var = strdup(var); +#ifdef __MINGW32__ + convert_to_MS_path(var); +#endif + ptr = var; + end = var+strlen(var); + int len = 0; + while (ptr <= end) { + if (*ptr == 0 || *ptr == path_sep) { + *ptr = 0; + if (len > 0) { + add_env_vpi_module_path(var); + } + len = 0; + var = ptr+1; + } else { + len++; + } + ptr++; + } +} + +static void add_vpi_module_path(const char*path) +{ +#ifdef __MINGW32__ + char*tmp_path = strdup(path); + convert_to_MS_path(tmp_path); + path = tmp_path; +#endif + vpi_path_list_size += 1; + vpi_path_list = (const char**)realloc(vpi_path_list, + vpi_path_list_size*sizeof(char*)); + vpi_path_list[vpi_path_list_size-1] = path; +} + +static int probe_for_vpi_module(const char*base_path, const char*name, + char*path, unsigned path_size) +{ + snprintf(path, path_size, "%s%c%s.vpi", base_path, sep, name); + if (access(path, R_OK) == 0) + return 1; + + snprintf(path, path_size, "%s%c%s.vpl", base_path, sep, name); + if (access(path, R_OK) == 0) + return 1; + + return 0; +} + /* * If it exists add the VPI file for the given module. */ @@ -874,6 +944,12 @@ static void add_vpi_file(const char *name) char path[4096]; +#ifdef __MINGW32__ + char*tmp_name = strdup(name); + convert_to_MS_path(name); + name = tmp_name; +#endif + int found = 0; if (strchr(name, sep)) { /* If the name has at least one directory character in it @@ -887,35 +963,31 @@ static void add_vpi_file(const char *name) snprintf(path, sizeof(path), "%s.vpl", name); found = access(path, R_OK) == 0; } - if (!found) - fprintf(stderr, "Unable to find VPI module '%s'\n", name); } else { strncpy(path, name, sizeof(path) - 1); } } else { - for (unsigned idx = 0; idx < vpi_path_list_size; idx += 1) { - snprintf(path, sizeof(path), "%s%c%s.vpi", - vpi_path_list[idx], sep, name); - found = access(path, R_OK) == 0; - if (found) break; - snprintf(path, sizeof(path), "%s%c%s.vpl", - vpi_path_list[idx], sep, name); - found = access(path, R_OK) == 0; - if (found) break; + for (unsigned idx = 0; !found && (idx < vpi_path_list_size); idx += 1) { + found = probe_for_vpi_module(vpi_path_list[idx], name, + path, sizeof(path)); + } + for (unsigned idx = 0; !found && (idx < env_vpi_path_list_size); idx += 1) { + found = probe_for_vpi_module(env_vpi_path_list[idx], name, + path, sizeof(path)); } if (!found) { - snprintf(path, sizeof(path), "%s%c%s.vpi", base_dir, sep, name); - found = access(path, R_OK) == 0; + found = probe_for_vpi_module(base_dir, name, + path, sizeof(path)); } - if (!found) { - snprintf(path, sizeof(path), "%s%c%s.vpl", base_dir, sep, name); - found = access(path, R_OK) == 0; - } - if (!found) - fprintf(stderr, "Unable to find VPI module '%s' on the search path.\n", name); } - if (found) + if (found) { fprintf(iconfig_file, "module:%s\n", path); + } else { + fprintf(stderr, "Unable to find VPI module '%s'\n", name); + } +#ifdef __MINGW32__ + free(tmp_name); +#endif } static void find_ivl_root_failed(const char *reason) @@ -1020,6 +1092,8 @@ int main(int argc, char **argv) find_ivl_root(); base = ivl_root; + get_env_vpi_module_paths(); + /* Create a temporary file for communicating input parameters to the preprocessor. */ source_path = strdup(my_tempfile("ivrlg", &source_file)); @@ -1143,10 +1217,7 @@ int main(int argc, char **argv) break; case 'L': - vpi_path_list_size += 1; - vpi_path_list = (const char**)realloc(vpi_path_list, - vpi_path_list_size*sizeof(char*)); - vpi_path_list[vpi_path_list_size-1] = optarg; + add_vpi_module_path(optarg); break; case 'l':