From eb0a78e9ce9c455e9acb9f7e996523e14a6d3f52 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 21 Jan 2006 21:42:31 +0000 Subject: [PATCH] When mux has wide select but sparse choices, use 1hot translation. --- netlist.h | 9 +++- synth2.cc | 133 +++++++++++++++++++++++++++++++++++++++++++++++- t-dll.cc | 7 ++- tgt-stub/stub.c | 11 +++- 4 files changed, 156 insertions(+), 4 deletions(-) diff --git a/netlist.h b/netlist.h index b63d8c0e9..291cd23e6 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.8 2006/01/18 01:23:24 steve Exp $" +#ident "$Id: netlist.h,v 1.321.2.9 2006/01/21 21:42:31 steve Exp $" #endif /* @@ -1647,6 +1647,10 @@ class NetCase : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; + private: + bool synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag, + NetNet*nex_map, NetNet*nex_out, NetNet*accum_in, + NetNet*esig, unsigned hot_items); private: TYPE type_; @@ -3398,6 +3402,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.321.2.9 2006/01/21 21:42:31 steve + * When mux has wide select but sparse choices, use 1hot translation. + * * Revision 1.321.2.8 2006/01/18 01:23:24 steve * Rework l-value handling to allow for more l-value type flexibility. * diff --git a/synth2.cc b/synth2.cc index c80199b41..635280ca6 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.17 2006/01/18 06:16:11 steve Exp $" +#ident "$Id: synth2.cc,v 1.39.2.18 2006/01/21 21:42:32 steve Exp $" #endif # include "config.h" @@ -354,6 +354,19 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag, } assert(cur == (1U << sel_pins)); + unsigned nondefault_items = 0; + for (unsigned item = 0 ; item < nitems_ ; item += 1) { + if (items_[item].guard != 0) + nondefault_items += 1; + } + + /* Handle the special case that this can be done it a smaller + 1-hot MUX. */ + if (nondefault_items < sel_pins) + return synth_async_1hot_(des, scope, sync_flag, + nex_map, nex_out, accum, + esig, nondefault_items); + NetMux*mux = new NetMux(scope, scope->local_symbol(), nex_out->pin_count(), 1U << sel_pins, sel_pins); @@ -499,6 +512,121 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag, return return_flag; } +bool NetCase::synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag, + NetNet*nex_map, NetNet*nex_out, NetNet*accum, + NetNet*esig, unsigned hot_items) +{ + unsigned sel_pins = hot_items; + + NetMux*mux = new NetMux(scope, scope->local_symbol(), + nex_out->pin_count(), + 1U << sel_pins, sel_pins); + mux->set_line(*this); + + /* Hook up the output of the mux to the mapped output pins. */ + for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) + connect(nex_out->pin(idx), mux->pin_Result(idx)); + + NetNet*tmps = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, sel_pins); + for (unsigned idx = 0 ; idx < sel_pins ; idx += 1) + connect(tmps->pin(idx), mux->pin_Sel(idx)); + + NetProc*default_statement = 0; + unsigned use_item = 0; + for (unsigned item = 0 ; item < nitems_ ; item += 1) { + if (items_[item].guard == 0) { + default_statement = items_[item].statement; + continue; + } + + NetNet*tmp1 = items_[item].guard->synthesize(des); + assert(tmp1); + + NetLogic*reduc = new NetLogic(scope, scope->local_symbol(), + 1 + esig->pin_count(), + NetLogic::AND); + des->add_node(reduc); + + tmps = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, esig->pin_count()); + for (unsigned idx = 0 ; idx < tmps->pin_count() ; idx += 1) + connect(tmps->pin(idx), reduc->pin(idx+1)); + + assert(tmp1->pin_count() == esig->pin_count()); + for (unsigned idx = 0 ; idx < tmp1->pin_count() ; idx += 1) { + NetCaseCmp*cmp = new NetCaseCmp(scope,scope->local_symbol()); + des->add_node(cmp); + connect(cmp->pin(0), reduc->pin(1+idx)); + connect(cmp->pin(1), esig->pin(idx)); + connect(cmp->pin(2), tmp1->pin(idx)); + } + + connect(mux->pin_Sel(item), reduc->pin(0)); + + NetNet*item_sig = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, nex_map->pin_count()); + assert(items_[item].statement); + items_[item].statement->synth_async(des, scope, sync_flag, + nex_map, item_sig, accum); + for (unsigned idx = 0 ; idx < item_sig->pin_count() ; idx += 1) + connect(mux->pin_Data(idx, 1<pin(idx)); + + use_item += 1; + } + + assert(use_item == hot_items); + + /* Set up a default default_sig that uses the accumulated + input pins. This binding is suppressed by an actual default + statement if one exists. */ + NetNet*default_sig = 0; + if (default_statement) { + default_sig = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, nex_map->pin_count()); + default_statement->synth_async(des, scope, sync_flag, + nex_map, default_sig, accum); + + } + + if (default_sig == 0 && default_statement == 0) { + default_sig = accum; + for (unsigned idx = 0 ; idx < accum->pin_count() ; idx += 1) { + if (! accum->pin(idx).is_linked()) { + default_sig = 0; + break; + } + } + } + + /* No explicit sig, so if this is a synchronous process, + connect the input to the output. */ + if (default_sig == 0 && sync_flag) { + default_sig = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, nex_map->pin_count()); + for (unsigned idx = 0; idx < default_sig->pin_count() ; idx += 1) + connect(default_sig->pin(idx), nex_map->pin(idx)); + } + + + for (unsigned item = 0 ; item < (1UL<width() ; idx += 1) + connect(mux->pin_Data(idx,item), default_sig->pin(idx)); + } + + des->add_node(mux); + return true; +} + /* * If the synth_async method is called without an accumulated input * (in other words not from within a block) then stub the input signal @@ -1446,6 +1574,9 @@ void synth2(Design*des) /* * $Log: synth2.cc,v $ + * Revision 1.39.2.18 2006/01/21 21:42:32 steve + * When mux has wide select but sparse choices, use 1hot translation. + * * Revision 1.39.2.17 2006/01/18 06:16:11 steve * Restrict DFF to only one of Sset and Sclr. * diff --git a/t-dll.cc b/t-dll.cc index 606a64bb2..f30b25d53 100644 --- a/t-dll.cc +++ b/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.1 2005/02/19 16:39:31 steve Exp $" +#ident "$Id: t-dll.cc,v 1.131.2.2 2006/01/21 21:42:33 steve Exp $" #endif # include "config.h" @@ -940,6 +940,8 @@ void dll_target::net_case_cmp(const NetCaseCmp*net) obj->delay[1] = net->fall_time(); obj->delay[2] = net->decay_time(); + logic_attributes(obj,net); + scope_add_logic(scope, obj); } @@ -2180,6 +2182,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.131.2.2 2006/01/21 21:42:33 steve + * When mux has wide select but sparse choices, use 1hot translation. + * * Revision 1.131.2.1 2005/02/19 16:39:31 steve * Spellig fixes. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index fbc5d24fa..e36eff551 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -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.3 2006/01/14 20:13:22 steve Exp $" +#ident "$Id: stub.c,v 1.90.2.4 2006/01/21 21:42:33 steve Exp $" #endif # include "config.h" @@ -844,6 +844,12 @@ static void show_logic(ivl_net_logic_t net) name, ivl_nexus_name(ivl_logic_pin(net, 0))); break; + + case IVL_LO_EEQ: + fprintf(out, " EEQ %s (%s", name, + ivl_nexus_name(ivl_logic_pin(net,0))); + break; + case IVL_LO_NOT: fprintf(out, " not #(%u) %s (%s", ivl_logic_delay(net, 0), @@ -1001,6 +1007,9 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.90.2.4 2006/01/21 21:42:33 steve + * When mux has wide select but sparse choices, use 1hot translation. + * * Revision 1.90.2.3 2006/01/14 20:13:22 steve * Show synchronous set/clr of FF. *