From 3a5e55b2297a50b4d0cd576049f1b7ef1f536c6e Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 20 Sep 1999 02:21:10 +0000 Subject: [PATCH] Elaborate parameters in phases. --- Makefile.in | 5 +- design_dump.cc | 10 ++- elab_expr.cc | 157 +++++++++++++++++++++++++++++++++++++++++++ elaborate.cc | 178 ++++++++++++++++--------------------------------- emit.cc | 11 ++- eval.cc | 11 ++- eval_tree.cc | 153 ++++++++++++++++++++++++++++++++++++++++++ netlist.cc | 131 ++++++++++++------------------------ netlist.h | 37 ++++++++-- 9 files changed, 475 insertions(+), 218 deletions(-) create mode 100644 elab_expr.cc create mode 100644 eval_tree.cc diff --git a/Makefile.in b/Makefile.in index 147e93ff4..cc547489e 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.16 1999/09/04 19:11:45 steve Exp $" +#ident "$Id: Makefile.in,v 1.17 1999/09/20 02:21:10 steve Exp $" # # SHELL = /bin/sh @@ -60,7 +60,8 @@ clean: TT = t-null.o t-verilog.o t-vvm.o t-xnf.o FF = nobufz.o propinit.o sigfold.o xnfio.o xnfsyn.o -O = main.o cprop.o design_dump.o elaborate.o emit.o eval.o functor.o \ +O = main.o cprop.o design_dump.o elaborate.o elab_expr.o emit.o eval.o \ +eval_tree.o functor.o \ lexor.o mangle.o netlist.o parse.o parse_misc.o pform.o pform_dump.o \ verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \ PTask.o PFunction.o PWire.o Statement.o \ diff --git a/design_dump.cc b/design_dump.cc index da332d7c5..85dbaaa6b 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) -#ident "$Id: design_dump.cc,v 1.41 1999/09/19 01:06:36 steve Exp $" +#ident "$Id: design_dump.cc,v 1.42 1999/09/20 02:21:10 steve Exp $" #endif /* @@ -644,6 +644,11 @@ void NetEMemory::dump(ostream&o) const o << "]"; } +void NetEParam::dump(ostream&o) const +{ + o << "<" << path_ << "." << name_ << ">"; +} + void NetESignal::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "Expression Node (NetESignal): " << @@ -748,6 +753,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.42 1999/09/20 02:21:10 steve + * Elaborate parameters in phases. + * * Revision 1.41 1999/09/19 01:06:36 steve * dump the repeat count, if applicable. * diff --git a/elab_expr.cc b/elab_expr.cc new file mode 100644 index 000000000..44f084175 --- /dev/null +++ b/elab_expr.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1999 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) +#ident "$Id: elab_expr.cc,v 1.1 1999/09/20 02:21:10 steve Exp $" +#endif + + +# include "pform.h" +# include "netlist.h" + + +NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const +{ + // System identifiers show up in the netlist as identifiers. + if (text_[0] == '$') + return new NetEIdent(text_, 64); + + string name = path+"."+text_; + + // 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_)) { + NetExpr*tmp; + if (dynamic_cast(ex)) + tmp = ex->dup_expr(); + else + tmp = new NetEParam(path, text_); + + tmp->set_line(*this); + return tmp; + } + + // 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 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); + if ((lsn == 0) || (msn == 0)) { + cerr << get_line() << ": Part select expresions " + " must be constant expressions." << endl; + des->errors += 1; + return 0; + } + + assert(lsn); + assert(msn); + unsigned long lsv = lsn->as_ulong(); + unsigned long msv = msn->as_ulong(); + unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv)); + assert(wid <= net->pin_count()); + assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv)); + + string tname = des->local_symbol(path); + NetESignal*tmp = new NetESignal(tname, wid); + tmp->set_line(*this); + + // Connect the pins from the lsb up to the msb. + unsigned off = net->sb_to_idx(lsv); + for (unsigned idx = 0 ; idx < wid ; idx += 1) + connect(tmp->pin(idx), net->pin(idx+off)); + + des->add_node(tmp); + return tmp; + } + + // If the bit select is constant, then treat it similar + // 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))) { + assert(idx_ == 0); + unsigned long msv = msn->as_ulong(); + + string tname = des->local_symbol(path); + NetESignal*tmp = new NetESignal(tname, 1); + tmp->set_line(*this); + connect(tmp->pin(0), net->pin(msv)); + + des->add_node(tmp); + return tmp; + } + + NetESignal*node = new NetESignal(net); + des->add_node(node); + assert(idx_ == 0); + + // 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); + NetESubSignal*ss = new NetESubSignal(node, ex); + ss->set_line(*this); + return ss; + } + + // All else fails, return the signal itself as the + // expression. + assert(msb_ == 0); + return node; + } + + // 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(name)) { + assert(msb_ != 0); + assert(lsb_ == 0); + assert(idx_ == 0); + NetExpr*i = msb_->elaborate_expr(des, path); + if (i == 0) { + cerr << get_line() << ": Unable to exaborate " + "index expression `" << *msb_ << "'" << endl; + des->errors += 1; + return 0; + } + + NetEMemory*node = new NetEMemory(mem, i); + node->set_line(*this); + return node; + } + + // I cannot interpret this identifier. Error message. + cerr << get_line() << ": Unable to bind wire/reg/memory " + "`" << path << "." << text_ << "'" << endl; + des->errors += 1; + return 0; +} + +/* + * $Log: elab_expr.cc,v $ + * Revision 1.1 1999/09/20 02:21:10 steve + * Elaborate parameters in phases. + * + */ + diff --git a/elaborate.cc b/elaborate.cc index d0a13b9c3..fa2c0b5ae 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) -#ident "$Id: elaborate.cc,v 1.92 1999/09/18 22:23:50 steve Exp $" +#ident "$Id: elaborate.cc,v 1.93 1999/09/20 02:21:10 steve Exp $" #endif /* @@ -1377,8 +1377,9 @@ NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const if (repeat_) { verinum*vrep = repeat_->eval_const(des, path); if (vrep == 0) { - cerr << get_line() << ": concatenation repeat expression" - " cannot be evaluated." << endl; + cerr << get_line() << ": error: " + "concatenation repeat expression cannot be evaluated." + << endl; des->errors += 1; return 0; } @@ -1417,121 +1418,6 @@ NetExpr* PEString::elaborate_expr(Design*des, const string&path) const return tmp; } -NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const -{ - // System identifiers show up in the netlist as identifiers. - if (text_[0] == '$') - return new NetEIdent(text_, 64); - - string name = path+"."+text_; - - // If the identifier name a parameter name, then return - // the expression that it represents. - if (const NetExpr*ex = des->find_parameter(path, text_)) - return ex->dup_expr(); - - // 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 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); - if ((lsn == 0) || (msn == 0)) { - cerr << get_line() << ": Part select expresions " - " must be constant expressions." << endl; - des->errors += 1; - return 0; - } - - assert(lsn); - assert(msn); - unsigned long lsv = lsn->as_ulong(); - unsigned long msv = msn->as_ulong(); - unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv)); - assert(wid <= net->pin_count()); - assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv)); - - string tname = des->local_symbol(path); - NetESignal*tmp = new NetESignal(tname, wid); - tmp->set_line(*this); - - // Connect the pins from the lsb up to the msb. - unsigned off = net->sb_to_idx(lsv); - for (unsigned idx = 0 ; idx < wid ; idx += 1) - connect(tmp->pin(idx), net->pin(idx+off)); - - des->add_node(tmp); - return tmp; - } - - // If the bit select is constant, then treat it similar - // 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))) { - assert(idx_ == 0); - unsigned long msv = msn->as_ulong(); - - string tname = des->local_symbol(path); - NetESignal*tmp = new NetESignal(tname, 1); - tmp->set_line(*this); - connect(tmp->pin(0), net->pin(msv)); - - des->add_node(tmp); - return tmp; - } - - NetESignal*node = new NetESignal(net); - des->add_node(node); - assert(idx_ == 0); - - // 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); - NetESubSignal*ss = new NetESubSignal(node, ex); - ss->set_line(*this); - return ss; - } - - // All else fails, return the signal itself as the - // expression. - assert(msb_ == 0); - return node; - } - - // 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(name)) { - assert(msb_ != 0); - assert(lsb_ == 0); - assert(idx_ == 0); - NetExpr*i = msb_->elaborate_expr(des, path); - if (i == 0) { - cerr << get_line() << ": Unable to exaborate " - "index expression `" << *msb_ << "'" << endl; - des->errors += 1; - return 0; - } - - NetEMemory*node = new NetEMemory(mem, i); - node->set_line(*this); - return node; - } - - // I cannot interpret this identifier. Error message. - cerr << get_line() << ": Unable to bind wire/reg/memory " - "`" << path << "." << text_ << "'" << endl; - des->errors += 1; - return 0; -} - NetExpr* PExpr::elaborate_expr(Design*des, const string&path) const { cerr << get_line() << ": I do not know how to elaborate expression: " @@ -2513,8 +2399,20 @@ bool Module::elaborate(Design*des, const string&path, svector*overrides_ bool result_flag = true; // Generate all the parameters that this instance of this - // module introduce to the design. + // 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, ... + for (mparm_it_t cur = parameters.begin() + ; cur != parameters.end() ; cur ++) { + string pname = path + "." + (*cur).first; + des->set_parameter(pname, new NetEParam); + } + + // and this loop elaborates the expressions. for (mparm_it_t cur = parameters.begin() ; cur != parameters.end() ; cur ++) { string pname = path + "." + (*cur).first; @@ -2535,6 +2433,45 @@ bool Module::elaborate(Design*des, const string&path, svector*overrides_ } } + // 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. const list&wl = get_wires(); @@ -2646,6 +2583,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.93 1999/09/20 02:21:10 steve + * Elaborate parameters in phases. + * * Revision 1.92 1999/09/18 22:23:50 steve * Match bit widths comming out of task output ports. * diff --git a/emit.cc b/emit.cc index 3ef093164..f13fb12c7 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) -#ident "$Id: emit.cc,v 1.21 1999/09/15 01:55:06 steve Exp $" +#ident "$Id: emit.cc,v 1.22 1999/09/20 02:21:10 steve Exp $" #endif /* @@ -287,6 +287,12 @@ void NetEMemory::expr_scan(struct expr_scan_t*tgt) const tgt->expr_memory(this); } +void NetEParam::expr_scan(struct expr_scan_t*tgt) const +{ + cerr << get_line() << ":internal error: unexpected NetEParam." + << endl; +} + void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const { tgt->expr_ufunc(this); @@ -331,6 +337,9 @@ void emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.22 1999/09/20 02:21:10 steve + * Elaborate parameters in phases. + * * Revision 1.21 1999/09/15 01:55:06 steve * Elaborate non-blocking assignment to memories. * diff --git a/eval.cc b/eval.cc index 33e0a7ce5..a98308c15 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) -#ident "$Id: eval.cc,v 1.7 1999/09/18 01:52:48 steve Exp $" +#ident "$Id: eval.cc,v 1.8 1999/09/20 02:21:10 steve Exp $" #endif # include "PExpr.h" @@ -68,6 +68,12 @@ verinum* PEIdent::eval_const(const Design*des, const string&path) const if (expr == 0) return 0; + if (dynamic_cast(expr)) { + cerr << get_line() << ": sorry: I cannot evaluate ``" << + text_ << "'' in this context." << endl; + return 0; + } + const NetEConst*eval = dynamic_cast(expr); assert(eval); return new verinum(eval->value()); @@ -86,6 +92,9 @@ verinum* PETernary::eval_const(const Design*, const string&) const /* * $Log: eval.cc,v $ + * Revision 1.8 1999/09/20 02:21:10 steve + * Elaborate parameters in phases. + * * Revision 1.7 1999/09/18 01:52:48 steve * Remove spurious message. * diff --git a/eval_tree.cc b/eval_tree.cc new file mode 100644 index 000000000..bfdad60be --- /dev/null +++ b/eval_tree.cc @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1999 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) +#ident "$Id: eval_tree.cc,v 1.1 1999/09/20 02:21:10 steve Exp $" +#endif + +# include "netlist.h" + +NetExpr* NetExpr::eval_tree() +{ + return 0; +} +/* + + * Some of the derived classes can be evaluated by the compiler, this + * method provides the common aid of evaluating the parameter + * expressions. + */ +void NetEBinary::eval_sub_tree_() +{ + NetExpr*tmp = left_->eval_tree(); + if (tmp) { + delete left_; + left_ = tmp; + } + tmp = right_->eval_tree(); + if (tmp){ + delete right_; + right_ = tmp; + } +} + + +NetExpr* NetEBComp::eval_eqeq_() +{ + NetEConst*l = dynamic_cast(left_); + if (l == 0) return 0; + NetEConst*r = dynamic_cast(right_); + if (r == 0) return 0; + + const verinum&lv = l->value(); + const verinum&rv = r->value(); + + if (lv.len() < rv.len()) + return 0; + + verinum result(verinum::V1, 1); + for (unsigned idx = 0 ; idx < lv.len(); idx += 1) { + if (lv[idx] != rv[idx]) + result = verinum::V0; + } + + return new NetEConst(result); +} + + +NetExpr* NetEBComp::eval_leeq_() +{ + NetEConst*r = dynamic_cast(right_); + if (r == 0) return 0; + + verinum rv = r->value(); + + /* Detect the case where the right side is greater that or + equal to the largest value the left side can possibly + have. */ + unsigned long lv = (1 << left_->expr_width()) - 1; + if (lv <= rv.as_ulong()) { + verinum result(verinum::V1, 1); + return new NetEConst(result); + } + + return 0; +} + + +NetExpr* NetEBComp::eval_tree() +{ + eval_sub_tree_(); + + switch (op_) { + case 'e': + return eval_eqeq_(); + + case 'L': + return eval_leeq_(); + + default: + return 0; + } +} + +NetExpr* NetEConcat::eval_tree() +{ + for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { + // If this parameter is already a constant, go on. + if (dynamic_cast(parms_[idx])) + continue; + + assert(parms_[idx]); + NetExpr*expr = parms_[idx]->eval_tree(); + if (expr) { + delete parms_[idx]; + parms_[idx] = expr; + } + } + + unsigned gap = expr_width() / repeat_; + verinum val (verinum::Vx, repeat_ * gap); + + + // build up the result from least significant to most. + + unsigned cur = 0; + for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) { + NetEConst*expr = dynamic_cast(parms_[idx-1]); + if (expr == 0) + return 0; + + verinum tmp = expr->value(); + for (unsigned bit = 0 ; bit < tmp.len() ; bit += 1, cur += 1) + for (unsigned rep = 0 ; rep < repeat_ ; rep += 1) + val.set(rep*gap+cur, tmp[bit]); + } + + NetEConst*res = new NetEConst(val); + res->set_width(val.len()); + return res; +} + +/* + * $Log: eval_tree.cc,v $ + * Revision 1.1 1999/09/20 02:21:10 steve + * Elaborate parameters in phases. + * + */ + diff --git a/netlist.cc b/netlist.cc index 5ede6a7e9..1297dc1b4 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) -#ident "$Id: netlist.cc,v 1.65 1999/09/18 01:53:08 steve Exp $" +#ident "$Id: netlist.cc,v 1.66 1999/09/20 02:21:10 steve Exp $" #endif # include @@ -729,6 +729,11 @@ NetUTask::~NetUTask() { } +NetExpr::NetExpr(unsigned w) +: width_(w) +{ +} + NetExpr::~NetExpr() { } @@ -741,11 +746,6 @@ bool NetExpr::set_width(unsigned w) return false; } -NetExpr* NetExpr::eval_tree() -{ - return 0; -} - NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r) : NetEBinary(op, l, r) { @@ -920,84 +920,6 @@ NetEBinary* NetEBinary::dup_expr() const assert(0); } -/* - * Some of the derived classes can be evaluated by the compiler, this - * method provides the common aid of evaluating the parameter - * expressions. - */ -void NetEBinary::eval_sub_tree_() -{ - NetExpr*tmp = left_->eval_tree(); - if (tmp) { - delete left_; - left_ = tmp; - } - tmp = right_->eval_tree(); - if (tmp){ - delete right_; - right_ = tmp; - } -} - - -NetExpr* NetEBComp::eval_eqeq_() -{ - NetEConst*l = dynamic_cast(left_); - if (l == 0) return 0; - NetEConst*r = dynamic_cast(right_); - if (r == 0) return 0; - - const verinum&lv = l->value(); - const verinum&rv = r->value(); - - if (lv.len() < rv.len()) - return 0; - - verinum result(verinum::V1, 1); - for (unsigned idx = 0 ; idx < lv.len(); idx += 1) { - if (lv[idx] != rv[idx]) - result = verinum::V0; - } - - return new NetEConst(result); -} - -NetExpr* NetEBComp::eval_leeq_() -{ - NetEConst*r = dynamic_cast(right_); - if (r == 0) return 0; - - verinum rv = r->value(); - - /* Detect the case where the right side is greater that or - equal to the largest value the left side can possibly - have. */ - unsigned long lv = (1 << left_->expr_width()) - 1; - if (lv <= rv.as_ulong()) { - verinum result(verinum::V1, 1); - return new NetEConst(result); - } - - return 0; -} - - -NetExpr* NetEBComp::eval_tree() -{ - eval_sub_tree_(); - - switch (op_) { - case 'e': - return eval_eqeq_(); - - case 'L': - return eval_leeq_(); - - default: - return 0; - } -} - NetEConcat::NetEConcat(unsigned cnt, unsigned r) : parms_(cnt), repeat_(r) { @@ -1015,7 +937,7 @@ void NetEConcat::set(unsigned idx, NetExpr*e) assert(idx < parms_.count()); assert(parms_[idx] == 0); parms_[idx] = e; - expr_width( expr_width() + e->expr_width() ); + expr_width( expr_width() + repeat_*e->expr_width() ); } /* @@ -1043,7 +965,7 @@ bool NetEConcat::set_width(unsigned w) NetEConcat* NetEConcat::dup_expr() const { - NetEConcat*dup = new NetEConcat(parms_.count()); + NetEConcat*dup = new NetEConcat(parms_.count(), repeat_); for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) if (parms_[idx]) { assert(parms_[idx]->dup_expr()); @@ -1055,17 +977,20 @@ NetEConcat* NetEConcat::dup_expr() const return dup; } +NetEConst::NetEConst(const verinum&val) +: NetExpr(val.len()), value_(val) +{ +} + NetEConst::~NetEConst() { } bool NetEConst::set_width(unsigned w) { - if (w > value_.len()) { - cerr << get_line() << ": Cannot expand " << *this - << " to " << w << " bits." << endl; + if (w > value_.len()) return false; - } + assert(w <= value_.len()); value_ = verinum(value_, w); expr_width(w); @@ -1135,6 +1060,29 @@ NetEMemory* NetEMemory::dup_expr() const assert(0); } +NetEParam::NetEParam() +{ +} + +NetEParam::NetEParam(const string&p, const string&n) +: path_(p), name_(n) +{ +} + +NetEParam::~NetEParam() +{ +} + +bool NetEParam::set_width(unsigned) +{ + return false; +} + +NetEParam* NetEParam::dup_expr() const +{ + return 0; +} + NetESignal::NetESignal(NetNet*n) : NetExpr(n->pin_count()), NetNode(n->name(), n->pin_count()) { @@ -1870,6 +1818,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * 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. * diff --git a/netlist.h b/netlist.h index d5ba171c0..f3fa252c5 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) -#ident "$Id: netlist.h,v 1.66 1999/09/18 01:53:08 steve Exp $" +#ident "$Id: netlist.h,v 1.67 1999/09/20 02:21:10 steve Exp $" #endif /* @@ -364,7 +364,7 @@ class NetMemory { */ class NetExpr : public LineInfo { public: - explicit NetExpr(unsigned w =0) : width_(w) { } + explicit NetExpr(unsigned w =0); virtual ~NetExpr() =0; virtual void expr_scan(struct expr_scan_t*) const =0; @@ -1249,6 +1249,7 @@ class NetEConcat : public NetExpr { virtual bool set_width(unsigned w); virtual NetEConcat* dup_expr() const; + virtual NetExpr* eval_tree(); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -1260,8 +1261,7 @@ class NetEConcat : public NetExpr { class NetEConst : public NetExpr { public: - NetEConst(const verinum&val) - : NetExpr(val.len()), value_(val) { } + explicit NetEConst(const verinum&val); ~NetEConst(); const verinum&value() const { return value_; } @@ -1276,6 +1276,32 @@ class NetEConst : public NetExpr { verinum value_; }; +/* + * This clas is a placeholder for a parameter expression. When + * parameters are first created, an instance of this object is used to + * hold the place where the parameter exression goes. Then, when the + * parameters are resolved, these objects are removed. + * + * If the parameter object is created with a path and name, then the + * object represents a reference to a parameter that is known to exist. + */ +class NetEParam : public NetExpr { + public: + NetEParam(); + NetEParam(const string&path, const string&name); + ~NetEParam(); + + virtual bool set_width(unsigned w); + virtual void expr_scan(struct expr_scan_t*) const; + virtual NetEParam* dup_expr() const; + + virtual void dump(ostream&) const; + + private: + string path_; + string name_; +}; + /* * This class represents the ternary (?:) operator. It has 3 * expressions, one of which is a condition used to select which of @@ -1585,6 +1611,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * 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. *