From bf427729952dd350f26e95e40ec82dd22409b344 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 16 Jun 2001 02:41:41 +0000 Subject: [PATCH] Generate code to support memory access in continuous assignment statements. (Stephan Boettcher) --- ivl_target.h | 26 +++++++--- t-dll-api.cc | 43 +++++++++++++++- t-dll.cc | 119 +++++++++++++++++++++++++++++++++++++++++++- t-dll.h | 14 +++++- tgt-vvp/vvp_scope.c | 69 ++++++++++++++++++++++--- 5 files changed, 254 insertions(+), 17 deletions(-) diff --git a/ivl_target.h b/ivl_target.h index 9befffa0d..fd984cf28 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.66 2001/06/15 04:14:18 steve Exp $" +#ident "$Id: ivl_target.h,v 1.67 2001/06/16 02:41:41 steve Exp $" #endif #ifdef __cplusplus @@ -206,7 +206,8 @@ typedef enum ivl_lpm_type_e { IVL_LPM_CMP_GT, IVL_LPM_FF, IVL_LPM_MUX, - IVL_LPM_SUB + IVL_LPM_SUB, + IVL_LPM_RAM, } ivl_lpm_type_t; /* Processes are initial or always blocks with a statement. This is @@ -500,7 +501,8 @@ extern const char* ivl_udp_name(ivl_udp_t net); * output vector. This is most devices, it turns out. * * ivl_lpm_selects - * This is the size of the select input for a LPM_MUX device + * This is the size of the select input for a LPM_MUX device, or the + * address bus width of an LPM_RAM. * * ivl_lpm_size * In addition to a width, some devices have a size. The size is @@ -511,22 +513,26 @@ 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); - /* IVL_LPM_FF */ + /* IVL_LPM_FF IVL_LPM_RAM */ extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net); - /* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_SUB */ + /* IVL_LPM_RAM */ +extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net); + /* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_RAM IVL_LPM_SUB */ extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx); /* IVL_LPM_ADD IVL_LPM_SUB */ extern ivl_nexus_t ivl_lpm_datab(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_ADD IVL_LPM_FF IVL_LPM_SUB */ + /* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_RAM IVL_LPM_SUB */ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); - /* IVL_LPM_MUX */ + /* IVL_LPM_MUX IVL_LPM_RAM */ extern unsigned ivl_lpm_selects(ivl_lpm_t net); - /* IVL_LPM_MUX */ + /* IVL_LPM_MUX IVL_LPM_RAM */ 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); + /* IVL_LPM_RAM */ +extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); /* LVAL @@ -875,6 +881,10 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.67 2001/06/16 02:41:41 steve + * Generate code to support memory access in continuous + * assignment statements. (Stephan Boettcher) + * * Revision 1.66 2001/06/15 04:14:18 steve * Generate vvp code for GT and GE comparisons. * diff --git a/t-dll-api.cc b/t-dll-api.cc index e55d6c322..81a5421e9 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.49 2001/06/15 04:14:19 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.50 2001/06/16 02:41:41 steve Exp $" #endif # include "t-dll.h" @@ -438,6 +438,7 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net) assert(net); switch (net->type) { case IVL_LPM_FF: + case IVL_LPM_RAM: return net->u_.ff.clk; default: assert(0); @@ -445,6 +446,18 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net) } } +extern "C" ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net) +{ + assert(net); + switch (net->type) { + case IVL_LPM_RAM: + return net->u_.ff.we; + default: + assert(0); + return 0; + } +} + extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) { assert(net); @@ -457,6 +470,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) return net->u_.arith.a[idx]; case IVL_LPM_FF: + case IVL_LPM_RAM: assert(idx < net->u_.ff.width); if (net->u_.ff.width == 1) return net->u_.ff.d.pin; @@ -523,6 +537,7 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx) return net->u_.arith.q[0]; case IVL_LPM_FF: + case IVL_LPM_RAM: assert(idx < net->u_.ff.width); if (net->u_.ff.width == 1) return net->u_.ff.q.pin; @@ -545,6 +560,13 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx) extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx) { switch (net->type) { + case IVL_LPM_RAM: + assert(idx < net->u_.ff.swid); + if (net->u_.ff.swid == 1) + return net->u_.ff.s.pin; + else + return net->u_.ff.s.pins[idx]; + case IVL_LPM_MUX: assert(idx < net->u_.mux.swid); if (net->u_.mux.swid == 1) @@ -561,6 +583,8 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx) extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net) { switch (net->type) { + case IVL_LPM_RAM: + return net->u_.ff.swid; case IVL_LPM_MUX: return net->u_.mux.swid; default: @@ -590,6 +614,7 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net) assert(net); switch (net->type) { case IVL_LPM_FF: + case IVL_LPM_RAM: return net->u_.ff.width; case IVL_LPM_MUX: return net->u_.mux.width; @@ -604,6 +629,18 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net) } } +extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net) +{ + assert(net); + switch (net->type) { + case IVL_LPM_RAM: + return net->u_.ff.mem; + default: + assert(0); + return 0; + } +} + extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net) { assert(net); @@ -1186,6 +1223,10 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.50 2001/06/16 02:41:41 steve + * Generate code to support memory access in continuous + * assignment statements. (Stephan Boettcher) + * * Revision 1.49 2001/06/15 04:14:19 steve * Generate vvp code for GT and GE comparisons. * diff --git a/t-dll.cc b/t-dll.cc index 3e55baae6..96286a84b 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.47 2001/06/15 05:01:09 steve Exp $" +#ident "$Id: t-dll.cc,v 1.48 2001/06/16 02:41:42 steve Exp $" #endif # include "compiler.h" @@ -820,6 +820,119 @@ void dll_target::lpm_ff(const NetFF*net) } } +void dll_target::lpm_ram_dq(const NetRamDq*net) +{ + ivl_lpm_t obj = new struct ivl_lpm_s; + obj->type = IVL_LPM_RAM; + obj->name = strdup(net->name()); + obj->u_.ff.mem = lookup_memory_(net->mem()); + assert(obj->u_.ff.mem); + obj->scope = find_scope(des_.root_, net->mem()->scope()); + assert(obj->scope); + + obj->u_.ff.width = net->width(); + obj->u_.ff.swid = net->awidth(); + + scope_add_lpm(obj->scope, obj); + + const Nexus*nex; + + // How do I find out if there is something + // connected to the clock input? + bool has_write_port = false; + + // Connect the write clock and write enable + + if (has_write_port) { + nex = net->pin_InClock().nexus(); + assert(nex->t_cookie()); + obj->u_.ff.clk = (ivl_nexus_t) nex->t_cookie(); + assert(obj->u_.ff.clk); + nexus_lpm_add(obj->u_.ff.clk, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); + + nex = net->pin_WE().nexus(); + if (nex && nex->t_cookie()) { + obj->u_.ff.we = (ivl_nexus_t) nex->t_cookie(); + assert(obj->u_.ff.we); + nexus_lpm_add(obj->u_.ff.we, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); + } + else + obj->u_.ff.we = 0x0; + } + else { + obj->u_.ff.clk = 0x0; + obj->u_.ff.we = 0x0; + } + + // Connect the address bus + + if (obj->u_.ff.swid == 1) { + nex = net->pin_Address(0).nexus(); + assert(nex->t_cookie()); + obj->u_.ff.s.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.s.pin, obj, 0, + IVL_DR_STRONG, IVL_DR_STRONG); + } + else { + obj->u_.ff.s.pins = new ivl_nexus_t [obj->u_.ff.swid]; + + for (unsigned idx = 0 ; idx < obj->u_.ff.swid ; idx += 1) { + nex = net->pin_Address(idx).nexus(); + assert(nex->t_cookie()); + obj->u_.ff.s.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.s.pins[idx], obj, 0, + IVL_DR_STRONG, IVL_DR_STRONG); + } + } + + // Connect the data busses + + if (obj->u_.ff.width == 1) { + nex = net->pin_Q(0).nexus(); + assert(nex->t_cookie()); + obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.q.pin, obj, 0, + IVL_DR_STRONG, IVL_DR_STRONG); + + if (has_write_port) { + nex = net->pin_Data(0).nexus(); + assert(nex->t_cookie()); + obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.d.pin, obj, + 0, IVL_DR_HiZ, IVL_DR_HiZ); + } + } + else if (has_write_port) { + 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->u_.ff.width ; idx += 1) { + nex = net->pin_Q(idx).nexus(); + assert(nex->t_cookie()); + obj->u_.ff.q.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.q.pins[idx], obj, 0, + IVL_DR_STRONG, IVL_DR_STRONG); + + nex = net->pin_Data(idx).nexus(); + assert(nex->t_cookie()); + obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0, + IVL_DR_HiZ, IVL_DR_HiZ); + } + } + else { + obj->u_.ff.q.pins = new ivl_nexus_t [obj->u_.ff.width]; + + for (unsigned idx = 0 ; idx < obj->u_.ff.width ; idx += 1) { + nex = net->pin_Q(idx).nexus(); + assert(nex->t_cookie()); + obj->u_.ff.q.pins[idx] = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.q.pins[idx], obj, 0, + IVL_DR_STRONG, IVL_DR_STRONG); + } + } +} + void dll_target::lpm_mux(const NetMux*net) { ivl_lpm_t obj = new struct ivl_lpm_s; @@ -1180,6 +1293,10 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.48 2001/06/16 02:41:42 steve + * Generate code to support memory access in continuous + * assignment statements. (Stephan Boettcher) + * * Revision 1.47 2001/06/15 05:01:09 steve * support LE and LT comparators. * diff --git a/t-dll.h b/t-dll.h index f251e190b..fe6b0d57b 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.47 2001/06/15 04:14:19 steve Exp $" +#ident "$Id: t-dll.h,v 1.48 2001/06/16 02:41:42 steve Exp $" #endif # include "target.h" @@ -65,6 +65,7 @@ struct dll_target : public target_t, public expr_scan_t { void lpm_compare(const NetCompare*); void lpm_ff(const NetFF*); void lpm_mux(const NetMux*); + void lpm_ram_dq(const NetRamDq*); void net_assign(const NetAssign_*); bool net_const(const NetConst*); void net_probe(const NetEvProbe*); @@ -223,7 +224,9 @@ struct ivl_lpm_s { union { struct ivl_lpm_ff_s { unsigned short width; + unsigned short swid; // ram only ivl_nexus_t clk; + ivl_nexus_t we; // ram only ?? union { ivl_nexus_t*pins; ivl_nexus_t pin; @@ -232,6 +235,11 @@ struct ivl_lpm_s { ivl_nexus_t*pins; ivl_nexus_t pin; } d; + union { // ram only + ivl_nexus_t*pins; + ivl_nexus_t pin; + } s; + ivl_memory_t mem; // ram only } ff; struct ivl_lpm_mux_s { @@ -529,6 +537,10 @@ struct ivl_statement_s { /* * $Log: t-dll.h,v $ + * Revision 1.48 2001/06/16 02:41:42 steve + * Generate code to support memory access in continuous + * assignment statements. (Stephan Boettcher) + * * Revision 1.47 2001/06/15 04:14:19 steve * Generate vvp code for GT and GE comparisons. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index af86f7b17..2a3fe95bc 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.32 2001/06/15 04:14:19 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.33 2001/06/16 02:41:42 steve Exp $" #endif # include "vvp_priv.h" @@ -115,6 +115,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) } break; + case IVL_LPM_RAM: case IVL_LPM_ADD: case IVL_LPM_SUB: for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1) @@ -619,6 +620,53 @@ static void draw_event_in_scope(ivl_event_t obj) } } +inline static void draw_lpm_ram(ivl_lpm_t net) +{ + unsigned idx; + unsigned width = ivl_lpm_width(net); + unsigned awidth = ivl_lpm_selects(net); + ivl_memory_t mem = ivl_lpm_memory(net); + ivl_nexus_t clk = ivl_lpm_clk(net); + ivl_nexus_t pin; + + if (clk) { + fprintf(vvp_out, + "CLK_%s .event posedge, ", + ivl_lpm_name(net)); + draw_input_from_net(pin); + fprintf(vvp_out, ";\n"); + } + + fprintf(vvp_out, + "L_%s .mem/port M_%s, %d,0, %d,\n ", + ivl_lpm_name(net), + ivl_memory_name(mem), + width-1, + awidth); + + for (idx = 0 ; idx < awidth ; idx += 1) { + pin = ivl_lpm_select(net, idx); + if (idx) fprintf(vvp_out, ", "); + draw_input_from_net(pin); + } + + if (clk) { + fprintf(vvp_out, ",\n CLK_%s, ", ivl_lpm_name(net)); + pin = ivl_lpm_enable(net); + if (pin) + draw_input_from_net(pin); + else + fprintf(vvp_out, "C<1>"); + for (idx=0; idx