diff --git a/Makefile.in b/Makefile.in index 7580e80d0..df56cce76 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 \ diff --git a/functor.cc b/functor.cc index 841598f28..d7aee8e1b 100644 --- a/functor.cc +++ b/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. * diff --git a/main.cc b/main.cc index d63b20858..c4129cad5 100644 --- a/main.cc +++ b/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. * diff --git a/netlist.cc b/netlist.cc index 689d89a60..59c18b5dc 100644 --- a/netlist.cc +++ b/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 @@ -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(pe), edge_(e) +{ +} + +NetNEvent::~NetNEvent() +{ +} + +NetPEvent::NetPEvent(const string&n, NetProc*st) +: name_(n), statement_(st) +{ +} + +NetPEvent::~NetPEvent() +{ + svector*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&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. * diff --git a/netlist.h b/netlist.h index c3c2b3609..917f79b28 100644 --- a/netlist.h +++ b/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 { 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 { public: enum Type { ANYEDGE, POSEDGE, NEGEDGE, POSITIVE }; - NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe) - : NetNode(ev, wid), sref(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 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. * diff --git a/sref.h b/sref.h index 1d4a518af..425588311 100644 --- a/sref.h +++ b/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 @@ -47,6 +47,7 @@ template class sref_back { svector* back_list() const; private: + void desert_(sref*); sref*sback_; }; @@ -56,7 +57,7 @@ template 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 sref { } } - // Not implemented yet. - void desert_() { assert(0); } }; template @@ -102,8 +101,31 @@ svector* sref_back::back_list() const return result; } +template void sref_back::desert_(sref*item) +{ + if (item == sback_) + sback_ = item->next_; + + if (item == sback_) { + sback_ = 0; + + } else { + sref*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. * diff --git a/xnfsyn.cc b/xnfsyn.cc new file mode 100644 index 000000000..82a9007b5 --- /dev/null +++ b/xnfsyn.cc @@ -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(st); + if (ev == 0) + return; + + // ... there must be a single event source, ... + svector*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(ev->statement()); + if (asn == 0) + return; + + // ... and the rval must be a simple signal. + const NetESignal*sig = dynamic_cast(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. + * + */ +