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. */ diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c index c2b9a4898..aff54193f 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,38 @@ 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) || ch == '_' || (value == 0 && ch == '-')) { match_fail = 0; - value *= 10; - value += ch - '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); + + if (match_fail) { + free(tmp); + break; } - if (match_fail) - 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; diff --git a/vvp/vpip_to_dec.cc b/vvp/vpip_to_dec.cc index 782c31c0c..50d76a9ac 100644 --- a/vvp/vpip_to_dec.cc +++ b/vvp/vpip_to_dec.cc @@ -229,7 +229,13 @@ 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; + slen--; + continue; + } if (isdigit(buf[slen-idx-1])) str[idx] = buf[slen-idx-1]; else @@ -266,5 +272,10 @@ void vpip_dec_str_to_vec4(vvp_vector4_t&vec, } + if (is_negative) { + vec.invert(); + vec += 1; + } + delete[]str; }