From 15584a4f81881e593cc45e518be9d4f245360a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20W=C3=A4chtler?= Date: Mon, 28 Jul 2008 20:24:08 +0200 Subject: [PATCH 1/5] fix $fscan("%d") for values > 32 bit The old code returns a vpiIntVal for $fscanf("%d") format strings. This limits the maximum input range arbitrarily to 32 bit. This patch implements %d parsing similiar to %b and %x. '?' and 'X' chars are not accepted for %d format. --- vpi/sys_scanf.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c index c2b9a4898..fb58ff919 100644 --- a/vpi/sys_scanf.c +++ b/vpi/sys_scanf.c @@ -281,7 +281,6 @@ static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv) int suppress_flag = 0; int length_field = -1; int code = 0; - int sign_flag = 1; PLI_INT32 value; char*tmp; @@ -373,30 +372,36 @@ static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv) break; case 'd': - match_fail = 1; - /* Decimal integer */ - ch = byte_getc(src); - if (ch == '-') { - sign_flag = -1; - ch = byte_getc(src); - } + /* decimal integer */ + tmp = malloc(2); value = 0; - while ( isdigit(ch) ) { + tmp[0] = 0; + match_fail = 1; + + ch = byte_getc(src); + while (isdigit(ch)) { match_fail = 0; - value *= 10; - value += ch - '0'; + tmp[value++] = ch; + tmp = realloc(tmp, value+1); + tmp[value] = 0; ch = byte_getc(src); } + byte_ungetc(src, ch); - if (match_fail) + if (match_fail) { + free(tmp); break; + } + /* Matched a decimal value, put it to an argument. */ item = vpi_scan(argv); assert(item); - val.format = vpiIntVal; - val.value.integer = value * sign_flag; + val.format = vpiDecStrVal; + val.value.str = tmp; vpi_put_value(item, &val, 0, vpiNoDelay); + + free(tmp); rc += 1; break; From c71e930ffa3ca7741d43654f8b20dcff57299236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20W=C3=A4chtler?= Date: Mon, 28 Jul 2008 20:50:00 +0200 Subject: [PATCH 2/5] $fscanf("%s"): accept '-' and '_' chars. --- vpi/sys_scanf.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c index fb58ff919..aff54193f 100644 --- a/vpi/sys_scanf.c +++ b/vpi/sys_scanf.c @@ -379,12 +379,14 @@ static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv) match_fail = 1; ch = byte_getc(src); - while (isdigit(ch)) { + while (isdigit(ch) || ch == '_' || (value == 0 && ch == '-')) { match_fail = 0; - tmp[value++] = ch; - tmp = realloc(tmp, value+1); - tmp[value] = 0; - ch = byte_getc(src); + if (ch != '_') { + tmp[value++] = ch; + tmp = realloc(tmp, value+1); + tmp[value] = 0; + ch = byte_getc(src); + } } byte_ungetc(src, ch); From 484d3ea36b3d82c7720484116be7087d076e727f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20W=C3=A4chtler?= Date: Mon, 28 Jul 2008 21:40:58 +0200 Subject: [PATCH 3/5] this patch adds support for conversion of negative vpiDecStrVal in vpip_dec_str_to_vec4() --- vvp/vpip_to_dec.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vvp/vpip_to_dec.cc b/vvp/vpip_to_dec.cc index 782c31c0c..a601f70bb 100644 --- a/vvp/vpip_to_dec.cc +++ b/vvp/vpip_to_dec.cc @@ -229,7 +229,12 @@ void vpip_dec_str_to_vec4(vvp_vector4_t&vec, input is "1234", str gets "4321". */ unsigned slen = strlen(buf); char*str = new char[slen + 1]; + int is_negative = 0; for (unsigned idx = 0 ; idx < slen ; idx += 1) { + if (idx == slen-1 && buf[slen-idx-1] == '-') { + is_negative = 1; + continue; + } if (isdigit(buf[slen-idx-1])) str[idx] = buf[slen-idx-1]; else @@ -266,5 +271,10 @@ void vpip_dec_str_to_vec4(vvp_vector4_t&vec, } + if (is_negative) { + vec.invert(); + vec += 1; + } + delete[]str; } From d84771428a6465060252e859452051fb75f361d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20W=C3=A4chtler?= Date: Mon, 28 Jul 2008 22:20:00 +0200 Subject: [PATCH 4/5] need to decrement string len if we have a '-' sign --- vvp/vpip_to_dec.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/vvp/vpip_to_dec.cc b/vvp/vpip_to_dec.cc index a601f70bb..50d76a9ac 100644 --- a/vvp/vpip_to_dec.cc +++ b/vvp/vpip_to_dec.cc @@ -233,6 +233,7 @@ void vpip_dec_str_to_vec4(vvp_vector4_t&vec, for (unsigned idx = 0 ; idx < slen ; idx += 1) { if (idx == slen-1 && buf[slen-idx-1] == '-') { is_negative = 1; + slen--; continue; } if (isdigit(buf[slen-idx-1])) From 893aae2ca44b30a11cf178ceef6036bb442b3e44 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 6 Aug 2008 21:04:52 -0700 Subject: [PATCH 5/5] Add BUFZ to input ports when necessary. When driving an input port to a module, watch out for the case where the net is also driven within the instance. If this is the case, take pains to make sure what goes on in the instance doesn't leak out through the input port. Add a BUFZ (continuous assignment) to isolate the context from internal driving. --- elaborate.cc | 28 +++++++++++++++++++++++++++- net_link.cc | 35 +++++++++++++++++++++++++++++++++++ netlist.h | 4 ++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/elaborate.cc b/elaborate.cc index f22e38f00..ad7c273ab 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -944,6 +944,17 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope, return tmp; } +static bool need_bufz_for_input_port(const svector&prts) +{ + if (prts[0]->port_type() != NetNet::PINPUT) + return false; + + if (prts[0]->pin(0).nexus()->drivers_present()) + return true; + + return false; +} + /* * Instantiate a module by recursively elaborating it. Set the path of * the recursive elaboration so that signal names get properly @@ -1162,7 +1173,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const width. We use that, then, to decide how to hook it up. - NOTE that this also handles the case that the +v NOTE that this also handles the case that the port is actually empty on the inside. We assume in that case that the port is input. */ @@ -1176,6 +1187,21 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const continue; } + if (need_bufz_for_input_port(prts)) { + NetBUFZ*tmp = new NetBUFZ(scope, scope->local_symbol(), + sig->vector_width()); + des->add_node(tmp); + connect(tmp->pin(1), sig->pin(0)); + + NetNet*tmp2 = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, sig->vector_width()); + tmp2->local_flag(true); + tmp2->set_line(*this); + tmp2->data_type(sig->data_type()); + connect(tmp->pin(0), tmp2->pin(0)); + sig = tmp2; + } + } else if (prts[0]->port_type() == NetNet::PINOUT) { /* Inout to/from module. This is a more diff --git a/net_link.cc b/net_link.cc index 228add8c0..5b2621b90 100644 --- a/net_link.cc +++ b/net_link.cc @@ -247,6 +247,41 @@ verinum::V Nexus::get_init() const return verinum::Vz; } +bool Nexus::drivers_present() const +{ + assert(list_); + for (Link*cur = list_ ; cur ; cur = cur->next_) { + if (cur->get_dir() == Link::OUTPUT) + return true; + + if (cur->get_dir() == Link::INPUT) + continue; + + // Must be PASSIVE, so if it is some kind of net, see if + // it is the sort that might drive the nexus. + const NetObj*obj; + unsigned pin; + cur->cur_link(obj, pin); + if (const NetNet*net = dynamic_cast(obj)) + switch (net->type()) { + case NetNet::SUPPLY0: + case NetNet::SUPPLY1: + case NetNet::TRI0: + case NetNet::TRI1: + case NetNet::WAND: + case NetNet::WOR: + case NetNet::TRIAND: + case NetNet::TRIOR: + case NetNet::REG: + return true; + default: + break; + } + } + + return false; +} + void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay) { for (Link*cur = list_ ; cur ; cur = cur->next_) { diff --git a/netlist.h b/netlist.h index d6e01bab2..7818938e8 100644 --- a/netlist.h +++ b/netlist.h @@ -290,6 +290,10 @@ class Nexus { NetNet* pick_any_net(); + /* This method returns true if there are any drivers + (including variables) attached to this nexus. */ + bool drivers_present() const; + /* This method returns true if all the possible drivers of this nexus are constant. It will also return true if there are no drivers at all. */