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:
parent
abfccb65e9
commit
685095b229
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue