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