From ada45acb0cadade1337774fccfa03c783d0a54ad Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 2 Dec 1998 04:37:13 +0000 Subject: [PATCH] Add the nobufz function to eliminate bufz objects, Object links are marked with direction, constant propagation is more careful will wide links, Signal folding is aware of attributes, and the XNF target can dump UDP objects based on LCA attributes. --- Makefile | 5 +- cprop.cc | 43 +++++++++----- design_dump.cc | 24 +++++++- elaborate.cc | 13 ++++- main.cc | 12 +++- netlist.cc | 73 ++++++++++++++++++++++- netlist.h | 47 +++++++++++---- nobufz.cc | 73 +++++++++++++++++++++++ sigfold.cc | 58 ++++++++++++++++-- t-xnf.cc | 156 +++++++++++++++++++++++++++++++++---------------- 10 files changed, 417 insertions(+), 87 deletions(-) create mode 100644 nobufz.cc diff --git a/Makefile b/Makefile index 9f92a8808..6b6764324 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,11 @@ CXXFLAGS = -O -g -Wall -Wno-uninitialized #TT = t-debug.o t-vvm.o TT = t-verilog.o t-vvm.o t-xnf.o +FF = nobufz.o sigfold.o stupid.o O = main.o cprop.o design_dump.o elaborate.o emit.o eval.o lexor.o mangle.o \ -netlist.o parse.o parse_misc.o pform.o pform_dump.o sigfold.o stupid.o \ -verinum.o target.o targets.o Module.o PExpr.o Statement.o $(TT) +netlist.o parse.o parse_misc.o pform.o pform_dump.o verinum.o target.o \ +targets.o Module.o PExpr.o Statement.o $(FF) $(TT) vl: $O $(CXX) $(CXXFLAGS) -o vl $O diff --git a/cprop.cc b/cprop.cc index f134d9451..f963aad4e 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.1 1998/11/13 06:23:17 steve Exp $" +#ident "$Id: cprop.cc,v 1.2 1998/12/02 04:37:13 steve Exp $" #endif # include "netlist.h" @@ -149,22 +149,27 @@ static void look_for_core_logic(Design*des, NetConst*obj) */ static void dangling_const(Design*des, NetConst*obj) { - NetObj*cur; - unsigned pin; - for (obj->pin(0).next_link(cur, pin) - ; cur != obj - ; cur->pin(pin).next_link(cur, pin)) { - if (! dynamic_cast(cur)) - return; + // If there are any links that take input, abort this + // operation. + if (count_inputs(obj->pin(0)) > 0) + return; + + // If there are no other drivers, delete all the signals that + // are also dangling. + if (count_outputs(obj->pin(0)) == 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); + } } - 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); - } + // Done. Delete me. delete obj; } @@ -182,6 +187,14 @@ void cprop(Design*des) /* * $Log: cprop.cc,v $ + * Revision 1.2 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.1 1998/11/13 06:23:17 steve * Introduce netlist optimizations with the * cprop function to do constant propogation. diff --git a/design_dump.cc b/design_dump.cc index 51df67b43..a78ee0b89 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.5 1998/12/01 00:42:13 steve Exp $" +#ident "$Id: design_dump.cc,v 1.6 1998/12/02 04:37:13 steve Exp $" #endif /* @@ -75,7 +75,19 @@ void NetNode::dump_node(ostream&o, unsigned ind) const void NetObj::dump_node_pins(ostream&o, unsigned ind) const { for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { - o << setw(ind) << "" << idx << ":"; + o << setw(ind) << "" << idx; + switch (pin(idx).get_dir()) { + case Link::PASSIVE: + o << " p"; + break; + case Link::INPUT: + o << " I"; + break; + case Link::OUTPUT: + o << " O"; + break; + } + o << ":"; unsigned cpin; const NetObj*cur; @@ -392,6 +404,14 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.6 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.5 1998/12/01 00:42:13 steve * Elaborate UDP devices, * Support UDP type attributes, and diff --git a/elaborate.cc b/elaborate.cc index c02f3e8a7..752eb0b4a 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.7 1998/12/01 00:42:14 steve Exp $" +#ident "$Id: elaborate.cc,v 1.8 1998/12/02 04:37:13 steve Exp $" #endif /* @@ -260,6 +260,9 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, const string&path) const net->set_attributes(udp->attributes); for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { + if (pin(idx) == 0) + continue; + NetNet*sig = pin(idx)->elaborate_net(des, path); if (sig == 0) { cerr << "Expression too complicated for elaboration:" @@ -729,6 +732,14 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.8 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.7 1998/12/01 00:42:14 steve * Elaborate UDP devices, * Support UDP type attributes, and diff --git a/main.cc b/main.cc index c1356bb37..40f11fa96 100644 --- a/main.cc +++ b/main.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: main.cc,v 1.7 1998/12/01 00:42:14 steve Exp $" +#ident "$Id: main.cc,v 1.8 1998/12/02 04:37:13 steve Exp $" #endif # include @@ -63,6 +63,7 @@ extern void emit(ostream&o, const Design*, const char*); extern void cprop(Design*des); extern void sigfold(Design*des); extern void stupid(Design*des); +extern void nobufz(Design*des); typedef void (*net_func)(Design*); static struct net_func_map { @@ -70,6 +71,7 @@ static struct net_func_map { void (*func)(Design*); } func_table[] = { { "cprop", &cprop }, + { "nobufz", &nobufz }, { "sigfold", &sigfold }, { "stupid", &stupid }, { 0, 0 } @@ -227,6 +229,14 @@ int main(int argc, char*argv[]) /* * $Log: main.cc,v $ + * Revision 1.8 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.7 1998/12/01 00:42:14 steve * Elaborate UDP devices, * Support UDP type attributes, and diff --git a/netlist.cc b/netlist.cc index ae0041116..e579cab3a 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.9 1998/12/01 00:42:14 steve Exp $" +#ident "$Id: netlist.cc,v 1.10 1998/12/02 04:37:13 steve Exp $" #endif # include @@ -115,6 +115,36 @@ bool connected(const NetObj&l, const NetObj&r) return true; } +unsigned count_inputs(const NetObj::Link&pin) +{ + unsigned count = (pin.get_dir() == NetObj::Link::INPUT)? 1 : 0; + const NetObj*cur; + unsigned cpin; + pin.next_link(cur, cpin); + while (cur->pin(cpin) != pin) { + if (cur->pin(cpin).get_dir() == NetObj::Link::INPUT) + count += 1; + cur->pin(cpin).next_link(cur, cpin); + } + + return count; +} + +unsigned count_outputs(const NetObj::Link&pin) +{ + unsigned count = (pin.get_dir() == NetObj::Link::OUTPUT)? 1 : 0; + const NetObj*cur; + unsigned cpin; + pin.next_link(cur, cpin); + while (cur->pin(cpin) != pin) { + if (cur->pin(cpin).get_dir() == NetObj::Link::OUTPUT) + count += 1; + cur->pin(cpin).next_link(cur, cpin); + } + + return count; +} + const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx) { const NetObj*cur; @@ -163,6 +193,23 @@ string NetObj::attribute(const string&key) const return (*idx).second; } +bool NetObj::has_compat_attributes(const NetObj&that) const +{ + map::const_iterator idx; + for (idx = that.attributes_.begin() + ; idx != that.attributes_.end() ; idx ++) { + map::const_iterator cur; + cur = attributes_.find((*idx).first); + + if (cur == attributes_.end()) + return false; + if ((*cur).second != (*idx).second) + return false; + } + + return true; +} + NetNode::~NetNode() { if (design_) @@ -344,6 +391,22 @@ void NetEUnary::set_width(unsigned w) expr_width(w); } +NetLogic::NetLogic(const string&n, unsigned pins, TYPE t) +: NetNode(n, pins), type_(t) +{ + pin(0).set_dir(Link::OUTPUT); + for (unsigned idx = 1 ; idx < pins ; idx += 1) + pin(idx).set_dir(Link::INPUT); +} + +NetUDP::NetUDP(const string&n, unsigned pins) +: NetNode(n, pins) +{ + pin(0).set_dir(Link::OUTPUT); + for (unsigned idx = 1 ; idx < pins ; idx += 1) + pin(idx).set_dir(Link::INPUT); +} + string Design::get_flag(const string&key) const { map::const_iterator tmp = flags_.find(key); @@ -496,6 +559,14 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.10 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.9 1998/12/01 00:42:14 steve * Elaborate UDP devices, * Support UDP type attributes, and diff --git a/netlist.h b/netlist.h index ca997e04c..b893c9310 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.9 1998/12/01 00:42:14 steve Exp $" +#ident "$Id: netlist.h,v 1.10 1998/12/02 04:37:13 steve Exp $" #endif /* @@ -49,6 +49,10 @@ struct target; * The web of nodes that makes up a circuit is held together by the * Link class. There is a link for each pin. All mutually connected * pins form a ring of links. + * + * A link can be INPUT, OUTPUT or PASSIVE. An input never drives the + * signal, and PASSIVE never receives the value of the signal. Wires + * are PASSIVE, for example. */ class NetObj { @@ -58,9 +62,14 @@ class NetObj { friend class NetObj; public: - Link() : next_(this), prev_(this) { } + enum DIR { PASSIVE, INPUT, OUTPUT }; + Link() : dir_(PASSIVE), next_(this), prev_(this) { } ~Link() { unlink(); } + // Manipulate the link direction. + void set_dir(DIR d) { dir_ = d; } + DIR get_dir() const { return dir_; } + void cur_link(NetObj*&net, unsigned &pin) { net = node_; pin = pin_; @@ -101,6 +110,7 @@ class NetObj { // NetNode so that following the links can get me here. NetObj *node_; unsigned pin_; + DIR dir_; private: Link *next_; @@ -130,6 +140,10 @@ class NetObj { void set_attributes(const map&); string attribute(const string&key) const; + // Return true if this has all the attributes in that and they + // all have the same values. + bool has_compat_attributes(const NetObj&that) const; + bool test_mark() const { return mark_; } void set_mark(bool flag=true) { mark_ = flag; } @@ -266,7 +280,10 @@ class NetBUFZ : public NetNode { public: explicit NetBUFZ(const string&n) - : NetNode(n, 2) { } + : NetNode(n, 2) + { pin(0).set_dir(Link::OUTPUT); + pin(1).set_dir(Link::INPUT); + } virtual void dump_node(ostream&, unsigned ind) const; virtual void emit_node(ostream&, struct target_t*) const; @@ -276,7 +293,7 @@ class NetConst : public NetNode { public: explicit NetConst(const string&n, verinum::V v) - : NetNode(n, 1), value_(v) { } + : NetNode(n, 1), value_(v) { pin(0).set_dir(Link::OUTPUT); } verinum::V value() const { return value_; } @@ -288,15 +305,15 @@ class NetConst : public NetNode { }; /* - * This class represents all manner of logic gates. + * This class represents all manner of logic gates. Pin 0 is OUTPUT and + * all the remaining pins are INPUT */ class NetLogic : public NetNode { public: enum TYPE { AND, NAND, NOR, NOT, OR, XNOR, XOR }; - explicit NetLogic(const string&n, unsigned pins, TYPE t) - : NetNode(n, pins), type_(t) { } + explicit NetLogic(const string&n, unsigned pins, TYPE t); TYPE type() const { return type_; } @@ -315,9 +332,7 @@ class NetLogic : public NetNode { class NetUDP : public NetNode { public: - explicit NetUDP(const string&n, unsigned pins) - : NetNode(n, pins) { } - + explicit NetUDP(const string&n, unsigned pins); virtual void emit_node(ostream&, struct target_t*) const; virtual void dump_node(ostream&, unsigned ind) const; @@ -752,6 +767,7 @@ inline bool operator != (const NetObj::Link&l, const NetObj::Link&r) connected to other things, connect is transitive. */ extern void connect(NetObj::Link&, NetObj::Link&); +/* Return true if l and r are connected. */ inline bool connected(const NetObj::Link&l, const NetObj::Link&r) { return l.is_linked(r); } @@ -760,6 +776,9 @@ inline bool connected(const NetObj::Link&l, const NetObj::Link&r) checking signal vectors. */ extern bool connected(const NetObj&l, const NetObj&r); +extern unsigned count_inputs(const NetObj::Link&pin); +extern unsigned count_outputs(const NetObj::Link&pin); + /* Find the signal connected to the given node pin. There should always be exactly one signal. The bidx parameter get filled with the signal index of the Net, in case it is a vector. */ @@ -773,6 +792,14 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.10 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.9 1998/12/01 00:42:14 steve * Elaborate UDP devices, * Support UDP type attributes, and diff --git a/nobufz.cc b/nobufz.cc new file mode 100644 index 000000000..67f35ab46 --- /dev/null +++ b/nobufz.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1998 Stephen Williams (steve@picturel.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: nobufz.cc,v 1.1 1998/12/02 04:37:13 steve Exp $" +#endif + +/* NOBUFZ Function + * This function transforms the netlist by removing BUFZ nodes that + * have no obvious effect. The assumption here is that the BUFZ node + * transmits information perfectly in one direction, and not at all in + * the other. + * + * A BUFZ will *not* be eliminated if the output link is connected to + * other outputs. The BUFZ protects its input link from the + * double-driving on its output, so the bufz is not meaningless and + * cannot be removed. + */ + +# include "netlist.h" +# include + +static bool is_a_bufz_node(const NetNode*obj) +{ + return dynamic_cast(obj); +} + +void nobufz(Design*des) +{ + des->clear_node_marks(); + while (NetNode*obj = des->find_node(&is_a_bufz_node)) { + NetBUFZ*cur = dynamic_cast(obj); + assert(cur); + + /* If there are more output pins on the output size of + the BUFZ, then the BUFZ has a real effect (it + protects its input side) and cannot be eliminated. */ + if (count_outputs(cur->pin(0)) == 1) { + connect(cur->pin(0), cur->pin(1)); + delete cur; + } else { + cur->set_mark(); + } + } +} + +/* + * $Log: nobufz.cc,v $ + * Revision 1.1 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * + */ + diff --git a/sigfold.cc b/sigfold.cc index 86a14a304..00cd57956 100644 --- a/sigfold.cc +++ b/sigfold.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: sigfold.cc,v 1.1 1998/11/16 05:03:53 steve Exp $" +#ident "$Id: sigfold.cc,v 1.2 1998/12/02 04:37:13 steve Exp $" #endif # include "netlist.h" @@ -39,6 +39,17 @@ * The result of this should be that signals of enclosing modules will * be preferred over signals of instantiated modules, and bussed * signals (vectors) will be preferred over scaler signals. + * + * The presence of attributes modifies the folding process, by placing + * restrictions on what is allowed. + * + * If two signals have an attribute key X, they can be folded + * only if X has the same value for both signals. + * + * If signal A has attribute X and signal B does not, then + * signals can be folded if B can take the attribute. + * + * All the pins in a vector have identical attributes. */ static unsigned depth(const string&sym) @@ -63,18 +74,49 @@ static void clear_extra_signals(NetNet*net, unsigned npin) unsigned pin = npin; for (net->pin(pin).next_link(cur, pin) ; cur != net ; ) { + // sig is the node I am going to try to subsume. NetNet*sig = dynamic_cast(cur); - if ((sig == 0) - || (depth(sig->name()) < mydepth) - || (sig->pin_count() > net->pin_count())) { + + // Skip the node if it isn't even a signal. + if (sig == 0) { cur->pin(pin).next_link(cur, pin); continue; } + // Skip the node if it has incompatible attributes. + if (! net->has_compat_attributes(*sig)) { + + // SPECIAL CASE! + if (sig->has_compat_attributes(*net)) { + net->pin(npin).unlink(); + return; + } + + cur->pin(pin).next_link(cur, pin); + continue; + } + + // Skip the node if it is higher up. + if (depth(sig->name()) < mydepth) { + cur->pin(pin).next_link(cur, pin); + continue; + } + + // Skip the node if it is a larger vector. + if (sig->pin_count() > net->pin_count()) { + cur->pin(pin).next_link(cur, pin); + continue; + } + + // save the next link, ... NetObj*nxt; unsigned pnxt; cur->pin(pin).next_link(nxt, pnxt); + + // disconnect the target signal, ... sig->pin(pin).unlink(); + + // And onward. cur = nxt; pin = pnxt; } @@ -110,6 +152,14 @@ void sigfold(Design*des) /* * $Log: sigfold.cc,v $ + * Revision 1.2 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.1 1998/11/16 05:03:53 steve * Add the sigfold function that unlinks excess * signal nodes, and add the XNF target. diff --git a/t-xnf.cc b/t-xnf.cc index 9a6e08e6f..5120b73f9 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.3 1998/11/23 00:20:24 steve Exp $" +#ident "$Id: t-xnf.cc,v 1.4 1998/12/02 04:37:13 steve Exp $" #endif /* XNF BACKEND @@ -31,7 +31,24 @@ * part= * Specify the part type. The part string is written into the * PART record. Valid types are defined by Xilinx or the - * receiving tools + * receiving tools. + * + * WIRE ATTRIBUTES + * + * PAD = + * Tell the XNF generator that this wire goes to a PAD. The + * is a single character that tells the direction, and is the + * pin number. For example, "o31" is output on pin 31. The PAD + * attribute is not practically connected to a vector, as all the + * bits would go to the same pad. + * + * NODE ATTRIBUTES + * + * XNF-LCA = :,... + * Specify the LCA library part type for the UDP node. The lname + * is the name of the symbol to use (i.e. DFF) and the comma + * seperated list is the names of the pins, in the order they + * appear in the verilog source. */ # include "netlist.h" @@ -44,9 +61,12 @@ class target_xnf : public target_t { void end_design(ostream&os, const Design*); void signal(ostream&os, const NetNet*); void logic(ostream&os, const NetLogic*); + void udp(ostream&os, const NetUDP*); private: static string mangle(const string&); + static void draw_pin(ostream&os, const string&name, char type, + const NetObj::Link&lnk); }; /* @@ -69,6 +89,27 @@ string target_xnf::mangle(const string&name) return result; } +void target_xnf::draw_pin(ostream&os, const string&name, char type, + const NetObj::Link&lnk) +{ + unsigned cpin; + const NetObj*cur; + for (lnk.next_link(cur, cpin) + ; cur->pin(cpin) != lnk + ; cur->pin(cpin).next_link(cur, cpin)) { + + const NetNet*sig = dynamic_cast(cur); + if (sig) { + os << " PIN, " << name << ", " << type << ", " + << mangle(sig->name()); + if (sig->pin_count() > 1) + os << "<" << cpin << ">"; + + os << endl; + } + } +} + void target_xnf::start_design(ostream&os, const Design*des) { @@ -82,11 +123,13 @@ void target_xnf::end_design(ostream&os, const Design*) os << "EOF" << endl; } -void scrape_pad_info(string&str, char&dir, unsigned&num) +void scrape_pad_info(string str, char&dir, unsigned&num) { + // Get rid of leading white space while (str[0] == ' ') str = str.substr(1); + // Get the direction letter switch (str[0]) { case 'b': case 'B': @@ -109,6 +152,7 @@ void scrape_pad_info(string&str, char&dir, unsigned&num) break; } + // Get the number part. str = str.substr(1); unsigned val = 0; while (str.size() && isdigit(str[0])) { @@ -116,13 +160,6 @@ void scrape_pad_info(string&str, char&dir, unsigned&num) str = str.substr(1); } num = val; - - while (str.size() && str[0] == ' ') - str = str.substr(1); - - if (str.size() && str[0] == ',') - str = str.substr(1); - } /* @@ -139,24 +176,20 @@ void scrape_pad_info(string&str, char&dir, unsigned&num) void target_xnf::signal(ostream&os, const NetNet*net) { string pad = net->attribute("PAD"); - if (pad != "") { + if (pad == "") + return; - if (net->pin_count() == 1) { - char dir; - unsigned num; - scrape_pad_info(pad, dir, num); - os << "EXT, " << mangle(net->name()) << ", " << dir - << ", " << num << endl; - - } else for (unsigned idx = net->pin_count(); idx > 0; idx -= 1) { - - char dir; - unsigned num; - scrape_pad_info(pad, dir, num); - os << "EXT, " << mangle(net->name()) << "<" << (idx-1) - << ">, " << dir << ", " << num << endl; - } + if (net->pin_count() > 1) { + cerr << "Signal ``" << net->name() << "'' with PAD=" << + pad << " is a vector." << endl; + return; } + + char dir; + unsigned num; + scrape_pad_info(pad, dir, num); + os << "EXT, " << mangle(net->name()) << ", " << dir + << ", " << num << endl; } /* @@ -188,45 +221,66 @@ void target_xnf::logic(ostream&os, const NetLogic*net) case NetLogic::XOR: os << "XOR"; break; + default: + cerr << "XNF: Unhandled logic type." << endl; + break; } os << ", LIBVER=2.0.0" << endl; - for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { - unsigned cpin; - const NetObj*cur; - for (net->pin(idx).next_link(cur, cpin) - ; (cur != net) || (cpin != idx) - ; cur->pin(cpin).next_link(cur, cpin)) { - - const NetNet*sig = dynamic_cast(cur); - if (sig) { - os << " PIN, "; - if (idx == 0) { - os << "O, O, "; - } else { - os << "I"; - if (net->pin_count() > 2) - os << idx-1; - os << ", I, "; - } - os << mangle(sig->name()); - if (sig->pin_count() > 1) - os << "<" << cpin << ">"; - - os << endl; - } - } + draw_pin(os, "O", 'O', net->pin(0)); + for (unsigned idx = 1 ; idx < net->pin_count() ; idx += 1) { + string name = "I"; + assert(net->pin_count() <= 11); + name += (char)('0'+idx-1); + draw_pin(os, name, 'I', net->pin(idx)); } os << "END" << endl; } +static string scrape_pin_name(string&list) +{ + unsigned idx = list.find(','); + string name = list.substr(0, idx); + list = list.substr(idx+1); + return name; +} + +void target_xnf::udp(ostream&os, const NetUDP*net) +{ + string lca = net->attribute("XNF-LCA"); + if (lca == "") { + cerr << "I don't understand this UDP." << endl; + return; + } + + unsigned idx = lca.find(':'); + string lcaname = lca.substr(0, idx); + lca = lca.substr(idx+1); + + os << "SYM, " << mangle(net->name()) << ", " << lcaname + << ", LIBVER=2.0.0" << endl; + draw_pin(os, scrape_pin_name(lca), 'O', net->pin(0)); + for (idx = 1 ; idx < net->pin_count() ; idx += 1) { + draw_pin(os, scrape_pin_name(lca), 'I', net->pin(idx)); + } + os << "END" << endl; +} + static target_xnf target_xnf_obj; extern const struct target tgt_xnf = { "xnf", &target_xnf_obj }; /* * $Log: t-xnf.cc,v $ + * Revision 1.4 1998/12/02 04:37:13 steve + * Add the nobufz function to eliminate bufz objects, + * Object links are marked with direction, + * constant propagation is more careful will wide links, + * Signal folding is aware of attributes, and + * the XNF target can dump UDP objects based on LCA + * attributes. + * * Revision 1.3 1998/11/23 00:20:24 steve * NetAssign handles lvalues as pin links * instead of a signal pointer,