/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2019  David Shah <dave@ds0.me>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

/*
 * Generic Frontend Framework
 *
 * This is designed to make it possible to build frontends for parsing any format isomorphic to Yosys JSON [1]
 * with maximal inlining and minimal need for overhead such as runtime polymorphism or extra wrapper types.
 *
 * [1] http://www.clifford.at/yosys/cmd_write_json.html
 *
 * The frontend should implement a class referred to as FrontendType that defines the following type(def)s and
 * functions:
 *
 * Types:
 *   ModuleDataType: corresponds to a single entry in "modules"
 *   ModulePortDataType: corresponds to a single entry in "ports" of a module
 *   CellDataType: corresponds to a single entry in "cells"
 *   NetnameDataType: corresponds to a single entry in "netnames"
 *   BitVectorDataType: corresponds to a signal/constant bit vector (e.g. a "connections" field)
 *
 * Functions:
 *
 *   void foreach_module(Func) const;
 *       calls Func(const std::string &name, const ModuleDataType &mod);
 *       for each module in the netlist
 *
 *   void foreach_port(const ModuleDataType &mod, Func) const;
 *       calls Func(const std::string &name, const ModulePortDataType &port);
 *       for each port of mod
 *
 *   void foreach_cell(const ModuleDataType &mod, Func) const;
 *       calls Func(const std::string &name, const CellDataType &cell)
 *       for each cell of mod
 *
 *   void foreach_netname(const ModuleDataType &mod, Func) const;
 *       calls Func(const std::string &name, const NetnameDataType &cell);
 *       for each netname entry of mod
 *
 *   PortType get_port_dir(const ModulePortDataType &port) const;
 *       gets the PortType direction of a module port
 *
 *   int get_array_offset(const ModulePortDataType &port) const;
 *       gets the start bit number of a port or netname entry
 *
 *   bool is_array_upto(const ModulePortDataType &port) const;
 *       returns true if a port/net is an "upto" type port or netname entry
 *
 *   const BitVectorDataType &get_port_bits(const ModulePortDataType &port) const;
 *       gets the bit vector of a module port
 *
 *   const std::string& get_cell_type(const CellDataType &cell) const;
 *       gets the type of a cell
 *
 *   void foreach_attr(const {ModuleDataType|CellDataType|ModulePortDataType|NetnameDataType} &obj, Func) const;
 *       calls Func(const std::string &name, const Property &value);
 *       for each attribute on a module, cell, module port or net
 *
 *   void foreach_param(const CellDataType &obj, Func) const;
 *       calls Func(const std::string &name, const Property &value);
 *       for each parameter of a cell
 *
 *   void foreach_setting(const ModuleDataType &obj, Func) const;
 *       calls Func(const std::string &name, const Property &value);
 *       for each module-level setting
 *
 *   void foreach_port_dir(const CellDataType &cell, Func) const;
 *       calls Func(const std::string &name, PortType dir);
 *       for each port direction of a cell
 *
 *   void foreach_port_conn(const CellDataType &cell, Func) const;
 *       calls Func(const std::string &name, const BitVectorDataType &conn);
 *       for each port connection of a cell
 *
 *   const BitVectorDataType &get_net_bits(const NetnameDataType &net) const;
 *       gets the BitVector corresponding to the bits entry of a netname field
 *
 *   int get_vector_length(const BitVectorDataType &bits) const;
 *       gets the length of a BitVector
 *
 *   bool is_vector_bit_constant(const BitVectorDataType &bits, int i) const;
 *       returns true if bit <i> of bits is constant
 *
 *   char get_vector_bit_constval(const BitVectorDataType &bits, int i) const;
 *       returns a char [01xz] corresponding to the constant value of bit <i>
 *
 *   int get_vector_bit_signal(const BitVectorDataType &bits, int i) const;
 *       returns the signal number of vector bit <i>
 *
 */

#include "design_utils.h"
#include "log.h"
#include "nextpnr.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN

namespace {

// Used for hierarchy resolution
struct ModuleInfo
{
    bool is_top = false, is_blackbox = false, is_whitebox = false;
    inline bool is_box() const { return is_blackbox || is_whitebox; }
    std::unordered_set<IdString> instantiated_celltypes;
};

template <typename FrontendType> struct GenericFrontend
{
    GenericFrontend(Context *ctx, const FrontendType &impl) : ctx(ctx), impl(impl) {}
    void operator()()
    {
        // Find which module is top
        find_top_module();
        HierModuleState m;
        m.is_toplevel = true;
        m.prefix = "";
        m.path = top;
        ctx->top_module = top;
        // Do the actual import, starting from the top level module
        import_module(m, top.str(ctx), top.str(ctx), mod_refs.at(top));
    }

    Context *ctx;
    const FrontendType &impl;
    using mod_dat_t = typename FrontendType::ModuleDataType;
    using mod_port_dat_t = typename FrontendType::ModulePortDataType;
    using cell_dat_t = typename FrontendType::CellDataType;
    using netname_dat_t = typename FrontendType::NetnameDataType;
    using bitvector_t = typename FrontendType::BitVectorDataType;

    std::unordered_map<IdString, ModuleInfo> mods;
    std::unordered_map<IdString, const mod_dat_t &> mod_refs;
    IdString top;

    // Process the list of modules and determine
    // the top module
    void find_top_module()
    {
        impl.foreach_module([&](const std::string &name, const mod_dat_t &mod) {
            IdString mod_id = ctx->id(name);
            auto &mi = mods[mod_id];
            mod_refs.emplace(mod_id, mod);
            impl.foreach_attr(mod, [&](const std::string &name, const Property &value) {
                if (name == "top")
                    mi.is_top = (value.intval != 0);
                else if (name == "blackbox")
                    mi.is_blackbox = (value.intval != 0);
                else if (name == "whitebox")
                    mi.is_whitebox = (value.intval != 0);
            });
            impl.foreach_cell(mod, [&](const std::string &name, const cell_dat_t &cell) {
                mi.instantiated_celltypes.insert(ctx->id(impl.get_cell_type(cell)));
            });
        });
        // First of all, see if a top module has been manually specified
        if (ctx->settings.count(ctx->id("frontend/top"))) {
            IdString user_top = ctx->id(ctx->settings.at(ctx->id("frontend/top")).as_string());
            if (!mods.count(user_top))
                log_error("Top module '%s' not found!\n", ctx->nameOf(user_top));
            top = user_top;
            return;
        }
        // If not, look for a module with the top attribute set
        IdString top_by_attr;
        for (auto &mod : mods) {
            if (mod.second.is_top && !mod.second.is_box()) {
                if (top_by_attr != IdString())
                    log_error("Found multiple modules with (* top *) set (including %s and %s).\n",
                              ctx->nameOf(top_by_attr), ctx->nameOf(mod.first));
                top_by_attr = mod.first;
            }
        }
        if (top_by_attr != IdString()) {
            top = top_by_attr;
            return;
        }
        // Finally, attempt to autodetect the top module using hierarchy
        // (a module that is not a box and is not used as a cell by any other module)
        std::unordered_set<IdString> candidate_top;
        for (auto &mod : mods)
            if (!mod.second.is_box())
                candidate_top.insert(mod.first);
        for (auto &mod : mods)
            for (auto &c : mod.second.instantiated_celltypes)
                candidate_top.erase(c);
        if (candidate_top.size() != 1) {
            if (candidate_top.size() == 0)
                log_info("No candidate top level modules.\n");
            else
                for (auto ctp : sorted(candidate_top))
                    log_info("Candidate top module: '%s'\n", ctx->nameOf(ctp));
            log_error("Failed to autodetect top module, please specify using --top.\n");
        }
        top = *(candidate_top.begin());
    }

    // Create a unique name (guaranteed collision free) for a net or a cell; based on
    // a base name and suffix. __unique__i will be be appended with increasing i
    // if a collision is found until no collision
    IdString unique_name(const std::string &base, const std::string &suffix, bool is_net)
    {
        IdString name;
        int incr = 0;
        do {
            std::string comb = base + suffix;
            if (incr > 0) {
                comb += "__unique__";
                comb += std::to_string(incr);
            }
            name = ctx->id(comb);
            incr++;
        } while (is_net ? ctx->nets.count(name) : ctx->cells.count(name));
        return name;
    }

    // A flat index of map; designed to cope with merging nets where pointers to nets would go stale
    // A net's udata points into this index
    std::vector<NetInfo *> net_flatindex;
    std::vector<std::vector<int>> net_old_indices; // the other indices of a net in net_flatindex for merging

    // This structure contains some structures specific to the import of a module at
    // a certain point in the hierarchy
    struct HierModuleState
    {
        bool is_toplevel;
        std::string prefix;
        IdString parent_path, path;
        // Map from index in module to "flat" index of nets
        std::vector<int> index_to_net_flatindex;
        // Get a reference to index_to_net; resizing if
        // appropriate
        int &net_by_idx(int idx)
        {
            NPNR_ASSERT(idx >= 0);
            if (idx >= int(index_to_net_flatindex.size()))
                index_to_net_flatindex.resize(idx + 1, -1);
            return index_to_net_flatindex.at(idx);
        }
        std::unordered_map<IdString, std::vector<int>> port_to_bus;
        // All of the names given to a net
        std::vector<std::vector<std::string>> net_names;
    };

    void import_module(HierModuleState &m, const std::string &name, const std::string &type, const mod_dat_t &data)
    {
        NPNR_ASSERT(!ctx->hierarchy.count(m.path));
        ctx->hierarchy[m.path].name = ctx->id(name);
        ctx->hierarchy[m.path].type = ctx->id(type);
        ctx->hierarchy[m.path].parent = m.parent_path;
        ctx->hierarchy[m.path].fullpath = m.path;

        std::vector<NetInfo *> index_to_net;
        if (!m.is_toplevel) {
            // Import port connections; for submodules only
            import_port_connections(m, data);
        } else {
            // Just create a list of ports for netname resolution
            impl.foreach_port(data,
                              [&](const std::string &name, const mod_port_dat_t &) { m.port_to_bus[ctx->id(name)]; });
            // Import module-level attributes
            impl.foreach_attr(
                    data, [&](const std::string &name, const Property &value) { ctx->attrs[ctx->id(name)] = value; });
            // Import settings
            impl.foreach_setting(data, [&](const std::string &name, const Property &value) {
                ctx->settings[ctx->id(name)] = value;
            });
        }
        import_module_netnames(m, data);
        import_module_cells(m, data);
        if (m.is_toplevel) {
            import_toplevel_ports(m, data);
            // Mark design as loaded through nextpnr
            ctx->settings[ctx->id("synth")] = 1;
            // Process nextpnr-specific attributes
            ctx->attributesToArchInfo();
        }
    }

    // Multiple labels might refer to the same net. Resolve conflicts for the primary name thus:
    //  - (toplevel) ports are always preferred
    //  - names with fewer $ are always prefered
    //  - between equal $ counts, fewer .s are prefered
    //  - ties are resolved alphabetically
    bool prefer_netlabel(HierModuleState &m, const std::string &a, const std::string &b)
    {
        if (m.port_to_bus.count(ctx->id(a)))
            return true;
        if (m.port_to_bus.count(ctx->id(b)))
            return false;

        if (b.empty())
            return true;
        long a_dollars = std::count(a.begin(), a.end(), '$'), b_dollars = std::count(b.begin(), b.end(), '$');
        if (a_dollars < b_dollars)
            return true;
        else if (a_dollars > b_dollars)
            return false;
        long a_dots = std::count(a.begin(), a.end(), '.'), b_dots = std::count(b.begin(), b.end(), '.');
        if (a_dots < b_dots)
            return true;
        else if (a_dots > b_dots)
            return false;
        return a < b;
    };

    // Get a net by index in modulestate (not flatindex); creating it if it doesn't already exist
    NetInfo *create_or_get_net(HierModuleState &m, int idx)
    {
        auto &midx = m.net_by_idx(idx);
        if (midx != -1) {
            return net_flatindex.at(midx);
        } else {
            std::string name;
            if (idx < int(m.net_names.size()) && !m.net_names.at(idx).empty()) {
                // Use the rule above to find the preferred name for a net
                name = m.net_names.at(idx).at(0);
                for (size_t j = 1; j < m.net_names.at(idx).size(); j++)
                    if (prefer_netlabel(m, m.net_names.at(idx).at(j), name))
                        name = m.net_names.at(idx).at(j);
            } else {
                name = "$frontend$" + std::to_string(idx);
            }
            NetInfo *net = ctx->createNet(unique_name(m.prefix, name, true));
            // Add to the flat index of nets
            net->udata = int(net_flatindex.size());
            net_flatindex.push_back(net);
            // Add to the module-level index of netsd
            midx = net->udata;
            // Create aliases for all possible names
            if (idx < int(m.net_names.size()) && !m.net_names.at(idx).empty()) {
                for (const auto &name : m.net_names.at(idx)) {
                    IdString name_id = ctx->id(name);
                    net->aliases.push_back(name_id);
                    ctx->net_aliases[name_id] = net->name;
                }
            } else {
                net->aliases.push_back(net->name);
                ctx->net_aliases[net->name] = net->name;
            }
            return net;
        }
    }

    // Get the name of a vector bit given basename; settings and index
    std::string get_bit_name(const std::string &base, int index, int length, int offset = 0, bool upto = false)
    {
        std::string port = base;
        if (length == 1 && offset == 0)
            return port;
        int real_index;
        if (upto)
            real_index = offset + length - index - 1; // reversed ports like [0:7]
        else
            real_index = offset + index; // normal 'downto' ports like [7:0]
        port += '[';
        port += std::to_string(real_index);
        port += ']';
        return port;
    }

    // Import the netnames section of a module
    void import_module_netnames(HierModuleState &m, const mod_dat_t &data)
    {
        impl.foreach_netname(data, [&](const std::string &basename, const netname_dat_t &nn) {
            bool upto = impl.is_array_upto(nn);
            int offset = impl.get_array_offset(nn);
            const auto &bits = impl.get_net_bits(nn);
            int width = impl.get_vector_length(bits);
            for (int i = 0; i < width; i++) {
                if (impl.is_vector_bit_constant(bits, i))
                    continue;

                std::string bit_name = get_bit_name(basename, i, width, offset, upto);

                int net_bit = impl.get_vector_bit_signal(bits, i);
                int mapped_bit = m.net_by_idx(net_bit);
                if (mapped_bit == -1) {
                    // Net doesn't exist yet. Add the name here to the list of candidate names so we have that for when
                    // we create it later
                    if (net_bit >= int(m.net_names.size()))
                        m.net_names.resize(net_bit + 1);
                    m.net_names.at(net_bit).push_back(bit_name);
                } else {
                    // Net already exists; add this name as an alias
                    NetInfo *ni = net_flatindex.at(mapped_bit);
                    IdString alias_name = ctx->id(m.prefix + bit_name);
                    if (ctx->net_aliases.count(alias_name))
                        continue; // don't add duplicate aliases
                    ctx->net_aliases[alias_name] = ni->name;
                    ni->aliases.push_back(alias_name);
                }
            }
        });
    }

    // Create a new constant net; given a hint for what the name should be and its value
    NetInfo *create_constant_net(HierModuleState &m, const std::string &name_hint, char constval)
    {
        IdString name = unique_name(m.prefix, name_hint, true);
        NetInfo *ni = ctx->createNet(name);
        add_constant_driver(m, ni, constval);
        return ni;
    }

    // Import a leaf cell - (white|black)box
    void import_leaf_cell(HierModuleState &m, const std::string &name, const cell_dat_t &cd)
    {
        IdString inst_name = unique_name(m.prefix, name, false);
        ctx->hierarchy[m.path].leaf_cells[ctx->id(name)] = inst_name;
        CellInfo *ci = ctx->createCell(inst_name, ctx->id(impl.get_cell_type(cd)));
        // Import port directions
        std::unordered_map<IdString, PortType> port_dirs;
        impl.foreach_port_dir(cd, [&](const std::string &port, PortType dir) { port_dirs[ctx->id(port)] = dir; });
        // Import port connectivity
        impl.foreach_port_conn(cd, [&](const std::string &name, const bitvector_t &bits) {
            if (!port_dirs.count(ctx->id(name)))
                log_error("Failed to get direction for port '%s' of cell '%s'\n", name.c_str(), inst_name.c_str(ctx));
            PortType dir = port_dirs.at(ctx->id(name));
            int width = impl.get_vector_length(bits);
            for (int i = 0; i < width; i++) {
                std::string port_bit_name = get_bit_name(name, i, width);
                IdString port_bit_ids = ctx->id(port_bit_name);
                // Create cell port
                ci->ports[port_bit_ids].name = port_bit_ids;
                ci->ports[port_bit_ids].type = dir;
                // Resolve connectivity
                NetInfo *net;
                if (impl.is_vector_bit_constant(bits, i)) {
                    // Create a constant driver if one is needed
                    net = create_constant_net(m, name + "." + port_bit_name + "$const",
                                              impl.get_vector_bit_constval(bits, i));
                } else {
                    // Otherwise, lookup (creating if needed) the net with this index
                    net = create_or_get_net(m, impl.get_vector_bit_signal(bits, i));
                }
                NPNR_ASSERT(net != nullptr);

                // Check for multiple drivers
                if (dir == PORT_OUT && net->driver.cell != nullptr)
                    log_error("Net '%s' is multiply driven by cell ports %s.%s and %s.%s\n", ctx->nameOf(net),
                              ctx->nameOf(net->driver.cell), ctx->nameOf(net->driver.port), ctx->nameOf(inst_name),
                              port_bit_name.c_str());
                connect_port(ctx, net, ci, port_bit_ids);
            }
        });
        // Import attributes and parameters
        impl.foreach_attr(cd,
                          [&](const std::string &name, const Property &value) { ci->attrs[ctx->id(name)] = value; });
        impl.foreach_param(cd,
                           [&](const std::string &name, const Property &value) { ci->params[ctx->id(name)] = value; });
    }

    // Import a submodule cell
    void import_submodule_cell(HierModuleState &m, const std::string &name, const cell_dat_t &cd)
    {
        HierModuleState submod;
        submod.is_toplevel = false;
        // Create mapping from submodule port to nets (referenced by index in flatindex)
        impl.foreach_port_conn(cd, [&](const std::string &name, const bitvector_t &bits) {
            int width = impl.get_vector_length(bits);
            for (int i = 0; i < width; i++) {
                // Index of port net in flatindex
                int net_ref = -1;
                if (impl.is_vector_bit_constant(bits, i)) {
                    // Create a constant driver if one is needed
                    std::string port_bit_name = get_bit_name(name, i, width);
                    NetInfo *cnet = create_constant_net(m, name + "." + port_bit_name + "$const",
                                                        impl.get_vector_bit_constval(bits, i));
                    cnet->udata = int(net_flatindex.size());
                    net_flatindex.push_back(cnet);
                    net_ref = cnet->udata;
                } else {
                    // Otherwise, lookup (creating if needed) the net with given in-module index
                    net_ref = create_or_get_net(m, impl.get_vector_bit_signal(bits, i))->udata;
                }
                NPNR_ASSERT(net_ref != -1);
                submod.port_to_bus[ctx->id(name)].push_back(net_ref);
            }
        });
        // Create prefix for submodule
        submod.prefix = m.prefix;
        submod.prefix += name;
        submod.prefix += '.';
        submod.parent_path = m.path;
        submod.path = ctx->id(m.path.str(ctx) + "/" + name);
        ctx->hierarchy[m.path].hier_cells[ctx->id(name)] = submod.path;
        // Do the submodule import
        auto type = impl.get_cell_type(cd);
        import_module(submod, name, type, mod_refs.at(ctx->id(type)));
    }

    // Import the cells section of a module
    void import_module_cells(HierModuleState &m, const mod_dat_t &data)
    {
        impl.foreach_cell(data, [&](const std::string &cellname, const cell_dat_t &cd) {
            IdString type = ctx->id(impl.get_cell_type(cd));
            if (mods.count(type) && !mods.at(type).is_box()) {
                // Module type is known; and not boxed. Import as a submodule by flattening hierarchy
                import_submodule_cell(m, cellname, cd);
            } else {
                // Module type is unknown or boxes. Import as a leaf cell (nextpnr CellInfo)
                import_leaf_cell(m, cellname, cd);
            }
        });
    }

    // Create a top level input/output buffer
    CellInfo *create_iobuf(NetInfo *net, PortType dir, const std::string &name)
    {
        // Skip IOBUF insertion if this is a design checkpoint (where they will already exist)
        if (ctx->settings.count(ctx->id("synth")))
            return nullptr;
        IdString name_id = ctx->id(name);
        if (ctx->cells.count(name_id))
            log_error("Cell '%s' of type '%s' with the same name as a top-level IO is not allowed.\n", name.c_str(),
                      ctx->cells.at(name_id)->type.c_str(ctx));
        CellInfo *iobuf = ctx->createCell(name_id, ctx->id("unknown_iob"));
        // Copy attributes from net to IOB
        for (auto &attr : net->attrs)
            iobuf->attrs[attr.first] = attr.second;
        // What we do now depends on port type
        if (dir == PORT_IN) {
            iobuf->type = ctx->id("$nextpnr_ibuf");
            iobuf->addOutput(ctx->id("O"));
            if (net->driver.cell != nullptr) {
                CellInfo *drv = net->driver.cell;
                if (drv->type != ctx->id("$nextpnr_iobuf"))
                    log_error("Net '%s' is multiply driven by cell port %s.%s and top level input '%s'.\n",
                              ctx->nameOf(net), ctx->nameOf(drv), ctx->nameOf(net->driver.port), name.c_str());
                // Special case: input, etc, directly drives inout
                // Use the input net of the inout instead
                net = drv->ports.at(ctx->id("I")).net;
            }
            NPNR_ASSERT(net->driver.cell == nullptr);
            // Connect IBUF output and net
            connect_port(ctx, net, iobuf, ctx->id("O"));
        } else if (dir == PORT_OUT) {
            iobuf->type = ctx->id("$nextpnr_obuf");
            iobuf->addInput(ctx->id("I"));
            // Connect IBUF input and net
            connect_port(ctx, net, iobuf, ctx->id("I"));
        } else if (dir == PORT_INOUT) {
            iobuf->type = ctx->id("$nextpnr_iobuf");
            iobuf->addInput(ctx->id("I"));
            iobuf->addOutput(ctx->id("O"));
            // Need to bifurcate the net to avoid multiple drivers and split
            // the input/output parts of an inout
            // Create a new net connecting only the current net's driver and the IOBUF input
            // Then use the IOBUF output to drive all of the current net's users
            NetInfo *split_iobuf_i = ctx->createNet(unique_name("", "$" + name + "$iobuf_i", true));
            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"));
            NPNR_ASSERT(net->driver.cell == nullptr);
            connect_port(ctx, net, iobuf, ctx->id("O"));
        }

        PortInfo pinfo;
        pinfo.name = name_id;
        pinfo.net = net;
        pinfo.type = dir;
        ctx->ports[pinfo.name] = pinfo;

        return iobuf;
    }

    // Import ports of the top level module
    void import_toplevel_ports(HierModuleState &m, const mod_dat_t &data)
    {
        // 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);
                }
            });
        }
    }

    // Add a constant-driving VCC or GND cell to make a net constant
    // (constval can be [01xz], x and z or no-ops)
    int const_autoidx = 0;
    void add_constant_driver(HierModuleState &m, NetInfo *net, char constval)
    {

        if (constval == 'x' || constval == 'z')
            return; // 'x' or 'z' is the same as undriven
        NPNR_ASSERT(constval == '0' || constval == '1');
        IdString cell_name = unique_name(
                m.prefix, net->name.str(ctx) + (constval == '1' ? "$VCC$" : "$GND$") + std::to_string(const_autoidx++),
                false);
        CellInfo *cc = ctx->createCell(cell_name, ctx->id(constval == '1' ? "VCC" : "GND"));
        cc->ports[ctx->id("Y")].name = ctx->id("Y");
        cc->ports[ctx->id("Y")].type = PORT_OUT;
        if (net->driver.cell != nullptr)
            log_error("Net '%s' is multiply driven by port %s.%s and constant '%c'\n", ctx->nameOf(net),
                      ctx->nameOf(net->driver.cell), ctx->nameOf(net->driver.port), constval);
        connect_port(ctx, net, cc, ctx->id("Y"));
    }

    // Merge two nets - e.g. if one net in a submodule bifurcates to two output bits and therefore two different
    // parent nets
    void merge_nets(NetInfo *base, NetInfo *mergee)
    {
        // Resolve drivers
        if (mergee->driver.cell != nullptr) {
            if (base->driver.cell != nullptr)
                log_error("Attempting to merge nets '%s' and '%s' due to port connectivity; but this would result in a "
                          "multiply driven net\n",
                          ctx->nameOf(base), ctx->nameOf(mergee));
            else {
                mergee->driver.cell->ports[mergee->driver.port].net = base;
                base->driver = mergee->driver;
            }
        }
        // Combine users
        for (auto &usr : mergee->users) {
            usr.cell->ports[usr.port].net = base;
            base->users.push_back(usr);
        }
        // Point aliases to the new net
        for (IdString alias : mergee->aliases) {
            ctx->net_aliases[alias] = base->name;
            base->aliases.push_back(alias);
        }
        // Create a new alias from mergee's name to new base name
        ctx->net_aliases[mergee->name] = base->name;
        // Update flat index of nets
        for (auto old_idx : net_old_indices.at(mergee->udata)) {
            net_old_indices.at(base->udata).push_back(old_idx);
            net_flatindex.at(old_idx) = base;
        }
        net_old_indices.at(base->udata).push_back(mergee->udata);
        net_flatindex.at(mergee->udata) = base;
        net_old_indices.at(mergee->udata).clear();
        // Remove merged net from context
        ctx->nets.erase(mergee->name);
    }

    // Import connections between a submodule and its parent
    void import_port_connections(HierModuleState &m, const mod_dat_t &data)
    {
        impl.foreach_port(data, [&](const std::string &name, const mod_port_dat_t &port) {
            // CHECK: should disconnected module inputs really just be skipped; or is it better
            // to insert a ground driver?
            if (!m.port_to_bus.count(ctx->id(name)))
                return;
            auto &p2b = m.port_to_bus.at(ctx->id(name));
            // Get direction and vector of port bits
            PortType dir = impl.get_port_dir(port);
            const auto &bv = impl.get_port_bits(port);
            int bv_size = impl.get_vector_length(bv);
            // Iterate over bits of port; making connections
            for (int i = 0; i < std::min<int>(bv_size, p2b.size()); i++) {
                int conn_net = p2b.at(i);
                if (conn_net == -1)
                    continue;
                NetInfo *conn_ni = net_flatindex.at(conn_net);
                NPNR_ASSERT(conn_ni != nullptr);
                if (impl.is_vector_bit_constant(bv, i)) {
                    // It is a constant, we might need to insert a constant driver here to drive the corresponding
                    // net in the parent
                    char constval = impl.get_vector_bit_constval(bv, i);
                    // Inputs cannot be driving a constant back to the parent
                    if (dir == PORT_IN)
                        log_error("Input port %s%s[%d] cannot be driving a constant '%c'.\n", m.prefix.c_str(),
                                  name.c_str(), i, constval);
                    // Insert the constant driver
                    add_constant_driver(m, conn_ni, constval);
                } else {
                    // If not driving a constant; simply make the port bit net index in the submodule correspond
                    // to connected net in the parent module
                    int &submod_net = m.net_by_idx(impl.get_vector_bit_signal(bv, i));
                    if (submod_net == -1) {
                        // A net at this index doesn't yet exist
                        // We can simply set this index to point to the net in the parent
                        submod_net = conn_net;
                    } else {
                        // A net at this index already exists (this would usually be a submodule net
                        // connected to more than one I/O port)
                        merge_nets(net_flatindex.at(submod_net), net_flatindex.at(conn_net));
                    }
                }
            }
        });
    }
};
} // namespace

NEXTPNR_NAMESPACE_END
