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

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

View File

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

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.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<NetPEvent,NetNEvent> {
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.

263
synth.cc
View File

@ -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<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 {
@ -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<class NetPEvent*>(top_->statement());
if (pclk_ == 0)
return;
// ... 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);
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_ = <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)
{
@ -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