Redo synth to use match_proc_t scanner.

This commit is contained in:
steve
1999-12-01 06:06:16 +00:00
parent 998c039fd9
commit b30b695ff0
4 changed files with 181 additions and 152 deletions
+43 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #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 #endif
# include "functor.h" # include "functor.h"
@@ -80,8 +80,50 @@ void NetFF::functor_node(Design*des, functor_t*fun)
fun->lpm_ff(des, this); 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 $ * $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 * Revision 1.4 1999/11/18 03:52:19 steve
* Turn NetTmp objects into normal local NetNet objects, * Turn NetTmp objects into normal local NetNet objects,
* and add the nodangle functor to clean up the local * and add the nodangle functor to clean up the local
+13 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #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 #endif
/* /*
@@ -46,8 +46,20 @@ struct functor_t {
virtual void lpm_ff(class Design*des, class NetFF*); 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 $ * $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 * Revision 1.2 1999/11/01 02:07:40 steve
* Add the synth functor to do generic synthesis * Add the synth functor to do generic synthesis
* and add the LPM_FF device to handle rows of * and add the LPM_FF device to handle rows of
+11 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #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 #endif
/* /*
@@ -863,6 +863,10 @@ class NetProc : public LineInfo {
// target. The target returns true if OK, false for errors. // target. The target returns true if OK, false for errors.
virtual bool emit_proc(ostream&, struct target_t*) const; 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; virtual void dump(ostream&, unsigned ind) const;
private: private:
@@ -918,6 +922,7 @@ class NetAssign : public NetAssign_ {
virtual bool emit_proc(ostream&, struct target_t*) const; virtual bool emit_proc(ostream&, struct target_t*) const;
virtual void emit_node(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(ostream&, unsigned ind) const;
virtual void dump_node(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; void emit_recurse_else(ostream&, struct target_t*) const;
virtual bool emit_proc(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; virtual void dump(ostream&, unsigned ind) const;
private: private:
@@ -1173,6 +1179,7 @@ class NetPEvent : public NetProc, public sref_back<NetPEvent,NetNEvent> {
NetProc* statement(); NetProc* statement();
const NetProc* statement() const; const NetProc* statement() const;
virtual int match_proc(struct proc_match_t*);
virtual bool emit_proc(ostream&, struct target_t*) const; virtual bool emit_proc(ostream&, struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@@ -2044,6 +2051,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $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 * Revision 1.96 1999/11/28 23:42:02 steve
* NetESignal object no longer need to be NetNode * NetESignal object no longer need to be NetNode
* objects. Let them keep a pointer to NetNet objects. * objects. Let them keep a pointer to NetNet objects.
+114 -149
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #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 #endif
/* /*
@@ -26,8 +26,12 @@
* is especially interesting for the sequential components such as * is especially interesting for the sequential components such as
* flip flops and latches. As threads are transformed into components, * flip flops and latches. As threads are transformed into components,
* the design is rewritten. * 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 @(posedge CLK) Q = D
* always @(negedge CLK) Q = D * always @(negedge CLK) Q = D
@@ -39,8 +43,105 @@
* registers) and the CE must be single-bit identifiers. The generated * registers) and the CE must be single-bit identifiers. The generated
* device will be wide enough to accomodate Q and D. * device will be wide enough to accomodate Q and D.
*/ */
# include "functor.h" class match_dff : public proc_match_t {
# include "netlist.h"
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<class NetNEvent*>*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 { class synth_f : public functor_t {
@@ -49,20 +150,8 @@ class synth_f : public functor_t {
private: private:
void proc_always_(class Design*); void proc_always_(class Design*);
void proc_casn_(class Design*);
void proc_ccon_(class Design*);
// The matcher does something like a recursive descent search NetProcTop*top_;
// 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_;
}; };
@@ -85,141 +174,14 @@ void synth_f::process(class Design*des, class NetProcTop*top)
*/ */
void synth_f::proc_always_(class Design*des) void synth_f::proc_always_(class Design*des)
{ {
// The statement must be a NetPEvent, ... match_dff dff_pat(des, top_);
pclk_ = dynamic_cast<class NetPEvent*>(top_->statement()); if (top_->statement()->match_proc(&dff_pat)) {
if (pclk_ == 0) dff_pat.make_it();
return; des->delete_process(top_);
// ... there must be a single event source, ...
svector<class NetNEvent*>*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<NetAssign*>(pclk_->statement());
if (asn_) {
proc_casn_(des);
return;
}
con_ = dynamic_cast<NetCondit*>(pclk_->statement());
if (con_) {
proc_ccon_(des);
return; return;
} }
} }
/*
* The process so far has been matched as:
*
* always @(posedge nclk_) asn_ = <r>;
* always @(negedge nclk_) asn_ = <r>;
*/
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<NetAssign*>(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<NetESignal*>(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) void synth(Design*des)
{ {
@@ -229,6 +191,9 @@ void synth(Design*des)
/* /*
* $Log: synth.cc,v $ * $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 * Revision 1.2 1999/11/02 04:55:34 steve
* Add the synthesize method to NetExpr to handle * Add the synthesize method to NetExpr to handle
* synthesis of expressions, and use that method * synthesis of expressions, and use that method