From b30b695ff054e3c99b842ebec4d4c349b6e507c2 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 1 Dec 1999 06:06:16 +0000 Subject: [PATCH] Redo synth to use match_proc_t scanner. --- functor.cc | 44 ++++++++- functor.h | 14 ++- netlist.h | 12 ++- synth.cc | 263 +++++++++++++++++++++++------------------------------ 4 files changed, 181 insertions(+), 152 deletions(-) diff --git a/functor.cc b/functor.cc index debf6d3aa..15ee3158c 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.4 1999/11/18 03:52:19 steve Exp $" +#ident "$Id: functor.cc,v 1.5 1999/12/01 06:06:16 steve Exp $" #endif # include "functor.h" @@ -80,8 +80,50 @@ void NetFF::functor_node(Design*des, functor_t*fun) fun->lpm_ff(des, this); } +proc_match_t::~proc_match_t() +{ +} + +int NetProc::match_proc(proc_match_t*that) +{ + return 0; +} + +int proc_match_t::assign(NetAssign*) +{ + return 0; +} + +int NetAssign::match_proc(proc_match_t*that) +{ + return that->assign(this); +} + +int proc_match_t::condit(NetCondit*) +{ + return 0; +} + +int NetCondit::match_proc(proc_match_t*that) +{ + return that->condit(this); +} + +int proc_match_t::pevent(NetPEvent*) +{ + return 0; +} + +int NetPEvent::match_proc(proc_match_t*that) +{ + return that->pevent(this); +} + /* * $Log: functor.cc,v $ + * Revision 1.5 1999/12/01 06:06:16 steve + * Redo synth to use match_proc_t scanner. + * * Revision 1.4 1999/11/18 03:52:19 steve * Turn NetTmp objects into normal local NetNet objects, * and add the nodangle functor to clean up the local diff --git a/functor.h b/functor.h index e3f549ab2..d9edf0a5d 100644 --- a/functor.h +++ b/functor.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.h,v 1.2 1999/11/01 02:07:40 steve Exp $" +#ident "$Id: functor.h,v 1.3 1999/12/01 06:06:16 steve Exp $" #endif /* @@ -46,8 +46,20 @@ struct functor_t { virtual void lpm_ff(class Design*des, class NetFF*); }; +struct proc_match_t { + virtual ~proc_match_t(); + + virtual int assign(class NetAssign*); + virtual int condit(class NetCondit*); + virtual int pevent(class NetPEvent*); +}; + + /* * $Log: functor.h,v $ + * Revision 1.3 1999/12/01 06:06:16 steve + * Redo synth to use match_proc_t scanner. + * * Revision 1.2 1999/11/01 02:07:40 steve * Add the synth functor to do generic synthesis * and add the LPM_FF device to handle rows of diff --git a/netlist.h b/netlist.h index 348864dac..6d07534b4 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.96 1999/11/28 23:42:02 steve Exp $" +#ident "$Id: netlist.h,v 1.97 1999/12/01 06:06:16 steve Exp $" #endif /* @@ -863,6 +863,10 @@ class NetProc : public LineInfo { // target. The target returns true if OK, false for errors. virtual bool emit_proc(ostream&, struct target_t*) const; + // This method is called by functors that want to scan a + // process in search of matchable patterns. + virtual int match_proc(struct proc_match_t*); + virtual void dump(ostream&, unsigned ind) const; private: @@ -918,6 +922,7 @@ class NetAssign : public NetAssign_ { virtual bool emit_proc(ostream&, struct target_t*) const; virtual void emit_node(ostream&, struct target_t*) const; + virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; virtual void dump_node(ostream&, unsigned ind) const; @@ -1080,6 +1085,7 @@ class NetCondit : public NetProc { void emit_recurse_else(ostream&, struct target_t*) const; virtual bool emit_proc(ostream&, struct target_t*) const; + virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; private: @@ -1173,6 +1179,7 @@ class NetPEvent : public NetProc, public sref_back { NetProc* statement(); const NetProc* statement() const; + virtual int match_proc(struct proc_match_t*); virtual bool emit_proc(ostream&, struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2044,6 +2051,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.97 1999/12/01 06:06:16 steve + * Redo synth to use match_proc_t scanner. + * * Revision 1.96 1999/11/28 23:42:02 steve * NetESignal object no longer need to be NetNode * objects. Let them keep a pointer to NetNet objects. diff --git a/synth.cc b/synth.cc index 08e2276eb..e25a9ae18 100644 --- a/synth.cc +++ b/synth.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: synth.cc,v 1.2 1999/11/02 04:55:34 steve Exp $" +#ident "$Id: synth.cc,v 1.3 1999/12/01 06:06:16 steve Exp $" #endif /* @@ -26,8 +26,12 @@ * 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: + */ +# include "functor.h" +# include "netlist.h" + +/* + * This transform recognizes the following patterns: * * always @(posedge CLK) Q = D * always @(negedge CLK) Q = D @@ -39,8 +43,105 @@ * registers) and the CE must be single-bit identifiers. The generated * device will be wide enough to accomodate Q and D. */ -# include "functor.h" -# include "netlist.h" +class match_dff : public proc_match_t { + + public: + match_dff(Design*d, NetProcTop*t) + : des_(d), top_(t), pclk_(0), nclk_(0), con_(0), ce_(0), + asn_(0), d_(0) + { } + + ~match_dff() { } + + void make_it(); + + private: + virtual int assign(NetAssign*); + virtual int condit(NetCondit*); + virtual int pevent(NetPEvent*); + + Design*des_; + NetProcTop*top_; + NetPEvent*pclk_; + NetNEvent*nclk_; + + NetCondit *con_; + NetNet*ce_; + NetAssign *asn_; + + NetNet*d_; +}; + +int match_dff::assign(NetAssign*as) +{ + if (!pclk_) + return 0; + if (asn_) + return 0; + + asn_ = as; + d_ = asn_->rval()->synthesize(des_); + if (d_ == 0) + return 0; + + return 1; +} + +int match_dff::condit(NetCondit*co) +{ + if (!pclk_) + return 0; + if (con_ || asn_) + return 0; + + con_ = co; + if (con_->else_clause()) + return 0; + ce_ = con_->expr()->synthesize(des_); + if (ce_ == 0) + return 0; + + return con_->if_clause()->match_proc(this); +} + +int match_dff::pevent(NetPEvent*pe) +{ + if (pclk_ || con_ || asn_) + return 0; + + pclk_ = pe; + + // ... there must be a single event source, ... + svector*neb = pclk_->back_list(); + if (neb == 0) + return 0; + if (neb->count() != 1) { + delete neb; + return 0; + } + nclk_ = (*neb)[0]; + delete neb; + return pclk_->statement()->match_proc(this); +} + +void match_dff::make_it() +{ + NetFF*ff = new NetFF(asn_->name(), asn_->pin_count()); + + for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) { + connect(ff->pin_Data(idx), d_->pin(idx)); + connect(ff->pin_Q(idx), asn_->pin(idx)); + } + + connect(ff->pin_Clock(), nclk_->pin(0)); + if (ce_) connect(ff->pin_Enable(), ce_->pin(0)); + + ff->attribute("LPM_FFType", "DFF"); + if (nclk_->type() == NetNEvent::NEGEDGE) + ff->attribute("Clock:LPM_Polarity", "INVERT"); + + des_->add_node(ff); +} class synth_f : public functor_t { @@ -49,20 +150,8 @@ class synth_f : public functor_t { private: 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_; + NetProcTop*top_; }; @@ -85,141 +174,14 @@ void synth_f::process(class Design*des, class NetProcTop*top) */ void synth_f::proc_always_(class Design*des) { - // The statement must be a NetPEvent, ... - pclk_ = dynamic_cast(top_->statement()); - if (pclk_ == 0) - return; - - // ... there must be a single event source, ... - svector*neb = pclk_->back_list(); - if (neb == 0) - return; - if (neb->count() != 1) { - delete neb; - return; - } - nclk_ = (*neb)[0]; - delete neb; - - // ... the event must be an edge, ... - switch (nclk_->type()) { - case NetNEvent::POSEDGE: - case NetNEvent::NEGEDGE: - break; - default: - return; - } - - // Is this a clocked assignment? - asn_ = dynamic_cast(pclk_->statement()); - if (asn_) { - proc_casn_(des); - return; - } - - con_ = dynamic_cast(pclk_->statement()); - if (con_) { - proc_ccon_(des); + match_dff dff_pat(des, top_); + if (top_->statement()->match_proc(&dff_pat)) { + dff_pat.make_it(); + des->delete_process(top_); return; } } -/* - * The process so far has been matched as: - * - * always @(posedge nclk_) asn_ = ; - * always @(negedge nclk_) asn_ = ; - */ -void synth_f::proc_casn_(class Design*des) -{ - // Turn the r-value into gates. - NetNet*sig = asn_->rval()->synthesize(des); - assert(sig); - - // The signal and the assignment must be the same width... - assert(asn_->pin_count() == sig->pin_count()); - - NetFF*ff = new NetFF(asn_->name(), asn_->pin_count()); - ff->attribute("LPM_FFType", "DFF"); - - for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) { - connect(ff->pin_Data(idx), sig->pin(idx)); - connect(ff->pin_Q(idx), asn_->pin(idx)); - } - - switch (nclk_->type()) { - case NetNEvent::POSEDGE: - connect(ff->pin_Clock(), nclk_->pin(0)); - break; - - case NetNEvent::NEGEDGE: - connect(ff->pin_Clock(), nclk_->pin(0)); - ff->attribute("Clock:LPM_Polarity", "INVERT"); - break; - } - - des->add_node(ff); - - // This process is matched and replaced with a DFF. Get - // rid of the now useless NetProcTop. - des->delete_process(top_); -} - -/* - * The process so far has been matched as: - * - * always @(posedge nclk_) if ...; - * always @(negedge nclk_) if ...; - */ -void synth_f::proc_ccon_(class Design*des) -{ - if (con_->else_clause()) - return; - - asn_ = dynamic_cast(con_->if_clause()); - if (asn_ == 0) - return; - - NetNet*sig = asn_->rval()->synthesize(des); - assert(sig); - - // The signal and the assignment must be the same width... - assert(asn_->pin_count() == sig->pin_count()); - - NetESignal*ce = dynamic_cast(con_->expr()); - if (ce == 0) - return; - if (ce->pin_count() != 1) - return; - - NetFF*ff = new NetFF(asn_->name(), asn_->pin_count()); - ff->attribute("LPM_FFType", "DFF"); - - for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) { - connect(ff->pin_Data(idx), sig->pin(idx)); - connect(ff->pin_Q(idx), asn_->pin(idx)); - } - - switch (nclk_->type()) { - case NetNEvent::POSEDGE: - connect(ff->pin_Clock(), nclk_->pin(0)); - connect(ff->pin_Enable(), ce->pin(0)); - break; - - case NetNEvent::NEGEDGE: - connect(ff->pin_Clock(), nclk_->pin(0)); - connect(ff->pin_Enable(), ce->pin(0)); - ff->attribute("Clock:LPM_Polarity", "INVERT"); - break; - } - - des->add_node(ff); - - - // This process is matched and replaced with a DFF. Get - // rid of the now useless NetProcTop. - des->delete_process(top_); -} void synth(Design*des) { @@ -229,6 +191,9 @@ void synth(Design*des) /* * $Log: synth.cc,v $ + * Revision 1.3 1999/12/01 06:06:16 steve + * Redo synth to use match_proc_t scanner. + * * Revision 1.2 1999/11/02 04:55:34 steve * Add the synthesize method to NetExpr to handle * synthesis of expressions, and use that method