Fix constant CA delays to support two/three values.
This patch fixes the code generator to correctly create three value
constant delays. It also fixes a bug in the compiler related to the
precalculation of the high-Z delay when only two delays are given.
Previously if was using a pointer not a value comparison to find
the minimum value.
Variable delays should work when one or three values are given.
For the two value case we need to do a comparison at run time and
that will require changing the compiler/run time interface so that
can only go into the V0.10 branch. This patch can be applied to
both development and V0.9. I have added a sorry message and an
assert for this case. I will add the variable two delay case at a
later time. We also do not support mixing constant and variable
delays on a single statement. That is a much bigger change and
can wait until someone asks for it.
(cherry picked from commit b1cb80b32e)
This commit is contained in:
parent
682e54841c
commit
ec809c9137
26
PDelays.cc
26
PDelays.cc
|
|
@ -119,6 +119,20 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall)
|
||||||
|
{
|
||||||
|
NetEConst *c_rise = dynamic_cast<NetEConst*>(rise);
|
||||||
|
NetEConst *c_fall = dynamic_cast<NetEConst*>(fall);
|
||||||
|
if (c_rise && c_fall) {
|
||||||
|
if (c_rise->value() < c_fall->value()) return rise;
|
||||||
|
else return fall;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << fall->get_fileline() << ": sorry: can not calculate the "
|
||||||
|
<< "decay time from " << *rise << " and " << *fall << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void PDelays::eval_delays(Design*des, NetScope*scope,
|
void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||||
NetExpr*&rise_time,
|
NetExpr*&rise_time,
|
||||||
NetExpr*&fall_time,
|
NetExpr*&fall_time,
|
||||||
|
|
@ -140,14 +154,14 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (delay_[2]) {
|
if (delay_[2]) {
|
||||||
decay_time = calculate_val(des, scope, delay_[2]);
|
decay_time = calculate_val(des, scope, delay_[2]);
|
||||||
if (as_nets_flag)
|
if (as_nets_flag)
|
||||||
decay_time = make_delay_nets(des, scope, decay_time);
|
decay_time = make_delay_nets(des, scope,
|
||||||
|
decay_time);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (rise_time < fall_time)
|
// If this is zero then we need to do the min()
|
||||||
decay_time = rise_time;
|
// at run time.
|
||||||
else
|
decay_time = calc_decay_time(rise_time, fall_time);
|
||||||
decay_time = fall_time;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(delay_[2] == 0);
|
assert(delay_[2] == 0);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -53,10 +53,13 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
|
||||||
number_is_immediate(d_decay, 64, 0)) {
|
number_is_immediate(d_decay, 64, 0)) {
|
||||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||||
net, get_number_immediate(d_rise),
|
net, get_number_immediate(d_rise),
|
||||||
get_number_immediate(d_rise),
|
get_number_immediate(d_fall),
|
||||||
get_number_immediate(d_rise), net);
|
get_number_immediate(d_decay), net);
|
||||||
} else {
|
} else {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
|
// We do not currently support calculating the decay from
|
||||||
|
// the rise and fall variable delays.
|
||||||
|
assert(d_decay != 0);
|
||||||
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
||||||
|
|
|
||||||
|
|
@ -391,11 +391,14 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
||||||
fprintf(vvp_out, "L_%p .delay "
|
fprintf(vvp_out, "L_%p .delay "
|
||||||
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
||||||
cptr, get_number_immediate64(d_rise),
|
cptr, get_number_immediate64(d_rise),
|
||||||
get_number_immediate64(d_rise),
|
get_number_immediate64(d_fall),
|
||||||
get_number_immediate64(d_rise), cptr);
|
get_number_immediate64(d_decay), cptr);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
|
// We do not currently support calculating the decay
|
||||||
|
// from the rise and fall variable delays.
|
||||||
|
assert(d_decay != 0);
|
||||||
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
||||||
|
|
|
||||||
|
|
@ -877,10 +877,13 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||||
lptr, get_number_immediate(rise_exp),
|
lptr, get_number_immediate(rise_exp),
|
||||||
get_number_immediate(rise_exp),
|
get_number_immediate(fall_exp),
|
||||||
get_number_immediate(rise_exp), lptr);
|
get_number_immediate(decay_exp), lptr);
|
||||||
} else {
|
} else {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
|
// We do not currently support calculating the decay from
|
||||||
|
// the rise and fall variable delays.
|
||||||
|
assert(decay_exp != 0);
|
||||||
assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);
|
||||||
|
|
@ -1080,8 +1083,8 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net)
|
||||||
dly = "/d";
|
dly = "/d";
|
||||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||||
net, get_number_immediate(d_rise),
|
net, get_number_immediate(d_rise),
|
||||||
get_number_immediate(d_rise),
|
get_number_immediate(d_fall),
|
||||||
get_number_immediate(d_rise), net);
|
get_number_immediate(d_decay), net);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dly;
|
return dly;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue