diff options
author | David Shah <dave@ds0.me> | 2019-12-01 14:03:23 +0000 |
---|---|---|
committer | David Shah <dave@ds0.me> | 2019-12-27 10:44:30 +0000 |
commit | fe40094216d0007797c51ff8894127b37a4ff045 (patch) | |
tree | 3ade1df159a81ea4a363d56f6c7f662266853c60 | |
parent | b1000870244dbb1a73198e23a859825865938b4c (diff) | |
download | nextpnr-fe40094216d0007797c51ff8894127b37a4ff045.tar.gz nextpnr-fe40094216d0007797c51ff8894127b37a4ff045.tar.bz2 nextpnr-fe40094216d0007797c51ff8894127b37a4ff045.zip |
Preserve hierarchy through packing
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r-- | common/nextpnr.cc | 73 | ||||
-rw-r--r-- | common/nextpnr.h | 7 | ||||
-rw-r--r-- | ecp5/cells.cc | 10 | ||||
-rw-r--r-- | frontend/frontend_base.h | 2 | ||||
-rw-r--r-- | ice40/cells.cc | 4 | ||||
-rw-r--r-- | ice40/pack.cc | 1 |
6 files changed, 97 insertions, 0 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 933f124c..a6345b42 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -21,6 +21,7 @@ #include <boost/algorithm/string.hpp> #include "design_utils.h" #include "log.h" +#include "util.h" NEXTPNR_NAMESPACE_BEGIN @@ -723,4 +724,76 @@ void BaseCtx::copyBelPorts(IdString cell, BelId bel) } } +namespace { +struct FixupHierarchyWorker +{ + FixupHierarchyWorker(Context *ctx) : ctx(ctx){}; + Context *ctx; + void run() + { + trim_hierarchy(ctx->top_module); + rebuild_hierarchy(); + }; + // Remove cells and nets that no longer exist in the netlist + std::vector<IdString> todelete_cells, todelete_nets; + void trim_hierarchy(IdString path) + { + auto &h = ctx->hierarchy.at(path); + todelete_cells.clear(); + todelete_nets.clear(); + for (auto &lc : h.leaf_cells) { + if (!ctx->cells.count(lc.second)) + todelete_cells.push_back(lc.first); + } + for (auto &n : h.nets) + if (!ctx->nets.count(n.second)) + todelete_nets.push_back(n.first); + for (auto tdc : todelete_cells) { + h.leaf_cells_by_gname.erase(h.leaf_cells.at(tdc)); + h.leaf_cells.erase(tdc); + } + for (auto tdn : todelete_nets) { + h.nets_by_gname.erase(h.nets.at(tdn)); + h.nets.erase(tdn); + } + for (auto &sc : h.hier_cells) + trim_hierarchy(sc.second); + } + + IdString construct_local_name(HierarchicalCell &hc, IdString global_name, bool is_cell) + { + std::string gn = global_name.str(ctx); + auto dp = gn.find_last_of('.'); + if (dp != std::string::npos) + gn = gn.substr(dp + 1); + IdString name = ctx->id(gn); + // Make sure name is unique + int adder = 0; + while (is_cell ? hc.leaf_cells.count(name) : hc.nets.count(name)) { + ++adder; + name = ctx->id(gn + "$" + std::to_string(adder)); + } + return name; + } + + // Update hierarchy structure for nets and cells that have hiercell set + void rebuild_hierarchy() + { + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->hierpath == IdString()) + ci->hierpath = ctx->top_module; + auto &hc = ctx->hierarchy.at(ci->hierpath); + if (hc.leaf_cells_by_gname.count(ci->name)) + continue; // already known + IdString local_name = construct_local_name(hc, ci->name, true); + hc.leaf_cells_by_gname[ci->name] = local_name; + hc.leaf_cells[local_name] = ci->name; + } + } +}; +} // namespace + +void Context::fixupHierarchy() { FixupHierarchyWorker(this).run(); } + NEXTPNR_NAMESPACE_END diff --git a/common/nextpnr.h b/common/nextpnr.h index 7dfebd62..61e04415 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -544,6 +544,9 @@ struct HierarchicalCell IdString name, type, parent, fullpath; // Name inside cell instance -> global name std::unordered_map<IdString, IdString> leaf_cells, nets; + // Global name -> name inside cell instance + std::unordered_map<IdString, IdString> leaf_cells_by_gname, nets_by_gname; + // Cell port to net std::unordered_map<IdString, HierarchicalPort> ports; // Name inside cell instance -> global name std::unordered_map<IdString, IdString> hier_cells; @@ -836,6 +839,10 @@ struct Context : Arch, DeterministicRNG std::unordered_map<WireId, PipId> *route = nullptr, bool useEstimate = true); // -------------------------------------------------------------- + // call after changing hierpath or adding/removing nets and cells + void fixupHierarchy(); + + // -------------------------------------------------------------- // provided by sdf.cc void writeSDF(std::ostream &out, bool cvc_mode = false) const; diff --git a/ecp5/cells.cc b/ecp5/cells.cc index b06350c7..c630c2c3 100644 --- a/ecp5/cells.cc +++ b/ecp5/cells.cc @@ -233,6 +233,8 @@ static void replace_port_safe(bool has_ff, CellInfo *ff, IdString ff_port, CellI void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool driven_by_lut) { + if (lc->hierpath == IdString()) + lc->hierpath = ff->hierpath; bool has_ff = lc->ports.at(ctx->id("Q0")).net != nullptr || lc->ports.at(ctx->id("Q1")).net != nullptr; std::string reg = "REG" + std::to_string(index); set_param_safe(has_ff, lc, ctx->id("SRMODE"), str_or_default(ff->params, ctx->id("SRMODE"), "LSR_OVER_CE")); @@ -271,6 +273,8 @@ void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool drive void lut_to_slice(Context *ctx, CellInfo *lut, CellInfo *lc, int index) { + if (lc->hierpath == IdString()) + lc->hierpath = lut->hierpath; lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] = get_or_default(lut->params, ctx->id("INIT"), Property(0, 16)); replace_port(lut, ctx->id("A"), lc, ctx->id("A" + std::to_string(index))); @@ -282,6 +286,8 @@ void lut_to_slice(Context *ctx, CellInfo *lut, CellInfo *lc, int index) void ccu2c_to_slice(Context *ctx, CellInfo *ccu, CellInfo *lc) { + if (lc->hierpath == IdString()) + lc->hierpath = ccu->hierpath; lc->params[ctx->id("MODE")] = std::string("CCU2"); lc->params[ctx->id("LUT0_INITVAL")] = get_or_default(ccu->params, ctx->id("INIT0"), Property(0, 16)); lc->params[ctx->id("LUT1_INITVAL")] = get_or_default(ccu->params, ctx->id("INIT1"), Property(0, 16)); @@ -309,6 +315,8 @@ void ccu2c_to_slice(Context *ctx, CellInfo *ccu, CellInfo *lc) void dram_to_ramw(Context *ctx, CellInfo *ram, CellInfo *lc) { + if (lc->hierpath == IdString()) + lc->hierpath = ram->hierpath; lc->params[ctx->id("MODE")] = std::string("RAMW"); replace_port(ram, ctx->id("WAD[0]"), lc, ctx->id("D0")); replace_port(ram, ctx->id("WAD[1]"), lc, ctx->id("B0")); @@ -340,6 +348,8 @@ static unsigned get_dram_init(const Context *ctx, const CellInfo *ram, int bit) void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw, int index) { + if (lc->hierpath == IdString()) + lc->hierpath = ram->hierpath; lc->params[ctx->id("MODE")] = std::string("DPRAM"); lc->params[ctx->id("WREMUX")] = str_or_default(ram->params, ctx->id("WREMUX"), "WRE"); lc->params[ctx->id("WCKMUX")] = str_or_default(ram->params, ctx->id("WCKMUX"), "WCK"); diff --git a/frontend/frontend_base.h b/frontend/frontend_base.h index 9e16cb24..45847e21 100644 --- a/frontend/frontend_base.h +++ b/frontend/frontend_base.h @@ -423,8 +423,10 @@ template <typename FrontendType> struct GenericFrontend 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_by_gname[inst_name] = ctx->id(name); ctx->hierarchy[m.path].leaf_cells[ctx->id(name)] = inst_name; CellInfo *ci = ctx->createCell(inst_name, ctx->id(impl.get_cell_type(cd))); + ci->hierpath = m.path; // 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; }); diff --git a/ice40/cells.cc b/ice40/cells.cc index 3def82bf..f1901c43 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -346,6 +346,8 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) { + if (lc->hierpath == IdString()) + lc->hierpath = lut->hierpath; lc->params[ctx->id("LUT_INIT")] = lut->params[ctx->id("LUT_INIT")].extract(0, 16, Property::State::S0); replace_port(lut, ctx->id("I0"), lc, ctx->id("I0")); replace_port(lut, ctx->id("I1"), lc, ctx->id("I1")); @@ -359,6 +361,8 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut) { + if (lc->hierpath == IdString()) + lc->hierpath = dff->hierpath; lc->params[ctx->id("DFF_ENABLE")] = Property::State::S1; std::string config = dff->type.str(ctx).substr(6); auto citer = config.begin(); diff --git a/ice40/pack.cc b/ice40/pack.cc index cb430eb9..5b13e9ee 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -1487,6 +1487,7 @@ bool Arch::pack() promote_globals(ctx); ctx->assignArchInfo(); constrain_chains(ctx); + ctx->fixupHierarchy(); ctx->assignArchInfo(); ctx->settings[ctx->id("pack")] = 1; archInfoToAttributes(); |