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.
This commit is contained in:
parent
e097c999d5
commit
ada45acb0c
5
Makefile
5
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
|
||||
|
|
|
|||
43
cprop.cc
43
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<NetNet*>(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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
13
elaborate.cc
13
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<string,Module*>&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
|
||||
|
|
|
|||
12
main.cc
12
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 <stdio.h>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
73
netlist.cc
73
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 <cassert>
|
||||
|
|
@ -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<string,string>::const_iterator idx;
|
||||
for (idx = that.attributes_.begin()
|
||||
; idx != that.attributes_.end() ; idx ++) {
|
||||
map<string,string>::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<string,string>::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
|
||||
|
|
|
|||
47
netlist.h
47
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,string>&);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 <assert.h>
|
||||
|
||||
static bool is_a_bufz_node(const NetNode*obj)
|
||||
{
|
||||
return dynamic_cast<const NetBUFZ*>(obj);
|
||||
}
|
||||
|
||||
void nobufz(Design*des)
|
||||
{
|
||||
des->clear_node_marks();
|
||||
while (NetNode*obj = des->find_node(&is_a_bufz_node)) {
|
||||
NetBUFZ*cur = dynamic_cast<NetBUFZ*>(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.
|
||||
*
|
||||
*/
|
||||
|
||||
58
sigfold.cc
58
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<NetNet*>(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.
|
||||
|
|
|
|||
156
t-xnf.cc
156
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=<foo>
|
||||
* 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 = <io><n>
|
||||
* Tell the XNF generator that this wire goes to a PAD. The <io>
|
||||
* is a single character that tells the direction, and <n> 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 = <lname>:<pin>,<pin>...
|
||||
* 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<const NetNet*>(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<const NetNet*>(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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue