diff --git a/design_dump.cc b/design_dump.cc index d58bccdcc..266b7d976 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.14 1999/02/21 17:01:57 steve Exp $" +#ident "$Id: design_dump.cc,v 1.15 1999/03/01 03:27:53 steve Exp $" #endif /* @@ -117,7 +117,7 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const void NetAssign::dump_node(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "Procedural assign: " << *rval_ << endl; + o << setw(ind) << "" << "Procedural assign: " << *rval_.ref() << endl; dump_node_pins(o, ind+4); } @@ -311,12 +311,12 @@ void NetBlock::dump(ostream&o, unsigned ind) const void NetCase::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "case (" << *expr_ << ")" << endl; + o << setw(ind) << "" << "case (" << *expr_.ref() << ")" << endl; for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { o << setw(ind+2) << ""; - if (items_[idx].guard) - o << *items_[idx].guard << ":"; + if (items_[idx].guard.ref()) + o << *items_[idx].guard.ref() << ":"; else o << "default:"; @@ -386,12 +386,12 @@ void NetTask::dump(ostream&o, unsigned ind) const if (nparms_ > 0) { o << "("; - if (parms_[0]) + if (parms_[0].ref()) parms_[0]->dump(o); for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) { o << ", "; - if (parms_[idx]) + if (parms_[idx].ref()) parms_[idx]->dump(o); } @@ -402,7 +402,7 @@ void NetTask::dump(ostream&o, unsigned ind) const void NetWhile::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "while (" << *cond_ << ")" << endl; + o << setw(ind) << "" << "while (" << *cond_.ref() << ")" << endl; proc_->dump(o, ind+3); } @@ -475,11 +475,11 @@ void Design::dump(ostream&o) const { o << "ELABORATED PARAMETERS:" << endl; { - map::const_iterator pp; + map::const_iterator pp; for (pp = parameters_.begin() ; pp != parameters_.end() ; pp ++) { o << " " << (*pp).first << " = " << - *(*pp).second << ";" << endl; + *(*pp).second.ref() << ";" << endl; } } @@ -515,6 +515,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.15 1999/03/01 03:27:53 steve + * Prevent the duplicate allocation of ESignal objects. + * * Revision 1.14 1999/02/21 17:01:57 steve * Add support for module parameters. * diff --git a/elaborate.cc b/elaborate.cc index ac01873ad..ec9dfe395 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.16 1999/02/21 17:01:57 steve Exp $" +#ident "$Id: elaborate.cc,v 1.17 1999/03/01 03:27:53 steve Exp $" #endif /* @@ -650,8 +650,7 @@ NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const return ex; if (NetNet*net = des->find_signal(name)) { - NetESignal*node = new NetESignal(net); - des->add_node(node); + NetESignal*node = des->get_esignal(net); return node; } @@ -964,6 +963,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.17 1999/03/01 03:27:53 steve + * Prevent the duplicate allocation of ESignal objects. + * * Revision 1.16 1999/02/21 17:01:57 steve * Add support for module parameters. * diff --git a/netlist.cc b/netlist.cc index 3464a13d6..5d2e39f15 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.17 1999/02/21 17:01:57 steve Exp $" +#ident "$Id: netlist.cc,v 1.18 1999/03/01 03:27:53 steve Exp $" #endif # include @@ -323,19 +323,18 @@ void NetBlock::append(NetProc*cur) NetCase::NetCase(NetExpr*ex, unsigned cnt) : expr_(ex), nitems_(cnt) { - assert(expr_); + assert(expr_.ref()); items_ = new Item[nitems_]; for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { - items_[idx].guard = 0; items_[idx].statement = 0; } } NetCase::~NetCase() { - delete expr_; + expr_.clr_and_delete(); for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { - if (items_[idx].guard) delete items_[idx].guard; + items_[idx].guard.clr_and_delete(); if (items_[idx].statement) delete items_[idx].statement; } delete[]items_; @@ -350,6 +349,9 @@ void NetCase::set_case(unsigned idx, NetExpr*e, NetProc*p) NetTask::~NetTask() { + for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) + parms_[idx].clr_and_delete(); + delete[]parms_; } @@ -364,9 +366,56 @@ void NetExpr::set_width(unsigned w) expr_width(w); } +void NetExpr::REF::clr() +{ + if (ref_ == 0) + return; + + NetExpr*ref = ref_; + ref_ = 0; + if (ref->reflist_ == this) { + ref->reflist_ = next_; + return; + } + + NetExpr::REF*cur; + for (cur = ref->reflist_ ; cur->next_ != this ; cur = cur->next_) { + assert(cur->next_); + } + + cur->next_ = next_; +} + +void NetExpr::REF::set(NetExpr*that) +{ + clr(); + if (that == 0) return; + ref_ = that; + next_ = that->reflist_; + that->reflist_ = this; +} + +void NetExpr::substitute(NetExpr*that) +{ + if (reflist_ == 0) + return; + + REF*cur = reflist_; + while (cur->next_) { + cur->ref_ = that; + cur = cur->next_; + } + + cur->next_ = that->reflist_; + cur->ref_ = that; + that->reflist_ = reflist_; + reflist_ = 0; +} NetEBinary::~NetEBinary() { + left_.clr_and_delete(); + right_.clr_and_delete(); } @@ -443,6 +492,7 @@ void NetESignal::set_width(unsigned w) NetEUnary::~NetEUnary() { + expr_.clr_and_delete(); } void NetEUnary::set_width(unsigned w) @@ -736,11 +786,11 @@ void Design::set_parameter(const string&key, NetExpr*expr) NetExpr* Design::get_parameter(const string&key) const { - map::const_iterator cur = parameters_.find(key); + map::const_iterator cur = parameters_.find(key); if (cur == parameters_.end()) return 0; else - return (*cur).second; + return (*cur).second.ref(); } string Design::get_flag(const string&key) const @@ -831,6 +881,17 @@ void Design::del_node(NetNode*net) net->design_ = 0; } +NetESignal* Design::get_esignal(NetNet*net) +{ + NetESignal*&node = esigs_[net->name()]; + if (node == 0) { + node = new NetESignal(net); + add_node(node); + } + + return node; +} + void Design::add_process(NetProcTop*pro) { pro->next_ = procs_; @@ -895,6 +956,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * 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. * diff --git a/netlist.h b/netlist.h index 294447a3f..0e12c16b1 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.20 1999/02/21 17:01:57 steve Exp $" +#ident "$Id: netlist.h,v 1.21 1999/03/01 03:27:53 steve Exp $" #endif /* @@ -282,6 +282,83 @@ class NetNet : public NetObj { verinum::V*ivalue_; }; +/* ========= + * There are cases where expressions need to be represented. The + * NetExpr class is the root of a heirarchy that serves that purpose. + * + * The expr_width() is the width of the expression, that accounts + * for the widths of the sub-expressions I might have. It is up to the + * derived classes to properly set the expr width, if need be. The + * set_width() method is used to compel an expression to have a + * certain width, and is used particulary when the expression is an + * rvalue in an assignment statement. + * + * The NetExpr::REF type can be used sort of like a pointer to + * NetExpr objects. The NetExpr uses this list to know if it is still + * being referenced, so can handle garbage collection. Also, this + * trick can be used to replace subexpressions. + */ +class NetExpr { + public: + explicit NetExpr(unsigned w =0) : width_(w), reflist_(0) { } + virtual ~NetExpr() =0; + + virtual void expr_scan(struct expr_scan_t*) const =0; + virtual void dump(ostream&) const; + + unsigned expr_width() const { return width_; } + virtual void set_width(unsigned); + + public: + class REF { + friend class NetExpr; + public: + void clr(); + void set(NetExpr*); + NetExpr*ref() const { return ref_; } + + void clr_and_delete() + { NetExpr*tmp = ref_; + clr(); + if (tmp && tmp->is_referenced() == false) + delete tmp; + } + + NetExpr*operator-> () const { return ref_; } + REF& operator=(NetExpr*that) { set(that); return *this; } + + REF() : ref_(0), next_(0) { } + REF(NetExpr*that) : ref_(0), next_(0) { set(that); } + REF(const REF&that) : ref_(0), next_(0) { set(that.ref_); } + ~REF() { clr(); } + private: + NetExpr*ref_; + REF*next_; + private:// not implemented + REF& operator=(const REF&); + }; + friend class NetExpr::REF; + + /* This method causes every item that references this object + to reference that object instead. When this complete, + no references to me will remain. */ + void substitute(NetExpr*that); + + bool is_referenced() const { return reflist_ != 0; } + + protected: + void expr_width(unsigned w) { width_ = w; } + + private: + unsigned width_; + + REF*reflist_; + + private: // not implemented + NetExpr(const NetExpr&); + NetExpr& operator=(const NetExpr&); +}; + /* * The NetTmp object is a network that is only used momentarily by * elaboration to carry links around. A completed netlist cannot have @@ -490,7 +567,7 @@ class NetAssign : public NetProc, public NetNode { explicit NetAssign(NetNet*lv, NetExpr*rv); ~NetAssign(); - const NetExpr*rval() const { return rval_; } + const NetExpr*rval() const { return rval_.ref(); } void find_lval_range(const NetNet*&net, unsigned&msb, unsigned&lsb) const; @@ -501,7 +578,7 @@ class NetAssign : public NetProc, public NetNode { virtual void dump_node(ostream&, unsigned ind) const; private: - NetExpr*const rval_; + NetExpr::REF rval_; }; /* A block is stuff line begin-end blocks, that contain and ordered @@ -544,10 +621,10 @@ class NetCase : public NetProc { void set_case(unsigned idx, NetExpr*ex, NetProc*st); - const NetExpr*expr() const { return expr_; } + const NetExpr*expr() const { return expr_.ref(); } unsigned nitems() const { return nitems_; } - const NetExpr*expr(unsigned idx) const { return items_[idx].guard; } + const NetExpr*expr(unsigned idx) const { return items_[idx].guard.ref();} const NetProc*stat(unsigned idx) const { return items_[idx].statement; } virtual void emit_proc(ostream&, struct target_t*) const; @@ -556,11 +633,11 @@ class NetCase : public NetProc { private: struct Item { - NetExpr*guard; + NetExpr::REF guard; NetProc*statement; }; - NetExpr*expr_; + NetExpr::REF expr_; unsigned nitems_; Item*items_; }; @@ -574,7 +651,7 @@ class NetCondit : public NetProc { NetCondit(NetExpr*ex, NetProc*i, NetProc*e) : expr_(ex), if_(i), else_(e) { } - NetExpr*expr() const { return expr_; } + NetExpr*expr() const { return expr_.ref(); } void emit_recurse_if(ostream&, struct target_t*) const; void emit_recurse_else(ostream&, struct target_t*) const; @@ -582,7 +659,7 @@ class NetCondit : public NetProc { virtual void dump(ostream&, unsigned ind) const; private: - NetExpr*expr_; + NetExpr::REF expr_; NetProc*if_; NetProc*else_; }; @@ -642,10 +719,7 @@ class NetTask : public NetProc { public: NetTask(const string&na, unsigned np) : name_(na), nparms_(np) - { parms_ = new NetExpr*[nparms_]; - for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) - parms_[idx] = 0; - } + { parms_ = new NetExpr::REF[nparms_]; } ~NetTask(); const string& name() const { return name_; } @@ -659,7 +733,7 @@ class NetTask : public NetProc { NetExpr* parm(unsigned idx) const { assert(idx < nparms_); - return parms_[idx]; + return parms_[idx].ref(); } virtual void emit_proc(ostream&, struct target_t*) const; @@ -668,7 +742,7 @@ class NetTask : public NetProc { private: string name_; unsigned nparms_; - NetExpr**parms_; + NetExpr::REF*parms_; }; /* @@ -682,7 +756,7 @@ class NetWhile : public NetProc { NetWhile(NetExpr*c, NetProc*p) : cond_(c), proc_(p) { } - NetExpr*expr() const { return cond_; } + const NetExpr*expr() const { return cond_.ref(); } void emit_proc_recurse(ostream&, struct target_t*) const; @@ -690,7 +764,7 @@ class NetWhile : public NetProc { virtual void dump(ostream&, unsigned ind) const; private: - NetExpr*cond_; + NetExpr::REF cond_; NetProc*proc_; }; @@ -719,38 +793,6 @@ class NetProcTop : public LineInfo { NetProcTop*next_; }; -/* ========= - * There are cases where expressions need to be represented. The - * NetExpr class is the root of a heirarchy that serves that purpose. - * - * The expr_width() is the width of the expression, that accounts - * for the widths of the sub-expressions I might have. It is up to the - * derived classes to properly set the expr width, if need be. The - * set_width() method is used to compel an expression to have a - * certain width, and is used particulary when the expression is an - * rvalue in an assignment statement. - */ -class NetExpr { - public: - explicit NetExpr(unsigned w =0) : width_(w) { } - virtual ~NetExpr() =0; - - virtual void expr_scan(struct expr_scan_t*) const =0; - virtual void dump(ostream&) const; - - unsigned expr_width() const { return width_; } - virtual void set_width(unsigned); - - protected: - void expr_width(unsigned w) { width_ = w; } - - private: - unsigned width_; - - private: // not implemented - NetExpr(const NetExpr&); - NetExpr& operator=(const NetExpr&); -}; class NetEBinary : public NetExpr { @@ -758,8 +800,8 @@ class NetEBinary : public NetExpr { NetEBinary(char op, NetExpr*l, NetExpr*r); ~NetEBinary(); - const NetExpr*left() const { return left_; } - const NetExpr*right() const { return right_; } + const NetExpr*left() const { return left_.ref(); } + const NetExpr*right() const { return right_.ref(); } char op() const { return op_; } @@ -770,8 +812,8 @@ class NetEBinary : public NetExpr { private: char op_; - NetExpr*left_; - NetExpr*right_; + NetExpr::REF left_; + NetExpr::REF right_; }; class NetEConst : public NetExpr { @@ -799,7 +841,7 @@ class NetEUnary : public NetExpr { ~NetEUnary(); char op() const { return op_; } - const NetExpr* expr() const { return expr_; } + const NetExpr* expr() const { return expr_.ref(); } void set_width(unsigned w); @@ -808,7 +850,7 @@ class NetEUnary : public NetExpr { private: char op_; - NetExpr*expr_; + NetExpr::REF expr_; }; /* System identifiers are represented here. */ @@ -827,9 +869,14 @@ class NetEIdent : public NetExpr { string name_; }; -/* When a signal shows up in an expression, this type represents - it. From this the expression can get any kind of access to the - structural signal. */ +/* + * When a signal shows up in an expression, this type represents + * it. From this the expression can get any kind of access to the + * structural signal. + * + * A signal shows up as a node in the netlist so that structural + * activity can invoke the expression. + */ class NetESignal : public NetExpr, public NetNode { public: @@ -874,7 +921,6 @@ class Design { NetExpr*get_parameter(const string&name) const; // SIGNALS - void add_signal(NetNet*); void del_signal(NetNet*); NetNet*find_signal(const string&name); @@ -883,6 +929,9 @@ class Design { void add_node(NetNode*); void del_node(NetNode*); + // ESIGNALS + NetESignal* get_esignal(NetNet*net); + // PROCESSES void add_process(NetProcTop*); @@ -904,7 +953,9 @@ class Design { string local_symbol(const string&path); private: - map parameters_; + // List all the parameters in the design. This table includes + // the parameters of instantiated modules in canonical names. + map parameters_; // List all the signals in the design. NetNet*signals_; @@ -917,6 +968,9 @@ class Design { map flags_; + // Use this map to prevent duplicate signals. + map esigs_; + unsigned lcounter_; private: // not implemented @@ -966,6 +1020,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.21 1999/03/01 03:27:53 steve + * Prevent the duplicate allocation of ESignal objects. + * * Revision 1.20 1999/02/21 17:01:57 steve * Add support for module parameters. *