Add support for CE input to XNF DFF, and do
complete cleanup of replaced design nodes.
This commit is contained in:
parent
7d876f7735
commit
563ec1bb81
14
elaborate.cc
14
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.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.
|
||||
*
|
||||
|
|
|
|||
71
netlist.cc
71
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.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.
|
||||
|
|
|
|||
28
netlist.h
28
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.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
30
sref.h
|
|
@ -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.
|
||||
|
|
|
|||
25
t-vvm.cc
25
t-vvm.cc
|
|
@ -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
54
xnf.txt
|
|
@ -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
179
xnfsyn.cc
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue