From a3987a112b43c40a46ea4a2595e9f12482cc997e Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 17 Aug 2012 08:43:56 +0100 Subject: [PATCH] V0.9: Fix for pr3557493. defparam assignments found inside a generate block were being stored in the enclosing module scope. They should be stored in the generate block scope. --- PGenerate.h | 6 +++++- elab_scope.cc | 25 ++++++++++++++++++++++++- pform.cc | 7 +++++-- pform_dump.cc | 12 +++++++++++- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/PGenerate.h b/PGenerate.h index 8a8dce377..1d49817fc 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -1,7 +1,7 @@ #ifndef __PGenerate_H #define __PGenerate_H /* - * Copyright (c) 2006-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2006-2009,2012 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 @@ -80,6 +80,10 @@ class PGenerate : public LineInfo, public LexicalScope { // test value. std::valarray item_test; + // defparam assignments found in this scope. + typedef pair named_expr_t; + listdefparms; + list gates; void add_gate(PGate*); diff --git a/elab_scope.cc b/elab_scope.cc index 34216b553..91783e421 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2012 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 @@ -1025,6 +1025,29 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope) // for use as parameter values. elaborate_scope_localparams_(des, scope, localparams); + // Run through the defparams for this module, elaborate the + // expressions in this context and save the result is a table + // for later final override. + + // It is OK to elaborate the expressions of the defparam here + // because Verilog requires that the expressions only use + // local parameter names. It is *not* OK to do the override + // here because the parameter receiving the assignment may be + // in a scope not discovered by this pass. + + typedef list::const_iterator defparms_iter_t; + for (defparms_iter_t cur = defparms.begin() + ; cur != defparms.end() ; cur ++) { + + PExpr*ex = cur->second; + assert(ex); + + NetExpr*val = ex->elaborate_pexpr(des, scope); + if (val == 0) continue; + + scope->defparams.push_back(make_pair(cur->first, val)); + } + // Scan the generated scope for nested generate schemes, // and *generate* new scopes, which is slightly different // from simple elaboration. diff --git a/pform.cc b/pform.cc index a84ddff5a..6f3f2f493 100644 --- a/pform.cc +++ b/pform.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2012 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 @@ -1967,7 +1967,10 @@ void pform_set_specparam(perm_string name, PExpr*expr) void pform_set_defparam(const pform_name_t&name, PExpr*expr) { assert(expr); - pform_cur_module->defparms.push_back(make_pair(name,expr)); + if (pform_cur_generate) + pform_cur_generate->defparms.push_back(make_pair(name,expr)); + else + pform_cur_module->defparms.push_back(make_pair(name,expr)); } /* diff --git a/pform_dump.cc b/pform_dump.cc index dc0c1dab6..44c212526 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2012 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 @@ -1018,6 +1018,16 @@ void PGenerate::dump(ostream&out, unsigned indent) const dump_localparams_(out, indent+2); + typedef list::const_iterator parm_hiter_t; + for (parm_hiter_t cur = defparms.begin() + ; cur != defparms.end() ; ++ cur ) { + out << setw(indent+2) << "" << "defparam " << (*cur).first << " = "; + if ((*cur).second) + out << *(*cur).second << ";" << endl; + else + out << "/* ERROR */;" << endl; + } + dump_events_(out, indent+2); dump_wires_(out, indent+2);