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-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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
49
elaborate.cc
49
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.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
11
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.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,
|
||||
|
|
|
|||
33
netlist.cc
33
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.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,
|
||||
|
|
|
|||
32
netlist.h
32
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.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
122
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.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,
|
||||
|
|
|
|||
|
|
@ -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