From 5e723bfd614b37ef1d3fcf64714a50fb340d6ebc Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 7 Apr 2009 18:31:42 -0700 Subject: [PATCH] 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. --- compiler.h | 8 +++++++- elab_scope.cc | 37 ++++++++++++++++++++++++++++++------- main.cc | 5 +++++ 3 files changed, 42 insertions(+), 8 deletions(-) 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]);