From 1609de6ed91cedcd479807ca7b50ecba8ad4da17 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 29 Jan 2008 09:46:14 -0800 Subject: [PATCH] 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. --- elab_net.cc | 157 ++++++++++++++++++++++++++++---------------- tgt-vvp/vvp_scope.c | 41 +++--------- 2 files changed, 110 insertions(+), 88 deletions(-) diff --git a/elab_net.cc b/elab_net.cc index f2d22fde4..385abdd7f 100644 --- a/elab_net.cc +++ b/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()); diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index fc93b33a3..e38430220 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -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)