xnfsyn generates DFF objects for XNF output, and
properly rewrites the Design netlist in the process.
This commit is contained in:
parent
9754507eb0
commit
7d876f7735
|
|
@ -18,7 +18,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.8 1999/07/17 22:01:13 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.9 1999/07/18 05:52:46 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -53,7 +53,7 @@ clean:
|
|||
cd ivlpp ; make clean
|
||||
|
||||
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
|
||||
FF = nobufz.o propinit.o sigfold.o xnfio.o
|
||||
FF = nobufz.o propinit.o sigfold.o xnfio.o xnfsyn.o
|
||||
|
||||
O = main.o cprop.o design_dump.o elaborate.o emit.o eval.o functor.o \
|
||||
lexor.o mangle.o netlist.o parse.o parse_misc.o pform.o pform_dump.o \
|
||||
|
|
|
|||
12
functor.cc
12
functor.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.cc,v 1.1 1999/07/17 22:01:13 steve Exp $"
|
||||
#ident "$Id: functor.cc,v 1.2 1999/07/18 05:52:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
|
|
@ -47,12 +47,20 @@ void Design::functor(functor_t*fun)
|
|||
}
|
||||
|
||||
// apply to processes
|
||||
for (NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
procs_idx_ = procs_;
|
||||
while (procs_idx_) {
|
||||
NetProcTop*idx = procs_idx_;
|
||||
procs_idx_ = idx->next_;
|
||||
fun->process(this, idx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.2 1999/07/18 05:52:46 steve
|
||||
* xnfsyn generates DFF objects for XNF output, and
|
||||
* properly rewrites the Design netlist in the process.
|
||||
*
|
||||
* Revision 1.1 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
*
|
||||
|
|
|
|||
8
main.cc
8
main.cc
|
|
@ -19,7 +19,7 @@ const char COPYRIGHT[] =
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: main.cc,v 1.20 1999/07/17 22:01:13 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.21 1999/07/18 05:52:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
const char NOTICE[] =
|
||||
|
|
@ -82,6 +82,7 @@ extern void propinit(Design*des);
|
|||
extern void sigfold(Design*des);
|
||||
extern void nobufz(Design*des);
|
||||
extern void xnfio(Design*des);
|
||||
extern void xnfsyn(Design*des);
|
||||
|
||||
typedef void (*net_func)(Design*);
|
||||
static struct net_func_map {
|
||||
|
|
@ -93,6 +94,7 @@ static struct net_func_map {
|
|||
{ "propinit", &propinit },
|
||||
{ "sigfold", &sigfold },
|
||||
{ "xnfio", &xnfio },
|
||||
{ "xnfsyn", &xnfsyn },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
@ -270,6 +272,10 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.21 1999/07/18 05:52:46 steve
|
||||
* xnfsyn generates DFF objects for XNF output, and
|
||||
* properly rewrites the Design netlist in the process.
|
||||
*
|
||||
* Revision 1.20 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
*
|
||||
|
|
|
|||
69
netlist.cc
69
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.45 1999/07/17 19:51:00 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.46 1999/07/18 05:52:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -273,6 +273,16 @@ NetProc::~NetProc()
|
|||
{
|
||||
}
|
||||
|
||||
NetProcTop::NetProcTop(Type t, NetProc*st)
|
||||
: type_(t), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
NetProcTop::~NetProcTop()
|
||||
{
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(const string&n, unsigned w)
|
||||
: NetNode(n, w)
|
||||
{
|
||||
|
|
@ -431,6 +441,37 @@ NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e)
|
|||
{
|
||||
}
|
||||
|
||||
NetNEvent::NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe)
|
||||
: NetNode(ev, wid), sref<NetPEvent,NetNEvent>(pe), edge_(e)
|
||||
{
|
||||
}
|
||||
|
||||
NetNEvent::~NetNEvent()
|
||||
{
|
||||
}
|
||||
|
||||
NetPEvent::NetPEvent(const string&n, NetProc*st)
|
||||
: name_(n), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
NetPEvent::~NetPEvent()
|
||||
{
|
||||
svector<const NetNEvent*>*back = back_list();
|
||||
if (back) {
|
||||
for (unsigned idx = 0 ; idx < back->count() ; idx += 1) {
|
||||
NetNEvent*ne = (*back)[idx];
|
||||
delete ne;
|
||||
}
|
||||
delete back;
|
||||
}
|
||||
}
|
||||
|
||||
const NetProc* NetPEvent::statement() const
|
||||
{
|
||||
return statement_;
|
||||
}
|
||||
|
||||
NetSTask::NetSTask(const string&na, const svector<NetExpr*>&pa)
|
||||
: name_(na), parms_(pa)
|
||||
{
|
||||
|
|
@ -1331,6 +1372,28 @@ void Design::add_process(NetProcTop*pro)
|
|||
procs_ = pro;
|
||||
}
|
||||
|
||||
void Design::delete_process(NetProcTop*top)
|
||||
{
|
||||
assert(top);
|
||||
if (procs_ == top) {
|
||||
procs_ = top->next_;
|
||||
|
||||
} else {
|
||||
NetProcTop*cur = procs_;
|
||||
while (cur->next_ != top) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
|
||||
cur->next_ = top->next_;
|
||||
}
|
||||
|
||||
if (procs_idx_ == top)
|
||||
procs_idx_ = top->next_;
|
||||
|
||||
delete top;
|
||||
}
|
||||
|
||||
void Design::clear_node_marks()
|
||||
{
|
||||
if (nodes_ == 0)
|
||||
|
|
@ -1389,6 +1452,10 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* 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.
|
||||
*
|
||||
* Revision 1.45 1999/07/17 19:51:00 steve
|
||||
* netlist support for ternary operator.
|
||||
*
|
||||
|
|
|
|||
24
netlist.h
24
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.48 1999/07/17 22:01:13 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.49 1999/07/18 05:52:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -768,19 +768,22 @@ class NetPDelay : public NetProc {
|
|||
|
||||
/*
|
||||
* The NetPEvent is associated with NetNEvents. The NetPEvent receives
|
||||
* eventss from any one of the associated NetNEvents and in response
|
||||
* events from any one of the associated NetNEvents and in response
|
||||
* causes the attached statement to be executed. Objects of this type
|
||||
* are not nodes, but require a name anyhow so that backends can
|
||||
* generate objects to refer to it.
|
||||
*
|
||||
* The NetPEvent is the procedural part of the event.
|
||||
*/
|
||||
class NetNEvent;
|
||||
class NetPEvent : public NetProc, public sref_back<NetPEvent,NetNEvent> {
|
||||
|
||||
public:
|
||||
NetPEvent(const string&n, NetProc*st)
|
||||
: name_(n), statement_(st) { }
|
||||
NetPEvent(const string&n, NetProc*st);
|
||||
~NetPEvent();
|
||||
|
||||
string name() const { return name_; }
|
||||
const NetProc* statement() const;
|
||||
|
||||
virtual void emit_proc(ostream&, struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -805,8 +808,8 @@ class NetNEvent : public NetNode, public sref<NetPEvent,NetNEvent> {
|
|||
public:
|
||||
enum Type { ANYEDGE, POSEDGE, NEGEDGE, POSITIVE };
|
||||
|
||||
NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe)
|
||||
: NetNode(ev, wid), sref<NetPEvent,NetNEvent>(pe), edge_(e) { }
|
||||
NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe);
|
||||
~NetNEvent();
|
||||
|
||||
Type type() const { return edge_; }
|
||||
|
||||
|
|
@ -946,7 +949,8 @@ class NetProcTop : public LineInfo {
|
|||
public:
|
||||
enum Type { KINITIAL, KALWAYS };
|
||||
|
||||
NetProcTop(Type t, NetProc*st) : type_(t), statement_(st) { }
|
||||
NetProcTop(Type t, NetProc*st);
|
||||
~NetProcTop();
|
||||
|
||||
Type type() const { return type_; }
|
||||
const NetProc*statement() const { return statement_; }
|
||||
|
|
@ -1276,6 +1280,7 @@ class Design {
|
|||
|
||||
// PROCESSES
|
||||
void add_process(NetProcTop*);
|
||||
void delete_process(NetProcTop*);
|
||||
|
||||
// Iterate over the design...
|
||||
void dump(ostream&) const;
|
||||
|
|
@ -1313,6 +1318,7 @@ class Design {
|
|||
|
||||
// List the processes in the design.
|
||||
NetProcTop*procs_;
|
||||
NetProcTop*procs_idx_;
|
||||
|
||||
map<string,string> flags_;
|
||||
|
||||
|
|
@ -1368,6 +1374,10 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* 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.
|
||||
*
|
||||
* Revision 1.48 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
*
|
||||
|
|
|
|||
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.1 1999/05/01 02:57:53 steve Exp $"
|
||||
#ident "$Id: sref.h,v 1.2 1999/07/18 05:52:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <assert.h>
|
||||
|
|
@ -47,6 +47,7 @@ template <class T1, class T2> class sref_back {
|
|||
svector<const T2*>* back_list() const;
|
||||
|
||||
private:
|
||||
void desert_(sref<T1,T2>*);
|
||||
sref<T1,T2>*sback_;
|
||||
};
|
||||
|
||||
|
|
@ -56,7 +57,7 @@ template <class T1, class T2> class sref {
|
|||
|
||||
public:
|
||||
sref(T1*d) : dest_(d) { insert_(); }
|
||||
virtual ~sref() { desert_(); }
|
||||
virtual ~sref() { dest_->desert_(this); }
|
||||
|
||||
T1*fore_ptr() { return dest_; }
|
||||
const T1*fore_ptr() const { return dest_; }
|
||||
|
|
@ -75,8 +76,6 @@ template <class T1, class T2> class sref {
|
|||
}
|
||||
}
|
||||
|
||||
// Not implemented yet.
|
||||
void desert_() { assert(0); }
|
||||
};
|
||||
|
||||
template <class T1,class T2>
|
||||
|
|
@ -102,8 +101,31 @@ svector<const T2*>* sref_back<T1,T2>::back_list() const
|
|||
return result;
|
||||
}
|
||||
|
||||
template <class T1, class T2> void sref_back<T1,T2>::desert_(sref<T1,T2>*item)
|
||||
{
|
||||
if (item == sback_)
|
||||
sback_ = item->next_;
|
||||
|
||||
if (item == sback_) {
|
||||
sback_ = 0;
|
||||
|
||||
} else {
|
||||
sref<T1,T2>*cur = sback_;
|
||||
while (cur->next_ != item) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
|
||||
cur->next_ = item->next_;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sref.h,v $
|
||||
* 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.
|
||||
*
|
||||
* Revision 1.1 1999/05/01 02:57:53 steve
|
||||
* Handle much more complex event expressions.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (c) 1999 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: xnfsyn.cc,v 1.1 1999/07/18 05:52:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The xnfsyn function searches the behavioral description for
|
||||
* patterns that are known to represent XNF library components. This
|
||||
* is especially interesting for the sequential components such as
|
||||
* flip flops and latches. As threads are transformed into components,
|
||||
* the design is rewritten.
|
||||
*
|
||||
* Currently, this transform recognizes the following patterns:
|
||||
*
|
||||
* always @(posedge CLK) Q = D // DFF
|
||||
*/
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
|
||||
class xnfsyn_f : public functor_t {
|
||||
|
||||
public:
|
||||
void process(class Design*, class NetProcTop*);
|
||||
|
||||
private:
|
||||
void proc_always(class Design*, class NetProcTop*);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Look at a process, and divide the problem into always and initial
|
||||
* threads.
|
||||
*/
|
||||
void xnfsyn_f::process(class Design*des, class NetProcTop*top)
|
||||
{
|
||||
switch (top->type()) {
|
||||
case NetProcTop::KALWAYS:
|
||||
proc_always(des, top);
|
||||
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.
|
||||
*/
|
||||
void xnfsyn_f::proc_always(class Design*des, class NetProcTop*top)
|
||||
{
|
||||
// The statement must be a NetPEvent, ...
|
||||
const NetProc*st = top->statement();
|
||||
const NetPEvent*ev = dynamic_cast<const NetPEvent*>(st);
|
||||
if (ev == 0)
|
||||
return;
|
||||
|
||||
// ... there must be a single event source, ...
|
||||
svector<const NetNEvent*>*neb = ev->back_list();
|
||||
if (neb == 0)
|
||||
return;
|
||||
if (neb->count() != 1) {
|
||||
delete neb;
|
||||
return;
|
||||
}
|
||||
const NetNEvent*nev = (*neb)[0];
|
||||
delete neb;
|
||||
|
||||
// ... the event must be POSEDGE, ...
|
||||
if (nev->type() != NetNEvent::POSEDGE)
|
||||
return;
|
||||
|
||||
// the NetPEvent must guard an assignment, ...
|
||||
const NetAssign*asn = dynamic_cast<const NetAssign*>(ev->statement());
|
||||
if (asn == 0)
|
||||
return;
|
||||
|
||||
// ... and the rval must be a simple signal.
|
||||
const NetESignal*sig = dynamic_cast<const NetESignal*>(asn->rval());
|
||||
if (sig == 0)
|
||||
return ;
|
||||
|
||||
// XXXX For now, only handle single bit.
|
||||
assert(asn->pin_count() == 1);
|
||||
assert(sig->pin_count() == 1);
|
||||
|
||||
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));
|
||||
|
||||
dff->attribute("XNF-LCA", "DFF:Q,D,CLK");
|
||||
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)
|
||||
{
|
||||
xnfsyn_f xnfsyn_obj;
|
||||
des->functor(&xnfsyn_obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: xnfsyn.cc,v $
|
||||
* 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