diff --git a/ivl.def b/ivl.def index fd5340702..dd3e5265c 100644 --- a/ivl.def +++ b/ivl.def @@ -41,15 +41,16 @@ ivl_logic_type ivl_logic_pin ivl_logic_pins +ivl_lpm_clk +ivl_lpm_data ivl_lpm_name +ivl_lpm_q +ivl_lpm_select +ivl_lpm_selects +ivl_lpm_size ivl_lpm_type ivl_lpm_width -ivl_lpm_ff -ivl_lpm_ff_clk -ivl_lpm_ff_data -ivl_lpm_ff_q - ivl_lval_mux ivl_lval_pin ivl_lval_pins diff --git a/ivl_target.h b/ivl_target.h index 4d31eeb9e..fd7c9f466 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: ivl_target.h,v 1.54 2001/04/22 23:09:46 steve Exp $" +#ident "$Id: ivl_target.h,v 1.55 2001/04/26 05:12:02 steve Exp $" #endif #ifdef __cplusplus @@ -82,12 +82,6 @@ _BEGIN_DECL * device nodes. This object carries a few base properties * (including a type) including a handle to the specific type. * - * All the ivl_lpm_*_t objects are derived from this type, and - * there are methods to get one from the other. - * - * ivl_lpm_ff_t - * This is a flip-flop. - * * ivl_net_logic_t * This object represents various built in logic devices. In fact, * this includes just about every directional device that has a @@ -131,7 +125,6 @@ typedef struct ivl_design_s *ivl_design_t; typedef struct ivl_event_s *ivl_event_t; typedef struct ivl_expr_s *ivl_expr_t; typedef struct ivl_lpm_s *ivl_lpm_t; -typedef struct ivl_lpm_ff_s *ivl_lpm_ff_t; typedef struct ivl_lval_s *ivl_lval_t; typedef struct ivl_net_const_s*ivl_net_const_t; typedef struct ivl_net_logic_s*ivl_net_logic_t; @@ -192,7 +185,8 @@ typedef enum ivl_logic_e { /* This is the type of an LPM object. */ typedef enum ivl_lpm_type_e { - IVL_LPM_FF + IVL_LPM_FF, + IVL_LPM_MUX } ivl_lpm_type_t; /* Processes are initial or always blocks with a statement. This is @@ -451,20 +445,37 @@ extern const char* ivl_udp_name(ivl_udp_t net); * Return the width of the LPM device. What this means depends on * the LPM type, but it generally has to do with the width of the * output data path. + * + * ivl_lpm_data + * Return the input data nexus for device types that have a single + * input vector. + * + * ivl_lpm_selects + * This is the size of the select input for a LPM_MUX device + * + * ivl_lpm_size + * In addition to a width, some devices have a size. The size is + * often the number of inputs per out, i.e. the number of inputs + * per bit for a MUX. */ extern const char* ivl_lpm_name(ivl_lpm_t net); extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net); extern unsigned ivl_lpm_width(ivl_lpm_t net); - -/* - * These are cast functions for the ivl_lpm_t. They cast the object to - * the requested type, checking for errors along the way. - */ -extern ivl_lpm_ff_t ivl_lpm_ff(ivl_lpm_t net); -extern ivl_nexus_t ivl_lpm_ff_clk(ivl_lpm_ff_t net); -extern ivl_nexus_t ivl_lpm_ff_data(ivl_lpm_ff_t net, unsigned idx); -extern ivl_nexus_t ivl_lpm_ff_q(ivl_lpm_ff_t net, unsigned idx); + /* IVL_LPM_FF */ +extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net); + /* IVL_LPM_FF */ +extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx); + /* IVL_LPM_MUX */ +extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx); + /* IVL_LPM_FF */ +extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); + /* IVL_LPM_MUX */ +extern unsigned ivl_lpm_selects(ivl_lpm_t net); + /* IVL_LPM_MUX */ +extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx); + /* IVL_LPM_MUX */ +extern unsigned ivl_lpm_size(ivl_lpm_t net); /* LVAL @@ -781,6 +792,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.55 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.54 2001/04/22 23:09:46 steve * More UDP consolidation from Stephan Boettcher. * diff --git a/t-dll-api.cc b/t-dll-api.cc index 23b1b4619..e27dac5b0 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll-api.cc,v 1.40 2001/04/22 23:09:46 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.41 2001/04/26 05:12:02 steve Exp $" #endif # include "t-dll.h" @@ -378,36 +378,48 @@ extern "C" const char* ivl_udp_name(ivl_udp_t net) } -extern "C" ivl_lpm_ff_t ivl_lpm_ff(ivl_lpm_t net) -{ - assert(net->type == IVL_LPM_FF); - return (ivl_lpm_ff_t)net; -} - -extern "C" ivl_nexus_t ivl_lpm_ff_clk(ivl_lpm_ff_t net) +extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net) { assert(net); - return net->clk; + switch (net->type) { + case IVL_LPM_FF: + return net->u_.ff.clk; + default: + assert(0); + return 0; + } } -extern "C" ivl_nexus_t ivl_lpm_ff_data(ivl_lpm_ff_t net, unsigned idx) +extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) { assert(net); - assert(idx < net->base.width); - if (net->base.width == 1) - return net->d.pin; - else - return net->d.pins[idx]; + switch (net->type) { + case IVL_LPM_FF: + assert(idx < net->u_.ff.width); + if (net->u_.ff.width == 1) + return net->u_.ff.d.pin; + else + return net->u_.ff.d.pins[idx]; + + default: + assert(0); + return 0; + } } -extern "C" ivl_nexus_t ivl_lpm_ff_q(ivl_lpm_ff_t net, unsigned idx) +extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx) { assert(net); - assert(idx < net->base.width); - if (net->base.width == 1) - return net->q.pin; - else - return net->q.pins[idx]; + switch (net->type) { + case IVL_LPM_MUX: + assert(sdx < net->u_.mux.size); + assert(idx < net->u_.mux.width); + return net->u_.mux.d[sdx*net->u_.mux.width + idx]; + + default: + assert(0); + return 0; + } } extern "C" const char* ivl_lpm_name(ivl_lpm_t net) @@ -415,6 +427,69 @@ extern "C" const char* ivl_lpm_name(ivl_lpm_t net) return net->name; } +extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx) +{ + assert(net); + + switch (net->type) { + case IVL_LPM_FF: + assert(idx < net->u_.ff.width); + if (net->u_.ff.width == 1) + return net->u_.ff.q.pin; + else + return net->u_.ff.q.pins[idx]; + + case IVL_LPM_MUX: + assert(idx < net->u_.mux.width); + if (net->u_.mux.width == 1) + return net->u_.mux.q.pin; + else + return net->u_.mux.q.pins[idx]; + + default: + assert(0); + return 0; + } +} + +extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx) +{ + switch (net->type) { + case IVL_LPM_MUX: + assert(idx < net->u_.mux.swid); + if (net->u_.mux.swid == 1) + return net->u_.mux.s.pin; + else + return net->u_.mux.s.pins[idx]; + + default: + assert(0); + return 0; + } +} + +extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net) +{ + switch (net->type) { + case IVL_LPM_MUX: + return net->u_.mux.swid; + default: + assert(0); + return 0; + } +} + +extern "C" unsigned ivl_lpm_size(ivl_lpm_t net) +{ + switch (net->type) { + case IVL_LPM_MUX: + return net->u_.mux.size; + default: + assert(0); + return 0; + } +} + extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net) { return net->type; @@ -422,7 +497,16 @@ extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net) extern "C" unsigned ivl_lpm_width(ivl_lpm_t net) { - return net->width; + assert(net); + switch (net->type) { + case IVL_LPM_FF: + return net->u_.ff.width; + case IVL_LPM_MUX: + return net->u_.mux.width; + default: + assert(0); + return 0; + } } extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net) @@ -949,6 +1033,9 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.41 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.40 2001/04/22 23:09:46 steve * More UDP consolidation from Stephan Boettcher. * diff --git a/t-dll.cc b/t-dll.cc index 0f4637490..3cb5b4091 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll.cc,v 1.35 2001/04/24 02:23:58 steve Exp $" +#ident "$Id: t-dll.cc,v 1.36 2001/04/26 05:12:02 steve Exp $" #endif # include "compiler.h" @@ -476,14 +476,15 @@ void dll_target::udp(const NetUDP*net) void dll_target::lpm_ff(const NetFF*net) { - ivl_lpm_ff_t obj = new struct ivl_lpm_ff_s; - obj->base.type = IVL_LPM_FF; - obj->base.name = strdup(net->name()); - obj->base.width = net->width(); - obj->base.scope = find_scope(des_.root_, net->scope()); - assert(obj->base.scope); + ivl_lpm_t obj = new struct ivl_lpm_s; + obj->type = IVL_LPM_FF; + obj->name = strdup(net->name()); + obj->scope = find_scope(des_.root_, net->scope()); + assert(obj->scope); - scope_add_lpm(obj->base.scope, &obj->base); + obj->u_.ff.width = net->width(); + + scope_add_lpm(obj->scope, obj); const Nexus*nex; @@ -491,39 +492,106 @@ void dll_target::lpm_ff(const NetFF*net) point back to this device. */ nex = net->pin_Clock().nexus(); assert(nex->t_cookie()); - obj->clk = (ivl_nexus_t) nex->t_cookie(); - assert(obj->clk); - nexus_lpm_add(obj->clk, &obj->base, 0); + obj->u_.ff.clk = (ivl_nexus_t) nex->t_cookie(); + assert(obj->u_.ff.clk); + nexus_lpm_add(obj->u_.ff.clk, obj, 0); - if (obj->base.width == 1) { + if (obj->u_.ff.width == 1) { nex = net->pin_Q(0).nexus(); assert(nex->t_cookie()); - obj->q.pin = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->q.pin, &obj->base, 0); + obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.q.pin, obj, 0); nex = net->pin_Data(0).nexus(); assert(nex->t_cookie()); - obj->d.pin = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->d.pin, &obj->base, 0); + obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.d.pin, obj, 0); } else { - obj->q.pins = new ivl_nexus_t [obj->base.width * 2]; - obj->d.pins = obj->q.pins + obj->base.width; + obj->u_.ff.q.pins = new ivl_nexus_t [obj->u_.ff.width * 2]; + obj->u_.ff.d.pins = obj->u_.ff.q.pins + obj->u_.ff.width; - for (unsigned idx = 0 ; idx < obj->base.width ; idx += 1) { + for (unsigned idx = 0 ; idx < obj->u_.ff.width ; idx += 1) { nex = net->pin_Q(idx).nexus(); assert(nex->t_cookie()); - obj->q.pins[idx] = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->q.pins[idx], &obj->base, 0); + obj->u_.ff.q.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.q.pins[idx], obj, 0); nex = net->pin_Data(idx).nexus(); assert(nex->t_cookie()); - obj->d.pins[idx] = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->d.pins[idx], &obj->base, 0); + obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0); } } } +void dll_target::lpm_mux(const NetMux*net) +{ + ivl_lpm_t obj = new struct ivl_lpm_s; + obj->type = IVL_LPM_MUX; + obj->name = strdup(net->name()); + obj->scope = find_scope(des_.root_, net->scope()); + assert(obj->scope); + + obj->u_.mux.width = net->width(); + obj->u_.mux.size = net->size(); + obj->u_.mux.swid = net->sel_width(); + + scope_add_lpm(obj->scope, obj); + + const Nexus*nex; + + /* Connect the output bits. */ + if (obj->u_.mux.width == 1) { + nex = net->pin_Result(0).nexus(); + assert(nex->t_cookie()); + obj->u_.mux.q.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.mux.q.pin, obj, 0); + + } else { + obj->u_.mux.q.pins = new ivl_nexus_t [obj->u_.mux.width]; + + for (unsigned idx = 0 ; idx < obj->u_.mux.width ; idx += 1) { + nex = net->pin_Result(idx).nexus(); + assert(nex->t_cookie()); + obj->u_.mux.q.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0); + } + } + + /* Connect the select bits. */ + if (obj->u_.mux.swid == 1) { + nex = net->pin_Sel(0).nexus(); + assert(nex->t_cookie()); + obj->u_.mux.s.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.mux.s.pin, obj, 0); + + } else { + obj->u_.mux.s.pins = new ivl_nexus_t [obj->u_.mux.swid]; + + for (unsigned idx = 0 ; idx < obj->u_.mux.swid ; idx += 1) { + nex = net->pin_Sel(idx).nexus(); + assert(nex->t_cookie()); + obj->u_.mux.s.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.mux.s.pins[idx], obj, 0); + } + } + + unsigned width = obj->u_.mux.width; + unsigned selects = obj->u_.mux.size; + + obj->u_.mux.d = new ivl_nexus_t [width * selects]; + + for (unsigned sdx = 0 ; sdx < selects ; sdx += 1) + for (unsigned ddx = 0 ; ddx < width ; ddx += 1) { + nex = net->pin_Data(ddx, sdx).nexus(); + ivl_nexus_t tmp = (ivl_nexus_t) nex->t_cookie(); + obj->u_.mux.d[sdx*width + ddx] = tmp; + nexus_lpm_add(tmp, obj, 0); + } + +} + /* * The assignment l-values are captured by the assignment statements * themselves in the process handling. @@ -811,6 +879,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.36 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.35 2001/04/24 02:23:58 steve * Support for UDP devices in VVP (Stephen Boettcher) * diff --git a/t-dll.h b/t-dll.h index 5ebe0ff0e..6c6b45bbf 100644 --- a/t-dll.h +++ b/t-dll.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll.h,v 1.39 2001/04/22 23:09:46 steve Exp $" +#ident "$Id: t-dll.h,v 1.40 2001/04/26 05:12:02 steve Exp $" #endif # include "target.h" @@ -59,6 +59,7 @@ struct dll_target : public target_t, public expr_scan_t { void logic(const NetLogic*); void udp(const NetUDP*); void lpm_ff(const NetFF*); + void lpm_mux(const NetMux*); void net_assign(const NetAssign_*); bool net_const(const NetConst*); void net_probe(const NetEvProbe*); @@ -186,31 +187,47 @@ struct ivl_expr_s { }; /* - * This is the base part of all ivl_lpm_*_t objects. It contains a - * type code to identify the extended type, and holds properties that - * are common to all (or most) lpm devices. + * LPM devices are handled by this suite of types. The ivl_lpm_s + * structure holds the core, including a type code, the object name + * and scope. The other properties of the device are held in the type + * specific member of the union. */ + struct ivl_lpm_s { ivl_lpm_type_t type; ivl_scope_t scope; char* name; - unsigned width; -}; - -struct ivl_lpm_ff_s { - struct ivl_lpm_s base; - - ivl_nexus_t clk; - union { - ivl_nexus_t*pins; - ivl_nexus_t pin; - } q; - union { - ivl_nexus_t*pins; - ivl_nexus_t pin; - } d; + struct ivl_lpm_ff_s { + unsigned short width; + ivl_nexus_t clk; + union { + ivl_nexus_t*pins; + ivl_nexus_t pin; + } q; + union { + ivl_nexus_t*pins; + ivl_nexus_t pin; + } d; + } ff; + + struct ivl_lpm_mux_s { + unsigned short width; + unsigned short size; + unsigned short swid; + ivl_nexus_t*d; + union { + ivl_nexus_t*pins; + ivl_nexus_t pin; + } q; + union { + ivl_nexus_t*pins; + ivl_nexus_t pin; + } s; + } mux; + + } u_; }; /* @@ -451,6 +468,9 @@ struct ivl_statement_s { /* * $Log: t-dll.h,v $ + * Revision 1.40 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.39 2001/04/22 23:09:46 steve * More UDP consolidation from Stephan Boettcher. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 7354b6fdc..d6a90d88c 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: stub.c,v 1.37 2001/04/05 01:12:28 steve Exp $" +#ident "$Id: stub.c,v 1.38 2001/04/26 05:12:02 steve Exp $" #endif /* @@ -100,24 +100,45 @@ static void show_lpm(ivl_lpm_t net) switch (ivl_lpm_type(net)) { case IVL_LPM_FF: { - ivl_lpm_ff_t ff = ivl_lpm_ff(net); fprintf(out, " LPM_FF %s: \n", ivl_lpm_name(net), width); fprintf(out, " clk: %s\n", - ivl_nexus_name(ivl_lpm_ff_clk(ff))); + ivl_nexus_name(ivl_lpm_clk(net))); for (idx = 0 ; idx < width ; idx += 1) fprintf(out, " Data %u: %s\n", idx, - ivl_nexus_name(ivl_lpm_ff_data(ff, idx))); + ivl_nexus_name(ivl_lpm_data(net, idx))); for (idx = 0 ; idx < width ; idx += 1) fprintf(out, " Q %u: %s\n", idx, - ivl_nexus_name(ivl_lpm_ff_q(ff, idx))); + ivl_nexus_name(ivl_lpm_q(net, idx))); break; } + case IVL_LPM_MUX: { + unsigned sdx; + + fprintf(out, " LPM_MUX %s: \n", + ivl_lpm_name(net), width, ivl_lpm_size(net), + ivl_lpm_selects(net)); + + for (idx = 0 ; idx < width ; idx += 1) + fprintf(out, " Q %u: %s\n", idx, + ivl_nexus_name(ivl_lpm_q(net, idx))); + + for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) + fprintf(out, " S %u: %s\n", idx, + ivl_nexus_name(ivl_lpm_select(net, idx))); + + for (sdx = 0 ; sdx < ivl_lpm_size(net) ; sdx += 1) + for (idx = 0 ; idx < width ; idx += 1) + fprintf(out, " D%u %u: %s\n", sdx, idx, + ivl_nexus_name(ivl_lpm_data2(net,sdx,idx))); + break; + } + default: fprintf(out, " %s: \n", ivl_lpm_name(net), ivl_lpm_width(net)); @@ -509,6 +530,9 @@ DECLARE_CYGWIN_DLL(DllMain); /* * $Log: stub.c,v $ + * Revision 1.38 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.37 2001/04/05 01:12:28 steve * Get signed compares working correctly in vvp. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 669431fd4..046472929 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.19 2001/04/24 02:59:52 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.20 2001/04/26 05:12:02 steve Exp $" #endif # include "vvp_priv.h" @@ -41,7 +41,8 @@ void draw_nexus_input(ivl_nexus_t nex) { ivl_net_logic_t lptr; ivl_signal_t sptr; - unsigned ndx; + ivl_lpm_t lpm; + unsigned idx, ndx; for (ndx = 0 ; ndx < ivl_nexus_ptrs(nex) ; ndx += 1) { ivl_nexus_ptr_t nptr = ivl_nexus_ptr(nex, ndx); @@ -63,6 +64,19 @@ void draw_nexus_input(ivl_nexus_t nex) ivl_nexus_ptr_pin(nptr)); return; } + + lpm = ivl_nexus_ptr_lpm(nptr); + if (lpm) switch (ivl_lpm_type(lpm)) { + + case IVL_LPM_MUX: + for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1) + if (ivl_lpm_q(lpm, idx) == nex) { + fprintf(vvp_out, "L_%s/%u", + ivl_lpm_name(lpm), idx); + return; + } + + } } } @@ -336,6 +350,47 @@ static void draw_event_in_scope(ivl_event_t obj) } } +static void draw_lpm_mux(ivl_lpm_t net) +{ + ivl_nexus_t s; + unsigned idx, width; + + /* XXXX Only support A-B muxes for now. */ + 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, 0x6a", + ivl_lpm_name(net), idx); + fprintf(vvp_out, ", "); + draw_nexus_input(a); + fprintf(vvp_out, ", "); + draw_nexus_input(b); + fprintf(vvp_out, ", "); + draw_nexus_input(s); + fprintf(vvp_out, ";\n"); + } + +} + +static void draw_lpm_in_scope(ivl_lpm_t net) +{ + switch (ivl_lpm_type(net)) { + case IVL_LPM_MUX: + draw_lpm_mux(net); + return; + + default: + fprintf(stderr, "XXXX LPM not supported: %s\n", + ivl_lpm_name(net)); + } +} + int draw_scope(ivl_scope_t net, ivl_scope_t parent) { unsigned idx; @@ -380,6 +435,11 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) draw_event_in_scope(event); } + for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) { + ivl_lpm_t lpm = ivl_scope_lpm(net, idx); + draw_lpm_in_scope(lpm); + } + if (ivl_scope_type(net) == IVL_SCT_TASK) draw_task_definition(net); @@ -392,6 +452,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.20 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.19 2001/04/24 02:59:52 steve * Fix generation of udp/comb definitions. * diff --git a/vvp/compile.cc b/vvp/compile.cc index e9603c944..50c3c1d5c 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: compile.cc,v 1.41 2001/04/26 03:10:55 steve Exp $" +#ident "$Id: compile.cc,v 1.42 2001/04/26 05:12:02 steve Exp $" #endif # include "compile.h" @@ -262,6 +262,9 @@ void compile_functor(char*label, char*type, unsigned init, } else if (strcmp(type, "BUF") == 0) { obj->table = ft_BUF; + } else if (strcmp(type, "MUXZ") == 0) { + obj->table = ft_MUXZ; + } else if (strcmp(type, "NAND") == 0) { obj->table = ft_NAND; @@ -954,6 +957,9 @@ void compile_dump(FILE*fd) /* * $Log: compile.cc,v $ + * Revision 1.42 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.41 2001/04/26 03:10:55 steve * Redo and simplify UDP behavior. * diff --git a/vvp/draw_tt.c b/vvp/draw_tt.c index 737a4764d..d60d21671 100644 --- a/vvp/draw_tt.c +++ b/vvp/draw_tt.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: draw_tt.c,v 1.6 2001/04/21 02:04:01 steve Exp $" +#ident "$Id: draw_tt.c,v 1.7 2001/04/26 05:12:02 steve Exp $" #endif # include @@ -122,6 +122,47 @@ static void draw_BUF(void) printf("};\n"); } +static void draw_MUXZ(void) +{ + unsigned i0, i1, i2, i3; + + printf("const unsigned char ft_MUXZ[64] = {"); + + for (i3 = 0 ; i3 < 4 ; i3 += 1) + for (i2 = 0 ; i2 < 4 ; i2 += 1) { + printf("\n "); + for (i1 = 0 ; i1 < 4 ; i1 += 1) { + unsigned idx = (i3 << 4) | (i2 << 2) | i1; + unsigned char byte = 0; + + for (i0 = 0 ; i0 < 4 ; i0 += 1) { + unsigned val; + if (i3 == 0) + val = 3; + else if (i3 == 2) + val = 2; + else if (i3 == 3) + val = 2; + else if (i2 >= 2) { + if (i0 == i1) + val = i0; + else + val = 2; + } else if (i2 == 0) + val = i0; + else + val = i1; + + byte |= val << (i0*2); + } + + printf("0x%02x, ", byte); + } + } + + printf("};\n"); +} + static void draw_NOR(void) { unsigned i0, i1, i2, i3; @@ -388,6 +429,7 @@ main() printf("# include \"functor.h\"\n"); draw_AND(); draw_BUF(); + draw_MUXZ(); draw_NAND(); draw_NOR(); draw_NOT(); @@ -401,6 +443,9 @@ main() /* * $Log: draw_tt.c,v $ + * Revision 1.7 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.6 2001/04/21 02:04:01 steve * Add NAND and XNOR functors. * diff --git a/vvp/functor.h b/vvp/functor.h index a863db2db..c60b29263 100644 --- a/vvp/functor.h +++ b/vvp/functor.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.h,v 1.14 2001/04/24 02:23:59 steve Exp $" +#ident "$Id: functor.h,v 1.15 2001/04/26 05:12:02 steve Exp $" #endif # include "pointers.h" @@ -174,6 +174,7 @@ extern void functor_dump(FILE*fd); extern const unsigned char ft_AND[]; extern const unsigned char ft_BUF[]; +extern const unsigned char ft_MUXZ[]; extern const unsigned char ft_NAND[]; extern const unsigned char ft_NOR[]; extern const unsigned char ft_NOT[]; @@ -184,6 +185,9 @@ extern const unsigned char ft_var[]; /* * $Log: functor.h,v $ + * Revision 1.15 2001/04/26 05:12:02 steve + * Implement simple MUXZ for ?: operators. + * * Revision 1.14 2001/04/24 02:23:59 steve * Support for UDP devices in VVP (Stephen Boettcher) * diff --git a/vvp/functor.txt b/vvp/functor.txt index 93b0b97c4..f270ea3c5 100644 --- a/vvp/functor.txt +++ b/vvp/functor.txt @@ -28,3 +28,41 @@ A propagation event is the only way that the output of a functor is moved to the input of another functor. The propagation event, which is given a pointer to the functor to propagate, looks at the output list and sets the listed inputs to the current value of the output. + + +BUILT-IN FUNCTOR TABLES + +* AND + +* BUF + +* MUXZ + +This is a single-bit A/B mux with an active sigh enable. The 4 inputs +are A, B, select and enable: + + Se En + 0 0 z + 0 1 A + 1 0 z + 1 1 B + xz 0 z + xz 1 x + +This is used to implement structural ?: operators. The enable is +normally initialized to 1 and left unconnected. The device is called +MUXZ because the x and z values of the A and B inputs are passed +through. + +* NAND + +* NOR + +* NOT + +* OR + +* XNOR + +* XOR +