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:
steve 1998-12-07 04:53:16 +00:00
parent ada45acb0c
commit 9a73433759
9 changed files with 402 additions and 56 deletions

View File

@ -7,7 +7,7 @@ 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
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 \
netlist.o parse.o parse_misc.o pform.o pform_dump.o verinum.o target.o \

View File

@ -78,6 +78,10 @@ not part of a type attribute.
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

View File

@ -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.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
/*
@ -137,6 +137,9 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
case AND:
o << "and";
break;
case BUF:
o << "buf";
break;
case NAND:
o << "nand";
break;
@ -404,6 +407,13 @@ void Design::dump(ostream&o) const
/*
* $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
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,

View File

@ -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.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
/*
@ -32,13 +32,12 @@
# include "pform.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";
strstream res;
res << "_L" << (counter++) << ends;
res << "_L" << (lcounter_++) << ends;
return path + "." + res.str();
}
@ -76,7 +75,7 @@ static void do_assign(Design*des, const string&path,
delete lval;
} 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(1), rval->pin(idx));
@ -153,12 +152,15 @@ void PGBuiltin::elaborate(Design*des, const string&path) const
NetLogic*cur = 0;
string name = get_name();
if (name == "")
name = local_symbol(path);
name = des->local_symbol(path);
switch (type()) {
case AND:
cur = new NetLogic(name, pin_count(), NetLogic::AND);
break;
case BUF:
cur = new NetLogic(name, pin_count(), NetLogic::BUF);
break;
case NAND:
cur = new NetLogic(name, pin_count(), NetLogic::NAND);
break;
@ -206,7 +208,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const
{
string my_name;
if (get_name() == "")
my_name = local_symbol(path);
my_name = des->local_symbol(path);
else
my_name = path + "." + get_name();
@ -333,10 +335,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path) const
case '^': // XOR
assert(lsig->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(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);
connect(gate->pin(0), osig->pin(0));
des->add_signal(osig);
@ -346,10 +348,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path) const
case '&': // AND
assert(lsig->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(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);
connect(gate->pin(0), osig->pin(0));
des->add_signal(osig);
@ -359,10 +361,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path) const
case 'e': // ==
assert(lsig->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(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);
connect(gate->pin(0), osig->pin(0));
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*net = new NetNet(local_symbol(path), NetNet::IMPLICIT);
NetNet*net = new NetNet(des->local_symbol(path), NetNet::IMPLICIT);
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_signal(net);
connect(net->pin(0), tmp->pin(0));
@ -446,9 +448,9 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path) const
switch (op_) {
case '~': // Bitwise NOT
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);
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(1), sub_sig->pin(0));
des->add_signal(sig);
@ -456,9 +458,9 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path) const
break;
case '&': // Reduction AND
sig = new NetNet(local_symbol(path), NetNet::WIRE);
sig = new NetNet(des->local_symbol(path), NetNet::WIRE);
sig->local_flag(true);
gate = new NetLogic(local_symbol(path),
gate = new NetLogic(des->local_symbol(path),
1+sub_sig->pin_count(),
NetLogic::AND);
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*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);
if (expr == 0) {
@ -732,6 +734,13 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $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
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,

11
main.cc
View File

@ -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.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
# include <stdio.h>
@ -64,6 +64,7 @@ extern void cprop(Design*des);
extern void sigfold(Design*des);
extern void stupid(Design*des);
extern void nobufz(Design*des);
extern void xnfio(Design*des);
typedef void (*net_func)(Design*);
static struct net_func_map {
@ -74,6 +75,7 @@ static struct net_func_map {
{ "nobufz", &nobufz },
{ "sigfold", &sigfold },
{ "stupid", &stupid },
{ "xnfio", &xnfio },
{ 0, 0 }
};
@ -229,6 +231,13 @@ int main(int argc, char*argv[])
/*
* $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
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,

View File

@ -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.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
# include <cassert>
@ -145,6 +145,25 @@ unsigned count_outputs(const NetObj::Link&pin)
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 NetObj*cur;
@ -193,6 +212,11 @@ string NetObj::attribute(const string&key) const
return (*idx).second;
}
void NetObj::attribute(const string&key, const string&value)
{
attributes_[key] = value;
}
bool NetObj::has_compat_attributes(const NetObj&that) const
{
map<string,string>::const_iterator idx;
@ -559,6 +583,13 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $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
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,

View File

@ -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.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
/*
@ -85,6 +85,9 @@ class NetObj {
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
// destructor will automatically do this if needed.
void unlink()
@ -105,6 +108,12 @@ class NetObj {
bool is_equal(const NetObj::Link&that) const
{ 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:
// The NetNode manages these. They point back to the
// NetNode so that following the links can get me here.
@ -139,6 +148,7 @@ class NetObj {
void set_attributes(const map<string,string>&);
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
// all have the same values.
@ -311,7 +321,7 @@ class NetConst : public NetNode {
class NetLogic : public NetNode {
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);
@ -699,7 +709,7 @@ class NetESignal : public NetExpr {
class Design {
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
parameters/flags and passing them to the processing steps
@ -736,6 +746,10 @@ class Design {
void clear_signal_marks();
NetNet*find_signal(bool (*test)(const NetNet*));
public:
string local_symbol(const string&path);
private:
// List all the signals in the design.
NetNet*signals_;
@ -748,6 +762,8 @@ class Design {
map<string,string> flags_;
unsigned lcounter_;
private: // not implemented
Design(const Design&);
Design& operator= (const Design&);
@ -776,8 +792,11 @@ inline bool connected(const NetObj::Link&l, const NetObj::Link&r)
checking signal vectors. */
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_outputs(const NetObj::Link&pin);
extern unsigned count_signals(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
@ -792,6 +811,13 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $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
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,

122
t-xnf.cc
View File

@ -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.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
/* XNF BACKEND
@ -45,10 +45,20 @@
* NODE ATTRIBUTES
*
* 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
* seperated list is the names of the pins, in the order they
* appear in the verilog source.
* separated list is the names of the pins, in the order they
* 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"
@ -65,8 +75,10 @@ class target_xnf : public target_t {
private:
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);
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;
}
void target_xnf::draw_pin(ostream&os, const string&name, char type,
const NetObj::Link&lnk)
void target_xnf::draw_pin(ostream&os, const string&name,
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;
const NetObj*cur;
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);
if (sig) {
os << " PIN, " << name << ", " << type << ", "
os << " PIN, " << use_name << ", " << type << ", "
<< mangle(sig->name());
if (sig->pin_count() > 1)
os << "<" << cpin << ">";
if (inv)
os << ",,INV";
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)
{
@ -198,11 +259,22 @@ void target_xnf::signal(ostream&os, const NetNet*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()) << ", ";
switch (net->type()) {
case NetLogic::AND:
os << "AND";
break;
case NetLogic::BUF:
os << "BUF";
break;
case NetLogic::NAND:
os << "NAND";
break;
@ -227,44 +299,29 @@ void target_xnf::logic(ostream&os, const NetLogic*net)
}
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) {
string name = "I";
assert(net->pin_count() <= 11);
name += (char)('0'+idx-1);
draw_pin(os, name, 'I', net->pin(idx));
draw_pin(os, name, 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");
// I only know how to draw a UDP if it has the XNF-LCA
// attribute attached to it.
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;
draw_sym_with_lcaname(os, lca, net);
}
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 $
* 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
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,

193
xnfio.cc Normal file
View File

@ -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.
*
*/