Synthesizer support for synchronous begin-end blocks.
This commit is contained in:
parent
df5ae54ec7
commit
3d4593d4d5
18
net_link.cc
18
net_link.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_link.cc,v 1.11 2002/08/18 22:07:16 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.12 2002/10/21 01:42:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -484,8 +484,24 @@ bool NexusSet::contains(const NexusSet&that) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NexusSet::intersect(const NexusSet&that) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) {
|
||||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
continue;
|
||||
if (items_[where] == that[idx])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.12 2002/10/21 01:42:08 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
* Revision 1.11 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
|
|
|
|||
12
netlist.h
12
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.265 2002/10/19 22:59:49 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.266 2002/10/21 01:42:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -297,6 +297,9 @@ class NexusSet {
|
|||
// Return true if this set contains every nexus in that set.
|
||||
bool contains(const NexusSet&that) const;
|
||||
|
||||
// Return true if this set contains any nexus in that set.
|
||||
bool intersect(const NexusSet&that) const;
|
||||
|
||||
private:
|
||||
Nexus**items_;
|
||||
unsigned nitems_;
|
||||
|
|
@ -1411,6 +1414,10 @@ class NetBlock : public NetProc {
|
|||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
// This version of emit_recurse scans all the statements of
|
||||
// the begin-end block sequentially. It is typically of use
|
||||
// for sequential blocks.
|
||||
|
|
@ -3070,6 +3077,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.266 2002/10/21 01:42:08 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
* Revision 1.265 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
|
|
|
|||
102
synth2.cc
102
synth2.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: synth2.cc,v 1.15 2002/10/20 19:19:37 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.16 2002/10/21 01:42:09 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -292,6 +292,103 @@ bool NetProcTop::synth_async(Design*des)
|
|||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called when a block is encountered near the surface
|
||||
* of a synchronous always statement. For example, this code will be
|
||||
* invoked for input like this:
|
||||
*
|
||||
* always @(posedge clk...) begin
|
||||
* <statement1>
|
||||
* <statement2>
|
||||
* ...
|
||||
* end
|
||||
*
|
||||
* This needs to be split into a DFF bank for each statement, because
|
||||
* the statements may each infer different reset and enable signals.
|
||||
*/
|
||||
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
if (last_ == 0)
|
||||
return true;
|
||||
|
||||
bool flag = true;
|
||||
|
||||
NetProc*cur = last_;
|
||||
unsigned offset = 0;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
|
||||
/* Create a temporary nex_map for the substatement. */
|
||||
NexusSet tmp_set;
|
||||
cur->nex_output(tmp_set);
|
||||
NetNet*tmp_map = new NetNet(scope, "tmp1", NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
|
||||
connect(tmp_set[idx], tmp_map->pin(idx));
|
||||
|
||||
/* Create also a temporary net_out to collect the
|
||||
output. */
|
||||
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
|
||||
/* Create a new DFF to handle this part of the begin-end
|
||||
block. Connect this NetFF to the associated pins of
|
||||
the existing wide NetFF device. */
|
||||
NetFF*ff2 = new NetFF(scope, scope->local_hsymbol().c_str(),
|
||||
tmp_out->pin_count());
|
||||
des->add_node(ff2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
|
||||
connect(ff->pin_Data(idx+offset), ff2->pin_Data(idx));
|
||||
connect(ff->pin_Q(idx+offset), ff2->pin_Q(idx));
|
||||
}
|
||||
if (ff->pin_Aclr().is_linked())
|
||||
connect(ff->pin_Aclr(), ff2->pin_Aclr());
|
||||
if (ff->pin_Aset().is_linked())
|
||||
connect(ff->pin_Aset(), ff2->pin_Aset());
|
||||
if (ff->pin_Clock().is_linked())
|
||||
connect(ff->pin_Clock(), ff2->pin_Clock());
|
||||
if (ff->pin_Enable().is_linked())
|
||||
connect(ff->pin_Enable(),ff2->pin_Enable());
|
||||
|
||||
/* Now go on with the synchronous synthesis for this
|
||||
subset of the statement. */
|
||||
bool ok_flag = cur->synth_sync(des, scope, ff2, tmp_map,
|
||||
tmp_out, events_in);
|
||||
flag = flag && ok_flag;
|
||||
|
||||
if (ok_flag == false)
|
||||
continue;
|
||||
|
||||
/* Use the nex_map to link up the output from the
|
||||
substatement to the output of the block as a whole. */
|
||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
||||
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
|
||||
connect(nex_out->pin(ptr), tmp_out->pin(idx));
|
||||
}
|
||||
|
||||
delete tmp_map;
|
||||
delete tmp_out;
|
||||
offset += ff2->width();
|
||||
|
||||
} while (cur != last_);
|
||||
|
||||
/* Done. The large NetFF is no longer needed, as it has been
|
||||
taken up by the smaller NetFF devices. */
|
||||
assert(offset == ff->width());
|
||||
delete ff;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method handles the case where I find a conditional near the
|
||||
* surface of a synchronous thread. This conditional can be a CE or an
|
||||
* asynchronous set/reset, depending on whether the pin of the
|
||||
* expression is connected to an event, or not.
|
||||
*/
|
||||
bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
|
|
@ -558,6 +655,9 @@ void synth2(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.16 2002/10/21 01:42:09 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
* Revision 1.15 2002/10/20 19:19:37 steve
|
||||
* Handle conditional error cases better.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue