diff --git a/frontend/frontend_base.h b/frontend/frontend_base.h index 35558d2f..d55e0329 100644 --- a/frontend/frontend_base.h +++ b/frontend/frontend_base.h @@ -538,6 +538,7 @@ template struct GenericFrontend auto drv = net->driver; if (drv.cell != nullptr) { disconnect_port(ctx, drv.cell, drv.port); + drv.cell->ports[drv.port].net = nullptr; connect_port(ctx, split_iobuf_i, drv.cell, drv.port); } connect_port(ctx, split_iobuf_i, iobuf, ctx->id("I")); @@ -557,25 +558,32 @@ template struct GenericFrontend // Import ports of the top level module void import_toplevel_ports(HierModuleState &m, const mod_dat_t &data) { - impl.foreach_port(data, [&](const std::string &portname, const mod_port_dat_t &pd) { - const auto &port_bv = impl.get_port_bits(pd); - int offset = impl.get_array_offset(pd); - bool is_upto = impl.is_array_upto(pd); - int width = impl.get_vector_length(port_bv); - PortType dir = impl.get_port_dir(pd); - for (int i = 0; i < width; i++) { - std::string pbit_name = get_bit_name(portname, i, width, offset, is_upto); - NetInfo *port_net = nullptr; - if (impl.is_vector_bit_constant(port_bv, i)) { - // Port bit is constant. Need to create a new constant net. - port_net = create_constant_net(m, pbit_name + "$const", impl.get_vector_bit_constval(port_bv, i)); - } else { - // Port bit is a signal. Need to create/get the associated net - port_net = create_or_get_net(m, impl.get_vector_bit_signal(port_bv, i)); + // For correct handling of inout ports driving other ports + // first import non-inouts then import inouts so that they bifurcate correctly + for (bool inout : {false, true}) { + impl.foreach_port(data, [&](const std::string &portname, const mod_port_dat_t &pd) { + const auto &port_bv = impl.get_port_bits(pd); + int offset = impl.get_array_offset(pd); + bool is_upto = impl.is_array_upto(pd); + int width = impl.get_vector_length(port_bv); + PortType dir = impl.get_port_dir(pd); + if ((dir == PORT_INOUT) != inout) + return; + for (int i = 0; i < width; i++) { + std::string pbit_name = get_bit_name(portname, i, width, offset, is_upto); + NetInfo *port_net = nullptr; + if (impl.is_vector_bit_constant(port_bv, i)) { + // Port bit is constant. Need to create a new constant net. + port_net = + create_constant_net(m, pbit_name + "$const", impl.get_vector_bit_constval(port_bv, i)); + } else { + // Port bit is a signal. Need to create/get the associated net + port_net = create_or_get_net(m, impl.get_vector_bit_signal(port_bv, i)); + } + create_iobuf(port_net, dir, pbit_name); } - create_iobuf(port_net, dir, pbit_name); - } - }); + }); + } } // Add a constant-driving VCC or GND cell to make a net constant @@ -688,4 +696,4 @@ template struct GenericFrontend }; } // namespace -NEXTPNR_NAMESPACE_END \ No newline at end of file +NEXTPNR_NAMESPACE_END diff --git a/frontend/json_frontend.cc b/frontend/json_frontend.cc index 2eb0a39b..0debd9f2 100644 --- a/frontend/json_frontend.cc +++ b/frontend/json_frontend.cc @@ -190,4 +190,4 @@ bool parse_json(std::istream &in, const std::string &filename, Context *ctx) return true; } -NEXTPNR_NAMESPACE_END \ No newline at end of file +NEXTPNR_NAMESPACE_END diff --git a/frontend/json_frontend.h b/frontend/json_frontend.h index 1e3deb8d..4d6c28f7 100644 --- a/frontend/json_frontend.h +++ b/frontend/json_frontend.h @@ -23,4 +23,4 @@ NEXTPNR_NAMESPACE_BEGIN bool parse_json(std::istream &in, const std::string &filename, Context *ctx); -NEXTPNR_NAMESPACE_END \ No newline at end of file +NEXTPNR_NAMESPACE_END diff --git a/ice40/pack.cc b/ice40/pack.cc index 90c6de31..cb430eb9 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -527,7 +527,9 @@ static void pack_io(Context *ctx) std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(sb->attrs, sb->attrs.begin())); } else if (is_sb_io(ctx, ci) || is_sb_gb_io(ctx, ci)) { NetInfo *net = ci->ports.at(ctx->id("PACKAGE_PIN")).net; - if ((net != nullptr) && (net->users.size() > 1)) + if ((net != nullptr) && ((net->users.size() > 2) || + (net->driver.cell != nullptr && + net->driver.cell->type == ctx->id("$nextpnr_obuf") && net->users.size() > 1))) log_error("PACKAGE_PIN of %s '%s' connected to more than a single top level IO.\n", ci->type.c_str(ctx), ci->name.c_str(ctx)); }