From e7efc2709a4a3b34361b639c278e2cdc53a75746 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 8 Mar 2000 04:36:53 +0000 Subject: [PATCH] Redesign the implementation of scopes and parameters. I now generate the scopes and notice the parameters in a separate pass over the pform. Once the scopes are generated, I can process overrides and evalutate paremeters before elaboration begins. --- Makefile.in | 7 +- Module.h | 21 +- PExpr.h | 37 ++- PGate.cc | 13 +- PGate.h | 13 +- PTask.h | 22 +- README.txt | 27 ++ design_dump.cc | 60 ++-- elab_expr.cc | 137 ++++++--- elab_net.cc | 11 +- elab_pexpr.cc | 53 ++++ elab_scope.cc | 242 ++++++++++++++++ elaborate.cc | 486 ++++++++++---------------------- emit.cc | 22 +- eval.cc | 13 +- eval_tree.cc | 14 +- net_design.cc | 533 +++++++++++++++++++++++++++++++++++ netlist.cc | 730 ++++++------------------------------------------ netlist.h | 352 ++++------------------- netlist.txt | 32 ++- parse.y | 5 +- pform.cc | 16 +- pform.h | 10 +- pform_dump.cc | 18 +- t-vvm.cc | 15 +- vpi/vpi_user.h | 11 +- vvm/vpi_scope.c | 35 ++- 27 files changed, 1545 insertions(+), 1390 deletions(-) create mode 100644 elab_pexpr.cc create mode 100644 elab_scope.cc create mode 100644 net_design.cc diff --git a/Makefile.in b/Makefile.in index 08b3c5329..87ebf0e7f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.36 2000/02/05 06:40:35 steve Exp $" +#ident "$Id: Makefile.in,v 1.37 2000/03/08 04:36:53 steve Exp $" # # SHELL = /bin/sh @@ -70,8 +70,9 @@ TT = t-null.o t-verilog.o t-vvm.o t-xnf.o FF = nobufz.o nodangle.o propinit.o synth.o xnfio.o xnfsyn.o O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \ -elab_net.o emit.o eval.o eval_tree.o expr_synth.o functor.o \ -lexor.o lexor_keyword.o mangle.o netlist.o pad_to_width.o \ +elab_net.o elab_pexpr.o elab_scope.o emit.o eval.o eval_tree.o \ +expr_synth.o functor.o lexor.o lexor_keyword.o mangle.o netlist.o \ +net_design.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o \ verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \ diff --git a/Module.h b/Module.h index 763c7670a..3d9f00dfd 100644 --- a/Module.h +++ b/Module.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: Module.h,v 1.14 2000/02/23 02:56:53 steve Exp $" +#ident "$Id: Module.h,v 1.15 2000/03/08 04:36:53 steve Exp $" #endif # include @@ -66,6 +66,12 @@ class Module { into this map. */ mapparameters; + /* The module also has defparam assignments which don't create + new parameters within the module, but may be used to set + values within this module (when instantiated) or in other + instantiated modules. */ + mapdefparms; + /* Parameters may be overridden at instantiation time; the overrides do not contain explicit parameter names, but rather refer to parameters in the order they @@ -101,9 +107,9 @@ class Module { const list& get_behaviors() const { return behaviors_; } void dump(ostream&out) const; - bool elaborate(Design*, NetScope*scope, - named*parms, unsigned nparms, - svector*overrides_) const; + bool elaborate(Design*, NetScope*scope) const; + + bool elaborate_scope(Design*, NetScope*scope) const; private: const string name_; @@ -123,6 +129,13 @@ class Module { /* * $Log: Module.h,v $ + * Revision 1.15 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.14 2000/02/23 02:56:53 steve * Macintosh compilers do not support ident. * diff --git a/PExpr.h b/PExpr.h index 969be0999..6600bc7bd 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PExpr.h,v 1.29 2000/02/23 02:56:53 steve Exp $" +#ident "$Id: PExpr.h,v 1.30 2000/03/08 04:36:53 steve Exp $" #endif # include @@ -32,6 +32,7 @@ class Design; class Module; class NetNet; class NetExpr; +class NetScope; /* * The PExpr class hierarchy supports the description of @@ -49,7 +50,13 @@ class PExpr : public LineInfo { virtual void dump(ostream&) const; // Procedural elaboration of the expression. - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope) const; + + // Elaborate expressions that are the r-value of parameter + // assignments. This elaboration follows the restrictions of + // constant expressions and supports later overriding and + // evaluation of parameters. + virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; // This method elaborate the expression as gates, for use in a // continuous assign or other wholly structural context. @@ -97,7 +104,7 @@ class PEConcat : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetExpr*elaborate_expr(Design*des, NetScope*) const; virtual bool is_constant(Module*) const; private: @@ -140,7 +147,7 @@ class PEIdent : public PExpr { unsigned long fall, unsigned long decay) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetExpr*elaborate_expr(Design*des, NetScope*) const; virtual bool is_constant(Module*) const; verinum* eval_const(const Design*des, const string&path) const; @@ -182,7 +189,8 @@ class PENumber : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetEConst*elaborate_expr(Design*des, NetScope*) const; + virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; virtual verinum* eval_const(const Design*des, const string&path) const; virtual bool is_the_same(const PExpr*that) const; @@ -200,7 +208,7 @@ class PEString : public PExpr { string value() const { return text_; } virtual void dump(ostream&) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetEConst*elaborate_expr(Design*des, NetScope*) const; virtual bool is_constant(Module*) const; @@ -220,7 +228,7 @@ class PEUnary : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetEUnary*elaborate_expr(Design*des, NetScope*) const; private: char op_; @@ -241,7 +249,7 @@ class PEBinary : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetEBinary*elaborate_expr(Design*des, NetScope*) const; virtual verinum* eval_const(const Design*des, const string&path) const; private: @@ -299,7 +307,7 @@ class PETernary : public PExpr { unsigned long rise =0, unsigned long fall =0, unsigned long decay =0) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetETernary*elaborate_expr(Design*des, NetScope*) const; virtual verinum* eval_const(const Design*des, const string&path) const; private: @@ -317,17 +325,24 @@ class PECallFunction : public PExpr { ~PECallFunction(); virtual void dump(ostream &) const; - virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual NetExpr*elaborate_expr(Design*des, NetScope*) const; private: string name_; svector parms_; - NetESFunc* elaborate_sfunc_(Design*des, const string&path) const; + NetESFunc* elaborate_sfunc_(Design*des, NetScope*scope) const; }; /* * $Log: PExpr.h,v $ + * Revision 1.30 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.29 2000/02/23 02:56:53 steve * Macintosh compilers do not support ident. * diff --git a/PGate.cc b/PGate.cc index 1df3b03b3..f4c5c7dce 100644 --- a/PGate.cc +++ b/PGate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PGate.cc,v 1.7 2000/02/23 02:56:53 steve Exp $" +#ident "$Id: PGate.cc,v 1.8 2000/03/08 04:36:53 steve Exp $" #endif # include "PGate.h" @@ -50,6 +50,10 @@ PGate::~PGate() { } +void PGate::elaborate_scope(Design*, NetScope*) const +{ +} + /* * This method is used during elaboration to calculate the * rise/fall/decay times for the gate. These values were set in pform @@ -148,6 +152,13 @@ void PGModule::set_range(PExpr*msb, PExpr*lsb) /* * $Log: PGate.cc,v $ + * Revision 1.8 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.7 2000/02/23 02:56:53 steve * Macintosh compilers do not support ident. * diff --git a/PGate.h b/PGate.h index a2f58075c..1bb5dcdc0 100644 --- a/PGate.h +++ b/PGate.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PGate.h,v 1.14 2000/02/23 02:56:53 steve Exp $" +#ident "$Id: PGate.h,v 1.15 2000/03/08 04:36:53 steve Exp $" #endif # include "svector.h" @@ -31,6 +31,7 @@ class PExpr; class PUdp; class Design; +class NetScope; class Module; /* @@ -69,6 +70,7 @@ class PGate : public LineInfo { virtual void dump(ostream&out) const; virtual void elaborate(Design*des, const string&path) const; + virtual void elaborate_scope(Design*des, NetScope*sc) const; protected: const svector* get_pins() const { return pins_; } @@ -175,6 +177,7 @@ class PGModule : public PGate { virtual void dump(ostream&out) const; virtual void elaborate(Design*, const string&path) const; + virtual void elaborate_scope(Design*des, NetScope*sc) const; private: string type_; @@ -192,10 +195,18 @@ class PGModule : public PGate { void elaborate_mod_(Design*, Module*mod, const string&path) const; void elaborate_udp_(Design*, PUdp *udp, const string&path) const; + void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const; }; /* * $Log: PGate.h,v $ + * Revision 1.15 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.14 2000/02/23 02:56:53 steve * Macintosh compilers do not support ident. * diff --git a/PTask.h b/PTask.h index dcacbd123..fa0f38abe 100644 --- a/PTask.h +++ b/PTask.h @@ -19,13 +19,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PTask.h,v 1.7 2000/02/23 02:56:53 steve Exp $" +#ident "$Id: PTask.h,v 1.8 2000/03/08 04:36:53 steve Exp $" #endif # include "LineInfo.h" # include "svector.h" # include class Design; +class NetScope; class PWire; class Statement; @@ -38,6 +39,12 @@ class PTask : public LineInfo { explicit PTask(svector*p, Statement*s); ~PTask(); + // Tasks introduce scope, to need to be handled during the + // scope elaboration pass. The scope passed is my scope, + // created by the containing scope. I fill it in with stuff if + // I need to. + void elaborate_scope(Design*des, NetScope*scope) const; + void elaborate_1(Design*des, const string&path) const; void elaborate_2(Design*des, const string&path) const; @@ -65,9 +72,11 @@ class PFunction : public LineInfo { void set_output(PWire*); + void elaborate_scope(Design*des, NetScope*scope) const; + /* Functions are elaborated in 2 passes. */ - void elaborate_1(Design *des, const string &path) const; - void elaborate_2(Design *des, const string &path) const; + void elaborate_1(Design *des, NetScope*) const; + void elaborate_2(Design *des, NetScope*) const; void dump(ostream&, unsigned) const; @@ -79,6 +88,13 @@ class PFunction : public LineInfo { /* * $Log: PTask.h,v $ + * Revision 1.8 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.7 2000/02/23 02:56:53 steve * Macintosh compilers do not support ident. * diff --git a/README.txt b/README.txt index 80d0a2c23..9e8a33871 100644 --- a/README.txt +++ b/README.txt @@ -104,6 +104,33 @@ optimized netlist by using the ``-N '' flag to the compiler. If elaboration succeeds, the final netlist (i.e. after optimizations but before code generation) will be dumped into the file named . +Elaboration is actually performed it two steps: scopes and parameters +first, followed by the structural and behavioral elaboration. + +3.3.1 Scope Elaboration + +This pass scans through the pform looking for scopes and +parameters. A tree of NetScope objects is built up and placed in the +Design object, with the root module represented by the root NetScope +object. + +The elab_scope.cc and elab_pexpr.cc files contain most of the code for +handling this phase. + +The tail of the elaborate_scope behavior (after the pform is +traversed) includes a scan of the NetScope tree to locate defparam +assignments that were collected during scope elaboration. This is when +the defparam overrides are applied to the parameters. + +3.3.2 Netlist Elaboration + +After the scopes and parameters are generated and the NetScope tree +fully formed, the elaboration runs through teh pform again, this time +generating the structural and behavioral netlist. Parameters are +elaborated and evaluated by now so all the constants of code +generation are now known locally, so the netlist can be generated by +simply passing through the pform. + 3.4 Optimization This is actually a collection of processing steps that perform diff --git a/design_dump.cc b/design_dump.cc index dd243861d..c9af0f967 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: design_dump.cc,v 1.67 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: design_dump.cc,v 1.68 2000/03/08 04:36:53 steve Exp $" #endif /* @@ -523,7 +523,7 @@ void NetForever::dump(ostream&o, unsigned ind) const void NetFuncDef::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "function " << name_ << endl; + o << setw(ind) << "" << "function " << scope_->name() << endl; if (statement_) statement_->dump(o, ind+2); else @@ -596,11 +596,41 @@ void NetScope::dump(ostream&o) const case FORK_JOIN: o << " parallel block"; break; + case FUNC: + o << " function"; + break; case MODULE: o << " module"; break; + case TASK: + o << " task"; + break; } o << endl; + + /* Dump the parameters for this scope. */ + { + map::const_iterator pp; + for (pp = parameters_.begin() + ; pp != parameters_.end() ; pp ++) { + o << " parameter " << (*pp).first << " = " << + *(*pp).second << ";" << endl; + } + } + + /* Dump the saved defparam assignments here. */ + { + map::const_iterator pp; + for (pp = defparams.begin() + ; pp != defparams.end() ; pp ++ ) { + o << " defparam " << (*pp).first << " = " << + *(*pp).second << ";" << endl; + } + } + + /* Dump any sub-scopes. */ + for (NetScope*cur = sub_ ; cur ; cur = cur->sib_) + cur->dump(o); } void NetSTask::dump(ostream&o, unsigned ind) const @@ -756,7 +786,7 @@ void NetEMemory::dump(ostream&o) const void NetEParam::dump(ostream&o) const { - o << "<" << path_ << "." << name_ << ">"; + o << "<" << scope_->name() << "." << name_ << ">"; } void NetETernary::dump(ostream&o) const @@ -795,22 +825,7 @@ void NetEUnary::dump(ostream&o) const void Design::dump(ostream&o) const { o << "SCOPES:" << endl; - { - map::const_iterator pp; - for (pp = scopes_.begin() - ; pp != scopes_.end() ; pp ++) - (*pp).second -> dump(o); - } - - o << "ELABORATED PARAMETERS:" << endl; - { - map::const_iterator pp; - for (pp = parameters_.begin() - ; pp != parameters_.end() ; pp ++) { - o << " " << (*pp).first << " = " << - *(*pp).second << ";" << endl; - } - } + root_scope_->dump(o); o << "ELABORATED SIGNALS:" << endl; @@ -871,6 +886,13 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.68 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.67 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * diff --git a/elab_expr.cc b/elab_expr.cc index 474ef4563..acbb76695 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -17,23 +17,30 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_expr.cc,v 1.16 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.17 2000/03/08 04:36:53 steve Exp $" #endif # include "pform.h" # include "netlist.h" +NetExpr* PExpr::elaborate_expr(Design*des, NetScope*) const +{ + cerr << get_line() << ": I do not know how to elaborate expression: " + << *this << endl; + return 0; +} + /* * Elaborate binary expressions. This involves elaborating the left * and right sides, and creating one of a variety of different NetExpr * types. */ -NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const +NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope) const { bool flag; - NetExpr*lp = left_->elaborate_expr(des, path); - NetExpr*rp = right_->elaborate_expr(des, path); + NetExpr*lp = left_->elaborate_expr(des, scope); + NetExpr*rp = right_->elaborate_expr(des, scope); if ((lp == 0) || (rp == 0)) { delete lp; delete rp; @@ -116,7 +123,7 @@ NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const return tmp; } -NetESFunc* PECallFunction::elaborate_sfunc_(Design*des, const string&path) const +NetESFunc* PECallFunction::elaborate_sfunc_(Design*des, NetScope*) const { cerr << get_line() << ": sorry: system functions not supported." << endl; @@ -124,29 +131,39 @@ NetESFunc* PECallFunction::elaborate_sfunc_(Design*des, const string&path) const return 0; } -NetExpr* PECallFunction::elaborate_expr(Design*des, const string&path) const +NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const { if (name_[0] == '$') - return elaborate_sfunc_(des, path); + return elaborate_sfunc_(des, scope); - string myname = path+"."+name_; - NetFuncDef*def = des->find_function(path, name_); + NetFuncDef*def = des->find_function(scope->name(), name_); if (def == 0) { cerr << get_line() << ": error: No function " << name_ << - " in this context (" << path << ")." << endl; + " in this context (" << scope->name() << ")." << endl; des->errors += 1; return 0; } assert(def); + + svector parms (parms_.count()); + /* Elaborate the input expressions for the function. This is + done in the scope of the function call, and not the scope + of the function being called. The scope of the called + function is elaborated when the definition is elaborated. */ + for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) { - NetExpr*tmp = parms_[idx]->elaborate_expr(des, myname); + NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope); parms[idx] = tmp; } - /* Look for the return value signal for the called function in - the context of the function definition, not my context. */ + + /* Look for the return value signal for the called + function. This return value is a magic signal in the scope + of the function, that has the name of the function. The + function code assigns to this signal to return a value. */ + NetNet*res = des->find_signal(def->name(), name_); if (res == 0) { cerr << get_line() << ": internal error: Unable to locate " @@ -164,14 +181,14 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, const string&path) const } -NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const +NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope) const { unsigned repeat = 1; /* If there is a repeat expression, then evaluate the constant value and set the repeat count. */ if (repeat_) { - verinum*vrep = repeat_->eval_const(des, path); + verinum*vrep = repeat_->eval_const(des, scope->name()); if (vrep == 0) { cerr << get_line() << ": error: " "concatenation repeat expression cannot be evaluated." @@ -191,7 +208,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const /* Elaborate all the parameters and attach them to the concat node. */ for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { assert(parms_[idx]); - NetExpr*ex = parms_[idx]->elaborate_expr(des, path); + NetExpr*ex = parms_[idx]->elaborate_expr(des, scope); if (ex == 0) continue; ex->set_line(*parms_[idx]); tmp->set(idx, ex); @@ -200,22 +217,23 @@ NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const return tmp; } -NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const +NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const { // System identifiers show up in the netlist as identifiers. if (text_[0] == '$') return new NetEIdent(text_, 64); - string name = path+"."+text_; + //string name = path+"."+text_; + assert(scope); // If the identifier name is a parameter name, then return // a reference to the parameter expression. - if (const NetExpr*ex = des->find_parameter(path, text_)) { + if (const NetExpr*ex = des->find_parameter(scope, text_)) { NetExpr*tmp; if (dynamic_cast(ex)) tmp = ex->dup_expr(); else - tmp = new NetEParam(des, path, text_); + tmp = new NetEParam(des, scope, text_); tmp->set_line(*this); return tmp; @@ -223,15 +241,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const // If the identifier names a signal (a register or wire) // then create a NetESignal node to handle it. - if (NetNet*net = des->find_signal(path, text_)) { + if (NetNet*net = des->find_signal(scope->name(), text_)) { // If this is a part select of a signal, then make a new // temporary signal that is connected to just the // selected bits. if (lsb_) { assert(msb_); - verinum*lsn = lsb_->eval_const(des, path); - verinum*msn = msb_->eval_const(des, path); + verinum*lsn = lsb_->eval_const(des, scope->name()); + verinum*msn = msb_->eval_const(des, scope->name()); if ((lsn == 0) || (msn == 0)) { cerr << get_line() << ": error: " "Part select expresions must be " @@ -248,7 +266,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const assert(wid <= net->pin_count()); assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv)); - string tname = des->local_symbol(path); + string tname = des->local_symbol(scope->name()); NetTmp*tsig = new NetTmp(tname, wid); // Connect the pins from the lsb up to the msb. @@ -267,11 +285,11 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const // to the part select, so that I save the effort of // making a mux part in the netlist. verinum*msn; - if (msb_ && (msn = msb_->eval_const(des, path))) { + if (msb_ && (msn = msb_->eval_const(des, scope->name()))) { assert(idx_ == 0); unsigned long msv = msn->as_ulong(); - string tname = des->local_symbol(path); + string tname = des->local_symbol(scope->name()); NetTmp*tsig = new NetTmp(tname); connect(tsig->pin(0), net->pin(msv)); NetESignal*tmp = new NetESignal(tsig); @@ -287,7 +305,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const // Non-constant bit select? punt and make a subsignal // device to mux the bit in the net. if (msb_) { - NetExpr*ex = msb_->elaborate_expr(des, path); + NetExpr*ex = msb_->elaborate_expr(des, scope); NetESubSignal*ss = new NetESubSignal(node, ex); ss->set_line(*this); return ss; @@ -302,22 +320,16 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const // If the identifier names a memory, then this is a // memory reference and I must generate a NetEMemory // object to handle it. - if (NetMemory*mem = des->find_memory(path, text_)) { + if (NetMemory*mem = des->find_memory(scope->name(), text_)) { if (msb_ == 0) { NetEMemory*node = new NetEMemory(mem); node->set_line(*this); return node; -#if 0 - cerr << get_line() << ": error: Memory ``" << name << - "'' referenced without an index expression." << endl; - des->errors += 1; - return 0; -#endif } assert(msb_ != 0); assert(lsb_ == 0); assert(idx_ == 0); - NetExpr*i = msb_->elaborate_expr(des, path); + NetExpr*i = msb_->elaborate_expr(des, scope); if (msb_ && i == 0) { cerr << get_line() << ": error: Unable to exaborate " "index expression `" << *msb_ << "'" << endl; @@ -339,33 +351,48 @@ NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const // I cannot interpret this identifier. Error message. cerr << get_line() << ": error: Unable to bind wire/reg/memory " - "`" << path << "." << text_ << "'" << endl; + "`" << text_ << "' in `" << scope->name() << "'" << endl; des->errors += 1; return 0; } +NetEConst* PENumber::elaborate_expr(Design*des, NetScope*) const +{ + assert(value_); + NetEConst*tmp = new NetEConst(*value_); + tmp->set_line(*this); + return tmp; +} + +NetEConst* PEString::elaborate_expr(Design*des, NetScope*) const +{ + NetEConst*tmp = new NetEConst(value()); + tmp->set_line(*this); + return tmp; +} + /* * Elaborate the Ternary operator. I know that the expressions were * parsed so I can presume that they exist, and call elaboration * methods. If any elaboration fails, then give up and return 0. */ -NetExpr*PETernary::elaborate_expr(Design*des, const string&path) const +NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope) const { assert(expr_); assert(tru_); assert(fal_); - NetExpr*con = expr_->elaborate_expr(des, path); + NetExpr*con = expr_->elaborate_expr(des, scope); if (con == 0) return 0; - NetExpr*tru = tru_->elaborate_expr(des, path); + NetExpr*tru = tru_->elaborate_expr(des, scope); if (tru == 0) { delete con; return 0; } - NetExpr*fal = fal_->elaborate_expr(des, path); + NetExpr*fal = fal_->elaborate_expr(des, scope); if (fal == 0) { delete con; delete tru; @@ -376,8 +403,38 @@ NetExpr*PETernary::elaborate_expr(Design*des, const string&path) const return res; } +NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const +{ + NetExpr*ip = expr_->elaborate_expr(des, scope); + if (ip == 0) return 0; + + /* Should we evaluate expressions ahead of time, + * just like in PEBinary::elaborate_expr() ? + */ + + NetEUnary*tmp; + switch (op_) { + default: + tmp = new NetEUnary(op_, ip); + tmp->set_line(*this); + break; + case '~': + tmp = new NetEUBits(op_, ip); + tmp->set_line(*this); + break; + } + return tmp; +} + /* * $Log: elab_expr.cc,v $ + * Revision 1.17 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.16 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * diff --git a/elab_net.cc b/elab_net.cc index ab220f007..994a8aade 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_net.cc,v 1.23 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: elab_net.cc,v 1.24 2000/03/08 04:36:53 steve Exp $" #endif # include "PExpr.h" @@ -823,7 +823,7 @@ NetNet* PEIdent::elaborate_net(Design*des, const string&path, rise, fall, decay); - if (const NetExpr*pe = des->find_parameter(path, text_)) { + if (const NetExpr*pe = des->find_parameter(scope, text_)) { const NetEConst*pc = dynamic_cast(pe); assert(pc); @@ -1336,6 +1336,13 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path, /* * $Log: elab_net.cc,v $ + * Revision 1.24 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.23 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * diff --git a/elab_pexpr.cc b/elab_pexpr.cc new file mode 100644 index 000000000..a1f89e19b --- /dev/null +++ b/elab_pexpr.cc @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2000 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) && !defined(macintosh) +#ident "$Id: elab_pexpr.cc,v 1.1 2000/03/08 04:36:53 steve Exp $" +#endif + +# include "PExpr.h" + +NetExpr*PExpr::elaborate_pexpr(Design*des, NetScope*sc) const +{ + cerr << get_line() << ": error: invalid parameter expression: " + << *this << endl; + des->errors += 1; + + return 0; +} + +/* + * Simple numbers can be elaborated by the elaborate_expr method. + */ +NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const +{ + return elaborate_expr(des, sc); +} + + +/* + * $Log: elab_pexpr.cc,v $ + * Revision 1.1 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * + */ + diff --git a/elab_scope.cc b/elab_scope.cc new file mode 100644 index 000000000..0ca0a0036 --- /dev/null +++ b/elab_scope.cc @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2000 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) && !defined(macintosh) +#ident "$Id: elab_scope.cc,v 1.1 2000/03/08 04:36:53 steve Exp $" +#endif + +/* + * Elaboration happens in two passes, generally. The first scans the + * pform to generate the NetScope tree and attach it to the Design + * object. The methods in this source file implement the elaboration + * of the scopes. + */ + +# include "Module.h" +# include "PExpr.h" +# include "PGate.h" +# include "PTask.h" +# include "netlist.h" + +bool Module::elaborate_scope(Design*des, NetScope*scope) const +{ + // Generate all the parameters that this instance of this + // module introduces to the design. This loop elaborates the + // parameters, but doesn't evaluate references to + // parameters. This scan practically locates all the + // parameters and puts them in the parameter table in the + // design. + + // No expressions are evaluated, yet. For now, leave them in + // the pform and just place a NetEParam placeholder in the + // place of the elaborated expression. + + typedef map::const_iterator mparm_it_t; + + + // This loop scans the parameters in the module, and creates + // stub parameter entries in the scope for the parameter name. + + for (mparm_it_t cur = parameters.begin() + ; cur != parameters.end() ; cur ++) { + + scope->set_parameter((*cur).first, new NetEParam); + } + + // Now scan the parameters again, this time elaborating them + // for use as parameter values. This is after the previous + // scan so that local parameter names can be used in the + // r-value expressions. + + for (mparm_it_t cur = parameters.begin() + ; cur != parameters.end() ; cur ++) { + + PExpr*ex = (*cur).second; + assert(ex); + + NetExpr*val = ex->elaborate_pexpr(des, scope); + val = scope->set_parameter((*cur).first, val); + assert(val); + delete val; + } + + // 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 becuase the parameter receiving the assignment may be + // in a scope not discovered by this pass. + + for (mparm_it_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[(*cur).first] = val; + } + + + // Tasks introduce new scopes, so scan the tasks in this + // module. Create a scope for the task and pass that to the + // elaborate_scope method of the PTask for detailed + // processing. + + typedef map::const_iterator tasks_it_t; + + for (tasks_it_t cur = tasks_.begin() + ; cur != tasks_.end() ; cur ++ ) { + + NetScope*task_scope = new NetScope(scope, (*cur).first, + NetScope::TASK); + (*cur).second->elaborate_scope(des, task_scope); + } + + + // Functions are very similar to tasks, at least from the + // perspective of scopes. So handle them exactly the same + // way. + + typedef map::const_iterator funcs_it_t; + + for (funcs_it_t cur = funcs_.begin() + ; cur != funcs_.end() ; cur ++ ) { + + NetScope*func_scope = new NetScope(scope, (*cur).first, + NetScope::FUNC); + (*cur).second->elaborate_scope(des, func_scope); + } + + + // Gates include modules, which might introduce new scopes, so + // scan all of them to create those scopes. + + typedef list::const_iterator gates_it_t; + + for (gates_it_t cur = gates_.begin() + ; cur != gates_.end() ; cur ++ ) { + + (*cur)->elaborate_scope(des, scope); + } + + + return des->errors == 0; +} + +void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const +{ + // Missing module instance names have already been rejected. + assert(get_name() != ""); + + string path = sc->name(); + + // Check for duplicate scopes. Simply look up the scope I'm + // about to create, and if I find it then somebody beat me to + // it. + + if (NetScope*tmp = des->find_scope(path + "." + get_name())) { + cerr << get_line() << ": error: Instance/Scope name " << + get_name() << " already used in this context." << + endl; + des->errors += 1; + return; + } + + // Create the new scope as a MODULE with my name. + NetScope*my_scope = des->make_scope(path, NetScope::MODULE, get_name()); + + // This call actually arranges for the description of the + // module type to process this instance and handle parameters + // and sub-scopes that might occur. Parameters are also + // created in that scope, as they exist. (I'll override them + // later.) + mod->elaborate_scope(des, my_scope); + + // Look for module parameter replacements. This map receives + // those replacements. + + typedef map::const_iterator mparm_it_t; + map replace; + + + // Positional parameter overrides are matched to parameter + // names by using the param_names list of parameter + // names. This is an ordered list of names so the first name + // is parameter 0, the second parameter 1, and so on. + + if (overrides_) { + assert(parms_ == 0); + list::const_iterator cur = mod->param_names.begin(); + for (unsigned idx = 0 + ; idx < overrides_->count() + ; idx += 1, cur++) { + replace[*cur] = (*overrides_)[idx]; + } + + } + + // Named parameter overrides carry a name with each override + // so the mapping into the replace list is much easier. + if (parms_) { + assert(overrides_ == 0); + for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) + replace[parms_[idx].name] = parms_[idx].parm; + + } + + + // And here we scan the replacements we collected. Elaborate + // the expression in my context, then replace the sub-scope + // parameter value with the new expression. + + for (mparm_it_t cur = replace.begin() + ; cur != replace.end() ; cur ++ ) { + + PExpr*tmp = (*cur).second; + NetExpr*val = tmp->elaborate_pexpr(des, sc); + val = my_scope->set_parameter((*cur).first, val); + assert(val); + delete val; + } +} + +void PFunction::elaborate_scope(Design*des, NetScope*scope) const +{ +} + +void PTask::elaborate_scope(Design*des, NetScope*scope) const +{ +} + + +/* + * $Log: elab_scope.cc,v $ + * Revision 1.1 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * + */ + diff --git a/elaborate.cc b/elaborate.cc index 13081a9f0..b133080f6 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elaborate.cc,v 1.145 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: elaborate.cc,v 1.146 2000/03/08 04:36:53 steve Exp $" #endif /* @@ -385,14 +385,6 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const { // Missing module instance names have already been rejected. assert(get_name() != ""); - // Check for duplicate scopes. - if (NetScope*tmp = des->find_scope(path + "." + get_name())) { - cerr << get_line() << ": error: Instance/Scope name " << - get_name() << " already used in this context." << - endl; - des->errors += 1; - return; - } if (msb_) { cerr << get_line() << ": sorry: Module instantiation arrays " @@ -401,7 +393,13 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const return; } - NetScope*my_scope = des->make_scope(path, NetScope::MODULE, get_name()); + NetScope*scope = des->find_scope(path); + assert(scope); + + // I know a priori that the elaborate_scope created the scope + // already, so just look it up as a child of the current scope. + NetScope*my_scope = scope->child(get_name()); + assert(my_scope); const string my_name = my_scope -> name(); const svector*pins; @@ -471,7 +469,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const // elaboration causes the module to generate a netlist with // the ports represented by NetNet objects. I will find them // later. - rmod->elaborate(des, my_scope, parms_, nparms_, overrides_); + rmod->elaborate(des, my_scope); // Now connect the ports of the newly elaborated designs to // the expressions that are the instantiation parameters. Scan @@ -614,7 +612,27 @@ void PGModule::elaborate(Design*des, const string&path) const return; } - cerr << get_line() << ": error: Unknown module: " << type_ << endl; + cerr << get_line() << ": internal error: Unknown module type: " << + type_ << endl; +} + +void PGModule::elaborate_scope(Design*des, NetScope*sc) const +{ + // Look for the module type + map::const_iterator mod = modlist->find(type_); + if (mod != modlist->end()) { + elaborate_scope_mod_(des, (*mod).second, sc); + return; + } + + // Try a primitive type + map::const_iterator udp = udplist->find(type_); + if (udp != udplist->end()) + return; + + + cerr << get_line() << ": error: Unknown module type: " << type_ << endl; + des->errors += 1; } /* @@ -672,51 +690,6 @@ NetNet* PEConcat::elaborate_lnet(Design*des, const string&path) const return osig; } -NetExpr* PENumber::elaborate_expr(Design*des, const string&path) const -{ - assert(value_); - NetEConst*tmp = new NetEConst(*value_); - tmp->set_line(*this); - return tmp; -} - -NetExpr* PEString::elaborate_expr(Design*des, const string&path) const -{ - NetEConst*tmp = new NetEConst(value()); - tmp->set_line(*this); - return tmp; -} - -NetExpr* PExpr::elaborate_expr(Design*des, const string&path) const -{ - cerr << get_line() << ": I do not know how to elaborate expression: " - << *this << endl; - return 0; -} - -NetExpr* PEUnary::elaborate_expr(Design*des, const string&path) const -{ - NetExpr*ip = expr_->elaborate_expr(des, path); - if (ip == 0) return 0; - - /* Should we evaluate expressions ahead of time, - * just like in PEBinary::elaborate_expr() ? - */ - - NetEUnary*tmp; - switch (op_) { - default: - tmp = new NetEUnary(op_, ip); - tmp->set_line(*this); - break; - case '~': - tmp = new NetEUBits(op_, ip); - tmp->set_line(*this); - break; - } - return tmp; -} - NetProc* Statement::elaborate(Design*des, const string&path) const { cerr << "internal error: elaborate: What kind of statement? " << @@ -728,7 +701,9 @@ NetProc* Statement::elaborate(Design*des, const string&path) const NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix, Design*des, const string&path) const { - NetExpr*rv = rval()->elaborate_expr(des, path); + NetScope*scope = des->find_scope(path); + assert(scope); + NetExpr*rv = rval()->elaborate_expr(des, scope); if (rv == 0) return 0; @@ -751,6 +726,9 @@ NetNet* PAssign_::elaborate_lval(Design*des, const string&path, unsigned&msb, unsigned&lsb, NetExpr*&mux) const { + NetScope*scope = des->find_scope(path); + assert(scope); + /* Get the l-value, and assume that it is an identifier. */ const PEIdent*id = dynamic_cast(lval()); @@ -828,7 +806,7 @@ NetNet* PAssign_::elaborate_lval(Design*des, const string&path, assert(id->lsb_ == 0); verinum*v = id->msb_->eval_const(des, path); if (v == 0) { - NetExpr*m = id->msb_->elaborate_expr(des, path); + NetExpr*m = id->msb_->elaborate_expr(des, scope); assert(m); msb = 0; lsb = 0; @@ -858,6 +836,9 @@ NetNet* PAssign_::elaborate_lval(Design*des, const string&path, NetProc* PAssign::elaborate(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + /* Catch the case where the lvalue is a reference to a memory item. These are handled differently. */ do { @@ -891,7 +872,7 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const rv = new NetEConst(*val); delete val; - } else if (rv = rval()->elaborate_expr(des, path)) { + } else if (rv = rval()->elaborate_expr(des, scope)) { /* OK, go on. */ @@ -1036,8 +1017,11 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const NetProc* PAssignNB::assign_to_memory_(NetMemory*mem, PExpr*ix, Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + /* Elaborate the r-value expression, ... */ - NetExpr*rv = rval()->elaborate_expr(des, path); + NetExpr*rv = rval()->elaborate_expr(des, scope); if (rv == 0) return 0; @@ -1065,6 +1049,9 @@ NetProc* PAssignNB::assign_to_memory_(NetMemory*mem, PExpr*ix, */ NetProc* PAssignNB::elaborate(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + /* Catch the case where the lvalue is a reference to a memory item. These are handled differently. */ do { @@ -1086,7 +1073,7 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const /* Elaborate the r-value expression. This generates a procedural expression that I attach to the assignment. */ - NetExpr*rv = rval()->elaborate_expr(des, path); + NetExpr*rv = rval()->elaborate_expr(des, scope); if (rv == 0) return 0; @@ -1132,6 +1119,9 @@ NetProc* PAssignNB::elaborate(Design*des, const string&path) const */ NetProc* PBlock::elaborate(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + NetBlock::Type type = (bl_type_==PBlock::BL_PAR) ? NetBlock::PARA : NetBlock::SEQU; @@ -1139,19 +1129,14 @@ NetProc* PBlock::elaborate(Design*des, const string&path) const bool fail_flag = false; string npath; + NetScope*nscope; if (name_.length()) { - // Check for duplicate scopes. - if (NetScope*tmp = des->find_scope(path + "." + name_)) { - cerr << get_line() << ": error: Instance/Scope name " << - name_ << " already used in this context." << - endl; - des->errors += 1; - return 0; - } - // Make this new scope. - npath = des->make_scope(path, NetScope::BEGIN_END, name_)->name(); + nscope = scope->child(name_); + assert(nscope); + npath = nscope->name(); } else { + nscope = scope; npath = path; } @@ -1184,7 +1169,10 @@ NetProc* PBlock::elaborate(Design*des, const string&path) const */ NetProc* PCase::elaborate(Design*des, const string&path) const { - NetExpr*expr = expr_->elaborate_expr(des, path); + NetScope*scope = des->find_scope(path); + assert(scope); + + NetExpr*expr = expr_->elaborate_expr(des, scope); if (expr == 0) { cerr << get_line() << ": error: Unable to elaborate this case" " expression." << endl; @@ -1229,7 +1217,7 @@ NetProc* PCase::elaborate(Design*des, const string&path) const NetExpr*gu = 0; NetProc*st = 0; assert(cur->expr[e]); - gu = cur->expr[e]->elaborate_expr(des, path); + gu = cur->expr[e]->elaborate_expr(des, scope); if (cur->stat) st = cur->stat->elaborate(des, path); @@ -1244,8 +1232,11 @@ NetProc* PCase::elaborate(Design*des, const string&path) const NetProc* PCondit::elaborate(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + // Elaborate and try to evaluate the conditional expression. - NetExpr*expr = expr_->elaborate_expr(des, path); + NetExpr*expr = expr_->elaborate_expr(des, scope); if (expr == 0) { cerr << get_line() << ": error: Unable to elaborate" " condition expression." << endl; @@ -1321,12 +1312,15 @@ NetProc* PCallTask::elaborate(Design*des, const string&path) const */ NetProc* PCallTask::elaborate_sys(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + svectoreparms (nparms()); for (unsigned idx = 0 ; idx < nparms() ; idx += 1) { PExpr*ex = parm(idx); - eparms[idx] = ex? ex->elaborate_expr(des, path) : 0; + eparms[idx] = ex? ex->elaborate_expr(des, scope) : 0; } NetSTask*cur = new NetSTask(name(), eparms); @@ -1363,6 +1357,9 @@ NetProc* PCallTask::elaborate_sys(Design*des, const string&path) const */ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + NetTaskDef*def = des->find_task(path, name_); if (def == 0) { cerr << get_line() << ": error: Enable of unknown task ``" << @@ -1400,7 +1397,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const if (port->port_type() == NetNet::POUTPUT) continue; - NetExpr*rv = parms_[idx]->elaborate_expr(des, path); + NetExpr*rv = parms_[idx]->elaborate_expr(des, scope); NetAssign*pr = new NetAssign("@", des, port->pin_count(), rv); for (unsigned pi = 0 ; pi < port->pin_count() ; pi += 1) connect(port->pin(pi), pr->pin(pi)); @@ -1566,6 +1563,9 @@ NetProc* PForever::elaborate(Design*des, const string&path) const */ NetProc* PForStatement::elaborate(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + const PEIdent*id1 = dynamic_cast(name1_); assert(id1); const PEIdent*id2 = dynamic_cast(name2_); @@ -1585,7 +1585,7 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const } assert(sig); NetAssign*init = new NetAssign("@for-assign", des, sig->pin_count(), - expr1_->elaborate_expr(des, path)); + expr1_->elaborate_expr(des, scope)); for (unsigned idx = 0 ; idx < init->pin_count() ; idx += 1) connect(init->pin(idx), sig->pin(idx)); @@ -1608,7 +1608,7 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const sig = des->find_signal(path, id2->name()); assert(sig); NetAssign*step = new NetAssign("@for-assign", des, sig->pin_count(), - expr2_->elaborate_expr(des, path)); + expr2_->elaborate_expr(des, scope)); for (unsigned idx = 0 ; idx < step->pin_count() ; idx += 1) connect(step->pin(idx), sig->pin(idx)); @@ -1618,7 +1618,7 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const /* Elaborate the condition expression. Try to evaluate it too, in case it is a constant. This is an interesting case worthy of a warning. */ - NetExpr*ce = cond_->elaborate_expr(des, path); + NetExpr*ce = cond_->elaborate_expr(des, scope); if (ce == 0) { delete top; return 0; @@ -1647,8 +1647,12 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const * within. These passes are needed because the statement may invoke * the function itself (or other functions) so can't be elaborated * until all the functions are partially elaborated. + * + * In both cases, the scope parameter is the scope of the function. In + * other words, it is the scope that has the name of the function with + * the path of the containing module. */ -void PFunction::elaborate_1(Design*des, const string&path) const +void PFunction::elaborate_1(Design*des, NetScope*scope) const { /* Translate the wires that are ports to NetNet pointers by presuming that the name is already elaborated, and look it @@ -1656,26 +1660,27 @@ void PFunction::elaborate_1(Design*des, const string&path) const calls to the task. (Remember, the task itself does not need these ports.) */ svectorports (ports_? ports_->count()+1 : 1); - ports[0] = des->find_signal(path, path); + ports[0] = des->find_signal(scope->name(), scope->name()); for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) { - NetNet*tmp = des->find_signal(path, (*ports_)[idx]->name()); + NetNet*tmp = des->find_signal(scope->name(), + (*ports_)[idx]->name()); ports[idx+1] = tmp; } - NetFuncDef*def = new NetFuncDef(path, ports); - des->add_function(path, def); + NetFuncDef*def = new NetFuncDef(scope, ports); + des->add_function(scope->name(), def); } -void PFunction::elaborate_2(Design*des, const string&path) const +void PFunction::elaborate_2(Design*des, NetScope*scope) const { - NetFuncDef*def = des->find_function(path); + NetFuncDef*def = des->find_function(scope->name()); assert(def); - NetProc*st = statement_->elaborate(des, path); + NetProc*st = statement_->elaborate(des, scope->name()); if (st == 0) { cerr << statement_->get_line() << ": error: Unable to elaborate " - "statement in function " << path << "." << endl; + "statement in function " << def->name() << "." << endl; des->errors += 1; return; } @@ -1685,7 +1690,10 @@ void PFunction::elaborate_2(Design*des, const string&path) const NetProc* PRepeat::elaborate(Design*des, const string&path) const { - NetExpr*expr = expr_->elaborate_expr(des, path); + NetScope*scope = des->find_scope(path); + assert(scope); + + NetExpr*expr = expr_->elaborate_expr(des, scope); if (expr == 0) { cerr << get_line() << ": Unable to elaborate" " repeat expression." << endl; @@ -1775,120 +1783,19 @@ void PTask::elaborate_2(Design*des, const string&path) const */ NetProc* PWhile::elaborate(Design*des, const string&path) const { - NetWhile*loop = new NetWhile(cond_->elaborate_expr(des, path), + NetScope*scope = des->find_scope(path); + assert(scope); + + NetWhile*loop = new NetWhile(cond_->elaborate_expr(des, scope), statement_->elaborate(des, path)); return loop; } -bool Module::elaborate(Design*des, NetScope*scope, - named*parms, unsigned nparms, - svector*overrides_) const +bool Module::elaborate(Design*des, NetScope*scope) const { const string path = scope->name(); bool result_flag = true; - // Generate all the parameters that this instance of this - // module introduce to the design. This needs to be done in - // two passes. The first pass marks the parameter names as - // available so that they can be discovered when the second - // pass references them during elaboration. - typedef map::const_iterator mparm_it_t; - - // So this loop elaborates the parameters, but doesn't - // evaluate references to parameters. This scan practically - // locates all the parameters and puts them in the parameter - // table in the design. No expressions are evaluated. - for (mparm_it_t cur = parameters.begin() - ; cur != parameters.end() ; cur ++) { - string pname = path + "." + (*cur).first; - des->set_parameter(pname, new NetEParam); - } - - // The replace map contains replacement expressions for the - // parameters. If there is a replacement expression, use that - // instead of the default expression. Otherwise, use the - // default expression. - - // Replacement expressions can come from the ordered list of - // overrides, or from the parameter replace by name list. - - map replace; - - if (overrides_) { - assert(parms == 0); - list::const_iterator cur = param_names.begin(); - for (unsigned idx = 0 - ; idx < overrides_->count() - ; idx += 1, cur++) { - replace[*cur] = (*overrides_)[idx]; - } - - } else if (parms) { - - for (unsigned idx = 0 ; idx < nparms ; idx += 1) - replace[parms[idx].name] = parms[idx].parm; - - } - - - // ... and this loop elaborates the expressions. The parameter - // expressions are reduced to ordinary expressions that do not - // include references to other parameters. Take careful note - // of the fact that override expressions are elaborated in the - // *parent* scope. - - for (mparm_it_t cur = parameters.begin() - ; cur != parameters.end() ; cur ++) { - string pname = path + "." + (*cur).first; - NetExpr*expr; - - if (PExpr*tmp = replace[(*cur).first]) - expr = tmp->elaborate_expr(des, scope->parent()->name()); - else - expr = (*cur).second->elaborate_expr(des, path); - - des->set_parameter(pname, expr); - } - - - // Finally, evaluate the parameter value. This step collapses - // the parameters to NetEConst values. - for (mparm_it_t cur = parameters.begin() - ; cur != parameters.end() ; cur ++) { - - // Get the NetExpr for the parameter. - string pname = path + "." + (*cur).first; - const NetExpr*expr = des->find_parameter(path, (*cur).first); - assert(expr); - - // If it's already a NetEConst, then this parameter is done. - if (dynamic_cast(expr)) - continue; - - // Get a non-constant copy of the expression to evaluate... - NetExpr*nexpr = expr->dup_expr(); - if (nexpr == 0) { - cerr << (*cur).second->get_line() << ": internal error: " - "unable to dup expression: " << *expr << endl; - des->errors += 1; - continue; - } - - // Try to evaluate the expression. - nexpr = nexpr->eval_tree(); - if (nexpr == 0) { - cerr << (*cur).second->get_line() << ": internal error: " - "unable to evaluate parm expression: " << - *expr << endl; - des->errors += 1; - continue; - } - - // The evaluate worked, replace the old expression with - // this constant value. - assert(nexpr); - des->set_parameter(pname, nexpr); - } // Get all the explicitly declared wires of the module and // start the signals list with them. @@ -1906,14 +1813,24 @@ bool Module::elaborate(Design*des, NetScope*scope, for (mfunc_it_t cur = funcs_.begin() ; cur != funcs_.end() ; cur ++) { - string pname = path + "." + (*cur).first; - (*cur).second->elaborate_1(des, pname); + NetScope*fscope = scope->child((*cur).first); + if (scope == 0) { + cerr << (*cur).second->get_line() << ": internal error: " + << "Child scope for function " << (*cur).first + << " missing in " << scope->name() << "." << endl; + des->errors += 1; + continue; + } + + (*cur).second->elaborate_1(des, fscope); } for (mfunc_it_t cur = funcs_.begin() ; cur != funcs_.end() ; cur ++) { - string pname = path + "." + (*cur).first; - (*cur).second->elaborate_2(des, pname); + + NetScope*fscope = scope->child((*cur).first); + assert(fscope); + (*cur).second->elaborate_2(des, fscope); } // Elaborate the task definitions. This is done before the @@ -1992,11 +1909,26 @@ Design* elaborate(const map&modules, // module and elaborate what I find. Design*des = new Design; - NetScope*scope = des->make_root_scope(root); - modlist = &modules; udplist = &primitives; - bool rc = rmod->elaborate(des, scope, 0, 0, (svector*)0); + + // Make the root scope, then scan the pform looking for scopes + // and parameters. + NetScope*scope = des->make_root_scope(root); + if (! rmod->elaborate_scope(des, scope)) { + delete des; + return 0; + } + + des->run_defparams(); + des->evaluate_parameters(); + + // Now that the structure and parameters are taken care of, + // run through the pform again and generate the full netlist. + + bool rc = rmod->elaborate(des, scope); + + modlist = 0; udplist = 0; @@ -2004,12 +1936,20 @@ Design* elaborate(const map&modules, delete des; des = 0; } + return des; } /* * $Log: elaborate.cc,v $ + * Revision 1.146 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.145 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * @@ -2024,145 +1964,5 @@ Design* elaborate(const map&modules, * * Revision 1.141 2000/01/10 01:35:23 steve * Elaborate parameters afer binding of overrides. - * - * Revision 1.140 2000/01/09 20:37:57 steve - * Careful with wires connected to multiple ports. - * - * Revision 1.139 2000/01/09 05:50:48 steve - * Support named parameter override lists. - * - * Revision 1.138 2000/01/02 19:39:03 steve - * Structural reduction XNOR. - * - * Revision 1.137 2000/01/02 18:25:37 steve - * Do not overrun the pin index when the LSB != 0. - * - * Revision 1.136 2000/01/01 06:18:00 steve - * Handle synthesis of concatenation. - * - * Revision 1.135 1999/12/14 23:42:16 steve - * Detect duplicate scopes. - * - * Revision 1.134 1999/12/11 05:45:41 steve - * Fix support for attaching attributes to primitive gates. - * - * Revision 1.133 1999/12/05 02:24:08 steve - * Synthesize LPM_RAM_DQ for writes into memories. - * - * Revision 1.132 1999/12/02 04:08:10 steve - * Elaborate net repeat concatenations. - * - * Revision 1.131 1999/11/28 23:42:02 steve - * NetESignal object no longer need to be NetNode - * objects. Let them keep a pointer to NetNet objects. - * - * Revision 1.130 1999/11/27 19:07:57 steve - * Support the creation of scopes. - * - * Revision 1.129 1999/11/24 04:01:58 steve - * Detect and list scope names. - * - * Revision 1.128 1999/11/21 20:03:24 steve - * Handle multiply in constant expressions. - * - * Revision 1.127 1999/11/21 17:35:37 steve - * Memory name lookup handles scopes. - * - * Revision 1.126 1999/11/21 01:16:51 steve - * Fix coding errors handling names of logic devices, - * and add support for buf device in vvm. - * - * Revision 1.125 1999/11/21 00:13:08 steve - * Support memories in continuous assignments. - * - * Revision 1.124 1999/11/18 03:52:19 steve - * Turn NetTmp objects into normal local NetNet objects, - * and add the nodangle functor to clean up the local - * symbols generated by elaboration and other steps. - * - * Revision 1.123 1999/11/10 02:52:24 steve - * Create the vpiMemory handle type. - * - * Revision 1.122 1999/11/05 21:45:19 steve - * Fix NetConst being set to zero width, and clean - * up elaborate_set_cmp_ for NetEBinary. - * - * Revision 1.121 1999/11/04 03:53:26 steve - * Patch to synthesize unary ~ and the ternary operator. - * Thanks to Larry Doolittle . - * - * Add the LPM_MUX device, and integrate it with the - * ternary synthesis from Larry. Replace the lpm_mux - * generator in t-xnf.cc to use XNF EQU devices to - * put muxs into function units. - * - * Rewrite elaborate_net for the PETernary class to - * also use the LPM_MUX device. - * - * Revision 1.120 1999/10/31 20:08:24 steve - * Include subtraction in LPM_ADD_SUB device. - * - * Revision 1.119 1999/10/31 04:11:27 steve - * Add to netlist links pin name and instance number, - * and arrange in vvm for pin connections by name - * and instance number. - * - * Revision 1.118 1999/10/18 00:02:21 steve - * Catch unindexed memory reference. - * - * Revision 1.117 1999/10/13 03:16:36 steve - * Remove commented out do_assign. - * - * Revision 1.116 1999/10/10 01:59:54 steve - * Structural case equals device. - * - * Revision 1.115 1999/10/09 21:30:16 steve - * Support parameters in continuous assignments. - * - * Revision 1.114 1999/10/09 19:24:04 steve - * Better message for combinational operators. - * - * Revision 1.113 1999/10/08 17:48:08 steve - * Support + in constant expressions. - * - * Revision 1.112 1999/10/08 17:27:23 steve - * Accept adder parameters with different widths, - * and simplify continuous assign construction. - * - * Revision 1.111 1999/10/07 05:25:33 steve - * Add non-const bit select in l-value of assignment. - * - * Revision 1.110 1999/10/06 00:39:00 steve - * == and != connected to the wrong pins of the compare. - * - * Revision 1.109 1999/10/05 06:19:46 steve - * Add support for reduction NOR. - * - * Revision 1.108 1999/10/05 02:00:06 steve - * sorry message for non-constant l-value bit select. - * - * Revision 1.107 1999/09/30 21:28:34 steve - * Handle mutual reference of tasks by elaborating - * task definitions in two passes, like functions. - * - * Revision 1.106 1999/09/30 17:22:33 steve - * catch non-constant delays as unsupported. - * - * Revision 1.105 1999/09/30 02:43:02 steve - * Elaborate ~^ and ~| operators. - * - * Revision 1.104 1999/09/30 00:48:50 steve - * Cope with errors during ternary operator elaboration. - * - * Revision 1.103 1999/09/29 22:57:10 steve - * Move code to elab_expr.cc - * - * Revision 1.102 1999/09/29 18:36:03 steve - * Full case support - * - * Revision 1.101 1999/09/29 00:42:50 steve - * Allow expanding of additive operators. - * - * Revision 1.100 1999/09/25 02:57:30 steve */ diff --git a/emit.cc b/emit.cc index 9e8fb0fea..7d67eb36b 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: emit.cc,v 1.33 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: emit.cc,v 1.34 2000/03/08 04:36:53 steve Exp $" #endif /* @@ -250,6 +250,13 @@ void NetRepeat::emit_recurse(ostream&o, struct target_t*tgt) const statement_->emit_proc(o, tgt); } +void NetScope::emit_scope(ostream&o, struct target_t*tgt) const +{ + tgt->scope(o, this); + for (NetScope*cur = sub_ ; cur ; cur = cur->sib_) + cur->emit_scope(o, tgt); +} + void NetWhile::emit_proc_recurse(ostream&o, struct target_t*tgt) const { proc_->emit_proc(o, tgt); @@ -261,11 +268,7 @@ bool Design::emit(ostream&o, struct target_t*tgt) const tgt->start_design(o, this); // enumerate the scopes - { map::const_iterator sc; - for (sc = scopes_.begin() ; sc != scopes_.end() ; sc++) { - tgt->scope(o, (*sc).second); - } - } + root_scope_->emit_scope(o, tgt); // emit signals if (signals_) { @@ -394,6 +397,13 @@ bool emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.34 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.33 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * diff --git a/eval.cc b/eval.cc index 0a34080bb..a1feb9727 100644 --- a/eval.cc +++ b/eval.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: eval.cc,v 1.13 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: eval.cc,v 1.14 2000/03/08 04:36:53 steve Exp $" #endif # include "PExpr.h" @@ -96,7 +96,9 @@ verinum* PEBinary::eval_const(const Design*des, const string&path) const */ verinum* PEIdent::eval_const(const Design*des, const string&path) const { - const NetExpr*expr = des->find_parameter(path, text_); + const NetScope*scope = des->find_scope(path); + assert(scope); + const NetExpr*expr = des->find_parameter(scope, text_); if (expr == 0) return 0; @@ -142,6 +144,13 @@ verinum* PETernary::eval_const(const Design*des, const string&path) const /* * $Log: eval.cc,v $ + * Revision 1.14 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.13 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * diff --git a/eval_tree.cc b/eval_tree.cc index 602f0f777..b3bc6ddd1 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: eval_tree.cc,v 1.8 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.9 2000/03/08 04:36:53 steve Exp $" #endif # include "netlist.h" @@ -241,7 +241,8 @@ NetExpr* NetEParam::eval_tree() if (des_ == 0) return 0; - const NetExpr*expr = des_->find_parameter(path_, name_); + assert(scope_); + const NetExpr*expr = scope_->get_parameter(name_); assert(expr); NetExpr*nexpr = expr->dup_expr(); @@ -262,12 +263,19 @@ NetExpr* NetEParam::eval_tree() // The result can be saved as the value of the parameter for // future reference, and return a copy to the caller. - des_->set_parameter(path_+"."+name_, res); + scope_->set_parameter(name_, res); return res->dup_expr(); } /* * $Log: eval_tree.cc,v $ + * Revision 1.9 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.8 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * diff --git a/net_design.cc b/net_design.cc new file mode 100644 index 000000000..4678c666c --- /dev/null +++ b/net_design.cc @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2000Stephen 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) && !defined(macintosh) +#ident "$Id: net_design.cc,v 1.1 2000/03/08 04:36:53 steve Exp $" +#endif + +/* + * This source file contains all the implementations of the Design + * class declared in netlist.h. + */ + +# include "netlist.h" + +static string parse_first_name(string&path) +{ + unsigned pos = path.find('.'); + if (pos > path.length()) { + string res = path; + path = ""; + return res; + } + + string res = path.substr(0, pos); + path = path.substr(pos+1, path.length()); + return res; +} + +static string parse_last_name(string&path) +{ + unsigned pos = path.rfind('.'); + if (pos > path.length()) { + string res = path; + path = ""; + return res; + } + + string res = path.substr(pos+1, path.length()); + path = path.substr(0, pos); + return res; +} + +Design:: Design() +: errors(0), root_scope_(0), signals_(0), nodes_(0), procs_(0), lcounter_(0) +{ +} + +Design::~Design() +{ +} + +NetScope* Design::make_root_scope(const string&root) +{ + assert(root_scope_ == 0); + root_scope_ = new NetScope(root); + return root_scope_; +} + +NetScope* Design::make_scope(const string&path, + NetScope::TYPE t, + const string&name) +{ + NetScope*up = find_scope(path); + assert(up); + + NetScope*scope = new NetScope(up, name, t); + + return scope; +} + + +/* + * This method locates a scope in the design, given its rooted + * heirarchical name. Each component of the key is used to scan one + * more step down the tree until the name runs out or the search + * fails. + */ +NetScope* Design::find_scope(const string&key) +{ + if (key == root_scope_->name()) + return root_scope_; + + string path = key; + string root = parse_first_name(path); + + NetScope*cur = root_scope_; + if (root != cur->name()) + return 0; + + while (cur) { + string next = parse_first_name(path); + cur = cur->child(next); + if (path == "") return cur; + } + + return cur; +} + +/* + * Find a parameter from within a specified context. If the name is + * not here, keep looking up until I run out of up to look at. The + * method works by scanning scopes, starting with the passed scope and + * working up towards the root, looking for the named parameter. The + * name in this case can be hierarchical, so there is an inner loop to + * follow the scopes of the name down to to key. + */ +const NetExpr* Design::find_parameter(const NetScope*scope, + const string&name) const +{ + for ( ; scope ; scope = scope->parent()) { + string path = name; + string key = parse_first_name(path); + + const NetScope*cur = scope; + while (path != "") { + cur = cur->child(key); + if (cur == 0) break; + key = parse_first_name(path); + } + + if (cur == 0) continue; + + if (const NetExpr*res = cur->get_parameter(key)) + return res; + } + + return 0; +} + + +/* + * This method runs through the scope, noticing the defparam + * statements that were collected during the elaborate_scope pass and + * applying them to the target parameters. The implementation actually + * works by using a specialized method from the NetScope class that + * does all the work for me. + */ +void Design::run_defparams() +{ + root_scope_->run_defparams(this); +} + +void NetScope::run_defparams(Design*des) +{ + NetScope*cur = sub_; + while (cur) { + cur->run_defparams(des); + cur = cur->sib_; + } + + map::const_iterator pp; + for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) { + NetExpr*val = (*pp).second; + string path = (*pp).first; + string name = parse_last_name(path); + + NetScope*targ_scope = des->find_scope(path); + if (targ_scope == 0) { + cerr << val->get_line() << ": warning: scope of " << + path << "." << name << " not found." << endl; + continue; + } + + val = targ_scope->set_parameter(name, val); + if (val == 0) { + cerr << val->get_line() << ": warning: parameter " + << name << " not found in " << targ_scope->name() + << "." << endl; + } else { + delete val; + } + } +} + +void Design::evaluate_parameters() +{ + root_scope_->evaluate_parameters(this); +} + +void NetScope::evaluate_parameters(Design*des) +{ + NetScope*cur = sub_; + while (cur) { + cur->evaluate_parameters(des); + cur = cur->sib_; + } + + + // Evaluate the parameter values. The parameter expressions + // have already been elaborated and replaced by the scope + // scanning code. Now the parameter expression can be fully + // evaluated, or it cannot be evaluated at all. + + typedef map::iterator mparm_it_t; + + for (mparm_it_t cur = parameters_.begin() + ; cur != parameters_.end() ; cur ++) { + + // Get the NetExpr for the parameter. + NetExpr*expr = (*cur).second; + assert(expr); + + // If it's already a NetEConst, then this parameter is done. + if (dynamic_cast(expr)) + continue; + + // Try to evaluate the expression. + NetExpr*nexpr = expr->eval_tree(); + if (nexpr == 0) { + cerr << (*cur).second->get_line() << ": internal error: " + "unable to evaluate parm expression: " << + *expr << endl; + des->errors += 1; + continue; + } + + // The evaluate worked, replace the old expression with + // this constant value. + assert(nexpr); + delete expr; + (*cur).second = nexpr; + } + +} + +string Design::get_flag(const string&key) const +{ + map::const_iterator tmp = flags_.find(key); + if (tmp == flags_.end()) + return ""; + else + return (*tmp).second; +} + +void Design::add_signal(NetNet*net) +{ + assert(net->design_ == 0); + if (signals_ == 0) { + net->sig_next_ = net; + net->sig_prev_ = net; + } else { + net->sig_next_ = signals_->sig_next_; + net->sig_prev_ = signals_; + net->sig_next_->sig_prev_ = net; + net->sig_prev_->sig_next_ = net; + } + signals_ = net; + net->design_ = this; +} + +void Design::del_signal(NetNet*net) +{ + assert(net->design_ == this); + if (signals_ == net) + signals_ = net->sig_prev_; + + if (signals_ == net) { + signals_ = 0; + } else { + net->sig_prev_->sig_next_ = net->sig_next_; + net->sig_next_->sig_prev_ = net->sig_prev_; + } + net->design_ = 0; +} + +/* + * This method looks for a string given a current context as a + * starting point. + */ +NetNet* Design::find_signal(const string&path, const string&name) +{ + if (signals_ == 0) + return 0; + + const NetScope*scope = find_scope(path); + if (scope == 0) { + cerr << "internal error: invalid scope: " << path << endl; + return 0; + } + assert(scope); + + for (;;) { + string fulname = scope? (scope->name() + "." + name) : name; + + NetNet*cur = signals_; + do { + if (cur->name() == fulname) + return cur; + + cur = cur->sig_prev_; + } while (cur != signals_); + + if (scope == 0) + return 0; + + scope = scope->parent(); + } +} + +void Design::add_memory(NetMemory*mem) +{ + memories_[mem->name()] = mem; +} + +NetMemory* Design::find_memory(const string&path, const string&name) +{ + string root = path; + + for (;;) { + string fulname = root + "." + name; + map::const_iterator cur + = memories_.find(fulname); + + if (cur != memories_.end()) + return (*cur).second; + + unsigned pos = root.rfind('.'); + if (pos > root.length()) + break; + + root = root.substr(0, pos); + } + + return 0; +} + +void Design::add_function(const string&key, NetFuncDef*def) +{ + funcs_[key] = def; +} + +NetFuncDef* Design::find_function(const string&path, const string&name) +{ + string root = path; + for (;;) { + string key = root + "." + name; + map::const_iterator cur = funcs_.find(key); + if (cur != funcs_.end()) + return (*cur).second; + + unsigned pos = root.rfind('.'); + if (pos > root.length()) + break; + + root = root.substr(0, pos); + } + + return 0; +} + +NetFuncDef* Design::find_function(const string&key) +{ + map::const_iterator cur = funcs_.find(key); + if (cur != funcs_.end()) + return (*cur).second; + return 0; +} + +void Design::add_task(const string&key, NetTaskDef*def) +{ + tasks_[key] = def; +} + +NetTaskDef* Design::find_task(const string&path, const string&name) +{ + string root = path; + for (;;) { + string key = root + "." + name; + map::const_iterator cur = tasks_.find(key); + if (cur != tasks_.end()) + return (*cur).second; + + unsigned pos = root.rfind('.'); + if (pos > root.length()) + break; + + root = root.substr(0, pos); + } + + return 0; +} + +NetTaskDef* Design::find_task(const string&key) +{ + map::const_iterator cur = tasks_.find(key); + if (cur == tasks_.end()) + return 0; + + return (*cur).second; +} + +void Design::add_node(NetNode*net) +{ + assert(net->design_ == 0); + if (nodes_ == 0) { + net->node_next_ = net; + net->node_prev_ = net; + } else { + net->node_next_ = nodes_->node_next_; + net->node_prev_ = nodes_; + net->node_next_->node_prev_ = net; + net->node_prev_->node_next_ = net; + } + nodes_ = net; + net->design_ = this; +} + +void Design::del_node(NetNode*net) +{ + assert(net->design_ == this); + if (nodes_ == net) + nodes_ = net->node_prev_; + + if (nodes_ == net) { + nodes_ = 0; + } else { + net->node_next_->node_prev_ = net->node_prev_; + net->node_prev_->node_next_ = net->node_next_; + } + + net->design_ = 0; +} + +void Design::add_process(NetProcTop*pro) +{ + pro->next_ = procs_; + procs_ = pro; +} + +void Design::delete_process(NetProcTop*top) +{ + assert(top); + if (procs_ == top) { + procs_ = top->next_; + + } else { + NetProcTop*cur = procs_; + while (cur->next_ != top) { + assert(cur->next_); + cur = cur->next_; + } + + cur->next_ = top->next_; + } + + if (procs_idx_ == top) + procs_idx_ = top->next_; + + delete top; +} + +void Design::clear_node_marks() +{ + if (nodes_ == 0) + return; + + NetNode*cur = nodes_; + do { + cur->set_mark(false); + cur = cur->node_next_; + } while (cur != nodes_); +} + +void Design::clear_signal_marks() +{ + if (signals_ == 0) + return; + + NetNet*cur = signals_; + do { + cur->set_mark(false); + cur = cur->sig_next_; + } while (cur != signals_); +} + +NetNode* Design::find_node(bool (*func)(const NetNode*)) +{ + if (nodes_ == 0) + return 0; + + NetNode*cur = nodes_->node_next_; + do { + if ((cur->test_mark() == false) && func(cur)) + return cur; + + cur = cur->node_next_; + } while (cur != nodes_->node_next_); + + return 0; +} + +NetNet* Design::find_signal(bool (*func)(const NetNet*)) +{ + if (signals_ == 0) + return 0; + + NetNet*cur = signals_->sig_next_; + do { + if ((cur->test_mark() == false) && func(cur)) + return cur; + + cur = cur->sig_next_; + } while (cur != signals_->sig_next_); + + return 0; +} + +/* + * $Log: net_design.cc,v $ + * Revision 1.1 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * + */ + diff --git a/netlist.cc b/netlist.cc index 10851c332..98617f94f 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.cc,v 1.105 2000/02/23 02:56:54 steve Exp $" +#ident "$Id: netlist.cc,v 1.106 2000/03/08 04:36:53 steve Exp $" #endif # include @@ -1639,8 +1639,8 @@ verinum::V NetConst::value(unsigned idx) const return value_[idx]; } -NetFuncDef::NetFuncDef(const string&n, const svector&po) -: name_(n), statement_(0), ports_(po) +NetFuncDef::NetFuncDef(NetScope*s, const svector&po) +: scope_(s), statement_(0), ports_(po) { } @@ -1648,9 +1648,9 @@ NetFuncDef::~NetFuncDef() { } -const string& NetFuncDef::name() const +const string NetFuncDef::name() const { - return name_; + return scope_->name(); } void NetFuncDef::set_proc(NetProc*st) @@ -1665,6 +1665,11 @@ const NetProc* NetFuncDef::proc() const return statement_; } +NetScope*NetFuncDef::scope() +{ + return scope_; +} + unsigned NetFuncDef::port_count() const { return ports_.count(); @@ -1747,7 +1752,7 @@ NetEUFunc::~NetEUFunc() delete parms_[idx]; } -const string& NetEUFunc::name() const +const string NetEUFunc::name() const { return func_->name(); } @@ -2054,8 +2059,8 @@ NetEParam::NetEParam() { } -NetEParam::NetEParam(Design*d, const string&p, const string&n) -: des_(d), path_(p), name_(n) +NetEParam::NetEParam(Design*d, NetScope*s, const string&n) +: des_(d), scope_(s), name_(n) { } @@ -2237,18 +2242,47 @@ const NetExpr* NetRepeat::expr() const return expr_; } +/* + * The NetScope class keeps a scope tree organized. Each node of the + * scope tree points to its parent, its right sibling and its leftmost + * child. The root node has no parent or siblings. The node stores the + * name of the scope. The complete hierarchical name of the scope is + * formed by appending the path of scopes from the root to the scope + * in question. + */ NetScope::NetScope(const string&n) -: type_(NetScope::MODULE), name_(n), up_(0) +: type_(NetScope::MODULE), name_(n), up_(0), sib_(0), sub_(0) { } NetScope::NetScope(NetScope*up, const string&n, NetScope::TYPE t) -: type_(t), name_(n), up_(up) +: type_(t), name_(n), up_(up), sib_(0), sub_(0) { + sib_ = up_->sub_; + up_->sub_ = this; } NetScope::~NetScope() { + assert(sib_ == 0); + assert(sub_ == 0); +} + +NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr) +{ + NetExpr*&ref = parameters_[key]; + NetExpr* res = ref; + ref = expr; + return res; +} + +const NetExpr* NetScope::get_parameter(const string&key) const +{ + map::const_iterator idx = parameters_.find(key); + if (idx == parameters_.end()) + return 0; + else + return (*idx).second; } NetScope::TYPE NetScope::type() const @@ -2264,6 +2298,36 @@ string NetScope::name() const return name_; } +/* + * This method locates a child scope by name. The name is the simple + * name of the child, no heirarchy is searched. + */ +NetScope* NetScope::child(const string&name) +{ + if (sub_ == 0) return 0; + + NetScope*cur = sub_; + while (cur->name_ != name) { + if (cur->sib_ == 0) return 0; + cur = cur->sib_; + } + + return cur; +} + +const NetScope* NetScope::child(const string&name) const +{ + if (sub_ == 0) return 0; + + NetScope*cur = sub_; + while (cur->name_ != name) { + if (cur->sib_ == 0) return 0; + cur = cur->sib_; + } + + return cur; +} + const NetScope* NetScope::parent() const { return up_; @@ -2561,357 +2625,15 @@ void NetUDP::set_initial(char val) init_ = val; } -Design:: Design() -: errors(0), signals_(0), nodes_(0), procs_(0), lcounter_(0) -{ -} - -Design::~Design() -{ -} - -NetScope* Design::make_root_scope(const string&root) -{ - NetScope*scope = new NetScope(root); - scopes_[root] = scope; - return scope; -} - -NetScope* Design::make_scope(const string&path, - NetScope::TYPE t, - const string&name) -{ - NetScope*up = find_scope(path); - assert(up); - - NetScope*scope = new NetScope(up, name, t); - scopes_[scope->name()] = scope; - - return scope; -} - -NetScope* Design::find_scope(const string&key) -{ - map::const_iterator tmp = scopes_.find(key); - if (tmp == scopes_.end()) - return 0; - else - return (*tmp).second; -} - -void Design::set_parameter(const string&key, NetExpr*expr) -{ - parameters_[key] = expr; -} - -/* - * Find a parameter from within a specified context. If the name is - * not here, keep looking up until I run out of up to look at. - */ -const NetExpr* Design::find_parameter(const string&path, - const string&name) const -{ - string root = path; - - for (;;) { - string fulname = root + "." + name; - map::const_iterator cur - = parameters_.find(fulname); - - if (cur != parameters_.end()) - return (*cur).second; - - unsigned pos = root.rfind('.'); - if (pos > root.length()) - break; - - root = root.substr(0, pos); - } - - return 0; -} - -string Design::get_flag(const string&key) const -{ - map::const_iterator tmp = flags_.find(key); - if (tmp == flags_.end()) - return ""; - else - return (*tmp).second; -} - -void Design::add_signal(NetNet*net) -{ - assert(net->design_ == 0); - if (signals_ == 0) { - net->sig_next_ = net; - net->sig_prev_ = net; - } else { - net->sig_next_ = signals_->sig_next_; - net->sig_prev_ = signals_; - net->sig_next_->sig_prev_ = net; - net->sig_prev_->sig_next_ = net; - } - signals_ = net; - net->design_ = this; -} - -void Design::del_signal(NetNet*net) -{ - assert(net->design_ == this); - if (signals_ == net) - signals_ = net->sig_prev_; - - if (signals_ == net) { - signals_ = 0; - } else { - net->sig_prev_->sig_next_ = net->sig_next_; - net->sig_next_->sig_prev_ = net->sig_prev_; - } - net->design_ = 0; -} - -/* - * This method looks for a string given a current context as a - * starting point. - */ -NetNet* Design::find_signal(const string&path, const string&name) -{ - if (signals_ == 0) - return 0; - - string root = path; - for (;;) { - - string fulname = root + "." + name; - NetNet*cur = signals_; - do { - if (cur->name() == fulname) - return cur; - - cur = cur->sig_prev_; - } while (cur != signals_); - - unsigned pos = root.rfind('.'); - if (pos > root.length()) - break; - - root = root.substr(0, pos); - } - - return 0; -} - -void Design::add_memory(NetMemory*mem) -{ - memories_[mem->name()] = mem; -} - -NetMemory* Design::find_memory(const string&path, const string&name) -{ - string root = path; - - for (;;) { - string fulname = root + "." + name; - map::const_iterator cur - = memories_.find(fulname); - - if (cur != memories_.end()) - return (*cur).second; - - unsigned pos = root.rfind('.'); - if (pos > root.length()) - break; - - root = root.substr(0, pos); - } - - return 0; -} - -void Design::add_function(const string&key, NetFuncDef*def) -{ - funcs_[key] = def; -} - -NetFuncDef* Design::find_function(const string&path, const string&name) -{ - string root = path; - for (;;) { - string key = root + "." + name; - map::const_iterator cur = funcs_.find(key); - if (cur != funcs_.end()) - return (*cur).second; - - unsigned pos = root.rfind('.'); - if (pos > root.length()) - break; - - root = root.substr(0, pos); - } - - return 0; -} - -NetFuncDef* Design::find_function(const string&key) -{ - map::const_iterator cur = funcs_.find(key); - if (cur != funcs_.end()) - return (*cur).second; - return 0; -} - -void Design::add_task(const string&key, NetTaskDef*def) -{ - tasks_[key] = def; -} - -NetTaskDef* Design::find_task(const string&path, const string&name) -{ - string root = path; - for (;;) { - string key = root + "." + name; - map::const_iterator cur = tasks_.find(key); - if (cur != tasks_.end()) - return (*cur).second; - - unsigned pos = root.rfind('.'); - if (pos > root.length()) - break; - - root = root.substr(0, pos); - } - - return 0; -} - -NetTaskDef* Design::find_task(const string&key) -{ - map::const_iterator cur = tasks_.find(key); - if (cur == tasks_.end()) - return 0; - - return (*cur).second; -} - -void Design::add_node(NetNode*net) -{ - assert(net->design_ == 0); - if (nodes_ == 0) { - net->node_next_ = net; - net->node_prev_ = net; - } else { - net->node_next_ = nodes_->node_next_; - net->node_prev_ = nodes_; - net->node_next_->node_prev_ = net; - net->node_prev_->node_next_ = net; - } - nodes_ = net; - net->design_ = this; -} - -void Design::del_node(NetNode*net) -{ - assert(net->design_ == this); - if (nodes_ == net) - nodes_ = net->node_prev_; - - if (nodes_ == net) { - nodes_ = 0; - } else { - net->node_next_->node_prev_ = net->node_prev_; - net->node_prev_->node_next_ = net->node_next_; - } - - net->design_ = 0; -} - -void Design::add_process(NetProcTop*pro) -{ - pro->next_ = procs_; - procs_ = pro; -} - -void Design::delete_process(NetProcTop*top) -{ - assert(top); - if (procs_ == top) { - procs_ = top->next_; - - } else { - NetProcTop*cur = procs_; - while (cur->next_ != top) { - assert(cur->next_); - cur = cur->next_; - } - - cur->next_ = top->next_; - } - - if (procs_idx_ == top) - procs_idx_ = top->next_; - - delete top; -} - -void Design::clear_node_marks() -{ - if (nodes_ == 0) - return; - - NetNode*cur = nodes_; - do { - cur->set_mark(false); - cur = cur->node_next_; - } while (cur != nodes_); -} - -void Design::clear_signal_marks() -{ - if (signals_ == 0) - return; - - NetNet*cur = signals_; - do { - cur->set_mark(false); - cur = cur->sig_next_; - } while (cur != signals_); -} - -NetNode* Design::find_node(bool (*func)(const NetNode*)) -{ - if (nodes_ == 0) - return 0; - - NetNode*cur = nodes_->node_next_; - do { - if ((cur->test_mark() == false) && func(cur)) - return cur; - - cur = cur->node_next_; - } while (cur != nodes_->node_next_); - - return 0; -} - -NetNet* Design::find_signal(bool (*func)(const NetNet*)) -{ - if (signals_ == 0) - return 0; - - NetNet*cur = signals_->sig_next_; - do { - if ((cur->test_mark() == false) && func(cur)) - return cur; - - cur = cur->sig_next_; - } while (cur != signals_->sig_next_); - - return 0; -} - /* * $Log: netlist.cc,v $ + * Revision 1.106 2000/03/08 04:36:53 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.105 2000/02/23 02:56:54 steve * Macintosh compilers do not support ident. * @@ -2951,295 +2673,5 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) * * Revision 1.93 1999/11/24 04:01:59 steve * Detect and list scope names. - * - * Revision 1.92 1999/11/21 18:03:35 steve - * Fix expression width of memory references. - * - * Revision 1.91 1999/11/21 17:35:37 steve - * Memory name lookup handles scopes. - * - * Revision 1.90 1999/11/21 00:13:08 steve - * Support memories in continuous assignments. - * - * Revision 1.89 1999/11/19 05:02:37 steve - * handle duplicate connect to a nexus. - * - * Revision 1.88 1999/11/19 03:02:25 steve - * Detect flip-flops connected to opads and turn - * them into OUTFF devices. Inprove support for - * the XNF-LCA attribute in the process. - * - * Revision 1.87 1999/11/18 03:52:19 steve - * Turn NetTmp objects into normal local NetNet objects, - * and add the nodangle functor to clean up the local - * symbols generated by elaboration and other steps. - * - * Revision 1.86 1999/11/14 23:43:45 steve - * Support combinatorial comparators. - * - * Revision 1.85 1999/11/14 20:24:28 steve - * Add support for the LPM_CLSHIFT device. - * - * Revision 1.84 1999/11/13 03:46:52 steve - * Support the LPM_MUX in vvm. - * - * Revision 1.83 1999/11/05 04:40:40 steve - * Patch to synthesize LPM_ADD_SUB from expressions, - * Thanks to Larry Doolittle. Also handle constants - * in expressions. - * - * Synthesize adders in XNF, based on a patch from - * Larry. Accept synthesis of constants from Larry - * as is. - * - * Revision 1.82 1999/11/04 03:53:26 steve - * Patch to synthesize unary ~ and the ternary operator. - * Thanks to Larry Doolittle . - * - * Add the LPM_MUX device, and integrate it with the - * ternary synthesis from Larry. Replace the lpm_mux - * generator in t-xnf.cc to use XNF EQU devices to - * put muxs into function units. - * - * Rewrite elaborate_net for the PETernary class to - * also use the LPM_MUX device. - * - * Revision 1.81 1999/11/04 01:12:42 steve - * Elaborate combinational UDP devices. - * - * Revision 1.80 1999/11/02 04:55:34 steve - * Add the synthesize method to NetExpr to handle - * synthesis of expressions, and use that method - * to improve r-value handling of LPM_FF synthesis. - * - * Modify the XNF target to handle LPM_FF objects. - * - * Revision 1.79 1999/11/01 02:07:40 steve - * Add the synth functor to do generic synthesis - * and add the LPM_FF device to handle rows of - * flip-flops. - * - * Revision 1.78 1999/10/31 04:11:27 steve - * Add to netlist links pin name and instance number, - * and arrange in vvm for pin connections by name - * and instance number. - * - * Revision 1.77 1999/10/10 23:29:37 steve - * Support evaluating + operator at compile time. - * - * Revision 1.76 1999/10/10 01:59:55 steve - * Structural case equals device. - * - * Revision 1.75 1999/10/07 05:25:34 steve - * Add non-const bit select in l-value of assignment. - * - * Revision 1.74 1999/10/06 05:06:16 steve - * Move the rvalue into NetAssign_ common code. - * - * Revision 1.73 1999/10/05 04:02:10 steve - * Relaxed width handling for <= assignment. - * - * Revision 1.72 1999/09/30 21:28:34 steve - * Handle mutual reference of tasks by elaborating - * task definitions in two passes, like functions. - * - * Revision 1.71 1999/09/29 18:36:03 steve - * Full case support - * - * Revision 1.70 1999/09/28 03:11:29 steve - * Get the bit widths of unary operators that return one bit. - * - * Revision 1.69 1999/09/23 03:56:57 steve - * Support shift operators. - * - * Revision 1.68 1999/09/23 00:21:54 steve - * Move set_width methods into a single file, - * Add the NetEBLogic class for logic expressions, - * Fix error setting with of && in if statements. - * - * Revision 1.67 1999/09/21 00:13:40 steve - * Support parameters that reference other paramters. - * - * Revision 1.66 1999/09/20 02:21:10 steve - * Elaborate parameters in phases. - * - * Revision 1.65 1999/09/18 01:53:08 steve - * Detect constant lessthen-equal expressions. - * - * Revision 1.64 1999/09/16 04:18:15 steve - * elaborate concatenation repeats. - * - * Revision 1.63 1999/09/16 00:33:45 steve - * Handle implicit !=0 in if statements. - * - * Revision 1.62 1999/09/15 01:55:06 steve - * Elaborate non-blocking assignment to memories. - * - * Revision 1.61 1999/09/13 03:10:59 steve - * Clarify msb/lsb in context of netlist. Properly - * handle part selects in lval and rval of expressions, - * and document where the least significant bit goes - * in NetNet objects. - * - * Revision 1.60 1999/09/12 01:16:51 steve - * Pad r-values in certain assignments. - * - * Revision 1.59 1999/09/11 04:43:17 steve - * Support ternary and <= operators in vvm. - * - * Revision 1.58 1999/09/08 04:05:30 steve - * Allow assign to not match rvalue width. - * - * Revision 1.57 1999/09/04 01:57:15 steve - * Generate fake adder code in vvm. - * - * Revision 1.56 1999/09/03 04:28:38 steve - * elaborate the binary plus operator. - * - * Revision 1.55 1999/09/01 20:46:19 steve - * Handle recursive functions and arbitrary function - * references to other functions, properly pass - * function parameters and save function results. - * - * Revision 1.54 1999/08/31 22:38:29 steve - * Elaborate and emit to vvm procedural functions. - * - * Revision 1.53 1999/08/25 22:22:41 steve - * elaborate some aspects of functions. - * - * Revision 1.52 1999/08/06 04:05:28 steve - * Handle scope of parameters. - * - * Revision 1.51 1999/08/01 21:48:11 steve - * set width of procedural r-values when then - * l-value is a memory word. - * - * Revision 1.50 1999/07/31 19:14:47 steve - * Add functions up to elaboration (Ed Carter) - * - * Revision 1.49 1999/07/31 03:16:54 steve - * move binary operators to derived classes. - * - * Revision 1.48 1999/07/24 02:11:20 steve - * Elaborate task input ports. - * - * Revision 1.47 1999/07/18 21:17:50 steve - * Add support for CE input to XNF DFF, and do - * complete cleanup of replaced design nodes. - * - * Revision 1.46 1999/07/18 05:52:46 steve - * xnfsyn generates DFF objects for XNF output, and - * properly rewrites the Design netlist in the process. - * - * Revision 1.45 1999/07/17 19:51:00 steve - * netlist support for ternary operator. - * - * Revision 1.44 1999/07/17 18:06:02 steve - * Better handling of bit width of + operators. - * - * Revision 1.43 1999/07/17 03:08:31 steve - * part select in expressions. - * - * Revision 1.42 1999/07/16 04:33:41 steve - * set_width for NetESubSignal. - * - * Revision 1.41 1999/07/03 02:12:51 steve - * Elaborate user defined tasks. - * - * Revision 1.40 1999/06/24 05:02:36 steve - * Properly terminate signal matching scan. - * - * Revision 1.39 1999/06/24 04:24:18 steve - * Handle expression widths for EEE and NEE operators, - * add named blocks and scope handling, - * add registers declared in named blocks. - * - * Revision 1.38 1999/06/19 21:06:16 steve - * Elaborate and supprort to vvm the forever - * and repeat statements. - * - * Revision 1.37 1999/06/13 23:51:16 steve - * l-value part select for procedural assignments. - * - * Revision 1.36 1999/06/13 16:30:06 steve - * Unify the NetAssign constructors a bit. - * - * Revision 1.35 1999/06/10 05:33:28 steve - * Handle a few more operator bit widths. - * - * Revision 1.34 1999/06/09 03:00:06 steve - * Add support for procedural concatenation expression. - * - * Revision 1.33 1999/06/07 02:23:31 steve - * Support non-blocking assignment down to vvm. - * - * Revision 1.32 1999/06/06 20:45:38 steve - * Add parse and elaboration of non-blocking assignments, - * Replace list with an svector version, - * Add integer support. - * - * Revision 1.31 1999/06/03 05:16:25 steve - * Compile time evalutation of constant expressions. - * - * Revision 1.30 1999/06/02 15:38:46 steve - * Line information with nets. - * - * Revision 1.29 1999/05/30 01:11:46 steve - * Exressions are trees that can duplicate, and not DAGS. - * - * Revision 1.28 1999/05/27 04:13:08 steve - * Handle expression bit widths with non-fatal errors. - * - * Revision 1.27 1999/05/20 05:07:37 steve - * Line number info with match error message. - * - * Revision 1.26 1999/05/16 05:08:42 steve - * Redo constant expression detection to happen - * after parsing. - * - * Parse more operators and expressions. - * - * Revision 1.25 1999/05/13 04:02:09 steve - * More precise handling of verinum bit lengths. - * - * Revision 1.24 1999/05/12 04:03:19 steve - * emit NetAssignMem objects in vvm target. - * - * Revision 1.23 1999/05/10 00:16:58 steve - * Parse and elaborate the concatenate operator - * in structural contexts, Replace vector - * and list with svector, evaluate - * constant expressions with parameters, handle - * memories as lvalues. - * - * Parse task declarations, integer types. - * - * Revision 1.22 1999/05/01 02:57:53 steve - * Handle much more complex event expressions. - * - * Revision 1.21 1999/04/25 00:44:10 steve - * Core handles subsignal expressions. - * - * Revision 1.20 1999/04/19 01:59:36 steve - * Add memories to the parse and elaboration phases. - * - * Revision 1.19 1999/03/15 02:43:32 steve - * Support more operators, especially logical. - * - * Revision 1.18 1999/03/01 03:27:53 steve - * Prevent the duplicate allocation of ESignal objects. - * - * Revision 1.17 1999/02/21 17:01:57 steve - * Add support for module parameters. - * - * Revision 1.16 1999/02/08 02:49:56 steve - * Turn the NetESignal into a NetNode so - * that it can connect to the netlist. - * Implement the case statement. - * Convince t-vvm to output code for - * the case statement. - * - * Revision 1.15 1999/02/03 04:20:11 steve - * Parse and elaborate the Verilog CASE statement. */ diff --git a/netlist.h b/netlist.h index 28c454b0c..475c48285 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.110 2000/02/23 02:56:55 steve Exp $" +#ident "$Id: netlist.h,v 1.111 2000/03/08 04:36:54 steve Exp $" #endif /* @@ -1201,13 +1201,14 @@ class NetForever : public NetProc { class NetFuncDef { public: - NetFuncDef(const string&, const svector&po); + NetFuncDef(NetScope*, const svector&po); ~NetFuncDef(); void set_proc(NetProc*st); - const string& name() const; + const string name() const; const NetProc*proc() const; + NetScope*scope(); unsigned port_count() const; const NetNet*port(unsigned idx) const; @@ -1215,7 +1216,7 @@ class NetFuncDef { virtual void dump(ostream&, unsigned ind) const; private: - string name_; + NetScope*scope_; NetProc*statement_; svectorports_; }; @@ -1389,7 +1390,7 @@ class NetEUFunc : public NetExpr { NetEUFunc(NetFuncDef*, NetESignal*, svector&); ~NetEUFunc(); - const string& name() const; + const string name() const; const NetESignal*result() const; unsigned parm_count() const; @@ -1718,7 +1719,7 @@ class NetEConcat : public NetExpr { class NetEParam : public NetExpr { public: NetEParam(); - NetEParam(class Design*des, const string&path, const string&name); + NetEParam(class Design*des, NetScope*scope, const string&name); ~NetEParam(); virtual bool set_width(unsigned w); @@ -1730,7 +1731,7 @@ class NetEParam : public NetExpr { private: Design*des_; - string path_; + NetScope*scope_; string name_; }; @@ -1980,21 +1981,52 @@ class NetESubSignal : public NetExpr { class NetScope { public: - enum TYPE { MODULE, BEGIN_END, FORK_JOIN }; + enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN }; NetScope(const string&root); NetScope(NetScope*up, const string&name, TYPE t); ~NetScope(); + /* Parameters exist within a scope, and these methods allow + one to manipulate the set. In these cases, the name is the + *simple* name of the paramter, the heirarchy is implicit in + the scope. The return value from set_parameter is the + previous expression, if there was one. */ + + NetExpr* set_parameter(const string&name, NetExpr*val); + const NetExpr*get_parameter(const string&name) const; + + + /* The parent and child() methods allow users of NetScope + objects to locate nearby scopes. */ + NetScope* child(const string&name); + const NetScope* parent() const; + const NetScope* child(const string&name) const; + TYPE type() const; string name() const; - const NetScope* parent() const; + + void run_defparams(class Design*); + void evaluate_parameters(class Design*); void dump(ostream&) const; + void emit_scope(ostream&o, struct target_t*tgt) const; + + + /* This member is used during elaboration to pass defparam + assignments from the scope pass to the parameter evaluation + step. After that, it is not used. */ + + mapdefparams; private: TYPE type_; string name_; + + mapparameters_; + NetScope*up_; + NetScope*sib_; + NetScope*sub_; }; /* @@ -2025,8 +2057,14 @@ class Design { NetScope* find_scope(const string&path); // PARAMETERS - void set_parameter(const string&, NetExpr*); - const NetExpr*find_parameter(const string&path, const string&name) const; + + /* This method searches for a parameter, starting in the given + scope. This method handles the upward searches that the + NetScope class itself does not support. */ + const NetExpr*find_parameter(const NetScope*, const string&name) const; + + void run_defparams(); + void evaluate_parameters(); // SIGNALS void add_signal(NetNet*); @@ -2074,11 +2112,9 @@ class Design { string local_symbol(const string&path); private: - map scopes_; - - // List all the parameters in the design. This table includes - // the parameters of instantiated modules in canonical names. - map parameters_; + // Keep a tree of scopes. The NetScope class handles the wide + // tree and per-hop searches for me. + NetScope*root_scope_; // List all the signals in the design. NetNet*signals_; @@ -2152,6 +2188,13 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.111 2000/03/08 04:36:54 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.110 2000/02/23 02:56:55 steve * Macintosh compilers do not support ident. * @@ -2175,282 +2218,5 @@ extern ostream& operator << (ostream&, NetNet::Type); * * Revision 1.103 1999/12/17 03:38:46 steve * NetConst can now hold wide constants. - * - * Revision 1.102 1999/12/16 02:42:15 steve - * Simulate carry output on adders. - * - * Revision 1.101 1999/12/12 06:03:14 steve - * Allow memories without indices in expressions. - * - * Revision 1.100 1999/12/09 06:00:00 steve - * Fix const/non-const errors. - * - * Revision 1.99 1999/12/05 19:30:43 steve - * Generate XNF RAMS from synthesized memories. - * - * Revision 1.98 1999/12/05 02:24:09 steve - * Synthesize LPM_RAM_DQ for writes into memories. - * - * Revision 1.97 1999/12/01 06:06:16 steve - * Redo synth to use match_proc_t scanner. - * - * Revision 1.96 1999/11/28 23:42:02 steve - * NetESignal object no longer need to be NetNode - * objects. Let them keep a pointer to NetNet objects. - * - * Revision 1.95 1999/11/27 19:07:58 steve - * Support the creation of scopes. - * - * Revision 1.94 1999/11/24 04:01:59 steve - * Detect and list scope names. - * - * Revision 1.93 1999/11/21 17:35:37 steve - * Memory name lookup handles scopes. - * - * Revision 1.92 1999/11/21 00:13:09 steve - * Support memories in continuous assignments. - * - * Revision 1.91 1999/11/19 05:02:37 steve - * handle duplicate connect to a nexus. - * - * Revision 1.90 1999/11/19 03:02:25 steve - * Detect flip-flops connected to opads and turn - * them into OUTFF devices. Inprove support for - * the XNF-LCA attribute in the process. - * - * Revision 1.89 1999/11/18 03:52:19 steve - * Turn NetTmp objects into normal local NetNet objects, - * and add the nodangle functor to clean up the local - * symbols generated by elaboration and other steps. - * - * Revision 1.88 1999/11/14 23:43:45 steve - * Support combinatorial comparators. - * - * Revision 1.87 1999/11/14 20:24:28 steve - * Add support for the LPM_CLSHIFT device. - * - * Revision 1.86 1999/11/05 04:40:40 steve - * Patch to synthesize LPM_ADD_SUB from expressions, - * Thanks to Larry Doolittle. Also handle constants - * in expressions. - * - * Synthesize adders in XNF, based on a patch from - * Larry. Accept synthesis of constants from Larry - * as is. - * - * Revision 1.85 1999/11/04 03:53:26 steve - * Patch to synthesize unary ~ and the ternary operator. - * Thanks to Larry Doolittle . - * - * Add the LPM_MUX device, and integrate it with the - * ternary synthesis from Larry. Replace the lpm_mux - * generator in t-xnf.cc to use XNF EQU devices to - * put muxs into function units. - * - * Rewrite elaborate_net for the PETernary class to - * also use the LPM_MUX device. - * - * Revision 1.84 1999/11/04 01:12:42 steve - * Elaborate combinational UDP devices. - * - * Revision 1.83 1999/11/02 04:55:34 steve - * Add the synthesize method to NetExpr to handle - * synthesis of expressions, and use that method - * to improve r-value handling of LPM_FF synthesis. - * - * Modify the XNF target to handle LPM_FF objects. - * - * Revision 1.82 1999/11/01 02:07:40 steve - * Add the synth functor to do generic synthesis - * and add the LPM_FF device to handle rows of - * flip-flops. - * - * Revision 1.81 1999/10/31 04:11:27 steve - * Add to netlist links pin name and instance number, - * and arrange in vvm for pin connections by name - * and instance number. - * - * Revision 1.80 1999/10/10 23:29:37 steve - * Support evaluating + operator at compile time. - * - * Revision 1.79 1999/10/10 01:59:55 steve - * Structural case equals device. - * - * Revision 1.78 1999/10/07 05:25:34 steve - * Add non-const bit select in l-value of assignment. - * - * Revision 1.77 1999/10/06 05:06:16 steve - * Move the rvalue into NetAssign_ common code. - * - * Revision 1.76 1999/09/30 21:28:34 steve - * Handle mutual reference of tasks by elaborating - * task definitions in two passes, like functions. - * - * Revision 1.75 1999/09/30 02:43:02 steve - * Elaborate ~^ and ~| operators. - * - * Revision 1.74 1999/09/29 18:36:03 steve - * Full case support - * - * Revision 1.73 1999/09/28 03:11:30 steve - * Get the bit widths of unary operators that return one bit. - * - * Revision 1.72 1999/09/25 02:57:30 steve - * Parse system function calls. - * - * Revision 1.71 1999/09/23 03:56:57 steve - * Support shift operators. - * - * Revision 1.70 1999/09/23 00:21:55 steve - * Move set_width methods into a single file, - * Add the NetEBLogic class for logic expressions, - * Fix error setting with of && in if statements. - * - * Revision 1.69 1999/09/22 16:57:23 steve - * Catch parallel blocks in vvm emit. - * - * Revision 1.68 1999/09/21 00:13:40 steve - * Support parameters that reference other paramters. - * - * Revision 1.67 1999/09/20 02:21:10 steve - * Elaborate parameters in phases. - * - * Revision 1.66 1999/09/18 01:53:08 steve - * Detect constant lessthen-equal expressions. - * - * Revision 1.65 1999/09/16 04:18:15 steve - * elaborate concatenation repeats. - * - * Revision 1.64 1999/09/15 01:55:06 steve - * Elaborate non-blocking assignment to memories. - * - * Revision 1.63 1999/09/13 03:10:59 steve - * Clarify msb/lsb in context of netlist. Properly - * handle part selects in lval and rval of expressions, - * and document where the least significant bit goes - * in NetNet objects. - * - * Revision 1.62 1999/09/11 04:43:17 steve - * Support ternary and <= operators in vvm. - * - * Revision 1.61 1999/09/08 04:05:30 steve - * Allow assign to not match rvalue width. - * - * Revision 1.60 1999/09/03 04:28:38 steve - * elaborate the binary plus operator. - * - * Revision 1.59 1999/09/01 20:46:19 steve - * Handle recursive functions and arbitrary function - * references to other functions, properly pass - * function parameters and save function results. - * - * Revision 1.58 1999/08/31 22:38:29 steve - * Elaborate and emit to vvm procedural functions. - * - * Revision 1.57 1999/08/25 22:22:41 steve - * elaborate some aspects of functions. - * - * Revision 1.56 1999/08/18 04:00:02 steve - * Fixup spelling and some error messages. - * - * Revision 1.55 1999/08/06 04:05:28 steve - * Handle scope of parameters. - * - * Revision 1.54 1999/08/01 21:48:11 steve - * set width of procedural r-values when then - * l-value is a memory word. - * - * Revision 1.53 1999/08/01 16:34:50 steve - * Parse and elaborate rise/fall/decay times - * for gates, and handle the rules for partial - * lists of times. - * - * Revision 1.52 1999/07/31 03:16:54 steve - * move binary operators to derived classes. - * - * Revision 1.51 1999/07/24 02:11:20 steve - * Elaborate task input ports. - * - * Revision 1.50 1999/07/18 21:17:50 steve - * Add support for CE input to XNF DFF, and do - * complete cleanup of replaced design nodes. - * - * Revision 1.49 1999/07/18 05:52:47 steve - * xnfsyn generates DFF objects for XNF output, and - * properly rewrites the Design netlist in the process. - * - * Revision 1.48 1999/07/17 22:01:13 steve - * Add the functor interface for functor transforms. - * - * Revision 1.47 1999/07/17 19:51:00 steve - * netlist support for ternary operator. - * - * Revision 1.46 1999/07/17 03:08:32 steve - * part select in expressions. - * - * Revision 1.45 1999/07/16 04:33:41 steve - * set_width for NetESubSignal. - * - * Revision 1.44 1999/07/07 04:20:57 steve - * Emit vvm for user defined tasks. - * - * Revision 1.43 1999/07/03 02:12:51 steve - * Elaborate user defined tasks. - * - * Revision 1.42 1999/06/24 04:24:18 steve - * Handle expression widths for EEE and NEE operators, - * add named blocks and scope handling, - * add registers declared in named blocks. - * - * Revision 1.41 1999/06/19 21:06:16 steve - * Elaborate and supprort to vvm the forever - * and repeat statements. - * - * Revision 1.40 1999/06/13 23:51:16 steve - * l-value part select for procedural assignments. - * - * Revision 1.39 1999/06/13 17:30:23 steve - * More unary operators. - * - * Revision 1.38 1999/06/13 16:30:06 steve - * Unify the NetAssign constructors a bit. - * - * Revision 1.37 1999/06/09 03:00:06 steve - * Add support for procedural concatenation expression. - * - * Revision 1.36 1999/06/06 20:45:38 steve - * Add parse and elaboration of non-blocking assignments, - * Replace list with an svector version, - * Add integer support. - * - * Revision 1.35 1999/06/03 05:16:25 steve - * Compile time evalutation of constant expressions. - * - * Revision 1.34 1999/06/02 15:38:46 steve - * Line information with nets. - * - * Revision 1.33 1999/05/30 01:11:46 steve - * Exressions are trees that can duplicate, and not DAGS. - * - * Revision 1.32 1999/05/27 04:13:08 steve - * Handle expression bit widths with non-fatal errors. - * - * Revision 1.31 1999/05/16 05:08:42 steve - * Redo constant expression detection to happen - * after parsing. - * - * Parse more operators and expressions. - * - * Revision 1.30 1999/05/12 04:03:19 steve - * emit NetAssignMem objects in vvm target. - * - * Revision 1.29 1999/05/10 00:16:58 steve - * Parse and elaborate the concatenate operator - * in structural contexts, Replace vector - * and list with svector, evaluate - * constant expressions with parameters, handle - * memories as lvalues. - * - * Parse task declarations, integer types. */ #endif diff --git a/netlist.txt b/netlist.txt index eb260916b..bc184043c 100644 --- a/netlist.txt +++ b/netlist.txt @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id: netlist.txt,v 1.7 1999/11/28 23:42:02 steve Exp $" +#ident "$Id: netlist.txt,v 1.8 2000/03/08 04:36:54 steve Exp $" Note that the netlist.h header contains detailed descriptions of how @@ -229,6 +229,29 @@ can operate globally, with optimizations freely crossing module boundaries. This makes coding of netlist transform functions such as constant propagation more effective and easier to write. + +SCOPE REPRESENTATION IN NETLISTS + +In spite of the literal flattening of the design, scope information is +preserved in the netlist, with the NetScope class. The Design class +keeps a single pointer to the root scope of the design. This is the +scope of the root module. Scopes that are then created within that +(or any nested) module are placed as children of the root scope, and +those children can have further children, and so on. + +Each scope in the tree carries its own name, and its relationship to +its parent and children. This makes it possible to walk the tree of +scopes. In practice, the walking of the scopes is handled by recursive +methods. + +Each scope also carries the parameters that are applicable to the +scope itself. The parameter expression (possibly evaluated) can be +located by name, given the scope object itself. The scan of the pform +to generate scopes also places the parameters that are declared in the +scope. Overrides are managed during the scan, and once the scan is +complete, defparam overrides are applied. + + TASKS IN NETLISTS The flattening of the design does not include tasks and named @@ -240,6 +263,13 @@ some task calls. C++ programmers recognize this as inlining a task.) $Log: netlist.txt,v $ + Revision 1.8 2000/03/08 04:36:54 steve + Redesign the implementation of scopes and parameters. + I now generate the scopes and notice the parameters + in a separate pass over the pform. Once the scopes + are generated, I can process overrides and evalutate + paremeters before elaboration begins. + Revision 1.7 1999/11/28 23:42:02 steve NetESignal object no longer need to be NetNode objects. Let them keep a pointer to NetNet objects. diff --git a/parse.y b/parse.y index 7a8647a25..f1445f402 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: parse.y,v 1.84 2000/03/05 18:26:51 steve Exp $" +#ident "$Id: parse.y,v 1.85 2000/03/08 04:36:54 steve Exp $" #endif # include "parse_misc.h" @@ -261,9 +261,8 @@ defparam_assign delete tmp; tmp = 0; } - yyerror(@1, "sorry: defparam assignments not supported."); + pform_set_defparam($1, $3); delete $1; - delete $3; } ; diff --git a/pform.cc b/pform.cc index 5e9507b6e..f38abb6b9 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: pform.cc,v 1.54 2000/02/23 02:56:55 steve Exp $" +#ident "$Id: pform.cc,v 1.55 2000/03/08 04:36:54 steve Exp $" #endif # include "compiler.h" @@ -727,10 +727,17 @@ void pform_set_net_range(list*names, const svector*range) void pform_set_parameter(const string&name, PExpr*expr) { + assert(expr); pform_cur_module->parameters[name] = expr; pform_cur_module->param_names.push_back(name); } +void pform_set_defparam(const string&name, PExpr*expr) +{ + assert(expr); + pform_cur_module->defparms[name] = expr; +} + void pform_set_port_type(list*names, NetNet::PortType pt) { for (list::const_iterator cur = names->begin() @@ -820,6 +827,13 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.55 2000/03/08 04:36:54 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.54 2000/02/23 02:56:55 steve * Macintosh compilers do not support ident. * diff --git a/pform.h b/pform.h index b296ea4ab..70ff61a10 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: pform.h,v 1.35 2000/02/23 02:56:55 steve Exp $" +#ident "$Id: pform.h,v 1.36 2000/03/08 04:36:54 steve Exp $" #endif # include "netlist.h" @@ -133,6 +133,7 @@ extern void pform_set_attrib(const string&name, const string&key, extern void pform_set_type_attrib(const string&name, const string&key, const string&value); extern void pform_set_parameter(const string&name, PExpr*expr); +extern void pform_set_defparam(const string&name, PExpr*expr); extern PProcess* pform_make_behavior(PProcess::Type, Statement*); extern svector* pform_make_udp_input_ports(list*); @@ -180,6 +181,13 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.36 2000/03/08 04:36:54 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.35 2000/02/23 02:56:55 steve * Macintosh compilers do not support ident. * diff --git a/pform_dump.cc b/pform_dump.cc index e6705e9e9..c71b76c27 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: pform_dump.cc,v 1.49 2000/02/23 02:56:55 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.50 2000/03/08 04:36:54 steve Exp $" #endif /* @@ -609,6 +609,15 @@ void Module::dump(ostream&out) const out << "/* ERROR */;" << endl; } + for (parm_iter_t cur = defparms.begin() + ; cur != defparms.end() ; cur ++) { + out << " defparam " << (*cur).first << " = "; + if ((*cur).second) + out << *(*cur).second << ";" << endl; + else + out << "/* ERROR */;" << endl; + } + // Iterate through and display all the wires. for (map::const_iterator wire = wires_.begin() ; wire != wires_.end() @@ -702,6 +711,13 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.50 2000/03/08 04:36:54 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.49 2000/02/23 02:56:55 steve * Macintosh compilers do not support ident. * diff --git a/t-vvm.cc b/t-vvm.cc index 5012ea8d2..253af8877 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-vvm.cc,v 1.106 2000/02/29 05:20:21 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.107 2000/03/08 04:36:54 steve Exp $" #endif # include @@ -691,6 +691,12 @@ void target_vvm::scope(ostream&os, const NetScope*scope) case NetScope::MODULE: type_code = "vpiModule"; break; + case NetScope::TASK: + type_code = "vpiTask"; + break; + case NetScope::FUNC: + type_code = "vpiFunction"; + break; case NetScope::BEGIN_END: type_code = "vpiNamedBegin"; break; @@ -2168,6 +2174,13 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.107 2000/03/08 04:36:54 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.106 2000/02/29 05:20:21 steve * Remove excess variable. * diff --git a/vpi/vpi_user.h b/vpi/vpi_user.h index aa417f7c4..3307e216b 100644 --- a/vpi/vpi_user.h +++ b/vpi/vpi_user.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_user.h,v 1.13 2000/02/23 02:56:56 steve Exp $" +#ident "$Id: vpi_user.h,v 1.14 2000/03/08 04:36:54 steve Exp $" #endif #ifdef __cplusplus @@ -99,6 +99,7 @@ typedef struct t_vpi_value { /* OBJECT CODES */ #define vpiConstant 7 +#define vpiFunction 20 #define vpiIterator 27 #define vpiMemory 29 #define vpiMemoryWord 30 @@ -108,6 +109,7 @@ typedef struct t_vpi_value { #define vpiNet 36 #define vpiReg 48 #define vpiSysTaskCall 57 +#define vpiTask 59 #define vpiTimeVar 63 #define vpiSysTfCall 85 #define vpiArgument 89 @@ -228,6 +230,13 @@ extern void (*vlog_startup_routines[])(); /* * $Log: vpi_user.h,v $ + * Revision 1.14 2000/03/08 04:36:54 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.13 2000/02/23 02:56:56 steve * Macintosh compilers do not support ident. * diff --git a/vvm/vpi_scope.c b/vvm/vpi_scope.c index e9bd561f6..c9b8f9b36 100644 --- a/vvm/vpi_scope.c +++ b/vvm/vpi_scope.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_scope.c,v 1.5 2000/02/23 02:56:56 steve Exp $" +#ident "$Id: vpi_scope.c,v 1.6 2000/03/08 04:36:54 steve Exp $" #endif # include "vpi_priv.h" @@ -47,6 +47,26 @@ static const struct __vpirt vpip_module_rt = { module_iter }; +static const struct __vpirt vpip_task_rt = { + vpiTask, + 0, + 0, + 0, + 0, + 0, + 0 +}; + +static const struct __vpirt vpip_function_rt = { + vpiFunction, + 0, + 0, + 0, + 0, + 0, + 0 +}; + static const struct __vpirt vpip_named_begin_rt = { vpiNamedBegin, 0, @@ -69,6 +89,12 @@ vpiHandle vpip_make_scope(struct __vpiScope*ref, int type, const char*name) case vpiNamedBegin: ref->base.vpi_type = &vpip_named_begin_rt; break; + case vpiTask: + ref->base.vpi_type = &vpip_task_rt; + break; + case vpiFunction: + ref->base.vpi_type = &vpip_function_rt; + break; default: assert(0); } @@ -90,6 +116,13 @@ void vpip_attach_to_scope(struct __vpiScope*ref, vpiHandle obj) /* * $Log: vpi_scope.c,v $ + * Revision 1.6 2000/03/08 04:36:54 steve + * Redesign the implementation of scopes and parameters. + * I now generate the scopes and notice the parameters + * in a separate pass over the pform. Once the scopes + * are generated, I can process overrides and evalutate + * paremeters before elaboration begins. + * * Revision 1.5 2000/02/23 02:56:56 steve * Macintosh compilers do not support ident. *