Handle statement output override better in blocks.

This commit is contained in:
steve 2006-07-23 19:42:33 +00:00
parent 22884f2e64
commit 0e3768f829
5 changed files with 113 additions and 23 deletions

View File

@ -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.14.2.2 2006/01/27 02:05:46 steve Exp $"
#ident "$Id: net_link.cc,v 1.14.2.3 2006/07/23 19:42:33 steve Exp $"
#endif
# include "config.h"
@ -244,6 +244,18 @@ verinum::V Nexus::get_init() const
return verinum::Vz;
}
int Nexus::is_driven() const
{
int count = 0;
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() == Link::OUTPUT)
count += 1;
}
return count;
}
void Nexus::unlink(Link*that)
{
if (name_) {
@ -501,6 +513,9 @@ bool NexusSet::intersect(const NexusSet&that) const
/*
* $Log: net_link.cc,v $
* Revision 1.14.2.3 2006/07/23 19:42:33 steve
* Handle statement output override better in blocks.
*
* Revision 1.14.2.2 2006/01/27 02:05:46 steve
* Speed up processing of connect when one side is empty.
*

View File

@ -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.321.2.20 2006/07/10 00:21:51 steve Exp $"
#ident "$Id: netlist.h,v 1.321.2.21 2006/07/23 19:42:33 steve Exp $"
#endif
/*
@ -264,6 +264,9 @@ class Nexus {
Link*first_nlink();
const Link* first_nlink()const;
/* Return the number of drivers, or 0 if undriven. */
int is_driven() const;
/* This method returns true if all the possible drivers of
this nexus are constant. It will also return true if there
are no drivers at all. */
@ -3537,6 +3540,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.321.2.21 2006/07/23 19:42:33 steve
* Handle statement output override better in blocks.
*
* Revision 1.321.2.20 2006/07/10 00:21:51 steve
* Add support for full_case attribute.
*

View File

@ -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.39.2.39 2006/07/10 00:21:54 steve Exp $"
#ident "$Id: synth2.cc,v 1.39.2.40 2006/07/23 19:42:34 steve Exp $"
#endif
# include "config.h"
@ -328,7 +328,8 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag,
if (debug_synth) {
cerr << get_line() << ": debug: "
<< (sync_flag?"sync":"async")
<< " synthesis of statement block." << endl;
<< " synthesis of statement block. "
<< "pin_count=" << nex_out->pin_count() << endl;
}
const perm_string tmp1 = perm_string::literal("tmp1");
@ -391,6 +392,7 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag,
new_accum = new NetNet(scope, tmp3, NetNet::WIRE,
nex_out->pin_count());
new_accum->set_line(*this);
new_accum->local_flag(true);
/* Use the nex_map to link up the output from the
substatement to the output of the block as a whole. */
@ -410,11 +412,20 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag,
delete tmp_map;
delete tmp_out;
assert(new_accum->pin_count() == accum_out->pin_count());
/* Anything that is not redriven by the current
statement inherits the value that was driven from any
previous statements. */
previous statements. Thus, the current statement can
*override* the outputs of any previous statements. */
for (unsigned idx = 0; idx < new_accum->pin_count(); idx += 1) {
if (new_accum->pin(idx).is_linked())
#if 0
cerr << cur->get_line() << ": XXXX: "
<< "Bit " << idx << " new_accum has "
<< new_accum->pin(idx).nexus()->is_driven()
<< " drivers." << endl;
#endif
if (new_accum->pin(idx).nexus()->is_driven())
continue;
connect(new_accum->pin(idx), accum_out->pin(idx));
@ -424,15 +435,27 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag,
} while (cur != last_);
/* Now bind the accumulated output valies to the nex_out
/* Now bind the accumulated output values to the nex_out
passed in. Note that each previous step has already did the
pin mapping, so just connect. */
assert(nex_out->pin_count() == accum_out->pin_count());
for (unsigned idx = 0 ; idx < accum_out->pin_count() ; idx += 1) {
connect(nex_out->pin(idx), accum_out->pin(idx));
}
delete accum_out;
if (debug_synth) {
cerr << get_line() << ": debug: "
<< (sync_flag?"sync":"async")
<< " synthesis of statement block complete. " << endl;
#if 0
for (unsigned idx = 0 ; idx < nex_out->pin_count() ; idx += 1)
cerr << get_line() << ": XXXX: Bit " << idx
<< " has " << nex_out->pin(idx).nexus()->is_driven()
<< " drivers." << endl;
#endif
}
return flag;
}
@ -1029,6 +1052,12 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
mux_width, 2, 1);
mux->set_line(*this);
if (debug_synth) {
cerr << get_line() << ": debug: Condit synth to MUX "
<< " width=" << mux_width
<< " sel_width=1" << endl;
}
connect(mux->pin_Sel(0), ssig->pin(0));
/* Connected the clauses to the data inputs of the
@ -1046,6 +1075,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
flag |= 0010;
if (accum->pin(idx).is_linked())
flag |= 0001;
switch (flag) {
case 0111:
case 0110:
@ -1328,10 +1358,13 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
}
NetFF*ff = nex_ff[0].ff;
assert(ff->width() == nex_out->pin_count());
unsigned block_width = nex_out->pin_count();
verinum tmp_aset = ff->aset_value();
verinum tmp_sset = ff->sset_value();
bool flag = true;
const perm_string tmp1 = perm_string::literal("tmp1");
@ -1361,9 +1394,6 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
NetNet*tmp_out = new NetNet(scope, tmp2, NetNet::WIRE,
tmp_map->pin_count());
verinum tmp_aset = ff->aset_value();
verinum tmp_sset = ff->sset_value();
/* 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. While I'm at it, also
@ -2211,6 +2241,9 @@ void synth2(Design*des)
/*
* $Log: synth2.cc,v $
* Revision 1.39.2.40 2006/07/23 19:42:34 steve
* Handle statement output override better in blocks.
*
* Revision 1.39.2.39 2006/07/10 00:21:54 steve
* Add support for full_case attribute.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.131.2.7 2006/04/16 19:26:40 steve Exp $"
#ident "$Id: t-dll.cc,v 1.131.2.8 2006/07/23 19:42:35 steve Exp $"
#endif
# include "config.h"
@ -1573,10 +1573,12 @@ bool dll_target::lpm_demux(const NetDemux*net)
for (idx = 0 ; idx < width ; idx += 1) {
const Nexus*nex = net->pin_Q(idx).nexus();
assert(nex->t_cookie());
obj->u_.demux.q[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.demux.q[idx], obj, idx,
IVL_DR_STRONG, IVL_DR_STRONG);
/* It is possible, but unlikely, that the Q is unused. */
if (obj->u_.demux.q[idx])
nexus_lpm_add(obj->u_.demux.q[idx], obj, idx,
IVL_DR_STRONG, IVL_DR_STRONG);
}
for (idx = 0 ; idx < width ; idx += 1) {
@ -1982,10 +1984,34 @@ void dll_target::lpm_mux(const NetMux*net)
for (unsigned idx = 0 ; idx < obj->u_.mux.width ; idx += 1) {
nex = net->pin_Result(idx).nexus();
assert(nex->t_cookie());
#if 0
if (! nex->t_cookie()) {
cerr << net->get_line() << ": internal error: "
<< "broken mux. name=" << net->name()
<< ", width=" << obj->u_.mux.width
<< ", swid=" << obj->u_.mux.swid << endl;
for (unsigned tmp = 0; tmp < obj->u_.mux.width; tmp += 1) {
const Nexus*tmpn = net->pin_Result(tmp).nexus();
if (tmpn->t_cookie() == 0)
continue;
cerr << net->get_line() << ": XXXX "
<< "Result(" << tmp << ") : "
<< tmpn->name() << endl;
}
}
#endif
obj->u_.mux.q.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
/* It is possible (although unlikely) that the
result bit of the mux is not used. This can
happen, for example, if the output is
overridden in the HDL. In that case, skip
it. But if the bit is used, then add it to the
nexus. */
if (obj->u_.mux.q.pins[idx])
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
}
}
@ -2334,6 +2360,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.131.2.8 2006/07/23 19:42:35 steve
* Handle statement output override better in blocks.
*
* Revision 1.131.2.7 2006/04/16 19:26:40 steve
* Fix handling of exploded memories with partial or missing resets.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.90.2.9 2006/04/16 19:26:41 steve Exp $"
#ident "$Id: stub.c,v 1.90.2.10 2006/07/23 19:42:35 steve Exp $"
#endif
# include "config.h"
@ -247,9 +247,11 @@ static void show_lpm_demux(ivl_lpm_t net)
fprintf(out, " ERROR: width %% size == %u\n", width%size);
}
for (idx = 0 ; idx < width ; idx += 1)
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_q(net, idx);
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
nex? ivl_nexus_name(nex) : "");
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx);
fprintf(out, " Data %u: %s\n", idx,
@ -509,9 +511,11 @@ static void show_lpm(ivl_lpm_t net)
ivl_lpm_basename(net), width, ivl_lpm_size(net),
ivl_lpm_selects(net));
for (idx = 0 ; idx < width ; idx += 1)
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_q(net, idx);
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
nex? ivl_nexus_name(nex) : "");
}
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1)
fprintf(out, " S %u: %s\n", idx,
@ -1114,6 +1118,9 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.90.2.10 2006/07/23 19:42:35 steve
* Handle statement output override better in blocks.
*
* Revision 1.90.2.9 2006/04/16 19:26:41 steve
* Fix handling of exploded memories with partial or missing resets.
*