diff options
| author | David Shah <dave@ds0.me> | 2019-11-12 11:33:49 +0000 | 
|---|---|---|
| committer | David Shah <dave@ds0.me> | 2019-12-27 10:44:29 +0000 | 
| commit | fffc3b844730d1241d0056f989b3a9492d62005c (patch) | |
| tree | 61d2fe1cd37f5675f352e9862d8b18775225642f /frontend | |
| parent | fa7317f5940841e7ff56fed748c4f1f4117baae4 (diff) | |
| download | nextpnr-fffc3b844730d1241d0056f989b3a9492d62005c.tar.gz nextpnr-fffc3b844730d1241d0056f989b3a9492d62005c.tar.bz2 nextpnr-fffc3b844730d1241d0056f989b3a9492d62005c.zip  | |
frontend/base: Top module handling
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/frontend_base.h (renamed from frontend/generic.h) | 92 | 
1 files changed, 91 insertions, 1 deletions
diff --git a/frontend/generic.h b/frontend/frontend_base.h index 35428052..8b76cc85 100644 --- a/frontend/generic.h +++ b/frontend/frontend_base.h @@ -99,4 +99,94 @@   *   int get_vector_bit_signal(const BitVectorDataType &bits, int i);   *       returns the signal number of vector bit <i>   * - */
\ No newline at end of file + */ + +#include "log.h" +#include "nextpnr.h" +NEXTPNR_NAMESPACE_BEGIN + +namespace { + +template <typename FrontendType> struct GenericFrontend +{ +    GenericFrontend(Context *ctx, const FrontendType &impl) : ctx(ctx), impl(impl) {} +    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; + +    // Used for hierarchy resolution +    struct ModuleInfo +    { +        mod_dat_t *mod_data; +        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; +    }; +    std::unordered_map<IdString, ModuleInfo> mods; +    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]; +            mi.mod_data = &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_cells.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) +            log_error("Failed to autodetect top module, please specify using --top.\n"); +        top = *(candidate_top.begin()); +    } +}; +} // namespace + +template <typename FrontendType> void run_frontend(Context *ctx, const FrontendType &impl) {} + +NEXTPNR_NAMESPACE_END
\ No newline at end of file  | 
