From 685095b2292bfc222b6f4d114d58dec8278211d0 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 28 Jan 2008 21:29:03 -0800 Subject: [PATCH] Support delay of user function output When used in continuous assignments, user defined functions may have delayed output. Handle that by generating the proper .delay node when needed to delay the output of a .ufunc node. --- design_dump.cc | 6 ++++-- tgt-stub/stub.c | 27 ++++++++++++++++++++++++++ tgt-vvp/vvp_scope.c | 47 ++++++++++++++++++++++++++++++--------------- 3 files changed, 62 insertions(+), 18 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index d0213725b..c502655e8 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -520,8 +520,10 @@ void NetSysFunc::dump_node(ostream&o, unsigned ind) const void NetUserFunc::dump_node(ostream&o, unsigned ind) const { - o << setw(ind) << "" << scope_path(def_) << "("; - o << ")" << endl; + o << setw(ind) << "" << "USER FUNC: " + << scope_path(def_) + << " #(" <<*rise_time()<<","<<*fall_time() << "," <<*decay_time() << ")" + << endl; dump_node_pins(o, ind+4); dump_obj_attr(o, ind+4); } diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index bb54a3149..300aefd30 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -740,6 +740,31 @@ static void show_lpm_sfunc(ivl_lpm_t net) } } +static void show_lpm_delays(ivl_lpm_t net) +{ + ivl_expr_t rise = ivl_lpm_delay(net, 0); + ivl_expr_t fall = ivl_lpm_delay(net, 1); + ivl_expr_t decay= ivl_lpm_delay(net, 2); + + if (rise==0 && fall==0 && decay==0) + return; + + fprintf(out, " #DELAYS\n"); + if (rise) + show_expression(rise, 8); + else + fprintf(out, " ERROR: missing rise delay\n"); + if (fall) + show_expression(fall, 8); + else + fprintf(out, " ERROR: missing fall delay\n"); + if (decay) + show_expression(decay, 8); + else + fprintf(out, " ERROR: missing decay delay\n"); + fprintf(out, " #END DELAYS\n"); +} + static void show_lpm_ufunc(ivl_lpm_t net) { unsigned width = ivl_lpm_width(net); @@ -751,6 +776,8 @@ static void show_lpm_ufunc(ivl_lpm_t net) fprintf(out, " LPM_UFUNC %s: \n", ivl_lpm_basename(net), ivl_scope_name(def), width, ports); + show_lpm_delays(net); + nex = ivl_lpm_q(net, 0); if (width != width_of_nexus(nex)) { fprintf(out, " ERROR: Q output nexus width=%u " diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index e8ed119a5..fc93b33a3 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1630,6 +1630,33 @@ static void draw_lpm_data_inputs(ivl_lpm_t net, unsigned base, } } +/* + * If needed, draw a .delay node to delay the output from the LPM + * device. Return the "/d" string if we drew this .delay node, or the + * "" string if the node was not needed. The caller uses that string + * to modify labels that are generated. + */ +static const char* draw_lpm_output_delay(ivl_lpm_t net) +{ + ivl_expr_t d_rise = ivl_lpm_delay(net, 0); + ivl_expr_t d_fall = ivl_lpm_delay(net, 1); + ivl_expr_t d_decay = ivl_lpm_delay(net, 2); + + const char*dly = ""; + if (d_rise != 0) { + assert(number_is_immediate(d_rise, 64)); + assert(number_is_immediate(d_fall, 64)); + assert(number_is_immediate(d_decay, 64)); + dly = "/d"; + fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n", + net, get_number_immediate(d_rise), + get_number_immediate(d_rise), + get_number_immediate(d_rise), net); + } + + return dly; +} + static void draw_lpm_add(ivl_lpm_t net) { const char*src_table[2]; @@ -1683,21 +1710,7 @@ static void draw_lpm_add(ivl_lpm_t net) draw_lpm_data_inputs(net, 0, 2, src_table); - ivl_expr_t d_rise = ivl_lpm_delay(net, 0); - ivl_expr_t d_fall = ivl_lpm_delay(net, 1); - ivl_expr_t d_decay = ivl_lpm_delay(net, 2); - - const char*dly = ""; - if (d_rise != 0) { - assert(number_is_immediate(d_rise, 64)); - assert(number_is_immediate(d_fall, 64)); - assert(number_is_immediate(d_decay, 64)); - dly = "/d"; - fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n", - net, get_number_immediate(d_rise), - get_number_immediate(d_rise), - get_number_immediate(d_rise), net); - } + const char*dly = draw_lpm_output_delay(net); fprintf(vvp_out, "L_%p%s .arith/%s %u, %s, %s;\n", net, dly, type, width, src_table[0], src_table[1]); @@ -2095,7 +2108,9 @@ static void draw_lpm_ufunc(ivl_lpm_t net) unsigned idx; ivl_scope_t def = ivl_lpm_define(net); - fprintf(vvp_out, "L_%p .ufunc TD_%s, %u", net, + const char*dly = draw_lpm_output_delay(net); + + fprintf(vvp_out, "L_%p%s .ufunc TD_%s, %u", net, dly, ivl_scope_name(def), ivl_lpm_width(net));