Fix some bit based delays in continuous assignments.
This patch fixes some of the delays in bit based continuous assignments (unary -, unary +constants, string constants, reduction operators and user functions). Use draw_lpm_output_delay() in all functions that need it.
This commit is contained in:
parent
d9ac146b8f
commit
1609de6ed9
157
elab_net.cc
157
elab_net.cc
|
|
@ -2731,16 +2731,17 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
|
|||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
NetNet *net;
|
||||
NetConst *con;
|
||||
|
||||
/* If we are constrained by a l-value size, then just make a
|
||||
number constant with the correct size and set as many bits
|
||||
in that constant as make sense. Pad excess with
|
||||
zeros. Also, assume that numbers are meant to be logic
|
||||
type. */
|
||||
|
||||
if (lwidth > 0) {
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, lwidth);
|
||||
net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, lwidth);
|
||||
net->data_type(IVL_VT_LOGIC);
|
||||
net->local_flag(true);
|
||||
net->set_signed(value_->has_sign());
|
||||
|
|
@ -2749,72 +2750,90 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
|
|||
if (num.len() > lwidth)
|
||||
num = verinum(num, lwidth);
|
||||
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
|
||||
tmp->pin(0).drive0(drive0);
|
||||
tmp->pin(0).drive1(drive1);
|
||||
connect(net->pin(0), tmp->pin(0));
|
||||
|
||||
des->add_node(tmp);
|
||||
return net;
|
||||
}
|
||||
con = new NetConst(scope, scope->local_symbol(), num);
|
||||
con->pin(0).drive0(drive0);
|
||||
con->pin(0).drive1(drive1);
|
||||
|
||||
/* If the number has a length, then use that to size the
|
||||
number. Generate a constant object of exactly the user
|
||||
specified size. */
|
||||
if (value_->has_len()) {
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, value_->len());
|
||||
} else if (value_->has_len()) {
|
||||
net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, value_->len());
|
||||
net->data_type(IVL_VT_LOGIC);
|
||||
net->local_flag(true);
|
||||
net->set_signed(value_->has_sign());
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
|
||||
*value_);
|
||||
connect(net->pin(0), tmp->pin(0));
|
||||
|
||||
des->add_node(tmp);
|
||||
return net;
|
||||
}
|
||||
con = new NetConst(scope, scope->local_symbol(),
|
||||
*value_);
|
||||
|
||||
/* None of the above tight constraints are present, so make a
|
||||
plausible choice for the width. Try to reduce the width as
|
||||
much as possible by eliminating high zeros of unsigned
|
||||
numbers. */
|
||||
} else {
|
||||
|
||||
if (must_be_self_determined_flag) {
|
||||
cerr << get_fileline() << ": error: No idea how wide to make "
|
||||
<< "the unsized constant " << *value_ << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
unsigned width = value_->len();
|
||||
|
||||
if (value_->has_sign() && (value_->get(width-1) == verinum::V0)) {
|
||||
|
||||
/* If the number is signed, but known to be positive,
|
||||
then reduce it down as if it were unsigned. */
|
||||
while (width > 1) {
|
||||
if (value_->get(width-1) != verinum::V0)
|
||||
break;
|
||||
width -= 1;
|
||||
if (must_be_self_determined_flag) {
|
||||
cerr << get_fileline() << ": error: No idea how wide to "
|
||||
<< "make the unsized constant " << *value_ << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
} else if (value_->has_sign() == false) {
|
||||
while ( (width > 1) && (value_->get(width-1) == verinum::V0))
|
||||
width -= 1;
|
||||
unsigned width = value_->len();
|
||||
|
||||
if (value_->has_sign() && (value_->get(width-1) == verinum::V0)) {
|
||||
|
||||
/* If the number is signed, but known to be positive,
|
||||
then reduce it down as if it were unsigned. */
|
||||
while (width > 1) {
|
||||
if (value_->get(width-1) != verinum::V0)
|
||||
break;
|
||||
width -= 1;
|
||||
|
||||
}
|
||||
|
||||
} else if (value_->has_sign() == false) {
|
||||
while ( (width > 1) && (value_->get(width-1) == verinum::V0))
|
||||
width -= 1;
|
||||
}
|
||||
|
||||
verinum num (verinum::V0, width);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
num.set(idx, value_->get(idx));
|
||||
|
||||
net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
net->data_type(IVL_VT_LOGIC);
|
||||
net->local_flag(true);
|
||||
con = new NetConst(scope, scope->local_symbol(), num);
|
||||
}
|
||||
|
||||
verinum num (verinum::V0, width);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
num.set(idx, value_->get(idx));
|
||||
/* If there are non-zero output delays, then create bufz
|
||||
devices to carry the propagation delays. Otherwise, just
|
||||
connect the result to the output. */
|
||||
if (rise || fall || decay) {
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, net->vector_width());
|
||||
tmp->data_type(IVL_VT_LOGIC);
|
||||
tmp->local_flag(true);
|
||||
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
net->data_type(IVL_VT_LOGIC);
|
||||
net->local_flag(true);
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
|
||||
connect(net->pin(0), tmp->pin(0));
|
||||
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(),
|
||||
net->vector_width());
|
||||
tmpz->rise_time(rise);
|
||||
tmpz->fall_time(fall);
|
||||
tmpz->decay_time(decay);
|
||||
tmpz->pin(0).drive0(drive0);
|
||||
tmpz->pin(0).drive1(drive1);
|
||||
|
||||
des->add_node(tmp);
|
||||
connect(con->pin(0), tmp->pin(0));
|
||||
connect(tmp->pin(0), tmpz->pin(1));
|
||||
connect(net->pin(0), tmpz->pin(0));
|
||||
|
||||
des->add_node(tmpz);
|
||||
} else {
|
||||
connect(con->pin(0), net->pin(0));
|
||||
}
|
||||
|
||||
des->add_node(con);
|
||||
return net;
|
||||
}
|
||||
|
||||
|
|
@ -2858,11 +2877,35 @@ NetNet* PEString::elaborate_net(Design*des, NetScope*scope,
|
|||
num.set(idx, (byte & mask)? verinum::V1 : verinum::V0);
|
||||
}
|
||||
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(), num);
|
||||
tmp->set_line(*this);
|
||||
des->add_node(tmp);
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(), num);
|
||||
con->set_line(*this);
|
||||
des->add_node(con);
|
||||
|
||||
connect(net->pin(0), tmp->pin(0));
|
||||
/* If there are non-zero output delays, then create bufz
|
||||
devices to carry the propagation delays. Otherwise, just
|
||||
connect the result to the output. */
|
||||
if (rise || fall || decay) {
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, net->vector_width());
|
||||
tmp->data_type(IVL_VT_LOGIC);
|
||||
tmp->local_flag(true);
|
||||
|
||||
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(),
|
||||
net->vector_width());
|
||||
tmpz->rise_time(rise);
|
||||
tmpz->fall_time(fall);
|
||||
tmpz->decay_time(decay);
|
||||
tmpz->pin(0).drive0(drive0);
|
||||
tmpz->pin(0).drive1(drive1);
|
||||
|
||||
connect(con->pin(0), tmp->pin(0));
|
||||
connect(tmp->pin(0), tmpz->pin(1));
|
||||
connect(net->pin(0), tmpz->pin(0));
|
||||
|
||||
des->add_node(tmpz);
|
||||
} else {
|
||||
connect(con->pin(0), net->pin(0));
|
||||
}
|
||||
|
||||
return net;
|
||||
}
|
||||
|
|
@ -3161,6 +3204,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
connect(gate->pin(0), sig->pin(0));
|
||||
connect(gate->pin(1), sub_sig->pin(0));
|
||||
des->add_node(gate);
|
||||
gate->set_line(*this);
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
|
|
@ -3171,7 +3215,10 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
sig->vector_width());
|
||||
sub->attribute(perm_string::literal("LPM_Direction"),
|
||||
verinum("SUB"));
|
||||
|
||||
sub->set_line(*this);
|
||||
sub->rise_time(rise);
|
||||
sub->fall_time(fall);
|
||||
sub->decay_time(decay);
|
||||
des->add_node(sub);
|
||||
|
||||
connect(sig->pin(0), sub->pin_Result());
|
||||
|
|
|
|||
|
|
@ -1793,21 +1793,7 @@ static void draw_lpm_cmp(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 .cmp/%s%s %u, %s, %s;\n",
|
||||
net, dly, type, signed_string, width,
|
||||
|
|
@ -2065,23 +2051,10 @@ static void draw_type_string_of_nex(ivl_nexus_t nex)
|
|||
|
||||
static void draw_lpm_sfunc(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);
|
||||
}
|
||||
|
||||
unsigned idx;
|
||||
|
||||
const char*dly = draw_lpm_output_delay(net);
|
||||
|
||||
fprintf(vvp_out, "L_%p%s .sfunc %u %u \"%s\"", net, dly,
|
||||
ivl_file_table_index(ivl_lpm_file(net)), ivl_lpm_lineno(net),
|
||||
ivl_lpm_string(net));
|
||||
|
|
@ -2285,8 +2258,10 @@ static void draw_lpm_part_bi(ivl_lpm_t net)
|
|||
*/
|
||||
static void draw_lpm_re(ivl_lpm_t net, const char*type)
|
||||
{
|
||||
fprintf(vvp_out, "L_%p .reduce/%s %s;\n",
|
||||
net, type, draw_net_input(ivl_lpm_data(net,0)));
|
||||
const char*dly = draw_lpm_output_delay(net);
|
||||
|
||||
fprintf(vvp_out, "L_%p%s .reduce/%s %s;\n", net, dly,
|
||||
type, draw_net_input(ivl_lpm_data(net,0)));
|
||||
}
|
||||
|
||||
static void draw_lpm_repeat(ivl_lpm_t net)
|
||||
|
|
|
|||
Loading…
Reference in New Issue