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
24
PDelays.cc
24
PDelays.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue