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:
Cary R 2009-04-03 11:40:03 -07:00 committed by Stephen Williams
parent 682e54841c
commit ec809c9137
4 changed files with 38 additions and 15 deletions

View File

@ -119,6 +119,20 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*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,
NetExpr*&rise_time,
NetExpr*&fall_time,
@ -141,13 +155,13 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, scope, decay_time);
decay_time = make_delay_nets(des, scope,
decay_time);
} else {
if (rise_time < fall_time)
decay_time = rise_time;
else
decay_time = fall_time;
// If this is zero then we need to do the min()
// at run time.
decay_time = calc_decay_time(rise_time, fall_time);
}
} else {
assert(delay_[2] == 0);

View File

@ -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
* 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)) {
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);
get_number_immediate(d_fall),
get_number_immediate(d_decay), net);
} else {
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_fall) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);

View File

@ -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 "
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
cptr, get_number_immediate64(d_rise),
get_number_immediate64(d_rise),
get_number_immediate64(d_rise), cptr);
get_number_immediate64(d_fall),
get_number_immediate64(d_decay), cptr);
} else {
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_fall) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);

View File

@ -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",
lptr, get_number_immediate(rise_exp),
get_number_immediate(rise_exp),
get_number_immediate(rise_exp), lptr);
get_number_immediate(fall_exp),
get_number_immediate(decay_exp), lptr);
} else {
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(fall_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";
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);
get_number_immediate(d_fall),
get_number_immediate(d_decay), net);
}
return dly;