diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 64314e5b4..92986ff33 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.8 2001/10/09 16:50:17 steve Exp $" +#ident "$Id: Makefile.in,v 1.9 2002/07/08 04:04:07 steve Exp $" # # SHELL = /bin/sh @@ -50,7 +50,7 @@ all: vvp.tgt $(CC) -Wall -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o mv $*.d dep -O = vvp.o eval_expr.o vvp_process.o vvp_scope.o +O = vvp.o draw_mux.o eval_expr.o vvp_process.o vvp_scope.o ifeq (@WIN32@,yes) TGTLDFLAGS=-L.. -livl diff --git a/tgt-vvp/draw_mux.c b/tgt-vvp/draw_mux.c new file mode 100644 index 000000000..ac5ac8af4 --- /dev/null +++ b/tgt-vvp/draw_mux.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) +#ident "$Id: draw_mux.c,v 1.1 2002/07/08 04:04:07 steve Exp $" +#endif + +# include "vvp_priv.h" +# include +#ifdef HAVE_MALLOC_H +# include +#endif +# include +# include + +static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice) +{ + unsigned sel = ivl_lpm_selects(net); + unsigned size = ivl_lpm_size(net); + unsigned seldx, idx; + ivl_nexus_t s; + + assert(size <= (1 << sel)); + + s = ivl_lpm_select(net, 0); + + /* Draw the leaf mux devices that take inputs from the + net. These also use up the least significant bit of the + select vector. */ + for (idx = 0 ; idx < size ; idx += 2) { + + fprintf(vvp_out, "L_%s/%u/%u/%u .functor MUXZ, ", + vvp_mangle_id(ivl_lpm_name(net)), slice, sel, idx); + + { + ivl_nexus_t a = ivl_lpm_data2(net, idx+0, slice); + draw_input_from_net(a); + fprintf(vvp_out, ", "); + } + + if ((idx+1) < size) { + ivl_nexus_t b = ivl_lpm_data2(net, idx+1, slice); + draw_input_from_net(b); + fprintf(vvp_out, ", "); + } else { + fprintf(vvp_out, "C, "); + } + + draw_input_from_net(s); + fprintf(vvp_out, ", C<1>;\n"); + } + + /* Draw the tree of MUXZ devices to connect the inner tree + nodes. */ + for (seldx = 1 ; seldx < (sel-1) ; seldx += 1) { + unsigned level = sel - seldx; + unsigned span = 2 << seldx; + s = ivl_lpm_select(net, seldx); + + for (idx = 0 ; idx < size ; idx += span) { + fprintf(vvp_out, "L_%s/%u/%u/%u .functor MUXZ, ", + vvp_mangle_id(ivl_lpm_name(net)), slice, level, idx); + + fprintf(vvp_out, "L_%s/%u/%u/%u, ", + vvp_mangle_id(ivl_lpm_name(net)), + slice, level+1, idx); + + if ((idx + span/2) < size) { + fprintf(vvp_out, "L_%s/%u/%u/%u, ", + vvp_mangle_id(ivl_lpm_name(net)), + slice, level+1, idx+span/2); + } else { + fprintf(vvp_out, "C, "); + } + + draw_input_from_net(s); + fprintf(vvp_out, ", C<1>;\n"); + } + } + + s = ivl_lpm_select(net, sel-1); + + fprintf(vvp_out, "L_%s/%u .functor MUXZ, ", + vvp_mangle_id(ivl_lpm_name(net)), slice); + + fprintf(vvp_out, "L_%s/%u/2/0, ", + vvp_mangle_id(ivl_lpm_name(net)), slice); + + + if ((2 << (sel-1))/2 < size) { + fprintf(vvp_out, "L_%s/%u/2/%u, ", + vvp_mangle_id(ivl_lpm_name(net)), + slice, (2 << (sel-1))/2); + } else { + fprintf(vvp_out, "C, "); + } + + draw_input_from_net(s); + fprintf(vvp_out, ", C<1>;\n"); +} + +/* + * 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) +{ + ivl_nexus_t s; + unsigned idx, width; + + /* Only support A-B muxes at this oint. */ + assert(ivl_lpm_size(net) == 2); + assert(ivl_lpm_selects(net) == 1); + + width = ivl_lpm_width(net); + s = ivl_lpm_select(net, 0); + + for (idx = 0 ; idx < width ; idx += 1) { + ivl_nexus_t a = ivl_lpm_data2(net, 0, idx); + ivl_nexus_t b = ivl_lpm_data2(net, 1, idx); + fprintf(vvp_out, "L_%s/%u .functor MUXZ, ", + vvp_mangle_id(ivl_lpm_name(net)), idx); + draw_input_from_net(a); + fprintf(vvp_out, ", "); + draw_input_from_net(b); + fprintf(vvp_out, ", "); + draw_input_from_net(s); + fprintf(vvp_out, ", C<1>;\n"); + } + +} + +void draw_lpm_mux(ivl_lpm_t net) +{ + unsigned idx; + + if ((ivl_lpm_size(net) == 2) && (ivl_lpm_selects(net) == 1)) { + draw_lpm_mux_ab(net); + return; + } + + for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) + draw_lpm_mux_bitslice(net, idx); + +} + diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index c06038a9d..7eb5b6b32 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 */ #if !defined(WINNT) -#ident "$Id: vvp_priv.h,v 1.14 2002/06/02 18:57:17 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.15 2002/07/08 04:04:07 steve Exp $" #endif # include "ivl_target.h" @@ -49,6 +49,8 @@ extern int draw_func_definition(ivl_scope_t scope); extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent); +extern void draw_lpm_mux(ivl_lpm_t net); + /* * Given a nexus, draw a string that represents the functor output * that feeds the nexus. This function can be used to get the input to @@ -59,6 +61,8 @@ extern void draw_nexus_input(ivl_nexus_t nex); extern const char* draw_net_input(ivl_nexus_t nex); +extern void draw_input_from_net(ivl_nexus_t nex); + /* * The draw_eval_expr function writes out the code to evaluate a * behavioral expression. @@ -93,6 +97,9 @@ extern unsigned thread_count; /* * $Log: vvp_priv.h,v $ + * Revision 1.15 2002/07/08 04:04:07 steve + * Generate code for wide muxes. + * * Revision 1.14 2002/06/02 18:57:17 steve * Generate %cmpi/u where appropriate. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index a0e36b16a..0c6f81bf8 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvp_scope.c,v 1.72 2002/07/05 21:26:17 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.73 2002/07/08 04:04:07 steve Exp $" #endif # include "vvp_priv.h" @@ -508,7 +508,7 @@ const char* draw_net_input(ivl_nexus_t nex) * functor inputs to. Sort the signals in the nexus by name, and * choose the lexically earliest one. */ -static void draw_input_from_net(ivl_nexus_t nex) +void draw_input_from_net(ivl_nexus_t nex) { const char*nex_private = (const char*)ivl_nexus_get_private(nex); if (nex_private == 0) @@ -1236,123 +1236,6 @@ static void draw_lpm_eq(ivl_lpm_t net) } } -static void draw_lpm_mux_bitwide(ivl_lpm_t net) -{ - unsigned sel = ivl_lpm_selects(net); - unsigned size = ivl_lpm_size(net); - unsigned seldx, idx; - ivl_nexus_t s; - - assert(size <= (1 << sel)); - - s = ivl_lpm_select(net, 0); - - /* Draw the leaf mux devices that take inputs from the - net. These also use up the least significant bit of the - select vector. */ - for (idx = 0 ; idx < size ; idx += 2) { - - fprintf(vvp_out, "L_%s/0/%u/%u .functor MUXZ, ", - vvp_mangle_id(ivl_lpm_name(net)), sel, idx); - - { - ivl_nexus_t a = ivl_lpm_data2(net, idx+0, 0); - draw_input_from_net(a); - fprintf(vvp_out, ", "); - } - - if ((idx+1) < size) { - ivl_nexus_t b = ivl_lpm_data2(net, idx+1, 0); - draw_input_from_net(b); - fprintf(vvp_out, ", "); - } else { - fprintf(vvp_out, "C, "); - } - - draw_input_from_net(s); - fprintf(vvp_out, ", C<1>;\n"); - } - - /* Draw the tree of MUXZ devices to connect the inner tree - nodes. */ - for (seldx = 1 ; seldx < (sel-1) ; seldx += 1) { - unsigned level = sel - seldx; - unsigned span = 2 << seldx; - s = ivl_lpm_select(net, seldx); - - for (idx = 0 ; idx < size ; idx += span) { - fprintf(vvp_out, "L_%s/0/%u/%u .functor MUXZ, ", - vvp_mangle_id(ivl_lpm_name(net)), level, idx); - - fprintf(vvp_out, "L_%s/0/%u/%u, ", - vvp_mangle_id(ivl_lpm_name(net)), - level+1, idx); - - if ((idx + span/2) < size) { - fprintf(vvp_out, "L_%s/0/%u/%u, ", - vvp_mangle_id(ivl_lpm_name(net)), - level+1, idx+span/2); - } else { - fprintf(vvp_out, "C, "); - } - - draw_input_from_net(s); - fprintf(vvp_out, ", C<1>;\n"); - } - } - - s = ivl_lpm_select(net, sel-1); - - fprintf(vvp_out, "L_%s/0 .functor MUXZ, ", - vvp_mangle_id(ivl_lpm_name(net))); - - fprintf(vvp_out, "L_%s/0/2/0, ", vvp_mangle_id(ivl_lpm_name(net))); - - - if ((2 << (sel-1))/2 < size) { - fprintf(vvp_out, "L_%s/0/2/%u, ", - vvp_mangle_id(ivl_lpm_name(net)), - (2 << (sel-1))/2); - } else { - fprintf(vvp_out, "C, "); - } - - draw_input_from_net(s); - fprintf(vvp_out, ", C<1>;\n"); -} - -static void draw_lpm_mux(ivl_lpm_t net) -{ - ivl_nexus_t s; - unsigned idx, width; - - if ((ivl_lpm_width(net) == 1) && (ivl_lpm_size(net) > 2)) { - draw_lpm_mux_bitwide(net); - return; - } - - /* Only support A-B muxes at this oint. */ - assert(ivl_lpm_size(net) == 2); - assert(ivl_lpm_selects(net) == 1); - - width = ivl_lpm_width(net); - s = ivl_lpm_select(net, 0); - - for (idx = 0 ; idx < width ; idx += 1) { - ivl_nexus_t a = ivl_lpm_data2(net, 0, idx); - ivl_nexus_t b = ivl_lpm_data2(net, 1, idx); - fprintf(vvp_out, "L_%s/%u .functor MUXZ, ", - vvp_mangle_id(ivl_lpm_name(net)), idx); - draw_input_from_net(a); - fprintf(vvp_out, ", "); - draw_input_from_net(b); - fprintf(vvp_out, ", "); - draw_input_from_net(s); - fprintf(vvp_out, ", C<1>;\n"); - } - -} - static void draw_lpm_shiftl(ivl_lpm_t net) { unsigned idx, width, selects; @@ -1577,6 +1460,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.73 2002/07/08 04:04:07 steve + * Generate code for wide muxes. + * * Revision 1.72 2002/07/05 21:26:17 steve * Avoid emitting to vvp local net symbols. *