diff --git a/ivl_target.h b/ivl_target.h index 5c4b883bc..59f3e6938 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.159 2005/08/06 17:58:16 steve Exp $" +#ident "$Id: ivl_target.h,v 1.160 2005/09/01 04:11:37 steve Exp $" #endif #ifdef __cplusplus @@ -920,7 +920,8 @@ extern const char* ivl_udp_name(ivl_udp_t net); * The ivl_lpm_data() method returns the inputs of the MUX device. The * ivl_lpm_size() method returns the number of data inputs there * are. All the data inputs have the same width, the width of the - * ivl_lpm_q output. + * ivl_lpm_q output. The type of the device is devined from the + * inputs and the Q. All the types must be exactly the same. * * - D-FlipFlop (IVL_LPM_FF) * This data is an edge sensitive register. The ivl_lpm_q output and @@ -1670,6 +1671,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.160 2005/09/01 04:11:37 steve + * Generate code to handle real valued muxes. + * * Revision 1.159 2005/08/06 17:58:16 steve * Implement bi-directional part selects. * diff --git a/netlist.h b/netlist.h index 75aa17a81..8c204a7a5 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.348 2005/08/31 05:07:31 steve Exp $" +#ident "$Id: netlist.h,v 1.349 2005/09/01 04:11:37 steve Exp $" #endif /* @@ -876,6 +876,12 @@ class NetMult : public NetNode { * width -- Width of the result and each possible Data input * size -- Number of Data input (each of width) * selw -- Width in bits of the select input + * + * All the data inputs must have the same type, and are the type of + * the result. The actual type does not matter, as the mux does not + * process data, just selects alternatives. + * + * The select input must be an integral type of some sort. Not real. */ class NetMux : public NetNode { @@ -3436,6 +3442,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.349 2005/09/01 04:11:37 steve + * Generate code to handle real valued muxes. + * * Revision 1.348 2005/08/31 05:07:31 steve * Handle memory references is continuous assignments. * diff --git a/tgt-vvp/draw_mux.c b/tgt-vvp/draw_mux.c index f04446064..84afa4788 100644 --- a/tgt-vvp/draw_mux.c +++ b/tgt-vvp/draw_mux.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: draw_mux.c,v 1.11 2005/08/27 04:32:08 steve Exp $" +#ident "$Id: draw_mux.c,v 1.12 2005/09/01 04:11:37 steve Exp $" #endif # include "vvp_priv.h" @@ -33,7 +33,7 @@ * This draws a simple A/B mux. The mux can have any width, enough * MUXZ nodes are created to support the vector. */ -static void draw_lpm_mux_ab(ivl_lpm_t net) +static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz) { unsigned width = ivl_lpm_width(net); @@ -41,14 +41,14 @@ static void draw_lpm_mux_ab(ivl_lpm_t net) assert(ivl_lpm_size(net) == 2); assert(ivl_lpm_selects(net) == 1); - fprintf(vvp_out, "L_%p .functor MUXZ %u", net, width); + fprintf(vvp_out, "L_%p .functor %s %u", net, muxz, width); fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,0))); fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,1))); fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_select(net))); fprintf(vvp_out, ", C4<>;\n"); } -static void draw_lpm_mux_nest(ivl_lpm_t net) +static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz) { int idx, level; unsigned width = ivl_lpm_width(net); @@ -63,8 +63,8 @@ static void draw_lpm_mux_nest(ivl_lpm_t net) net, select_input); for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 2) { - fprintf(vvp_out, "L_%p/0/%d .functor MUXZ %u", - net, idx/2, width); + fprintf(vvp_out, "L_%p/0/%d .functor %s %u", + net, idx/2, muxz, width); fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx+0))); fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx+1))); fprintf(vvp_out, ", L_%p/0s, C4<>;\n", net); @@ -75,8 +75,8 @@ static void draw_lpm_mux_nest(ivl_lpm_t net) net, level, select_input, level); for (idx = 0 ; idx < (ivl_lpm_size(net) >> level); idx += 2) { - fprintf(vvp_out, "L_%p/%d/%d .functor MUXZ %u", - net, width, level,idx); + fprintf(vvp_out, "L_%p/%d/%d .functor %s %u", + net, width, level, muxz, idx); fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+0); fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+1); fprintf(vvp_out, ", L_%p/%ds", net, level); @@ -90,28 +90,46 @@ static void draw_lpm_mux_nest(ivl_lpm_t net) net, swidth-1, select_input, swidth-1, swidth-1); - fprintf(vvp_out, "L_%p .functor MUXZ %u", net, width); + fprintf(vvp_out, "L_%p .functor %s %u", net, muxz, width); fprintf(vvp_out, ", L_%p/%d/0", net, swidth-2); fprintf(vvp_out, ", L_%p/%d/1", net, swidth-2); fprintf(vvp_out, ", L_%p/%ds", net, swidth-1); fprintf(vvp_out, ", C4<>;\n"); - free(select_input);} + free(select_input); +} void draw_lpm_mux(ivl_lpm_t net) { + const char*muxz = "MUXZ"; + + /* The output of the mux defines the type of the mux. the + ivl_target should guarantee that all the inputs are the + same type as the output. */ + switch (data_type_of_nexus(ivl_lpm_q(net,0))) { + case IVL_VT_REAL: + muxz = "MUXR"; + break; + default: + muxz = "MUXZ"; + break; + } + if ((ivl_lpm_size(net) == 2) && (ivl_lpm_selects(net) == 1)) { - draw_lpm_mux_ab(net); + draw_lpm_mux_ab(net, muxz); return; } /* Here we are at the worst case, we generate a tree of MUXZ devices to handle the arbitrary size. */ - draw_lpm_mux_nest(net); + draw_lpm_mux_nest(net, muxz); } /* * $Log: draw_mux.c,v $ + * Revision 1.12 2005/09/01 04:11:37 steve + * Generate code to handle real valued muxes. + * * Revision 1.11 2005/08/27 04:32:08 steve * Handle synthesis of fully packed case statements. * diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 8519dcade..c15b77bfd 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_priv.h,v 1.32 2005/08/06 17:58:16 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.33 2005/09/01 04:11:37 steve Exp $" #endif # include "vvp_config.h" @@ -49,6 +49,9 @@ extern const char* vvp_signal_label(ivl_signal_t sig); */ extern const char* vvp_memory_label(ivl_memory_t mem); +extern unsigned width_of_nexus(ivl_nexus_t nex); +extern ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex); + /* * This function draws a process (initial or always) into the output * file. It normally returns 0, but returns !0 of there is some sort @@ -198,6 +201,9 @@ extern unsigned thread_count; /* * $Log: vvp_priv.h,v $ + * Revision 1.33 2005/09/01 04:11:37 steve + * Generate code to handle real valued muxes. + * * Revision 1.32 2005/08/06 17:58:16 steve * Implement bi-directional part selects. *