diff --git a/compiler.h b/compiler.h index c70c50d2b..e604e4da2 100644 --- a/compiler.h +++ b/compiler.h @@ -1,7 +1,7 @@ #ifndef __compiler_H #define __compiler_H /* - * Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -36,6 +36,12 @@ */ extern unsigned integer_width; +/* + * This is the maximum number of recursive module loops allowed within + * a generate block. + */ +extern unsigned recursive_mod_limit; + /* The TIME_WIDTH is the width of time variables. */ #ifndef TIME_WIDTH # define TIME_WIDTH 64 diff --git a/elab_scope.cc b/elab_scope.cc index 5ee6861de..03bb3664a 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -919,21 +919,44 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const // check for recursive instantiation by scanning the current // scope and its parents. Look for a module instantiation of // the same module, but farther up in the scope. - + unsigned rl_count = 0; + bool in_genblk = false; for (NetScope*scn = sc ; scn ; scn = scn->parent()) { - if (scn->type() != NetScope::MODULE) + // We need to know if we are inside a generate block to allow + // recursive instances. + if (scn->type() == NetScope::GENBLOCK) { + in_genblk = true; continue; + } - if (strcmp(mod->mod_name(), scn->module_name()) != 0) + if (scn->type() != NetScope::MODULE) continue; + + if (strcmp(mod->mod_name(), scn->module_name()) != 0) continue; + + // We allow nested scopes if they are inside a generate block, + // but only to a certain nesting depth. + if (in_genblk) { + rl_count += 1; + if (rl_count > recursive_mod_limit) { + cerr << get_fileline() << ": error: instance " + << scope_path(sc) << "." << get_name() + << " of module " << mod->mod_name() + << " is nested too deep." << endl; + cerr << get_fileline() << ": : check for " + "proper recursion termination or increase the " + "limit (" << recursive_mod_limit + << ") with the -pRECURSIVE_MOD_LIMIT flag." + << endl; + des->errors += 1; + return; + } continue; + } cerr << get_fileline() << ": error: You cannot instantiate " << "module " << mod->mod_name() << " within itself." << endl; - cerr << get_fileline() << ": : The offending instance is " - << scope_path(sc) << "." << get_name() << " within " - << scope_path(scn) << "." << endl; - + << get_name() << " within " << scope_path(scn) << "." << endl; des->errors += 1; return; } diff --git a/main.cc b/main.cc index f4b18ab01..c692a154a 100644 --- a/main.cc +++ b/main.cc @@ -133,6 +133,7 @@ bool debug_optimizer = false; */ bool disable_virtual_pins = false; unsigned long array_size_limit = 16777216; // Minimum required by IEEE-1364? +unsigned recursive_mod_limit = 10; /* * Verbose messages enabled. @@ -717,9 +718,13 @@ int main(int argc, char*argv[]) const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"]; if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0; + flag_tmp = flags["ARRAY_SIZE_LIMIT"]; if (flag_tmp) array_size_limit = strtoul(flag_tmp,NULL,0); + flag_tmp = flags["RECURSIVE_MOD_LIMIT"]; + if (flag_tmp) recursive_mod_limit = strtoul(flag_tmp,NULL,0); + /* Parse the input. Make the pform. */ int rc = pform_parse(argv[optind]);