From a0ec981c50a0b4724011378f0365cc0c58ac1741 Mon Sep 17 00:00:00 2001 From: steve Date: Tue, 8 Aug 2006 02:17:48 +0000 Subject: [PATCH] Improved nexus management performance. --- expr_synth.cc | 8 +- net_link.cc | 101 +++++++++++++--- net_nex_output.cc | 6 +- netlist.h | 7 +- synth2.cc | 296 ++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 370 insertions(+), 48 deletions(-) diff --git a/expr_synth.cc b/expr_synth.cc index 424035ba4..3784f3e61 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: expr_synth.cc,v 1.59.2.8 2006/06/15 01:57:26 steve Exp $" +#ident "$Id: expr_synth.cc,v 1.59.2.9 2006/08/08 02:17:48 steve Exp $" #endif # include "config.h" @@ -742,6 +742,9 @@ NetNet* NetEMemory::synthesize(Design*des) connect(mux->pin_Data(idx, wrd), explode->pin(bit)); } + if (debug_synth) + cerr << get_line() << ": debug: synthesis done." << endl; + } else { cerr << get_line() << ": internal error: Synthesize memory " << "expression that is not exploded?" << endl; @@ -1003,6 +1006,9 @@ NetNet* NetESignal::synthesize(Design*des) /* * $Log: expr_synth.cc,v $ + * Revision 1.59.2.9 2006/08/08 02:17:48 steve + * Improved nexus management performance. + * * Revision 1.59.2.8 2006/06/15 01:57:26 steve * Handle simple memory addressing in expression synthesis. * diff --git a/net_link.cc b/net_link.cc index fda43e7c6..a9f59c3fc 100644 --- a/net_link.cc +++ b/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.3 2006/07/23 19:42:33 steve Exp $" +#ident "$Id: net_link.cc,v 1.14.2.4 2006/08/08 02:17:48 steve Exp $" #endif # include "config.h" @@ -40,8 +40,8 @@ void connect(Nexus*l, Link&r) if (l == r.nexus_) return; - Nexus*tmp = r.nexus_; + while (Link*cur = tmp->list_) { tmp->list_ = cur->next_; cur->nexus_ = 0; @@ -49,9 +49,6 @@ void connect(Nexus*l, Link&r) l->relink(cur); } - l->driven_ = Nexus::NO_GUESS; - - assert(tmp->list_ == 0); delete tmp; } @@ -60,6 +57,8 @@ void connect(Link&l, Link&r) assert(&l != &r); if (r.is_linked() && !l.is_linked()) connect(r.nexus_, l); + else if (r.nexus_->list_len_ > l.nexus_->list_len_) + connect(r.nexus_, l); else connect(l.nexus_, r); } @@ -218,6 +217,7 @@ Nexus::Nexus() { name_ = 0; list_ = 0; + list_len_ = 0; driven_ = NO_GUESS; t_cookie_ = 0; } @@ -269,10 +269,12 @@ void Nexus::unlink(Link*that) driven_ = NO_GUESS; assert(that); + assert(that->nexus_ == this); if (list_ == that) { list_ = that->next_; that->next_ = 0; that->nexus_ = 0; + list_len_ -= 1; return; } @@ -285,6 +287,7 @@ void Nexus::unlink(Link*that) cur->next_ = that->next_; that->nexus_ = 0; that->next_ = 0; + list_len_ -= 1; } void Nexus::relink(Link*that) @@ -304,6 +307,7 @@ void Nexus::relink(Link*that) that->next_ = list_; that->nexus_ = this; list_ = that; + list_len_ += 1; } Link* Nexus::first_nlink() @@ -393,6 +397,7 @@ const char* Nexus::name() const NexusSet::NexusSet() { items_ = 0; + index_ = 0; nitems_ = 0; } @@ -401,8 +406,11 @@ NexusSet::~NexusSet() if (nitems_ > 0) { assert(items_ != 0); delete[] items_; + assert(index_ != 0); + delete[] index_; } else { assert(items_ == 0); + assert(index_ == 0); } } @@ -411,26 +419,44 @@ unsigned NexusSet::count() const return nitems_; } +/* + * Add the Nexus to the nexus set at the *end* of the array. This + * preserves order, which is used in a few cases by the + * synthesizer. But for efficiency, also create a sorted index. + */ void NexusSet::add(Nexus*that) { + /* Handle the special case that the set is empty. */ if (nitems_ == 0) { assert(items_ == 0); + assert(index_ == 0); items_ = (Nexus**)malloc(sizeof(Nexus*)); items_[0] = that; + index_ = (unsigned*)malloc(sizeof(unsigned)); + index_[0] = 0; nitems_ = 1; return; } unsigned ptr = bsearch_(that); - if (ptr < nitems_) { - assert(items_[ptr] == that); + if (ptr < nitems_ && items_[index_[ptr]] == that) { + assert(items_[index_[ptr]] == that); return; } - assert(ptr == nitems_); + items_ = (Nexus**) realloc(items_, (nitems_+1) * sizeof(Nexus*)); + index_ = (unsigned*)realloc(index_, (nitems_+1) * sizeof(unsigned)); + + items_[nitems_] = that; + + unsigned dest = nitems_; + for (unsigned idx = ptr ; idx < nitems_ ; idx += 1) { + unsigned tmp = index_[idx]; + index_[idx] = dest; + dest = tmp; + } + index_[nitems_] = dest; - items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*)); - items_[ptr] = that; nitems_ += 1; } @@ -446,20 +472,31 @@ void NexusSet::rem(Nexus*that) return; unsigned ptr = bsearch_(that); - if (ptr >= nitems_) + if (ptr >= nitems_ || items_[index_[ptr]] != that) return; if (nitems_ == 1) { free(items_); + free(index_); items_ = 0; + index_ = 0; nitems_ = 0; return; } - for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1) + unsigned index_ptr = index_[ptr]; + for (unsigned idx = index_ptr ; idx < (nitems_-1) ; idx += 1) items_[idx] = items_[idx+1]; - items_ = (Nexus**)realloc(items_, (nitems_-1) * sizeof(Nexus*)); + for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1) + index_[idx] = index_[idx+1]; + + for (unsigned idx = 0 ; idx < (nitems_-1) ; idx += 1) + if (index_[idx] > index_ptr) + index_[idx] -= 1; + + items_ = (Nexus**) realloc(items_, (nitems_-1) * sizeof(Nexus*)); + index_ = (unsigned*)realloc(index_, (nitems_-1) * sizeof(unsigned)); nitems_ -= 1; } @@ -475,14 +512,37 @@ Nexus* NexusSet::operator[] (unsigned idx) const return items_[idx]; } +/* + * This method uses binary search to locate the item in the list of + * nexus pointers. If the item is in the set, then this method returns + * the index where it exists in the *index* array. If the item is not + * in the set, the index points to where in the array the item should go. + */ unsigned NexusSet::bsearch_(Nexus*that) const { - for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { - if (items_[idx] == that) - return idx; + + unsigned low = 0, hig = nitems_; + + while (low < hig) { + unsigned mid = (low + hig) / 2; + if (mid == hig) mid -= 1; + assert(mid >= low); + assert(mid < hig); + + if (items_[index_[mid]] == that) { + return mid; + + } else if (items_[index_[mid]] > that) { + hig = mid; + + } else { + low = mid+1; + } } - return nitems_; + assert(low == hig); + assert(low == nitems_ || items_[index_[low]] >= that); + return low; } bool NexusSet::contains(const NexusSet&that) const @@ -491,7 +551,7 @@ bool NexusSet::contains(const NexusSet&that) const unsigned where = bsearch_(that[idx]); if (where == nitems_) return false; - if (items_[where] != that[idx]) + if (items_[index_[where]] != that[idx]) return false; } @@ -504,7 +564,7 @@ bool NexusSet::intersect(const NexusSet&that) const unsigned where = bsearch_(that[idx]); if (where == nitems_) continue; - if (items_[where] == that[idx]) + if (items_[index_[where]] == that[idx]) return true; } @@ -513,6 +573,9 @@ bool NexusSet::intersect(const NexusSet&that) const /* * $Log: net_link.cc,v $ + * Revision 1.14.2.4 2006/08/08 02:17:48 steve + * Improved nexus management performance. + * * Revision 1.14.2.3 2006/07/23 19:42:33 steve * Handle statement output override better in blocks. * diff --git a/net_nex_output.cc b/net_nex_output.cc index 9e86a6756..7f7f919b9 100644 --- a/net_nex_output.cc +++ b/net_nex_output.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_nex_output.cc,v 1.11.2.7 2006/06/02 23:42:48 steve Exp $" +#ident "$Id: net_nex_output.cc,v 1.11.2.8 2006/08/08 02:17:48 steve Exp $" #endif # include "config.h" @@ -115,7 +115,6 @@ void NetBlock::nex_output(NexusSet&out) return; NetProc*cur = last_->next_; - NexusSet accum; do { cur->nex_output(out); cur = cur->next_; @@ -168,6 +167,9 @@ void NetWhile::nex_output(NexusSet&out) /* * $Log: net_nex_output.cc,v $ + * Revision 1.11.2.8 2006/08/08 02:17:48 steve + * Improved nexus management performance. + * * Revision 1.11.2.7 2006/06/02 23:42:48 steve * Compilation warnings. * diff --git a/netlist.h b/netlist.h index bb5d4f6e1..cfef4fc23 100644 --- a/netlist.h +++ b/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.321.2.21 2006/07/23 19:42:33 steve Exp $" +#ident "$Id: netlist.h,v 1.321.2.22 2006/08/08 02:17:48 steve Exp $" #endif /* @@ -281,6 +281,7 @@ class Nexus { private: Link*list_; + int list_len_; void unlink(Link*); void relink(Link*); @@ -321,6 +322,7 @@ class NexusSet { private: Nexus**items_; + unsigned*index_; unsigned nitems_; unsigned bsearch_(Nexus*that) const; @@ -3540,6 +3542,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.321.2.22 2006/08/08 02:17:48 steve + * Improved nexus management performance. + * * Revision 1.321.2.21 2006/07/23 19:42:33 steve * Handle statement output override better in blocks. * diff --git a/synth2.cc b/synth2.cc index 7c14b832f..73ae0a692 100644 --- a/synth2.cc +++ b/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.40 2006/07/23 19:42:34 steve Exp $" +#ident "$Id: synth2.cc,v 1.39.2.41 2006/08/08 02:17:49 steve Exp $" #endif # include "config.h" @@ -71,7 +71,7 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, { return synth_async_noaccum(des, scope, true, nex_ff, nex_map, nex_out); } - +#if 0 static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex) { unsigned idx = 0; @@ -81,6 +81,48 @@ static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex) return idx; } +#endif +struct nexus_map_t { + const Nexus*nex; + int idx; +}; +static int ncp_compare(const void*p1, const void*p2) +{ + const Nexus*a1 = ((const struct nexus_map_t*)p1) -> nex; + const Nexus*a2 = ((const struct nexus_map_t*)p2) -> nex; + if (a1 < a2) + return -1; + if (a1 > a2) + return 1; + return 0; +} + +static struct nexus_map_t*make_nexus_index(const NetNet*nset) +{ + struct nexus_map_t*table = new struct nexus_map_t[nset->pin_count()]; + for (unsigned idx = 0 ; idx < nset->pin_count() ; idx += 1) { + table[idx].nex = nset->pin(idx).nexus(); + table[idx].idx = idx; + } + qsort(table, nset->pin_count(), sizeof(struct nexus_map_t), ncp_compare); + return table; +} + +static int map_nexus_in_index(struct nexus_map_t*table, size_t ntable, + const Nexus*nex) +{ + struct nexus_map_t key; + key.nex = nex; + struct nexus_map_t*res = (struct nexus_map_t*) + bsearch(&key, table, ntable, + sizeof(struct nexus_map_t), ncp_compare); + + if (res == 0) + return -1; + + assert(res->nex == nex); + return res->idx; +} /* * Async synthesis of assignments is done by synthesizing the rvalue @@ -191,13 +233,20 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, connect(nex_ff[0].ff->pin_Q(off), dq->pin_Data(idx)); } + struct nexus_map_t*nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1) { unsigned off = cur->get_loff()+idx; - unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus()); - assert(ptr < nex_out->pin_count()); + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + lsig->pin(off).nexus()); + assert(tmp >= 0); + unsigned ptr = tmp; connect(nex_out->pin(ptr), dq->pin_Q(idx)); } + delete[]nex_map_idx; + /* The r-value (1 bit) connects to the WriteData input of the demux. */ connect(dq->pin_WriteData(0), rsig->pin(roff)); @@ -214,11 +263,16 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag, /* Bind the outputs that we do make to the nex_out. Use the nex_map to map the l-value bit position to the nex_out bit position. */ + + struct nexus_map_t*nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) { unsigned off = cur->get_loff()+idx; - unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus()); - - assert(ptr <= nex_map->pin_count()); + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + lsig->pin(off).nexus()); + assert(tmp >= 0); + unsigned ptr = tmp; connect(nex_out->pin(ptr), rsig->pin(roff+idx)); } @@ -250,6 +304,11 @@ bool NetAssignBase::synth_async_mem_sync_(Design*des, NetScope*scope, NetMemory*lmem = cur->mem(); assert(lmem); + if (debug_synth) { + cerr << get_line() << ": debug: Start synthesis of assign " + "to memory " << lmem->name() << "." << endl; + } + NetNet*msig = lmem->explode_to_reg(); cur->incr_mem_lref(); @@ -266,14 +325,21 @@ bool NetAssignBase::synth_async_mem_sync_(Design*des, NetScope*scope, return false; } + struct nexus_map_t*nex_map_idx = make_nexus_index(nex_map); + unsigned adr = lmem->index_to_address(adr_s) * lmem->width(); for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) { unsigned off = adr+idx; - unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus()); - assert(ptr <= nex_map->pin_count()); + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + msig->pin(off).nexus()); + assert(tmp >= 0); + unsigned ptr = tmp; connect(nex_out->pin(ptr), rsig->pin(roff+idx)); } + delete[]nex_map_idx; + cur->turn_sig_to_wire_on_release(); return true; } @@ -292,13 +358,20 @@ bool NetAssignBase::synth_async_mem_sync_(Design*des, NetScope*scope, for (unsigned idx = 0; idx < adr->pin_count() ; idx += 1) connect(dq->pin_Address(idx), adr->pin(idx)); + struct nexus_map_t*nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0; idx < msig->pin_count(); idx += 1) { unsigned off = idx; - unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus()); - assert(ptr <= nex_map->pin_count()); + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + msig->pin(off).nexus()); + assert(tmp >= 0); + unsigned ptr = tmp; connect(nex_out->pin(ptr), dq->pin_Q(idx)); } + delete[]nex_map_idx; + for (unsigned idx = 0 ; idx < msig->pin_count(); idx += 1) connect(dq->pin_Data(idx), nex_map->pin(roff+idx)); @@ -308,6 +381,11 @@ bool NetAssignBase::synth_async_mem_sync_(Design*des, NetScope*scope, roff += cur->lwidth(); cur->turn_sig_to_wire_on_release(); + if (debug_synth) { + cerr << get_line() << ": debug: Finish synthesis of assign " + "to memory " << lmem->name() << "." << endl; + } + return true; } @@ -367,12 +445,20 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag, handle default cases specially. We will delete this temporary map as soon as the synth_async is done. */ new_accum = new NetNet(scope, tmp3, NetNet::WIRE, tmp_set.count()); + struct nexus_map_t*nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0 ; idx < tmp_set.count() ; idx += 1) { - unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]); + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + tmp_set[idx]); + assert(tmp >= 0); + unsigned ptr = tmp; if (accum_out->pin(ptr).is_linked()) connect(new_accum->pin(idx), accum_out->pin(ptr)); } + delete [] nex_map_idx; + bool ok_flag = cur->synth_async(des, scope, sync_flag, nex_ff, tmp_map, tmp_out, new_accum); flag = flag && ok_flag; @@ -395,20 +481,29 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag, 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. */ + substatement to the output of the block as a + whole. */ + + nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) { - unsigned ptr = find_nexus_in_set(nex_map, tmp_map->pin(idx).nexus()); - if (ptr >= nex_map->pin_count()) { + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + tmp_map->pin(idx).nexus()); + if (tmp < 0) { cerr << cur->get_line() << ": internal error: " << "Nexus isn't in nex_map?! idx=" << idx << " map width = " << nex_map->pin_count() << " tmp_map count = " << tmp_map->pin_count() << endl; } - assert(ptr < new_accum->pin_count()); + assert(tmp >= 0); + unsigned ptr = tmp; connect(new_accum->pin(ptr), tmp_out->pin(idx)); } + delete[]nex_map_idx; + delete tmp_map; delete tmp_out; @@ -1272,6 +1367,11 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope, /* There is no memory address, so resort to async assignments. */ if (demux == 0) { + if (debug_synth) { + cerr << get_line() << ": debug: Looks like simple assign " + << "to a synchronous vector." << endl; + } + /* Synthesize the input to the DFF. */ return synth_async_noaccum(des, scope, true, nex_ff, nex_map, nex_out); @@ -1287,6 +1387,11 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope, assign to a constant bit. We don't need a demux in that case. */ if (demux->mem() && dynamic_cast(demux->bmux())) { + if (debug_synth) { + cerr << get_line() << ": debug: Looks like an assign " + << "to a fixed memory word." << endl; + } + NetMemory*lmem = demux->mem(); NetNet*msig = lmem->explode_to_reg(); demux->incr_mem_lref(); @@ -1295,16 +1400,29 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope, long adr = ae->value().as_long(); adr = lmem->index_to_address(adr) * lmem->width(); + struct nexus_map_t*nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0 ; idx < demux->lwidth() ; idx += 1) { unsigned off = adr+idx; - unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus()); - assert(ptr <= nex_map->pin_count()); + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + msig->pin(off).nexus()); + assert(tmp >= 0); + unsigned ptr = tmp; connect(nex_out->pin(ptr), rsig->pin(idx)); } + + delete[]nex_map_idx; + lval_->turn_sig_to_wire_on_release(); return true; } + if (debug_synth) { + cerr << get_line() << ": debug: Looks like an assign " + << "to an addressed memory word." << endl; + } + /* We also need the address (now known to be non-constant) synthesized and connected to a decoder. */ NetNet*adr = demux->bmux()->synthesize(des); @@ -1326,6 +1444,11 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope, lval_->incr_mem_lref(); } lval_->turn_sig_to_wire_on_release(); + + if (debug_synth) { + cerr << get_line() << ": debug: Synchronous assign done." << endl; + } + return true; } @@ -1352,6 +1475,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, if (last_ == 0) return true; + if (debug_synth) { + cerr << get_line() << ": debug: Start synthesis of block" << endl; + } + /* Assert that this region still represents a single DFF. */ for (unsigned idx = 1 ; idx < nex_out->pin_count() ; idx += 1) { assert(nex_ff[0].ff == nex_ff[idx].ff); @@ -1374,6 +1501,12 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, do { cur = cur->next_; + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Collect information for statement at " + << cur->get_line() << endl; + } + /* Create a temporary nex_map for the substatement. */ NexusSet tmp_set; cur->nex_output(tmp_set); @@ -1406,11 +1539,22 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, struct sync_accounting_cell*tmp_ff = new struct sync_accounting_cell[ff2->width()]; + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Map pins for statement at " + << cur->get_line() << endl; + } + verinum aset_value2 (verinum::V1, ff2->width()); verinum sset_value2 (verinum::V1, ff2->width()); + struct nexus_map_t*nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) { - unsigned ptr = find_nexus_in_set(nex_map, - tmp_map->pin(idx).nexus()); + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + tmp_map->pin(idx).nexus()); + assert(tmp >= 0); + unsigned ptr = tmp; /* Copy the asynch set bit to the new device. */ if (ptr < tmp_aset.len()) @@ -1429,6 +1573,14 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, tmp_ff[idx].proc = cur; } + delete[]nex_map_idx; + + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Propagate FF controls for statement at " + << cur->get_line() << endl; + } + /* PUll the non-sliced inputs (clock, set, reset, etc) forward to the new FF we are building. */ if (ff->pin_Aclr().is_linked()) @@ -1475,6 +1627,12 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, } } + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Start substatement synthesis at " + << cur->get_line() << endl; + } + /* Now go on with the synchronous synthesis for this statement of the block. The tmp_map is the output nexa that we expect, and the tmp_out is where we want @@ -1488,16 +1646,27 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, if (ok_flag == false) continue; + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Bind block substatement to ff bits." << endl; + } /* Use the nex_map to link up the output from the substatement to the output of the block as a whole. It is occasionally possible to have outputs beyond the input set, for example when the l-value of an assignment is smaller then the r-value. */ + + nex_map_idx = make_nexus_index(nex_map); + for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) { ff2 = tmp_ff[idx].ff; unsigned ff2_pin = tmp_ff[idx].pin; - unsigned ptr = find_nexus_in_set(nex_map, - tmp_map->pin(idx).nexus()); + + int tmp = map_nexus_in_index(nex_map_idx, + nex_map->pin_count(), + tmp_map->pin(idx).nexus()); + assert(tmp >= 0); + unsigned ptr = tmp; if (ptr >= nex_out->pin_count()) continue; @@ -1536,6 +1705,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, } } } + delete[]nex_map_idx; delete tmp_map; delete tmp_out; @@ -1552,6 +1722,11 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, delete ff; ff = 0; + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Check block synthesis for completelness. " << endl; + } + /* Run through the pin accounting one more time to make sure the data inputs are all connected. */ for (unsigned idx = 0 ; idx < block_width ; idx += 1) { @@ -1582,6 +1757,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, } } + if (debug_synth) { + cerr << get_line() << ": debug: Finish synthesis of block" << endl; + } + return flag; } @@ -1706,6 +1885,11 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetNet*nex_map, NetNet*nex_out, const svector&events_in) { + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Start sync synthesis of conditional" << endl; + } + /* First try to turn the condition expression into an asynchronous set/reset. If the condition expression has inputs that are included in the sensitivity list, then it @@ -1899,11 +2083,20 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, nex_ff, nex_map, nex_out, events_tmp); + if (debug_synth) + cerr << get_line() << ": debug: " + << "End synthesis of conditional" << endl; return flag; } delete expr_input; + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Condit expression input not sensitive, " + << "so must be synchronous. " << endl; + } + /* Detect the case that this is a *synchronous* set/reset. It is not asyncronous because we know the condition is not included in the sensitivity list, but if the if_ case is @@ -1970,6 +2163,10 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, nex_ff, nex_map, nex_out, svector(0)) && flag; + + if (debug_synth) + cerr << get_line() << ": debug: " + << "End synthesis of conditional" << endl; return flag; } while (0); } @@ -1983,14 +2180,30 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, /* If this is an if/then/else, then it is likely a combinational if, and I should synthesize it that way. */ if (if_ && else_) { + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Condit expression looks like a synchronous mux." + << endl; + } + bool flag =synth_async_noaccum(des, scope, true, nex_ff, nex_map, nex_out); + + if (debug_synth) + cerr << get_line() << ": debug: " + << "End synthesis of conditional" << endl; return flag; } assert(if_); assert(!else_); + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Condit expression looks like a synchronous enable. " + << endl; + } + /* Synthesize the enable expression. */ NetNet*ce = expr_->synthesize(des); assert(ce->pin_count() == 1); @@ -2007,10 +2220,20 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, unsigned nbits = nex_map->pin_count(); connect_enable_range_(des, scope, nex_ff, nbits, ce); + if (debug_synth) { + cerr << get_line() << ": debug: " + << "Condit expression make input that is sync enabled." + << endl; + } + bool flag = if_->synth_sync(des, scope, nex_ff, nex_map, nex_out, events_in); + + if (debug_synth) + cerr << get_line() << ": debug: " + << "End synthesis of conditional" << endl; return flag; } @@ -2019,7 +2242,6 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetNet*nex_map, NetNet*nex_out, const svector&events_in) { - DEBUG_SYNTH2_ENTRY("NetEvWait") if (events_in.count() > 0) { cerr << get_line() << ": error: Events are unaccounted" << " for in process synthesis. (evw)" << endl; @@ -2028,6 +2250,11 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, assert(events_in.count() == 0); + if (debug_synth) { + cerr << get_line() << ": debug: Start synthesis of event wait statement." + << endl; + } + /* This can't be other then one unless there are named events, which I cannot synthesize. */ assert(nevents_ == 1); @@ -2072,7 +2299,6 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, cerr << get_line() << ": : Perhaps the clock" << " is read by a statement or expression?" << endl; des->errors += 1; - DEBUG_SYNTH2_EXIT("NetEvWait",false) return false; } @@ -2095,7 +2321,11 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, bool flag = statement_->synth_sync(des, scope, nex_ff, nex_map, nex_out, events); - DEBUG_SYNTH2_EXIT("NetEvWait",flag) + if (debug_synth) { + cerr << get_line() << ": debug: Finished synthesis of event wait statement." + << endl; + } + return flag; } @@ -2112,9 +2342,18 @@ bool NetWhile::synth_async(Design*des, NetScope*scope, bool sync_flag, bool NetProcTop::synth_sync(Design*des) { + if (debug_synth) { + cerr << get_line() << ": debug: Start synthesis of process." << endl; + } + NexusSet nex_set; statement_->nex_output(nex_set); + if (debug_synth) { + cerr << get_line() << ": debug: Process seems to have " + << nex_set.count() << " output bits." << endl; + } + NetFF*ff = new NetFF(scope(), scope()->local_symbol(), nex_set.count()); des->add_node(ff); @@ -2159,6 +2398,10 @@ bool NetProcTop::synth_sync(Design*des) delete nex_q; delete[]nex_ff; + if (debug_synth) { + cerr << get_line() << ": debug: Finished synthesis of process." << endl; + } + return flag; } @@ -2241,6 +2484,9 @@ void synth2(Design*des) /* * $Log: synth2.cc,v $ + * Revision 1.39.2.41 2006/08/08 02:17:49 steve + * Improved nexus management performance. + * * Revision 1.39.2.40 2006/07/23 19:42:34 steve * Handle statement output override better in blocks. *