xnfsyn generates DFF objects for XNF output, and

properly rewrites the Design netlist in the process.
This commit is contained in:
steve 1999-07-18 05:52:46 +00:00
parent 9754507eb0
commit 7d876f7735
7 changed files with 262 additions and 17 deletions

View File

@ -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 \

View File

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

View File

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

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

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

132
xnfsyn.cc Normal file
View File

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