From 9ef49379f49cf42838378609f38412cc471f1702 Mon Sep 17 00:00:00 2001 From: steve Date: Tue, 23 Apr 2002 03:53:59 +0000 Subject: [PATCH] Add support for non-constant bit select. --- PExpr.h | 14 +++++++- elab_net.cc | 48 +++++++++++++++++++++++---- tgt-vvp/vvp_scope.c | 80 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 133 insertions(+), 9 deletions(-) diff --git a/PExpr.h b/PExpr.h index 765187bec..642f08765 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PExpr.h,v 1.58 2002/04/14 03:55:25 steve Exp $" +#ident "$Id: PExpr.h,v 1.59 2002/04/23 03:53:59 steve Exp $" #endif # include @@ -261,6 +261,15 @@ class PEIdent : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; + + NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope, + NetNet*sig, + unsigned long rise, + unsigned long fall, + unsigned long decay, + Link::strength_t drive0, + Link::strength_t drive1) const; + }; class PENumber : public PExpr { @@ -487,6 +496,9 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.59 2002/04/23 03:53:59 steve + * Add support for non-constant bit select. + * * Revision 1.58 2002/04/14 03:55:25 steve * Precalculate unary - if possible. * diff --git a/elab_net.cc b/elab_net.cc index dd9da65df..2e5c439c1 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_net.cc,v 1.88 2002/04/22 00:53:39 steve Exp $" +#ident "$Id: elab_net.cc,v 1.89 2002/04/23 03:53:59 steve Exp $" #endif # include "config.h" @@ -1163,6 +1163,41 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope, return osig; } +/* + * This provate method handles the special case that we have a + * non-constant bit-select of an identifier. We already know that the + * signal that is represented is "sig". + */ +NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope, + NetNet*sig, + unsigned long rise, + unsigned long fall, + unsigned long decay, + Link::strength_t drive0, + Link::strength_t drive1) const +{ + /* Elaborate the selector. */ + NetNet*sel = msb_->elaborate_net(des, scope, 0, 0, 0, 0); + + NetMux*mux = new NetMux(scope, scope->local_hsymbol(), 1, + sig->pin_count(), + sel->pin_count()); + + for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) + connect(mux->pin_Data(0, idx), sig->pin(idx)); + + for (unsigned idx = 0 ; idx < sel->pin_count() ; idx += 1) + connect(mux->pin_Sel(idx), sel->pin(idx)); + + NetNet*out = new NetNet(scope, scope->local_hsymbol(), + NetNet::IMPLICIT, 1); + connect(mux->pin_Result(0), out->pin(0)); + + des->add_node(mux); + out->local_flag(true); + return out; +} + NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope, unsigned lwidth, unsigned long rise, @@ -1288,12 +1323,10 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope, } else if (msb_) { verinum*mval = msb_->eval_const(des, scope); if (mval == 0) { - cerr << get_line() << ": error: index of " << path_ << - " needs to be constant in this context." << - endl; - des->errors += 1; - return 0; + return elaborate_net_bitmux_(des, scope, sig, rise, + fall, decay, drive0, drive1); } + assert(mval); unsigned idx = sig->sb_to_idx(mval->as_long()); if (idx >= sig->pin_count()) { @@ -2069,6 +2102,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $Log: elab_net.cc,v $ + * Revision 1.89 2002/04/23 03:53:59 steve + * Add support for non-constant bit select. + * * Revision 1.88 2002/04/22 00:53:39 steve * Do not allow implicit wires in sensitivity lists. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 7bbff1dd0..fe43dfe58 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.67 2002/04/22 03:15:25 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.68 2002/04/23 03:53:59 steve Exp $" #endif # include "vvp_priv.h" @@ -1231,12 +1231,85 @@ 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) { + ivl_nexus_t a = ivl_lpm_data2(net, idx+0, 0); + ivl_nexus_t b = ivl_lpm_data2(net, idx+1, 0); + + fprintf(vvp_out, "L_%s/0/%u/%u .functor MUXZ, ", + vvp_mangle_id(ivl_lpm_name(net)), sel, 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"); + } + + /* 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); + + fprintf(vvp_out, "L_%s/0/%u/%u, ", + vvp_mangle_id(ivl_lpm_name(net)), + level+1, idx+span/2); + + 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))); + + fprintf(vvp_out, "L_%s/0/2/%u, ", + vvp_mangle_id(ivl_lpm_name(net)), + size/2); + + 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; - /* XXXX Only support A-B muxes for now. */ + 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); @@ -1482,6 +1555,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.68 2002/04/23 03:53:59 steve + * Add support for non-constant bit select. + * * Revision 1.67 2002/04/22 03:15:25 steve * Keep delays applied to BUFZ devices. *