Better synthesys of DFF w/ complex l-values. (Larry Doolittle)

This commit is contained in:
steve 2001-11-30 01:22:21 +00:00
parent 65f835f3eb
commit 0cebef872a
1 changed files with 49 additions and 34 deletions

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: syn-rules.y,v 1.16 2001/11/29 01:58:18 steve Exp $"
#ident "$Id: syn-rules.y,v 1.17 2001/11/30 01:22:21 steve Exp $"
#endif
# include "config.h"
@ -27,11 +27,11 @@
# include <iostream>
/*
* This file implements synthesys based on matching threads and
* converting them to equivilent devices. The trick here is that the
* This file implements synthesis based on matching threads and
* converting them to equivalent devices. The trick here is that the
* proc_match_t functor can be used to scan a process and generate a
* string of tokens. That string of tokens can then be matched by the
* rules to determin what kind of device is to be made.
* rules to determine what kind of device is to be made.
*/
# include "netlist.h"
@ -134,6 +134,34 @@ start
/* Various actions. */
static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
NetNet*ce, NetAssign_*a, unsigned rval_pinoffset)
{
// a->sig() is a *NetNet, which doesn't have the loff_ and
// lwid_ context. Add the correction for loff_ ourselves.
// This extra calculation allows for assignments like:
// lval[7:1] <= foo;
// where lval is really a "reg [7:0]". In other words, part
// selects in the l-value are handled by loff and the lwidth().
int loff = a->get_loff();
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
connect(ff->pin_Data(idx), d->bit(idx+rval_pinoffset));
connect(ff->pin_Q(idx), a->sig()->pin(idx+loff));
}
connect(ff->pin_Clock(), pclk->pin(0));
if (ce) connect(ff->pin_Enable(), ce->pin(0));
ff->attribute("LPM_FFType", "DFF");
if (pclk->edge() == NetEvProbe::NEGEDGE)
ff->attribute("Clock:LPM_Polarity", "INVERT");
}
static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
NetEvent*eclk, NetExpr*cexp, NetAssignBase*asn)
{
@ -150,39 +178,26 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
assert(d);
// FIXME!
// asn->l_val(0) is good as far as it goes, that's a
// *NetAssign_. Really need to chase the link list to the end,
// otherwise we don't assign properly to constructs like {a,b}.
// Should turn asn->l_val(0)->lwidth() below into
// asn->lwidth() and follow the linked list of l-values.
NetFF*ff = new NetFF(top->scope(), asn->l_val(0)->name(),
asn->l_val(0)->lwidth());
NetAssign_*a;
unsigned rval_pinoffset=0;
for (unsigned i=0; a=asn->l_val(i); i++) {
// asn->l_val(0)->sig() is a *NetNet, which doesn't have the
// loff_ and lwid_ context. Add the correction for loff_
// ourselves.
// asn->l_val(i) are the set of *NetAssign_'s that form the list
// of lval expressions. Treat each one independently, keeping
// track of which bits of rval to use for each set of DFF inputs.
// For example, given:
// {carry,data} <= x + y + z;
// run through this loop twice, where a and rval_pinoffset are
// first data and 0, then carry and 1.
// FIXME: ff gets its pin names wrong when loff_ is nonzero.
// This extra calculations allows for statments like, for
// example:
// lval[7:1] <= foo;
// where lval is really a "reg [7:0]". In other words, part
// selects in the l-value are handled by loff and the lwidth().
int loff = asn->l_val(0)->get_loff();
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
connect(ff->pin_Data(idx), d->bit(idx));
connect(ff->pin_Q(idx), asn->l_val(0)->sig()->pin(idx+loff));
// cerr << "new NetFF named " << a->name() << endl;
NetFF*ff = new NetFF(top->scope(), a->name(),
a->lwidth());
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
des->add_node(ff);
rval_pinoffset += a->lwidth();
}
connect(ff->pin_Clock(), pclk->pin(0));
if (ce) connect(ff->pin_Enable(), ce->pin(0));
ff->attribute("LPM_FFType", "DFF");
if (pclk->edge() == NetEvProbe::NEGEDGE)
ff->attribute("Clock:LPM_Polarity", "INVERT");
des->add_node(ff);
des->delete_process(top);
}