Generate OBUF or IBUF attributes (and the gates
to garry them) where a wire is a pad. This involved figuring out enough of the netlist to know when such was needed, and to generate new gates and signales to handle what's missing.
This commit is contained in:
parent
ada45acb0c
commit
9a73433759
2
Makefile
2
Makefile
|
|
@ -7,7 +7,7 @@ CXXFLAGS = -O -g -Wall -Wno-uninitialized
|
||||||
|
|
||||||
#TT = t-debug.o t-vvm.o
|
#TT = t-debug.o t-vvm.o
|
||||||
TT = t-verilog.o t-vvm.o t-xnf.o
|
TT = t-verilog.o t-vvm.o t-xnf.o
|
||||||
FF = nobufz.o sigfold.o stupid.o
|
FF = nobufz.o sigfold.o stupid.o xnfio.o
|
||||||
|
|
||||||
O = main.o cprop.o design_dump.o elaborate.o emit.o eval.o lexor.o mangle.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 verinum.o target.o \
|
netlist.o parse.o parse_misc.o pform.o pform_dump.o verinum.o target.o \
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,10 @@ not part of a type attribute.
|
||||||
|
|
||||||
Currently, type attributes are only supported for UDP types.
|
Currently, type attributes are only supported for UDP types.
|
||||||
|
|
||||||
|
Note that attributes are also occasionally used for communication
|
||||||
|
between processing steps. Processing steps that are aware of others
|
||||||
|
may place attributes on netlist objects to communicate information to
|
||||||
|
later steps.
|
||||||
|
|
||||||
HOW IT WORKS -- STAGES OF PROCESSING
|
HOW IT WORKS -- STAGES OF PROCESSING
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: design_dump.cc,v 1.6 1998/12/02 04:37:13 steve Exp $"
|
#ident "$Id: design_dump.cc,v 1.7 1998/12/07 04:53:17 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -137,6 +137,9 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||||
case AND:
|
case AND:
|
||||||
o << "and";
|
o << "and";
|
||||||
break;
|
break;
|
||||||
|
case BUF:
|
||||||
|
o << "buf";
|
||||||
|
break;
|
||||||
case NAND:
|
case NAND:
|
||||||
o << "nand";
|
o << "nand";
|
||||||
break;
|
break;
|
||||||
|
|
@ -404,6 +407,13 @@ void Design::dump(ostream&o) const
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: design_dump.cc,v $
|
* $Log: design_dump.cc,v $
|
||||||
|
* Revision 1.7 1998/12/07 04:53:17 steve
|
||||||
|
* Generate OBUF or IBUF attributes (and the gates
|
||||||
|
* to garry them) where a wire is a pad. This involved
|
||||||
|
* figuring out enough of the netlist to know when such
|
||||||
|
* was needed, and to generate new gates and signales
|
||||||
|
* to handle what's missing.
|
||||||
|
*
|
||||||
* Revision 1.6 1998/12/02 04:37:13 steve
|
* Revision 1.6 1998/12/02 04:37:13 steve
|
||||||
* Add the nobufz function to eliminate bufz objects,
|
* Add the nobufz function to eliminate bufz objects,
|
||||||
* Object links are marked with direction,
|
* Object links are marked with direction,
|
||||||
|
|
|
||||||
49
elaborate.cc
49
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: elaborate.cc,v 1.8 1998/12/02 04:37:13 steve Exp $"
|
#ident "$Id: elaborate.cc,v 1.9 1998/12/07 04:53:17 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -32,13 +32,12 @@
|
||||||
# include "pform.h"
|
# include "pform.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
||||||
static string local_symbol(const string&path)
|
string Design::local_symbol(const string&path)
|
||||||
{
|
{
|
||||||
static unsigned counter = 0;
|
|
||||||
string result = "_L";
|
string result = "_L";
|
||||||
|
|
||||||
strstream res;
|
strstream res;
|
||||||
res << "_L" << (counter++) << ends;
|
res << "_L" << (lcounter_++) << ends;
|
||||||
return path + "." + res.str();
|
return path + "." + res.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +75,7 @@ static void do_assign(Design*des, const string&path,
|
||||||
delete lval;
|
delete lval;
|
||||||
|
|
||||||
} else for (unsigned idx = 0 ; idx < pin_count ; idx += 1) {
|
} else for (unsigned idx = 0 ; idx < pin_count ; idx += 1) {
|
||||||
NetBUFZ*cur = new NetBUFZ(local_symbol(path));
|
NetBUFZ*cur = new NetBUFZ(des->local_symbol(path));
|
||||||
|
|
||||||
connect(cur->pin(0), lval->pin(idx));
|
connect(cur->pin(0), lval->pin(idx));
|
||||||
connect(cur->pin(1), rval->pin(idx));
|
connect(cur->pin(1), rval->pin(idx));
|
||||||
|
|
@ -153,12 +152,15 @@ void PGBuiltin::elaborate(Design*des, const string&path) const
|
||||||
NetLogic*cur = 0;
|
NetLogic*cur = 0;
|
||||||
string name = get_name();
|
string name = get_name();
|
||||||
if (name == "")
|
if (name == "")
|
||||||
name = local_symbol(path);
|
name = des->local_symbol(path);
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case AND:
|
case AND:
|
||||||
cur = new NetLogic(name, pin_count(), NetLogic::AND);
|
cur = new NetLogic(name, pin_count(), NetLogic::AND);
|
||||||
break;
|
break;
|
||||||
|
case BUF:
|
||||||
|
cur = new NetLogic(name, pin_count(), NetLogic::BUF);
|
||||||
|
break;
|
||||||
case NAND:
|
case NAND:
|
||||||
cur = new NetLogic(name, pin_count(), NetLogic::NAND);
|
cur = new NetLogic(name, pin_count(), NetLogic::NAND);
|
||||||
break;
|
break;
|
||||||
|
|
@ -206,7 +208,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const
|
||||||
{
|
{
|
||||||
string my_name;
|
string my_name;
|
||||||
if (get_name() == "")
|
if (get_name() == "")
|
||||||
my_name = local_symbol(path);
|
my_name = des->local_symbol(path);
|
||||||
else
|
else
|
||||||
my_name = path + "." + get_name();
|
my_name = path + "." + get_name();
|
||||||
|
|
||||||
|
|
@ -333,10 +335,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path) const
|
||||||
case '^': // XOR
|
case '^': // XOR
|
||||||
assert(lsig->pin_count() == 1);
|
assert(lsig->pin_count() == 1);
|
||||||
assert(rsig->pin_count() == 1);
|
assert(rsig->pin_count() == 1);
|
||||||
gate = new NetLogic(local_symbol(path), 3, NetLogic::XOR);
|
gate = new NetLogic(des->local_symbol(path), 3, NetLogic::XOR);
|
||||||
connect(gate->pin(1), lsig->pin(0));
|
connect(gate->pin(1), lsig->pin(0));
|
||||||
connect(gate->pin(2), rsig->pin(0));
|
connect(gate->pin(2), rsig->pin(0));
|
||||||
osig = new NetNet(local_symbol(path), NetNet::WIRE);
|
osig = new NetNet(des->local_symbol(path), NetNet::WIRE);
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
connect(gate->pin(0), osig->pin(0));
|
connect(gate->pin(0), osig->pin(0));
|
||||||
des->add_signal(osig);
|
des->add_signal(osig);
|
||||||
|
|
@ -346,10 +348,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path) const
|
||||||
case '&': // AND
|
case '&': // AND
|
||||||
assert(lsig->pin_count() == 1);
|
assert(lsig->pin_count() == 1);
|
||||||
assert(rsig->pin_count() == 1);
|
assert(rsig->pin_count() == 1);
|
||||||
gate = new NetLogic(local_symbol(path), 3, NetLogic::AND);
|
gate = new NetLogic(des->local_symbol(path), 3, NetLogic::AND);
|
||||||
connect(gate->pin(1), lsig->pin(0));
|
connect(gate->pin(1), lsig->pin(0));
|
||||||
connect(gate->pin(2), rsig->pin(0));
|
connect(gate->pin(2), rsig->pin(0));
|
||||||
osig = new NetNet(local_symbol(path), NetNet::WIRE);
|
osig = new NetNet(des->local_symbol(path), NetNet::WIRE);
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
connect(gate->pin(0), osig->pin(0));
|
connect(gate->pin(0), osig->pin(0));
|
||||||
des->add_signal(osig);
|
des->add_signal(osig);
|
||||||
|
|
@ -359,10 +361,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path) const
|
||||||
case 'e': // ==
|
case 'e': // ==
|
||||||
assert(lsig->pin_count() == 1);
|
assert(lsig->pin_count() == 1);
|
||||||
assert(rsig->pin_count() == 1);
|
assert(rsig->pin_count() == 1);
|
||||||
gate = new NetLogic(local_symbol(path), 3, NetLogic::XNOR);
|
gate = new NetLogic(des->local_symbol(path), 3, NetLogic::XNOR);
|
||||||
connect(gate->pin(1), lsig->pin(0));
|
connect(gate->pin(1), lsig->pin(0));
|
||||||
connect(gate->pin(2), rsig->pin(0));
|
connect(gate->pin(2), rsig->pin(0));
|
||||||
osig = new NetNet(local_symbol(path), NetNet::WIRE);
|
osig = new NetNet(des->local_symbol(path), NetNet::WIRE);
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
connect(gate->pin(0), osig->pin(0));
|
connect(gate->pin(0), osig->pin(0));
|
||||||
des->add_signal(osig);
|
des->add_signal(osig);
|
||||||
|
|
@ -427,9 +429,9 @@ NetNet* PEIdent::elaborate_net(Design*des, const string&path) const
|
||||||
*/
|
*/
|
||||||
NetNet* PENumber::elaborate_net(Design*des, const string&path) const
|
NetNet* PENumber::elaborate_net(Design*des, const string&path) const
|
||||||
{
|
{
|
||||||
NetNet*net = new NetNet(local_symbol(path), NetNet::IMPLICIT);
|
NetNet*net = new NetNet(des->local_symbol(path), NetNet::IMPLICIT);
|
||||||
net->local_flag(true);
|
net->local_flag(true);
|
||||||
NetConst*tmp = new NetConst(local_symbol(path), value_->get(0));
|
NetConst*tmp = new NetConst(des->local_symbol(path), value_->get(0));
|
||||||
des->add_node(tmp);
|
des->add_node(tmp);
|
||||||
des->add_signal(net);
|
des->add_signal(net);
|
||||||
connect(net->pin(0), tmp->pin(0));
|
connect(net->pin(0), tmp->pin(0));
|
||||||
|
|
@ -446,9 +448,9 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path) const
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case '~': // Bitwise NOT
|
case '~': // Bitwise NOT
|
||||||
assert(sub_sig->pin_count() == 1);
|
assert(sub_sig->pin_count() == 1);
|
||||||
sig = new NetNet(local_symbol(path), NetNet::WIRE);
|
sig = new NetNet(des->local_symbol(path), NetNet::WIRE);
|
||||||
sig->local_flag(true);
|
sig->local_flag(true);
|
||||||
gate = new NetLogic(local_symbol(path), 2, NetLogic::NOT);
|
gate = new NetLogic(des->local_symbol(path), 2, NetLogic::NOT);
|
||||||
connect(gate->pin(0), sig->pin(0));
|
connect(gate->pin(0), sig->pin(0));
|
||||||
connect(gate->pin(1), sub_sig->pin(0));
|
connect(gate->pin(1), sub_sig->pin(0));
|
||||||
des->add_signal(sig);
|
des->add_signal(sig);
|
||||||
|
|
@ -456,9 +458,9 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '&': // Reduction AND
|
case '&': // Reduction AND
|
||||||
sig = new NetNet(local_symbol(path), NetNet::WIRE);
|
sig = new NetNet(des->local_symbol(path), NetNet::WIRE);
|
||||||
sig->local_flag(true);
|
sig->local_flag(true);
|
||||||
gate = new NetLogic(local_symbol(path),
|
gate = new NetLogic(des->local_symbol(path),
|
||||||
1+sub_sig->pin_count(),
|
1+sub_sig->pin_count(),
|
||||||
NetLogic::AND);
|
NetLogic::AND);
|
||||||
connect(gate->pin(0), sig->pin(0));
|
connect(gate->pin(0), sig->pin(0));
|
||||||
|
|
@ -598,7 +600,7 @@ NetProc* PDelayStatement::elaborate(Design*des, const string&path) const
|
||||||
NetProc* PEventStatement::elaborate(Design*des, const string&path) const
|
NetProc* PEventStatement::elaborate(Design*des, const string&path) const
|
||||||
{
|
{
|
||||||
NetProc*enet = statement_->elaborate(des, path);
|
NetProc*enet = statement_->elaborate(des, path);
|
||||||
NetPEvent*ev = new NetPEvent(local_symbol(path), type_, enet);
|
NetPEvent*ev = new NetPEvent(des->local_symbol(path), type_, enet);
|
||||||
|
|
||||||
NetNet*expr = expr_->elaborate_net(des, path);
|
NetNet*expr = expr_->elaborate_net(des, path);
|
||||||
if (expr == 0) {
|
if (expr == 0) {
|
||||||
|
|
@ -732,6 +734,13 @@ Design* elaborate(const map<string,Module*>&modules,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: elaborate.cc,v $
|
* $Log: elaborate.cc,v $
|
||||||
|
* Revision 1.9 1998/12/07 04:53:17 steve
|
||||||
|
* Generate OBUF or IBUF attributes (and the gates
|
||||||
|
* to garry them) where a wire is a pad. This involved
|
||||||
|
* figuring out enough of the netlist to know when such
|
||||||
|
* was needed, and to generate new gates and signales
|
||||||
|
* to handle what's missing.
|
||||||
|
*
|
||||||
* Revision 1.8 1998/12/02 04:37:13 steve
|
* Revision 1.8 1998/12/02 04:37:13 steve
|
||||||
* Add the nobufz function to eliminate bufz objects,
|
* Add the nobufz function to eliminate bufz objects,
|
||||||
* Object links are marked with direction,
|
* Object links are marked with direction,
|
||||||
|
|
|
||||||
11
main.cc
11
main.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: main.cc,v 1.8 1998/12/02 04:37:13 steve Exp $"
|
#ident "$Id: main.cc,v 1.9 1998/12/07 04:53:17 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
@ -64,6 +64,7 @@ extern void cprop(Design*des);
|
||||||
extern void sigfold(Design*des);
|
extern void sigfold(Design*des);
|
||||||
extern void stupid(Design*des);
|
extern void stupid(Design*des);
|
||||||
extern void nobufz(Design*des);
|
extern void nobufz(Design*des);
|
||||||
|
extern void xnfio(Design*des);
|
||||||
|
|
||||||
typedef void (*net_func)(Design*);
|
typedef void (*net_func)(Design*);
|
||||||
static struct net_func_map {
|
static struct net_func_map {
|
||||||
|
|
@ -74,6 +75,7 @@ static struct net_func_map {
|
||||||
{ "nobufz", &nobufz },
|
{ "nobufz", &nobufz },
|
||||||
{ "sigfold", &sigfold },
|
{ "sigfold", &sigfold },
|
||||||
{ "stupid", &stupid },
|
{ "stupid", &stupid },
|
||||||
|
{ "xnfio", &xnfio },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -229,6 +231,13 @@ int main(int argc, char*argv[])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: main.cc,v $
|
* $Log: main.cc,v $
|
||||||
|
* Revision 1.9 1998/12/07 04:53:17 steve
|
||||||
|
* Generate OBUF or IBUF attributes (and the gates
|
||||||
|
* to garry them) where a wire is a pad. This involved
|
||||||
|
* figuring out enough of the netlist to know when such
|
||||||
|
* was needed, and to generate new gates and signales
|
||||||
|
* to handle what's missing.
|
||||||
|
*
|
||||||
* Revision 1.8 1998/12/02 04:37:13 steve
|
* Revision 1.8 1998/12/02 04:37:13 steve
|
||||||
* Add the nobufz function to eliminate bufz objects,
|
* Add the nobufz function to eliminate bufz objects,
|
||||||
* Object links are marked with direction,
|
* Object links are marked with direction,
|
||||||
|
|
|
||||||
33
netlist.cc
33
netlist.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: netlist.cc,v 1.10 1998/12/02 04:37:13 steve Exp $"
|
#ident "$Id: netlist.cc,v 1.11 1998/12/07 04:53:17 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
@ -145,6 +145,25 @@ unsigned count_outputs(const NetObj::Link&pin)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned count_signals(const NetObj::Link&pin)
|
||||||
|
{
|
||||||
|
unsigned count = 0;
|
||||||
|
if (dynamic_cast<const NetNet*>(pin.get_obj()))
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
const NetObj*cur;
|
||||||
|
unsigned cpin;
|
||||||
|
pin.next_link(cur, cpin);
|
||||||
|
while (cur->pin(cpin) != pin) {
|
||||||
|
if (dynamic_cast<const NetNet*>(cur))
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
cur->pin(cpin).next_link(cur, cpin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
|
const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
|
||||||
{
|
{
|
||||||
const NetObj*cur;
|
const NetObj*cur;
|
||||||
|
|
@ -193,6 +212,11 @@ string NetObj::attribute(const string&key) const
|
||||||
return (*idx).second;
|
return (*idx).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetObj::attribute(const string&key, const string&value)
|
||||||
|
{
|
||||||
|
attributes_[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
bool NetObj::has_compat_attributes(const NetObj&that) const
|
bool NetObj::has_compat_attributes(const NetObj&that) const
|
||||||
{
|
{
|
||||||
map<string,string>::const_iterator idx;
|
map<string,string>::const_iterator idx;
|
||||||
|
|
@ -559,6 +583,13 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.cc,v $
|
* $Log: netlist.cc,v $
|
||||||
|
* Revision 1.11 1998/12/07 04:53:17 steve
|
||||||
|
* Generate OBUF or IBUF attributes (and the gates
|
||||||
|
* to garry them) where a wire is a pad. This involved
|
||||||
|
* figuring out enough of the netlist to know when such
|
||||||
|
* was needed, and to generate new gates and signales
|
||||||
|
* to handle what's missing.
|
||||||
|
*
|
||||||
* Revision 1.10 1998/12/02 04:37:13 steve
|
* Revision 1.10 1998/12/02 04:37:13 steve
|
||||||
* Add the nobufz function to eliminate bufz objects,
|
* Add the nobufz function to eliminate bufz objects,
|
||||||
* Object links are marked with direction,
|
* Object links are marked with direction,
|
||||||
|
|
|
||||||
32
netlist.h
32
netlist.h
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: netlist.h,v 1.10 1998/12/02 04:37:13 steve Exp $"
|
#ident "$Id: netlist.h,v 1.11 1998/12/07 04:53:17 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -85,6 +85,9 @@ class NetObj {
|
||||||
pin = next_->pin_;
|
pin = next_->pin_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Link* next_link() { return next_; }
|
||||||
|
const Link* next_link() const { return next_; }
|
||||||
|
|
||||||
// Remove this link from the set of connected pins. The
|
// Remove this link from the set of connected pins. The
|
||||||
// destructor will automatically do this if needed.
|
// destructor will automatically do this if needed.
|
||||||
void unlink()
|
void unlink()
|
||||||
|
|
@ -105,6 +108,12 @@ class NetObj {
|
||||||
bool is_equal(const NetObj::Link&that) const
|
bool is_equal(const NetObj::Link&that) const
|
||||||
{ return (node_ == that.node_) && (pin_ == that.pin_); }
|
{ return (node_ == that.node_) && (pin_ == that.pin_); }
|
||||||
|
|
||||||
|
// Return information about the object that this link is
|
||||||
|
// a part of.
|
||||||
|
const NetObj*get_obj() const { return node_; }
|
||||||
|
NetObj*get_obj() { return node_; }
|
||||||
|
unsigned get_pin() const { return pin_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The NetNode manages these. They point back to the
|
// The NetNode manages these. They point back to the
|
||||||
// NetNode so that following the links can get me here.
|
// NetNode so that following the links can get me here.
|
||||||
|
|
@ -139,6 +148,7 @@ class NetObj {
|
||||||
|
|
||||||
void set_attributes(const map<string,string>&);
|
void set_attributes(const map<string,string>&);
|
||||||
string attribute(const string&key) const;
|
string attribute(const string&key) const;
|
||||||
|
void attribute(const string&key, const string&value);
|
||||||
|
|
||||||
// Return true if this has all the attributes in that and they
|
// Return true if this has all the attributes in that and they
|
||||||
// all have the same values.
|
// all have the same values.
|
||||||
|
|
@ -311,7 +321,7 @@ class NetConst : public NetNode {
|
||||||
class NetLogic : public NetNode {
|
class NetLogic : public NetNode {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum TYPE { AND, NAND, NOR, NOT, OR, XNOR, XOR };
|
enum TYPE { AND, BUF, NAND, NOR, NOT, OR, XNOR, XOR };
|
||||||
|
|
||||||
explicit NetLogic(const string&n, unsigned pins, TYPE t);
|
explicit NetLogic(const string&n, unsigned pins, TYPE t);
|
||||||
|
|
||||||
|
|
@ -699,7 +709,7 @@ class NetESignal : public NetExpr {
|
||||||
class Design {
|
class Design {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Design() : signals_(0), nodes_(0), procs_(0) { }
|
Design() : signals_(0), nodes_(0), procs_(0), lcounter_(0) { }
|
||||||
|
|
||||||
/* The flags are a generic way of accepting command line
|
/* The flags are a generic way of accepting command line
|
||||||
parameters/flags and passing them to the processing steps
|
parameters/flags and passing them to the processing steps
|
||||||
|
|
@ -736,6 +746,10 @@ class Design {
|
||||||
void clear_signal_marks();
|
void clear_signal_marks();
|
||||||
NetNet*find_signal(bool (*test)(const NetNet*));
|
NetNet*find_signal(bool (*test)(const NetNet*));
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
string local_symbol(const string&path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// List all the signals in the design.
|
// List all the signals in the design.
|
||||||
NetNet*signals_;
|
NetNet*signals_;
|
||||||
|
|
@ -748,6 +762,8 @@ class Design {
|
||||||
|
|
||||||
map<string,string> flags_;
|
map<string,string> flags_;
|
||||||
|
|
||||||
|
unsigned lcounter_;
|
||||||
|
|
||||||
private: // not implemented
|
private: // not implemented
|
||||||
Design(const Design&);
|
Design(const Design&);
|
||||||
Design& operator= (const Design&);
|
Design& operator= (const Design&);
|
||||||
|
|
@ -776,8 +792,11 @@ inline bool connected(const NetObj::Link&l, const NetObj::Link&r)
|
||||||
checking signal vectors. */
|
checking signal vectors. */
|
||||||
extern bool connected(const NetObj&l, const NetObj&r);
|
extern bool connected(const NetObj&l, const NetObj&r);
|
||||||
|
|
||||||
|
/* return the number of links in the ring that are of the specified
|
||||||
|
type. */
|
||||||
extern unsigned count_inputs(const NetObj::Link&pin);
|
extern unsigned count_inputs(const NetObj::Link&pin);
|
||||||
extern unsigned count_outputs(const NetObj::Link&pin);
|
extern unsigned count_outputs(const NetObj::Link&pin);
|
||||||
|
extern unsigned count_signals(const NetObj::Link&pin);
|
||||||
|
|
||||||
/* Find the signal connected to the given node pin. There should
|
/* Find the signal connected to the given node pin. There should
|
||||||
always be exactly one signal. The bidx parameter get filled with
|
always be exactly one signal. The bidx parameter get filled with
|
||||||
|
|
@ -792,6 +811,13 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.h,v $
|
* $Log: netlist.h,v $
|
||||||
|
* Revision 1.11 1998/12/07 04:53:17 steve
|
||||||
|
* Generate OBUF or IBUF attributes (and the gates
|
||||||
|
* to garry them) where a wire is a pad. This involved
|
||||||
|
* figuring out enough of the netlist to know when such
|
||||||
|
* was needed, and to generate new gates and signales
|
||||||
|
* to handle what's missing.
|
||||||
|
*
|
||||||
* Revision 1.10 1998/12/02 04:37:13 steve
|
* Revision 1.10 1998/12/02 04:37:13 steve
|
||||||
* Add the nobufz function to eliminate bufz objects,
|
* Add the nobufz function to eliminate bufz objects,
|
||||||
* Object links are marked with direction,
|
* Object links are marked with direction,
|
||||||
|
|
|
||||||
122
t-xnf.cc
122
t-xnf.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#if !defined(WINNT)
|
||||||
#ident "$Id: t-xnf.cc,v 1.4 1998/12/02 04:37:13 steve Exp $"
|
#ident "$Id: t-xnf.cc,v 1.5 1998/12/07 04:53:17 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* XNF BACKEND
|
/* XNF BACKEND
|
||||||
|
|
@ -45,10 +45,20 @@
|
||||||
* NODE ATTRIBUTES
|
* NODE ATTRIBUTES
|
||||||
*
|
*
|
||||||
* XNF-LCA = <lname>:<pin>,<pin>...
|
* XNF-LCA = <lname>:<pin>,<pin>...
|
||||||
* Specify the LCA library part type for the UDP node. The lname
|
* Specify the LCA library part type for the gate. The lname
|
||||||
* is the name of the symbol to use (i.e. DFF) and the comma
|
* 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
|
* separated list is the names of the pins, in the order they
|
||||||
* appear in the verilog source.
|
* appear in the verilog source. If the name is prefixed with a
|
||||||
|
* tilde (~) then the pin is inverted, and the proper "INV" token
|
||||||
|
* will be added to the PIN record.
|
||||||
|
*
|
||||||
|
* This attribute can override even the typical generation of
|
||||||
|
* gates that one might naturally expect of the code generator,
|
||||||
|
* but may be used by the optimizers for placing parts.
|
||||||
|
*
|
||||||
|
* An example is "XNF-LCA=OBUF:O,~I". This attribute means that
|
||||||
|
* the object is an OBUF. Pin 0 is called "O", and pin 1 is
|
||||||
|
* called "I". In addition, pin 1 is inverted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
@ -65,8 +75,10 @@ class target_xnf : public target_t {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static string mangle(const string&);
|
static string mangle(const string&);
|
||||||
static void draw_pin(ostream&os, const string&name, char type,
|
static void draw_pin(ostream&os, const string&name,
|
||||||
const NetObj::Link&lnk);
|
const NetObj::Link&lnk);
|
||||||
|
static void draw_sym_with_lcaname(ostream&os, string lca,
|
||||||
|
const NetNode*net);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -89,9 +101,27 @@ string target_xnf::mangle(const string&name)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void target_xnf::draw_pin(ostream&os, const string&name, char type,
|
void target_xnf::draw_pin(ostream&os, const string&name,
|
||||||
const NetObj::Link&lnk)
|
const NetObj::Link&lnk)
|
||||||
{
|
{
|
||||||
|
bool inv = false;
|
||||||
|
string use_name = name;
|
||||||
|
if (use_name[0] == '~') {
|
||||||
|
inv = true;
|
||||||
|
use_name = use_name.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char type;
|
||||||
|
switch (lnk.get_dir()) {
|
||||||
|
case NetObj::Link::INPUT:
|
||||||
|
case NetObj::Link::PASSIVE:
|
||||||
|
type = 'I';
|
||||||
|
break;
|
||||||
|
case NetObj::Link::OUTPUT:
|
||||||
|
type = 'O';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned cpin;
|
unsigned cpin;
|
||||||
const NetObj*cur;
|
const NetObj*cur;
|
||||||
for (lnk.next_link(cur, cpin)
|
for (lnk.next_link(cur, cpin)
|
||||||
|
|
@ -100,16 +130,47 @@ void target_xnf::draw_pin(ostream&os, const string&name, char type,
|
||||||
|
|
||||||
const NetNet*sig = dynamic_cast<const NetNet*>(cur);
|
const NetNet*sig = dynamic_cast<const NetNet*>(cur);
|
||||||
if (sig) {
|
if (sig) {
|
||||||
os << " PIN, " << name << ", " << type << ", "
|
os << " PIN, " << use_name << ", " << type << ", "
|
||||||
<< mangle(sig->name());
|
<< mangle(sig->name());
|
||||||
if (sig->pin_count() > 1)
|
if (sig->pin_count() > 1)
|
||||||
os << "<" << cpin << ">";
|
os << "<" << cpin << ">";
|
||||||
|
|
||||||
|
if (inv)
|
||||||
|
os << ",,INV";
|
||||||
|
|
||||||
os << endl;
|
os << 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method draws an LCA item based on the XNF-LCA attribute
|
||||||
|
* given. The LCA attribute gives enough information to completely
|
||||||
|
* draw the node in XNF, which is pretty handy at this point.
|
||||||
|
*/
|
||||||
|
void target_xnf::draw_sym_with_lcaname(ostream&os, string lca,
|
||||||
|
const NetNode*net)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
for (idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||||
|
draw_pin(os, scrape_pin_name(lca), net->pin(idx));
|
||||||
|
|
||||||
|
os << "END" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void target_xnf::start_design(ostream&os, const Design*des)
|
void target_xnf::start_design(ostream&os, const Design*des)
|
||||||
{
|
{
|
||||||
|
|
@ -198,11 +259,22 @@ void target_xnf::signal(ostream&os, const NetNet*net)
|
||||||
*/
|
*/
|
||||||
void target_xnf::logic(ostream&os, const NetLogic*net)
|
void target_xnf::logic(ostream&os, const NetLogic*net)
|
||||||
{
|
{
|
||||||
|
// The XNF-LCA attribute overrides anything I might guess
|
||||||
|
// about this object.
|
||||||
|
string lca = net->attribute("XNF-LCA");
|
||||||
|
if (lca != "") {
|
||||||
|
draw_sym_with_lcaname(os, lca, net);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
os << "SYM, " << mangle(net->name()) << ", ";
|
os << "SYM, " << mangle(net->name()) << ", ";
|
||||||
switch (net->type()) {
|
switch (net->type()) {
|
||||||
case NetLogic::AND:
|
case NetLogic::AND:
|
||||||
os << "AND";
|
os << "AND";
|
||||||
break;
|
break;
|
||||||
|
case NetLogic::BUF:
|
||||||
|
os << "BUF";
|
||||||
|
break;
|
||||||
case NetLogic::NAND:
|
case NetLogic::NAND:
|
||||||
os << "NAND";
|
os << "NAND";
|
||||||
break;
|
break;
|
||||||
|
|
@ -227,44 +299,29 @@ void target_xnf::logic(ostream&os, const NetLogic*net)
|
||||||
}
|
}
|
||||||
os << ", LIBVER=2.0.0" << endl;
|
os << ", LIBVER=2.0.0" << endl;
|
||||||
|
|
||||||
draw_pin(os, "O", 'O', net->pin(0));
|
draw_pin(os, "O", net->pin(0));
|
||||||
for (unsigned idx = 1 ; idx < net->pin_count() ; idx += 1) {
|
for (unsigned idx = 1 ; idx < net->pin_count() ; idx += 1) {
|
||||||
string name = "I";
|
string name = "I";
|
||||||
assert(net->pin_count() <= 11);
|
assert(net->pin_count() <= 11);
|
||||||
name += (char)('0'+idx-1);
|
name += (char)('0'+idx-1);
|
||||||
draw_pin(os, name, 'I', net->pin(idx));
|
draw_pin(os, name, net->pin(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
os << "END" << endl;
|
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)
|
void target_xnf::udp(ostream&os, const NetUDP*net)
|
||||||
{
|
{
|
||||||
string lca = net->attribute("XNF-LCA");
|
string lca = net->attribute("XNF-LCA");
|
||||||
|
|
||||||
|
// I only know how to draw a UDP if it has the XNF-LCA
|
||||||
|
// attribute attached to it.
|
||||||
if (lca == "") {
|
if (lca == "") {
|
||||||
cerr << "I don't understand this UDP." << endl;
|
cerr << "I don't understand this UDP." << endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned idx = lca.find(':');
|
draw_sym_with_lcaname(os, lca, net);
|
||||||
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;
|
static target_xnf target_xnf_obj;
|
||||||
|
|
@ -273,6 +330,13 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: t-xnf.cc,v $
|
* $Log: t-xnf.cc,v $
|
||||||
|
* Revision 1.5 1998/12/07 04:53:17 steve
|
||||||
|
* Generate OBUF or IBUF attributes (and the gates
|
||||||
|
* to garry them) where a wire is a pad. This involved
|
||||||
|
* figuring out enough of the netlist to know when such
|
||||||
|
* was needed, and to generate new gates and signales
|
||||||
|
* to handle what's missing.
|
||||||
|
*
|
||||||
* Revision 1.4 1998/12/02 04:37:13 steve
|
* Revision 1.4 1998/12/02 04:37:13 steve
|
||||||
* Add the nobufz function to eliminate bufz objects,
|
* Add the nobufz function to eliminate bufz objects,
|
||||||
* Object links are marked with direction,
|
* Object links are marked with direction,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 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: xnfio.cc,v 1.1 1998/12/07 04:53:17 steve Exp $"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# include "netlist.h"
|
||||||
|
|
||||||
|
static bool is_a_pad(const NetNet*net)
|
||||||
|
{
|
||||||
|
if (net->attribute("PAD") == "")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The xnfio function looks for the PAD signals in the design, and
|
||||||
|
* generates the needed IOB devices to handle being connected to the
|
||||||
|
* actual FPGA PAD. This will add items to the netlist if needed.
|
||||||
|
*
|
||||||
|
* FIXME: If there is a DFF connected to the pad, try to convert it
|
||||||
|
* to an IO DFF instead. This would save a CLB, and it is
|
||||||
|
* really lame to not do the obvious optimization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void make_obuf(Design*des, NetNet*net)
|
||||||
|
{
|
||||||
|
assert(net->pin_count() == 1);
|
||||||
|
|
||||||
|
/* FIXME: If there is nothing internally driving this PAD, I
|
||||||
|
can connect the PAD to a pullup and disconnect it from the
|
||||||
|
rest of the circuit. This would save routing resources. */
|
||||||
|
assert(count_outputs(net->pin(0)) > 0);
|
||||||
|
|
||||||
|
/* Look for an existing OBUF connected to this signal. If it
|
||||||
|
is there, then no need to add one. */
|
||||||
|
for (NetObj::Link*idx = net->pin(0).next_link()
|
||||||
|
; *idx != net->pin(0) ; idx = idx->next_link()) {
|
||||||
|
NetLogic*tmp;
|
||||||
|
if ((tmp = dynamic_cast<NetLogic*>(idx->get_obj())) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Try to use an existing BUF as an OBUF. This moves the
|
||||||
|
// BUF into the IOB.
|
||||||
|
if ((tmp->type() == NetLogic::BUF) &&
|
||||||
|
(count_inputs(tmp->pin(0)) == 0) &&
|
||||||
|
(count_outputs(tmp->pin(0)) == 1)) {
|
||||||
|
tmp->attribute("XNF-LCA", "OBUF:O,I");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to use an existing INV as an OBUF. Certain
|
||||||
|
// technologies support inverting the input of an OBUF,
|
||||||
|
// which looks just like an inverter. This uses the
|
||||||
|
// available resources of an IOB to optimize away an
|
||||||
|
// otherwise expensive inverter.
|
||||||
|
if ((tmp->type() == NetLogic::NOT) &&
|
||||||
|
(count_inputs(tmp->pin(0)) == 0) &&
|
||||||
|
(count_outputs(tmp->pin(0)) == 1)) {
|
||||||
|
tmp->attribute("XNF-LCA", "OBUF:O,~I");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't seem to find a way to rearrange the existing netlist,
|
||||||
|
// so I am stuck creating a new buffer, the OBUF.
|
||||||
|
NetLogic*buf = new NetLogic(des->local_symbol("$"), 2, NetLogic::BUF);
|
||||||
|
des->add_node(buf);
|
||||||
|
|
||||||
|
map<string,string>attr;
|
||||||
|
attr["XNF-LCA"] = "OBUF:O,I";
|
||||||
|
buf->set_attributes(attr);
|
||||||
|
|
||||||
|
// Put the buffer between this signal and the rest of the
|
||||||
|
// netlist.
|
||||||
|
connect(net->pin(0), buf->pin(1));
|
||||||
|
net->pin(0).unlink();
|
||||||
|
connect(net->pin(0), buf->pin(0));
|
||||||
|
|
||||||
|
// It is possible, in putting an OBUF between net and the rest
|
||||||
|
// of the netlist, to create a ring without a signal. Detect
|
||||||
|
// this case and create a new signal.
|
||||||
|
if (count_signals(buf->pin(1)) == 0) {
|
||||||
|
NetNet*tmp = new NetNet(des->local_symbol("$"), NetNet::WIRE);
|
||||||
|
connect(buf->pin(1), tmp->pin(0));
|
||||||
|
des->add_signal(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_ibuf(Design*des, NetNet*net)
|
||||||
|
{
|
||||||
|
assert(net->pin_count() == 1);
|
||||||
|
// XXXX For now, require at least one input.
|
||||||
|
assert(count_inputs(net->pin(0)) > 0);
|
||||||
|
|
||||||
|
/* Look for an existing BUF connected to this signal and
|
||||||
|
suitably connected that I can use it as an IBUF. */
|
||||||
|
for (NetObj::Link*idx = net->pin(0).next_link()
|
||||||
|
; *idx != net->pin(0) ; idx = idx->next_link()) {
|
||||||
|
NetLogic*tmp;
|
||||||
|
if ((tmp = dynamic_cast<NetLogic*>(idx->get_obj())) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Found a BUF, it is only useable if the only input is
|
||||||
|
// the signal and there are no other inputs.
|
||||||
|
if ((tmp->type() == NetLogic::BUF) &&
|
||||||
|
(count_inputs(tmp->pin(1)) == 1) &&
|
||||||
|
(count_outputs(tmp->pin(1)) == 0)) {
|
||||||
|
tmp->attribute("XNF-LCA", "IBUF:O,I");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// I give up, create an IBUF.
|
||||||
|
NetLogic*buf = new NetLogic(des->local_symbol("$"), 2, NetLogic::BUF);
|
||||||
|
des->add_node(buf);
|
||||||
|
|
||||||
|
map<string,string>attr;
|
||||||
|
attr["XNF-LCA"] = "IBUF:O,I";
|
||||||
|
buf->set_attributes(attr);
|
||||||
|
|
||||||
|
// Put the buffer between this signal and the rest of the
|
||||||
|
// netlist.
|
||||||
|
connect(net->pin(0), buf->pin(0));
|
||||||
|
net->pin(0).unlink();
|
||||||
|
connect(net->pin(0), buf->pin(1));
|
||||||
|
|
||||||
|
// It is possible, in putting an OBUF between net and the rest
|
||||||
|
// of the netlist, to create a ring without a signal. Detect
|
||||||
|
// this case and create a new signal.
|
||||||
|
if (count_signals(buf->pin(0)) == 0) {
|
||||||
|
NetNet*tmp = new NetNet(des->local_symbol("$"), NetNet::WIRE);
|
||||||
|
connect(buf->pin(0), tmp->pin(0));
|
||||||
|
des->add_signal(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void xnfio(Design*des)
|
||||||
|
{
|
||||||
|
des->clear_signal_marks();
|
||||||
|
while (NetNet*net = des->find_signal(&is_a_pad)) {
|
||||||
|
|
||||||
|
assert(net->pin_count() == 1);
|
||||||
|
string pattr = net->attribute("PAD");
|
||||||
|
|
||||||
|
switch (pattr[0]) {
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
make_ibuf(des, net);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
case 'O':
|
||||||
|
make_obuf(des, net);
|
||||||
|
break;
|
||||||
|
// FIXME: Only IPAD and OPAD supported. Need to
|
||||||
|
// add support for IOPAD.
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
net->set_mark();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Log: xnfio.cc,v $
|
||||||
|
* Revision 1.1 1998/12/07 04:53:17 steve
|
||||||
|
* Generate OBUF or IBUF attributes (and the gates
|
||||||
|
* to garry them) where a wire is a pad. This involved
|
||||||
|
* figuring out enough of the netlist to know when such
|
||||||
|
* was needed, and to generate new gates and signales
|
||||||
|
* to handle what's missing.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
Loading…
Reference in New Issue