diff --git a/net_nex_output.cc b/net_nex_output.cc index b5414eae1..540c281ac 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 */ #if !defined(WINNT) -#ident "$Id: net_nex_output.cc,v 1.2 2002/07/01 00:54:21 steve Exp $" +#ident "$Id: net_nex_output.cc,v 1.3 2002/07/07 22:32:15 steve Exp $" #endif # include "config.h" @@ -47,6 +47,16 @@ void NetAssignBase::nex_output(NexusSet&out) } +void NetCase::nex_output(NexusSet&out) +{ + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + + assert(items_[idx].statement); + items_[idx].statement->nex_output(out); + } + +} + void NetCondit::nex_output(NexusSet&out) { if (if_ != 0) @@ -63,6 +73,9 @@ void NetEvWait::nex_output(NexusSet&out) /* * $Log: net_nex_output.cc,v $ + * Revision 1.3 2002/07/07 22:32:15 steve + * Asynchronous synthesis of case statements. + * * Revision 1.2 2002/07/01 00:54:21 steve * synth_asych of if/else requires redirecting the target * if sub-statements. Use NetNet objects to manage the diff --git a/netlist.h b/netlist.h index a53e93dcf..16087c33f 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.251 2002/07/03 05:35:00 steve Exp $" +#ident "$Id: netlist.h,v 1.252 2002/07/07 22:32:15 steve Exp $" #endif /* @@ -1430,6 +1430,11 @@ class NetCase : public NetProc { const NetProc*stat(unsigned idx) const { return items_[idx].statement; } virtual NexusSet* nex_input(); + virtual void nex_output(NexusSet&out); + + bool synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out); + virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2997,6 +3002,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.252 2002/07/07 22:32:15 steve + * Asynchronous synthesis of case statements. + * * Revision 1.251 2002/07/03 05:35:00 steve * Fix scope search for events. * diff --git a/synth2.cc b/synth2.cc index 6b72322f8..fa315f12a 100644 --- a/synth2.cc +++ b/synth2.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: synth2.cc,v 1.2 2002/07/01 00:54:21 steve Exp $" +#ident "$Id: synth2.cc,v 1.3 2002/07/07 22:32:15 steve Exp $" #endif # include "config.h" @@ -68,6 +68,88 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, return true; } +bool NetCase::synth_async(Design*des, NetScope*scope, + const NetNet*nex_map, NetNet*nex_out) +{ + unsigned cur; + + NetNet*esig = expr_->synthesize(des); + + /* Scan the select vector looking for constant bits. The + constant bits will be elided from the select input connect, + but we still need to keep track of them. */ + unsigned sel_pins = 0; + unsigned long sel_mask = 0; + unsigned long sel_ref = 0; + for (unsigned idx = 0 ; idx < esig->pin_count() ; idx += 1) { + + if (esig->pin(idx).nexus()->drivers_constant()) { + verinum::V bit = esig->pin(idx).nexus()->driven_value(); + if (bit == verinum::V1) + sel_ref |= 1 << idx; + + } else { + sel_pins += 1; + sel_mask |= 1 << idx; + } + } + + /* Build a map of guard values to mux select values. This + helps account for constant select bits that are being + elided. */ + mapguard2sel; + cur = 0; + for (unsigned idx = 0 ; idx < (1<pin_count()) ; idx += 1) { + if ((idx & ~sel_mask) == sel_ref) { + guard2sel[idx] = cur; + cur += 1; + } + } + assert(cur == (1 << sel_pins)); + + NetMux*mux = new NetMux(scope, scope->local_hsymbol(), + nex_out->pin_count(), + 1 << sel_pins, sel_pins); + + /* Connect the non-constant select bits to the select input of + the mux device. */ + cur = 0; + for (unsigned idx = 0 ; idx < esig->pin_count() ; idx += 1) { + /* skip bits that are known to be constant. */ + if ((sel_mask & (1 << idx)) == 0) + continue; + + connect(mux->pin_Sel(cur), esig->pin(idx)); + cur += 1; + } + assert(cur == sel_pins); + + for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) + connect(nex_out->pin(idx), mux->pin_Result(idx)); + + for (unsigned item = 0 ; item < nitems_ ; item += 1) { + assert(items_[item].guard); + assert(items_[item].statement); + + NetEConst*ge = dynamic_cast(items_[item].guard); + assert(ge); + verinum gval = ge->value(); + unsigned sel_idx = guard2sel[gval.as_ulong()]; + + NetNet*sig = new NetNet(scope, scope->local_hsymbol(), + NetNet::WIRE, nex_map->pin_count()); + sig->local_flag(true); + items_[item].statement->synth_async(des, scope, nex_map, sig); + + for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) + connect(mux->pin_Data(idx, sel_idx), sig->pin(idx)); + } + + des->add_node(mux); + + return true; +} + bool NetCondit::synth_async(Design*des, NetScope*scope, const NetNet*nex_map, NetNet*nex_out) { @@ -177,6 +259,9 @@ void synth2(Design*des) /* * $Log: synth2.cc,v $ + * Revision 1.3 2002/07/07 22:32:15 steve + * Asynchronous synthesis of case statements. + * * Revision 1.2 2002/07/01 00:54:21 steve * synth_asych of if/else requires redirecting the target * if sub-statements. Use NetNet objects to manage the