Handle statement output override better in blocks.
This commit is contained in:
parent
22884f2e64
commit
0e3768f829
17
net_link.cc
17
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.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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
51
synth2.cc
51
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.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.
|
||||
*
|
||||
|
|
|
|||
43
t-dll.cc
43
t-dll.cc
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue