From 65ae92859ccd9611e20c2709531e72512aa120ad Mon Sep 17 00:00:00 2001 From: steve Date: Fri, 17 Dec 1999 03:38:46 +0000 Subject: [PATCH] NetConst can now hold wide constants. --- cprop.cc | 50 ++++++++++++++------------ design_dump.cc | 10 ++++-- elab_net.cc | 26 +++++++------- expr_synth.cc | 16 +++++---- netlist.cc | 27 ++++++++++++-- netlist.h | 19 +++++++--- t-vvm.cc | 96 +++++++++++++++++++++++--------------------------- t-xnf.cc | 23 +++++++----- 8 files changed, 156 insertions(+), 111 deletions(-) diff --git a/cprop.cc b/cprop.cc index f963aad4e..03fc22781 100644 --- a/cprop.cc +++ b/cprop.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: cprop.cc,v 1.2 1998/12/02 04:37:13 steve Exp $" +#ident "$Id: cprop.cc,v 1.3 1999/12/17 03:38:46 steve Exp $" #endif # include "netlist.h" @@ -35,7 +35,7 @@ static bool is_a_const_node(const NetNode*obj) return dynamic_cast(obj); } -static bool const_into_xnor(Design*des, NetConst*obj, +static bool const_into_xnor(Design*des, verinum::V cval, NetLogic*log, unsigned pin) { assert(pin > 0); @@ -44,7 +44,7 @@ static bool const_into_xnor(Design*des, NetConst*obj, the device is simply buffering the constant value. */ if (log->pin_count() == 2) { cerr << "cprop: delete gate " << log->name() << - " and propogate " << obj->value() << "." << endl; + " and propogate " << cval << "." << endl; assert(pin == 1); connect(log->pin(0), log->pin(1)); @@ -55,7 +55,7 @@ static bool const_into_xnor(Design*des, NetConst*obj, /* If this is a constant 0, then replace the gate with one 1-pin smaller. Skip this pin. */ - if (obj->value() == verinum::V0) { + if (cval == verinum::V0) { cerr << "cprop: disconnect pin " << pin << " from gate " << log->name() << "." << endl; @@ -78,7 +78,7 @@ static bool const_into_xnor(Design*des, NetConst*obj, /* If this is a constant 1, then replace the gate with an XOR that is 1-pin smaller. Removing the constant 1 causes the sense of the output to change. */ - if (obj->value() == verinum::V1) { + if (cval == verinum::V1) { cerr << "cprop: disconnect pin " << pin << " from gate " << log->name() << "." << endl; @@ -101,7 +101,7 @@ static bool const_into_xnor(Design*des, NetConst*obj, /* If this is a constant X or Z, then the gate is certain to generate an X. Replace the gate with a constant X. This may cause other signals all over to become dangling. */ - if ((obj->value() == verinum::Vx) || (obj->value() == verinum::Vz)) { + if ((cval == verinum::Vx) || (cval == verinum::Vz)) { cerr << "cprop: replace gate " << log->name() << " with " "a constant X." << endl; @@ -115,11 +115,11 @@ static bool const_into_xnor(Design*des, NetConst*obj, return false; } -static void look_for_core_logic(Design*des, NetConst*obj) +static void look_for_core_logic(Design*des, NetConst*obj, unsigned cpin) { NetObj*cur = obj; unsigned pin = 0; - for (obj->pin(0).next_link(cur, pin) + for (obj->pin(cpin).next_link(cur, pin) ; cur != obj ; cur->pin(pin).next_link(cur, pin)) { @@ -130,7 +130,7 @@ static void look_for_core_logic(Design*des, NetConst*obj) bool flag = false; switch (log->type()) { case NetLogic::XNOR: - flag = const_into_xnor(des, obj, log, pin); + flag = const_into_xnor(des, obj->value(cpin), log, pin); break; default: break; @@ -151,23 +151,25 @@ static void dangling_const(Design*des, NetConst*obj) { // If there are any links that take input, abort this // operation. - if (count_inputs(obj->pin(0)) > 0) - return; + for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) + if (count_inputs(obj->pin(idx)) > 0) + return; // If there are no other drivers, delete all the signals that // are also dangling. - if (count_outputs(obj->pin(0)) == 1) { + for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) + if (count_outputs(obj->pin(idx)) == 1) { - NetObj*cur; - unsigned pin; - obj->pin(0).next_link(cur, pin); - while (cur != obj) { - cerr << "cprop: delete dangling signal " << cur->name() << - "." << endl; - delete cur; - obj->pin(0).next_link(cur, pin); + NetObj*cur; + unsigned pin; + obj->pin(idx).next_link(cur, pin); + while (cur != obj) { + cerr << "cprop: delete dangling signal " << + cur->name() << "." << endl; + delete cur; + obj->pin(idx).next_link(cur, pin); + } } - } // Done. Delete me. delete obj; @@ -178,7 +180,8 @@ void cprop(Design*des) des->clear_node_marks(); while (NetNode*obj = des->find_node(&is_a_const_node)) { NetConst*cur = dynamic_cast(obj); - look_for_core_logic(des, cur); + for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1) + look_for_core_logic(des, cur, idx); cur->set_mark(); dangling_const(des, cur); } @@ -187,6 +190,9 @@ void cprop(Design*des) /* * $Log: cprop.cc,v $ + * Revision 1.3 1999/12/17 03:38:46 steve + * NetConst can now hold wide constants. + * * Revision 1.2 1998/12/02 04:37:13 steve * Add the nobufz function to eliminate bufz objects, * Object links are marked with direction, diff --git a/design_dump.cc b/design_dump.cc index f0bdf1b32..28e7102c2 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.63 1999/12/12 06:03:14 steve Exp $" +#ident "$Id: design_dump.cc,v 1.64 1999/12/17 03:38:46 steve Exp $" #endif /* @@ -189,7 +189,10 @@ void NetCaseCmp::dump_node(ostream&o, unsigned ind) const void NetConst::dump_node(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "constant " << value_ << ": " << name() << endl; + o << setw(ind) << "" << "constant "; + for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1) + o << value_[idx-1]; + o << ": " << name() << endl; dump_node_pins(o, ind+4); } @@ -862,6 +865,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.64 1999/12/17 03:38:46 steve + * NetConst can now hold wide constants. + * * Revision 1.63 1999/12/12 06:03:14 steve * Allow memories without indices in expressions. * diff --git a/elab_net.cc b/elab_net.cc index 8a4b2d20d..2555627bc 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) -#ident "$Id: elab_net.cc,v 1.13 1999/12/16 03:46:39 steve Exp $" +#ident "$Id: elab_net.cc,v 1.14 1999/12/17 03:38:46 steve Exp $" #endif # include "PExpr.h" @@ -641,12 +641,11 @@ NetNet* PEIdent::elaborate_net(Design*des, const string&path, verinum pvalue = pc->value(); sig = new NetNet(0, path+"."+text_, NetNet::IMPLICIT, pc->expr_width()); - for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) { - NetConst*cp = new NetConst(des->local_symbol(path), - pvalue[idx]); - connect(sig->pin(idx), cp->pin(0)); - des->add_node(cp); - } + NetConst*cp = new NetConst(des->local_symbol(path), pvalue); + des->add_node(cp); + des->add_signal(sig); + for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) + connect(sig->pin(idx), cp->pin(idx)); } else { @@ -886,13 +885,11 @@ NetNet* PENumber::elaborate_net(Design*des, const string&path, NetNet*net = new NetNet(0, des->local_symbol(path), NetNet::IMPLICIT, width); net->local_flag(true); - for (unsigned idx = 0 ; idx < width ; idx += 1) { - NetConst*tmp = new NetConst(des->local_symbol(path), - value_->get(idx)); - des->add_node(tmp); - connect(net->pin(idx), tmp->pin(0)); - } + NetConst*tmp = new NetConst(des->local_symbol(path), *value_); + for (unsigned idx = 0 ; idx < width ; idx += 1) + connect(net->pin(idx), tmp->pin(idx)); + des->add_node(tmp); des->add_signal(net); return net; } @@ -941,6 +938,9 @@ NetNet* PETernary::elaborate_net(Design*des, const string&path, /* * $Log: elab_net.cc,v $ + * Revision 1.14 1999/12/17 03:38:46 steve + * NetConst can now hold wide constants. + * * Revision 1.13 1999/12/16 03:46:39 steve * Structural logical or. * diff --git a/expr_synth.cc b/expr_synth.cc index 54fa947cc..d142ca861 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: expr_synth.cc,v 1.6 1999/11/28 23:42:02 steve Exp $" +#ident "$Id: expr_synth.cc,v 1.7 1999/12/17 03:38:46 steve Exp $" #endif # include "netlist.h" @@ -125,12 +125,11 @@ NetNet* NetEConst::synthesize(Design*des) unsigned width=expr_width(); NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width); - for (unsigned idx = 0 ; idx < width; idx += 1) { - string oname = des->local_symbol(path); - NetConst *c = new NetConst(oname, value().get(idx)); - connect(osig->pin(idx), c->pin(0)); - des->add_node(c); - } + NetConst*con = new NetConst(des->local_symbol(path), value()); + for (unsigned idx = 0 ; idx < width; idx += 1) + connect(osig->pin(idx), con->pin(idx)); + + des->add_node(con); des->add_signal(osig); return osig; } @@ -200,6 +199,9 @@ NetNet* NetESignal::synthesize(Design*des) /* * $Log: expr_synth.cc,v $ + * Revision 1.7 1999/12/17 03:38:46 steve + * NetConst can now hold wide constants. + * * Revision 1.6 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/netlist.cc b/netlist.cc index 9aef91940..2d81be5db 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.100 1999/12/16 02:42:15 steve Exp $" +#ident "$Id: netlist.cc,v 1.101 1999/12/17 03:38:46 steve Exp $" #endif # include @@ -1489,14 +1489,34 @@ NetProc* NetCondit::else_clause() } NetConst::NetConst(const string&n, verinum::V v) -: NetNode(n, 1), value_(v) +: NetNode(n, 1) { pin(0).set_dir(Link::OUTPUT); pin(0).set_name("O", 0); + value_ = new verinum::V[1]; + value_[0] = v; +} + +NetConst::NetConst(const string&n, const verinum&val) +: NetNode(n, val.len()) +{ + value_ = new verinum::V[pin_count()]; + for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { + pin(idx).set_dir(Link::OUTPUT); + pin(idx).set_name("O", idx); + value_[idx] = val.get(idx); + } } NetConst::~NetConst() { + delete[]value_; +} + +verinum::V NetConst::value(unsigned idx) const +{ + assert(idx < pin_count()); + return value_[idx]; } NetFuncDef::NetFuncDef(const string&n, const svector&po) @@ -2744,6 +2764,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.101 1999/12/17 03:38:46 steve + * NetConst can now hold wide constants. + * * Revision 1.100 1999/12/16 02:42:15 steve * Simulate carry output on adders. * diff --git a/netlist.h b/netlist.h index 690236ed4..b991bc1b0 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.102 1999/12/16 02:42:15 steve Exp $" +#ident "$Id: netlist.h,v 1.103 1999/12/17 03:38:46 steve Exp $" #endif /* @@ -707,20 +707,28 @@ class NetCaseCmp : public NetNode { virtual void emit_node(ostream&, struct target_t*) const; }; - +/* + * This class represents instances of the LPM_CONSTANT device. The + * node has only outputs and a constant value. The width is available + * by getting the pin_count(), and the value bits are available one at + * a time. There is no meaning to the aggregation of bits to form a + * wide NetConst object, although some targets may have an easier time + * detecting interesting constructs if they are combined. + */ class NetConst : public NetNode { public: explicit NetConst(const string&n, verinum::V v); + explicit NetConst(const string&n, const verinum&val); ~NetConst(); - verinum::V value() const { return value_; } + verinum::V value(unsigned idx) const; virtual void emit_node(ostream&, struct target_t*) const; virtual void dump_node(ostream&, unsigned ind) const; private: - verinum::V value_; + verinum::V*value_; }; /* @@ -2070,6 +2078,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * 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. * diff --git a/t-vvm.cc b/t-vvm.cc index 2140a38f1..884505a1e 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) -#ident "$Id: t-vvm.cc,v 1.91 1999/12/16 02:42:15 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.92 1999/12/17 03:38:46 steve Exp $" #endif # include @@ -94,6 +94,7 @@ class target_vvm : public target_t { void end_process(ostream&os, const NetProcTop*); private: + void emit_init_value_(const NetObj::Link&lnk, verinum::V val); void emit_gate_outputfun_(const NetNode*, unsigned); string defn_gate_outputfun_(ostream&os, const NetNode*, unsigned); @@ -745,36 +746,12 @@ void target_vvm::signal(ostream&os, const NetNet*sig) if (sig->get_ival(idx) == verinum::Vz) continue; - mapwritten; - init_code << " " << mangle(sig->name()) << ".init_P(" << idx << ", V" << sig->get_ival(idx) << ");" << endl; - for (const NetObj::Link*lnk = sig->pin(idx).next_link() - ; (*lnk) != sig->pin(idx) ; lnk = lnk->next_link()) { - - if (lnk->get_dir() == NetObj::Link::OUTPUT) - continue; - - // Check to see if the name has already been - // written to. This can happen if the object is a - // NetESignal, because there can be many of them - // with the same name. - if (written[lnk->get_obj()->name()]) - continue; - - written[lnk->get_obj()->name()] = true; - - - if (dynamic_cast(lnk->get_obj())) { - init_code << " " << - mangle(lnk->get_obj()->name()) << - ".init_" << lnk->get_name() << "(" << - lnk->get_inst() << ", V" << - sig->get_ival(idx) << ");" << endl; - } - } + // Propogate the initial value to inputs throughout. + emit_init_value_(sig->pin(idx), sig->get_ival(idx)); } } @@ -857,6 +834,36 @@ string target_vvm::defn_gate_outputfun_(ostream&os, return name; } +void target_vvm::emit_init_value_(const NetObj::Link&lnk, verinum::V val) +{ + mapwritten; + + for (const NetObj::Link*cur = lnk.next_link() + ; (*cur) != lnk ; cur = cur->next_link()) { + + if (cur->get_dir() == NetObj::Link::OUTPUT) + continue; + + // Check to see if the name has already been + // written to. This can happen if the object is a + // NetESignal, because there can be many of them + // with the same name. + if (written[cur->get_obj()->name()]) + continue; + + written[cur->get_obj()->name()] = true; + + // Write initial values to nodes and nets. + if (dynamic_cast(cur->get_obj())) { + init_code << " " << + mangle(cur->get_obj()->name()) << + ".init_" << cur->get_name() << "(" << + cur->get_inst() << ", V" << val << ");" << + endl; + } + } +} + /* * This method handles writing output functions for gates that have a * single output (at pin 0). This writes the output_fun method into @@ -878,7 +885,11 @@ void target_vvm::emit_gate_outputfun_(const NetNode*gate, unsigned gpin) const NetObj*cur; unsigned pin; gate->pin(gpin).next_link(cur, pin); - while (cur != gate) { + for ( ; cur != gate ; cur->pin(pin).next_link(cur, pin)) { + + // Skip pins that are output only. + if (cur->pin(pin).get_dir() == NetObj::Link::OUTPUT) + continue; if (cur->pin(pin).get_name() != "") { @@ -892,7 +903,6 @@ void target_vvm::emit_gate_outputfun_(const NetNode*gate, unsigned gpin) << pin << ", val);" << endl; } - cur->pin(pin).next_link(cur, pin); } delayed << "}" << endl; @@ -1290,29 +1300,8 @@ void target_vvm::net_case_cmp(ostream&os, const NetCaseCmp*gate) */ void target_vvm::net_const(ostream&os, const NetConst*gate) { - string outfun = defn_gate_outputfun_(os, gate, 0); - - os << "static vvm_bufz " << mangle(gate->name()) << "(&" << - outfun << ");" << endl; - - init_code << " " << mangle(gate->name()) << ".set(1, "; - switch (gate->value()) { - case verinum::V0: - init_code << "V0"; - break; - case verinum::V1: - init_code << "V1"; - break; - case verinum::Vx: - init_code << "Vx"; - break; - case verinum::Vz: - init_code << "Vz"; - break; - } - init_code << ");" << endl; - - emit_gate_outputfun_(gate, 0); + for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1) + emit_init_value_(gate->pin(idx), gate->value(idx)); } /* @@ -1965,6 +1954,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.92 1999/12/17 03:38:46 steve + * NetConst can now hold wide constants. + * * Revision 1.91 1999/12/16 02:42:15 steve * Simulate carry output on adders. * diff --git a/t-xnf.cc b/t-xnf.cc index 77627ad67..1427ef926 100644 --- a/t-xnf.cc +++ b/t-xnf.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: t-xnf.cc,v 1.21 1999/12/16 18:54:32 steve Exp $" +#ident "$Id: t-xnf.cc,v 1.22 1999/12/17 03:38:46 steve Exp $" #endif /* XNF BACKEND @@ -603,15 +603,17 @@ void target_xnf::lpm_ram_dq(ostream&os, const NetRamDq*ram) void target_xnf::net_const(ostream&os, const NetConst*c) { - verinum::V v=c->value(); - assert(v==verinum::V0 || v==verinum::V1); - const NetObj::Link& lnk = c->pin(0); - // Code parallels draw_pin above, some smart c++ guru should - // find a way to make a method out of this. - unsigned cpin; - const NetObj*cur; + for (unsigned idx = 0 ; idx < c->pin_count() ; idx += 1) { + verinum::V v=c->value(idx); + assert(v==verinum::V0 || v==verinum::V1); + const NetObj::Link& lnk = c->pin(idx); + // Code parallels draw_pin above, some smart c++ guru should + // find a way to make a method out of this. + unsigned cpin; + const NetObj*cur; - os << " PWR, " << v << ", " << choose_sig_name(&lnk) << endl; + os << " PWR, " << v << ", " << choose_sig_name(&lnk) << endl; + } } /* @@ -709,6 +711,9 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj }; /* * $Log: t-xnf.cc,v $ + * Revision 1.22 1999/12/17 03:38:46 steve + * NetConst can now hold wide constants. + * * Revision 1.21 1999/12/16 18:54:32 steve * Capture the carry out of carry-chain addition. *