Add support for CE input to XNF DFF, and do

complete cleanup of replaced design nodes.
This commit is contained in:
steve 1999-07-18 21:17:50 +00:00
parent 7d876f7735
commit 563ec1bb81
7 changed files with 318 additions and 83 deletions

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.57 1999/07/17 19:50:59 steve Exp $"
#ident "$Id: elaborate.cc,v 1.58 1999/07/18 21:17:50 steve Exp $"
#endif
/*
@ -987,7 +987,6 @@ NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const
connect(tmp->pin(idx), net->pin(idx+lsv));
des->add_node(tmp);
des->set_esignal(tmp);
return tmp;
}
@ -1005,11 +1004,11 @@ NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const
connect(tmp->pin(0), net->pin(msv));
des->add_node(tmp);
des->set_esignal(tmp);
return tmp;
}
NetESignal*node = des->get_esignal(net);
NetESignal*node = new NetESignal(net);
des->add_node(node);
assert(idx_ == 0);
// Non-constant bit select? punt and make a subsignal
@ -1258,7 +1257,8 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const
connect(a1->pin(idx), tmp->pin(idx));
n = des->local_symbol(path);
NetESignal*sig = des->get_esignal(tmp);
NetESignal*sig = new NetESignal(tmp);
des->add_node(sig);
NetAssign*a2 = new NetAssign(n, des, wid, sig);
a2->set_line(*this);
des->add_node(a2);
@ -1862,6 +1862,10 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.58 1999/07/18 21:17:50 steve
* Add support for CE input to XNF DFF, and do
* complete cleanup of replaced design nodes.
*
* Revision 1.57 1999/07/17 19:50:59 steve
* netlist support for ternary operator.
*

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.46 1999/07/18 05:52:46 steve Exp $"
#ident "$Id: netlist.cc,v 1.47 1999/07/18 21:17:50 steve Exp $"
#endif
# include <cassert>
@ -283,6 +283,16 @@ NetProcTop::~NetProcTop()
delete statement_;
}
NetProc* NetProcTop::statement()
{
return statement_;
}
const NetProc* NetProcTop::statement() const
{
return statement_;
}
NetAssign_::NetAssign_(const string&n, unsigned w)
: NetNode(n, w)
{
@ -309,6 +319,7 @@ NetAssign::NetAssign(const string&n, Design*des, unsigned w, NetExpr*rv)
NetAssign::~NetAssign()
{
delete rval_;
}
NetAssignNB::NetAssignNB(const string&n, Design*des, unsigned w, NetExpr*rv)
@ -441,6 +452,33 @@ NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e)
{
}
NetCondit::~NetCondit()
{
delete expr_;
if (if_) delete if_;
if (else_) delete else_;
}
const NetExpr* NetCondit::expr() const
{
return expr_;
}
NetExpr* NetCondit::expr()
{
return expr_;
}
NetProc* NetCondit::if_clause()
{
return if_;
}
NetProc* NetCondit::else_clause()
{
return else_;
}
NetNEvent::NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe)
: NetNode(ev, wid), sref<NetPEvent,NetNEvent>(pe), edge_(e)
{
@ -457,7 +495,7 @@ NetPEvent::NetPEvent(const string&n, NetProc*st)
NetPEvent::~NetPEvent()
{
svector<const NetNEvent*>*back = back_list();
svector<NetNEvent*>*back = back_list();
if (back) {
for (unsigned idx = 0 ; idx < back->count() ; idx += 1) {
NetNEvent*ne = (*back)[idx];
@ -465,6 +503,13 @@ NetPEvent::~NetPEvent()
}
delete back;
}
delete statement_;
}
NetProc* NetPEvent::statement()
{
return statement_;
}
const NetProc* NetPEvent::statement() const
@ -1348,24 +1393,6 @@ void Design::del_node(NetNode*net)
net->design_ = 0;
}
NetESignal* Design::get_esignal(NetNet*net)
{
NetESignal*&node = esigs_[net->name()];
if (node == 0) {
node = new NetESignal(net);
add_node(node);
}
return node;
}
void Design::set_esignal(NetESignal*sig)
{
NetESignal*&node = esigs_[sig->name()];
assert( node == 0 );
node = sig;
}
void Design::add_process(NetProcTop*pro)
{
pro->next_ = procs_;
@ -1452,6 +1479,10 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: netlist.cc,v $
* Revision 1.47 1999/07/18 21:17:50 steve
* Add support for CE input to XNF DFF, and do
* complete cleanup of replaced design nodes.
*
* Revision 1.46 1999/07/18 05:52:46 steve
* xnfsyn generates DFF objects for XNF output, and
* properly rewrites the Design netlist in the process.

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.49 1999/07/18 05:52:47 steve Exp $"
#ident "$Id: netlist.h,v 1.50 1999/07/18 21:17:50 steve Exp $"
#endif
/*
@ -581,6 +581,7 @@ class NetAssign : public NetAssign_ {
explicit NetAssign(const string&, Design*des, unsigned w, NetExpr*rv);
~NetAssign();
NetExpr*rval() { return rval_; }
const NetExpr*rval() const { return rval_; }
void find_lval_range(const NetNet*&net, unsigned&msb,
@ -715,8 +716,14 @@ class NetCondit : public NetProc {
public:
explicit NetCondit(NetExpr*ex, NetProc*i, NetProc*e);
~NetCondit();
const NetExpr*expr() const;
NetExpr*expr();
NetProc* if_clause();
NetProc* else_clause();
const NetExpr*expr() const { return expr_; }
void emit_recurse_if(ostream&, struct target_t*) const;
void emit_recurse_else(ostream&, struct target_t*) const;
@ -783,6 +790,7 @@ class NetPEvent : public NetProc, public sref_back<NetPEvent,NetNEvent> {
~NetPEvent();
string name() const { return name_; }
NetProc* statement();
const NetProc* statement() const;
virtual void emit_proc(ostream&, struct target_t*) const;
@ -949,11 +957,12 @@ class NetProcTop : public LineInfo {
public:
enum Type { KINITIAL, KALWAYS };
NetProcTop(Type t, NetProc*st);
NetProcTop(Type t, class NetProc*st);
~NetProcTop();
Type type() const { return type_; }
const NetProc*statement() const { return statement_; }
NetProc*statement();
const NetProc*statement() const;
void dump(ostream&, unsigned ind) const;
void emit(ostream&, struct target_t*tgt) const;
@ -1274,10 +1283,6 @@ class Design {
void add_node(NetNode*);
void del_node(NetNode*);
// ESIGNALS
NetESignal* get_esignal(NetNet*net);
void set_esignal(NetESignal*sig);
// PROCESSES
void add_process(NetProcTop*);
void delete_process(NetProcTop*);
@ -1322,9 +1327,6 @@ class Design {
map<string,string> flags_;
// Use this map to prevent duplicate signals.
map<string,NetESignal*> esigs_;
unsigned lcounter_;
private: // not implemented
@ -1374,6 +1376,10 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.50 1999/07/18 21:17:50 steve
* Add support for CE input to XNF DFF, and do
* complete cleanup of replaced design nodes.
*
* Revision 1.49 1999/07/18 05:52:47 steve
* xnfsyn generates DFF objects for XNF output, and
* properly rewrites the Design netlist in the process.

30
sref.h
View File

@ -21,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: sref.h,v 1.2 1999/07/18 05:52:47 steve Exp $"
#ident "$Id: sref.h,v 1.3 1999/07/18 21:17:51 steve Exp $"
#endif
# include <assert.h>
@ -45,6 +45,7 @@ template <class T1, class T2> class sref_back {
~sref_back() { assert(sback_ == 0); }
svector<const T2*>* back_list() const;
svector<T2*>* back_list();
private:
void desert_(sref<T1,T2>*);
@ -101,6 +102,29 @@ svector<const T2*>* sref_back<T1,T2>::back_list() const
return result;
}
template <class T1,class T2>
svector<class T2*>* sref_back<T1,T2>::back_list()
{
if (sback_ == 0) return 0;
unsigned cnt = 1;
sref<T1,T2>*cur = sback_->next_;
while (cur != sback_) {
cnt += 1;
cur = cur->next_;
}
svector<class T2*>* result = new svector<class T2*>(cnt);
(*result)[0] = dynamic_cast<class T2*>(sback_);
cur = sback_->next_;
cnt = 1;
while (cur != sback_) {
(*result)[cnt] = dynamic_cast<class T2*>(cur);
cnt += 1;
cur = cur->next_;
}
return result;
}
template <class T1, class T2> void sref_back<T1,T2>::desert_(sref<T1,T2>*item)
{
if (item == sback_)
@ -122,6 +146,10 @@ template <class T1, class T2> void sref_back<T1,T2>::desert_(sref<T1,T2>*item)
/*
* $Log: sref.h,v $
* Revision 1.3 1999/07/18 21:17:51 steve
* Add support for CE input to XNF DFF, and do
* complete cleanup of replaced design nodes.
*
* Revision 1.2 1999/07/18 05:52:47 steve
* xnfsyn generates DFF objects for XNF output, and
* properly rewrites the Design netlist in the process.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-vvm.cc,v 1.31 1999/07/17 03:39:11 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.32 1999/07/18 21:17:51 steve Exp $"
#endif
# include <iostream>
@ -77,6 +77,11 @@ class target_vvm : public target_t {
ostrstream start_code;
unsigned process_counter;
unsigned thread_step_;
// These methods are use to help prefent duplicate printouts
// of things that may be scanned multiple times.
map<string,bool>esignal_printed_flag;
map<string,bool>pevent_printed_flag;
};
@ -790,6 +795,11 @@ void target_vvm::net_const(ostream&os, const NetConst*gate)
void target_vvm::net_esignal(ostream&os, const NetESignal*net)
{
bool&flag = esignal_printed_flag[net->name()];
if (flag)
return;
flag = true;
os << "static vvm_bitset_t<" << net->pin_count() << "> " <<
mangle(net->name()) << "_bits; /* " << net->name() <<
" */" << endl;
@ -813,10 +823,11 @@ void target_vvm::net_event(ostream&os, const NetNEvent*gate)
string pevent = mangle(gate->fore_ptr()->name());
os << " /* " << gate->name() << " */" << endl;
os << "#ifndef PEVENT_" << pevent << endl;
os << "#define PEVENT_" << pevent << endl;
os << "static vvm_sync " << pevent << ";" << endl;
os << "#endif" << endl;
bool&printed = pevent_printed_flag[pevent];
if (! printed) {
printed = true;
os << "static vvm_sync " << pevent << ";" << endl;
}
os << "static vvm_pevent<" << gate->pin_count() << "> " <<
mangle(gate->name()) << "(&" << pevent << ", ";
@ -1276,6 +1287,10 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.32 1999/07/18 21:17:51 steve
* Add support for CE input to XNF DFF, and do
* complete cleanup of replaced design nodes.
*
* Revision 1.31 1999/07/17 03:39:11 steve
* simplified process scan for targets.
*

54
xnf.txt
View File

@ -1,15 +1,49 @@
WHAT IS XNF
Xilinx Netlist Format. This is somewhat specific to the Xilinx tool
chain, but that is sufficiently ubiquitous that it is worth it. This
format can be fed to place and route tools and simulators. since third
party simulators accept XNF, the format may be useful even independent
of Xilinx parts.
XNF is the Xilinx Netlist Format. This is somewhat specific to the
Xilinx tool chain, but it is sufficiently ubiquitous that it's still
worth it. This format can be fed to place and route tools and
simulators. Since some third party simulators accept XNF, the format
may be useful even independent of Xilinx parts.
The xnfio function is highly recommended as it optimizes use of the IO
blocks. Without this function, the I/O blocks will probably remain
unused.
Icarus Verilog supports XNF as specified by the Xilinx Netlist Format
Specification, Version 6.1.
IVL SUPPORT FOR XNF
Icarus Verilog has a code generator and synthesis functions that
support generation of XNF netlists. The XNF modules also allow the
programmer to use $attributes to control certain aspects of code
generation.
XNF code generation is enabled with the ``-t xnf'' flag on the command
line. The XNF code generator needs to know the type of part to
generate code for, so the ``-fpart=<type>'' flag is also needed. For
example, to generate code for the 4010E the command line might start
out as:
ivl -txnf -fpart=4010e -Fxnfsyn -Fxnfio [...]
Icarus Verilog includes the functions ``xnfsyn'' and ``xnfio'' to
perform transformations and optimizations on the design before code is
generated. The xnfsyn function matches certain behavioral constructs
to XNF components, and the xnfio function generates pads and fills the
IOBs.
XNFSYN FUNCTION
This function does synthesis transformations on the entered design,
making it possible to generate XNF netlist components from certain
behavioral constructs. This is needed in Verilog for example to model
some of the synchronous components of the XNF library.
It is a bit much to expect a Verilog compiler in general to generate
components from arbitrary behavioral descriptions, so the xnfsyn
function works by matching statements that have some documented
structure, and substituting them for the equivalent XNF component. A
fully synthesize-able design, then, is one where the behavioral
statements can all be matched and substituted by the xnfsyn function.
XNFIO FUNCTION
@ -50,6 +84,10 @@ IBUF, NOT gates cannot be absorbed as in the OPAD case.
$Log: xnf.txt,v $
Revision 1.2 1999/07/18 21:17:51 steve
Add support for CE input to XNF DFF, and do
complete cleanup of replaced design nodes.
Revision 1.1 1999/05/01 02:57:11 steve
XNF target documentation.

179
xnfsyn.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: xnfsyn.cc,v 1.1 1999/07/18 05:52:47 steve Exp $"
#ident "$Id: xnfsyn.cc,v 1.2 1999/07/18 21:17:51 steve Exp $"
#endif
/*
@ -29,7 +29,16 @@
*
* Currently, this transform recognizes the following patterns:
*
* always @(posedge CLK) Q = D // DFF
* always @(posedge CLK) Q = D // DFF:D,Q,C
* always @(negedge CLK) Q = D // DFF:D,Q,~C
*
* always @(posedge CLK) if (CE) Q = D;
* always @(negedge CLK) if (CE) Q = D;
*
* The r-value of the assignments must be identifiers (i.e. wires or
* registers) and the CE must be single-bine identifiers. Enough
* devices will be created to accommodate the width of Q and D, though
* the CLK and CE will be shared by all the devices.
*/
# include "functor.h"
# include "netlist.h"
@ -40,7 +49,21 @@ class xnfsyn_f : public functor_t {
void process(class Design*, class NetProcTop*);
private:
void proc_always(class Design*, class NetProcTop*);
void proc_always_(class Design*);
void proc_casn_(class Design*);
void proc_ccon_(class Design*);
// The matcher does something like a recursive descent search
// for the templates. These variables are filled in as the
// searcher finds them.
class NetProcTop*top_;
class NetPEvent *pclk_;
class NetNEvent *nclk_;
class NetCondit *con_;
class NetAssign *asn_;
};
@ -52,68 +75,154 @@ void xnfsyn_f::process(class Design*des, class NetProcTop*top)
{
switch (top->type()) {
case NetProcTop::KALWAYS:
proc_always(des, top);
top_ = top;
proc_always_(des);
break;
}
}
/*
* Look for DFF devices. The pattern I'm looking for is:
*
* always @(posedge CLK) Q = D;
*
* This creates a DFF with the CLK, D and Q hooked up the obvious
* way. CE and PRE/CLR are left unconnected.
* An "always ..." statement has been found.
*/
void xnfsyn_f::proc_always(class Design*des, class NetProcTop*top)
void xnfsyn_f::proc_always_(class Design*des)
{
// The statement must be a NetPEvent, ...
const NetProc*st = top->statement();
const NetPEvent*ev = dynamic_cast<const NetPEvent*>(st);
if (ev == 0)
pclk_ = dynamic_cast<class NetPEvent*>(top_->statement());
if (pclk_ == 0)
return;
// ... there must be a single event source, ...
svector<const NetNEvent*>*neb = ev->back_list();
svector<class NetNEvent*>*neb = pclk_->back_list();
if (neb == 0)
return;
if (neb->count() != 1) {
delete neb;
return;
}
const NetNEvent*nev = (*neb)[0];
nclk_ = (*neb)[0];
delete neb;
// ... the event must be POSEDGE, ...
if (nev->type() != NetNEvent::POSEDGE)
// ... the event must be an edge, ...
switch (nclk_->type()) {
case NetNEvent::POSEDGE:
case NetNEvent::NEGEDGE:
break;
default:
return;
}
// the NetPEvent must guard an assignment, ...
const NetAssign*asn = dynamic_cast<const NetAssign*>(ev->statement());
if (asn == 0)
// Is this a clocked assignment?
asn_ = dynamic_cast<NetAssign*>(pclk_->statement());
if (asn_) {
proc_casn_(des);
return;
}
con_ = dynamic_cast<NetCondit*>(pclk_->statement());
if (con_) {
proc_ccon_(des);
return;
}
}
/*
* The process so far has been matched as:
*
* always @(posedge nclk_) asn_ = <r>;
* always @(negedge nclk_) asn_ = <r>;
*/
void xnfsyn_f::proc_casn_(class Design*des)
{
// ... and the rval must be a simple signal.
const NetESignal*sig = dynamic_cast<const NetESignal*>(asn->rval());
NetESignal*sig = dynamic_cast<NetESignal*>(asn_->rval());
if (sig == 0)
return ;
// XXXX For now, only handle single bit.
assert(asn->pin_count() == 1);
assert(sig->pin_count() == 1);
// The signal and the assignment must be the same width...
assert(asn_->pin_count() == sig->pin_count());
NetUDP*dff = new NetUDP(asn->name(), 3, true);
connect(dff->pin(0), asn->pin(0));
connect(dff->pin(1), sig->pin(0));
connect(dff->pin(2), nev->pin(0));
// Geneate enough DFF objects to handle the entire width.
for (unsigned idx = 0 ; idx < asn_->pin_count() ; idx += 1) {
dff->attribute("XNF-LCA", "DFF:Q,D,CLK");
des->add_node(dff);
// XXXX FIXME: Objects need unique names!
NetUDP*dff = new NetUDP(asn_->name(), 3, true);
connect(dff->pin(0), asn_->pin(idx));
connect(dff->pin(1), sig->pin(idx));
connect(dff->pin(2), nclk_->pin(0));
switch (nclk_->type()) {
case NetNEvent::POSEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,C");
break;
case NetNEvent::NEGEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,~C");
break;
}
des->add_node(dff);
}
// This process is matched and replaced with a DFF. Get
// rid of the now useless NetProcTop.
des->delete_process(top);
des->delete_process(top_);
}
/*
* The process si far has been matches as:
*
* always @(posedge nclk_) if ...;
* always @(negedge nclk_) if ...;
*/
void xnfsyn_f::proc_ccon_(class Design*des)
{
if (con_->else_clause())
return;
asn_ = dynamic_cast<NetAssign*>(con_->if_clause());
if (asn_ == 0)
return;
NetESignal*sig = dynamic_cast<NetESignal*>(asn_->rval());
if (sig == 0)
return;
// The signal and the assignment must be the same width...
assert(asn_->pin_count() == sig->pin_count());
NetESignal*ce = dynamic_cast<NetESignal*>(con_->expr());
if (ce == 0)
return;
if (ce->pin_count() != 1)
return;
// Geneate enough DFF objects to handle the entire width.
for (unsigned idx = 0 ; idx < asn_->pin_count() ; idx += 1) {
// XXXX FIXME: Objects need unique names!
NetUDP*dff = new NetUDP(asn_->name(), 4, true);
connect(dff->pin(0), asn_->pin(idx));
connect(dff->pin(1), sig->pin(idx));
connect(dff->pin(2), nclk_->pin(0));
connect(dff->pin(3), ce->pin(0));
switch (nclk_->type()) {
case NetNEvent::POSEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,C,CE");
break;
case NetNEvent::NEGEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,~C,CE");
break;
}
des->add_node(dff);
}
// This process is matched and replaced with a DFF. Get
// rid of the now useless NetProcTop.
des->delete_process(top_);
}
void xnfsyn(Design*des)
@ -124,6 +233,10 @@ void xnfsyn(Design*des)
/*
* $Log: xnfsyn.cc,v $
* Revision 1.2 1999/07/18 21:17:51 steve
* Add support for CE input to XNF DFF, and do
* complete cleanup of replaced design nodes.
*
* Revision 1.1 1999/07/18 05:52:47 steve
* xnfsyn generates DFF objects for XNF output, and
* properly rewrites the Design netlist in the process.