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.
This commit is contained in:
Stephen Williams 2008-01-28 21:29:03 -08:00
parent abfccb65e9
commit 685095b229
3 changed files with 62 additions and 18 deletions

View File

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

View File

@ -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: <call=%s, width=%u, ports=%u>\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 "

View File

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