Generate code for wide muxes.
This commit is contained in:
parent
8114523be2
commit
472f98affe
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <assert.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
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<x>, ");
|
||||
}
|
||||
|
||||
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<x>, ");
|
||||
}
|
||||
|
||||
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<x>, ");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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<x>, ");
|
||||
}
|
||||
|
||||
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<x>, ");
|
||||
}
|
||||
|
||||
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<x>, ");
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue