Add support for recursive modules inside generate blocks

This patch adds support for recursive module loops if the
loop contains a generate block. The assumption is that the
user is doing the right thing in the generate block to make
the loop terminate. For this case there is also a check
that limits the number of loops (default 10). This prevents
the system from crashing when the user did not correctly
terminate the looping structure. The limit can be changed
by the user if needed.
This commit is contained in:
Cary R 2009-04-07 18:31:42 -07:00 committed by Stephen Williams
parent a7741d2bd5
commit 5e723bfd61
3 changed files with 42 additions and 8 deletions

View File

@ -1,7 +1,7 @@
#ifndef __compiler_H #ifndef __compiler_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -36,6 +36,12 @@
*/ */
extern unsigned integer_width; 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. */ /* The TIME_WIDTH is the width of time variables. */
#ifndef TIME_WIDTH #ifndef TIME_WIDTH
# define TIME_WIDTH 64 # define TIME_WIDTH 64

View File

@ -919,21 +919,44 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// check for recursive instantiation by scanning the current // check for recursive instantiation by scanning the current
// scope and its parents. Look for a module instantiation of // scope and its parents. Look for a module instantiation of
// the same module, but farther up in the scope. // 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()) { 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; 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; continue;
}
cerr << get_fileline() << ": error: You cannot instantiate " cerr << get_fileline() << ": error: You cannot instantiate "
<< "module " << mod->mod_name() << " within itself." << endl; << "module " << mod->mod_name() << " within itself." << endl;
cerr << get_fileline() << ": : The offending instance is " cerr << get_fileline() << ": : The offending instance is "
<< scope_path(sc) << "." << get_name() << " within " << get_name() << " within " << scope_path(scn) << "." << endl;
<< scope_path(scn) << "." << endl;
des->errors += 1; des->errors += 1;
return; return;
} }

View File

@ -133,6 +133,7 @@ bool debug_optimizer = false;
*/ */
bool disable_virtual_pins = false; bool disable_virtual_pins = false;
unsigned long array_size_limit = 16777216; // Minimum required by IEEE-1364? unsigned long array_size_limit = 16777216; // Minimum required by IEEE-1364?
unsigned recursive_mod_limit = 10;
/* /*
* Verbose messages enabled. * Verbose messages enabled.
@ -717,9 +718,13 @@ int main(int argc, char*argv[])
const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"]; const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"];
if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0; if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0;
flag_tmp = flags["ARRAY_SIZE_LIMIT"]; flag_tmp = flags["ARRAY_SIZE_LIMIT"];
if (flag_tmp) array_size_limit = strtoul(flag_tmp,NULL,0); 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. */ /* Parse the input. Make the pform. */
int rc = pform_parse(argv[optind]); int rc = pform_parse(argv[optind]);