Generate code for wide muxes.

This commit is contained in:
steve 2002-07-08 04:04:07 +00:00
parent 8114523be2
commit 472f98affe
4 changed files with 176 additions and 122 deletions

View File

@ -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

161
tgt-vvp/draw_mux.c Normal file
View File

@ -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);
}

View File

@ -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.
*

View File

@ -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.
*