diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/arch_pybindings_shared.h | 4 | ||||
-rw-r--r-- | common/command.cc | 20 | ||||
-rw-r--r-- | common/nextpnr.cc | 84 | ||||
-rw-r--r-- | common/nextpnr.h | 40 | ||||
-rw-r--r-- | common/pybindings.cc | 28 |
5 files changed, 151 insertions, 25 deletions
diff --git a/common/arch_pybindings_shared.h b/common/arch_pybindings_shared.h index f681af92..89a61dad 100644 --- a/common/arch_pybindings_shared.h +++ b/common/arch_pybindings_shared.h @@ -5,6 +5,10 @@ readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_conte readonly_wrapper<Context, decltype(&Context::nets), &Context::nets, wrap_context<NetMap &>>::def_wrap(ctx_cls, "nets"); readonly_wrapper<Context, decltype(&Context::net_aliases), &Context::net_aliases, wrap_context<AliasMap &>>::def_wrap( ctx_cls, "net_aliases"); +readonly_wrapper<Context, decltype(&Context::hierarchy), &Context::hierarchy, wrap_context<HierarchyMap &>>::def_wrap( + ctx_cls, "hierarchy"); +readwrite_wrapper<Context, decltype(&Context::top_module), &Context::top_module, conv_to_str<IdString>, + conv_from_str<IdString>>::def_wrap(ctx_cls, "top_module"); fn_wrapper_1a<Context, decltype(&Context::getNetByAlias), &Context::getNetByAlias, deref_and_wrap<NetInfo>, conv_from_str<IdString>>::def_wrap(ctx_cls, "getNetByAlias"); diff --git a/common/command.cc b/common/command.cc index fd310789..c2f02b27 100644 --- a/common/command.cc +++ b/common/command.cc @@ -35,7 +35,7 @@ #include <iostream> #include "command.h" #include "design_utils.h" -#include "jsonparse.h" +#include "json_frontend.h" #include "jsonwrite.h" #include "log.h" #include "timing.h" @@ -265,9 +265,8 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx) if (vm.count("json")) { std::string filename = vm["json"].as<std::string>(); std::ifstream f(filename); - if (!parse_json_file(f, filename, w.getContext())) + if (!parse_json(f, filename, w.getContext())) log_error("Loading design failed.\n"); - customAfterLoad(w.getContext()); w.notifyChangeContext(); w.updateActions(); @@ -284,7 +283,7 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx) if (vm.count("json")) { std::string filename = vm["json"].as<std::string>(); std::ifstream f(filename); - if (!parse_json_file(f, filename, ctx.get())) + if (!parse_json(f, filename, ctx.get())) log_error("Loading design failed.\n"); customAfterLoad(ctx.get()); @@ -382,12 +381,6 @@ int CommandHandler::exec() return 0; std::unordered_map<std::string, Property> values; - if (vm.count("json")) { - std::string filename = vm["json"].as<std::string>(); - std::ifstream f(filename); - if (!load_json_settings(f, filename, values)) - log_error("Loading design failed.\n"); - } std::unique_ptr<Context> ctx = createContext(values); setupContext(ctx.get()); setupArchContext(ctx.get()); @@ -404,17 +397,12 @@ std::unique_ptr<Context> CommandHandler::load_json(std::string filename) { vm.clear(); std::unordered_map<std::string, Property> values; - { - std::ifstream f(filename); - if (!load_json_settings(f, filename, values)) - log_error("Loading design failed.\n"); - } std::unique_ptr<Context> ctx = createContext(values); setupContext(ctx.get()); setupArchContext(ctx.get()); { std::ifstream f(filename); - if (!parse_json_file(f, filename, ctx.get())) + if (!parse_json(f, filename, ctx.get())) log_error("Loading design failed.\n"); } customAfterLoad(ctx.get()); diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 933f124c..1156490c 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 @@ -522,7 +523,16 @@ void BaseCtx::createRectangularRegion(IdString name, int x0, int y0, int x1, int void BaseCtx::addBelToRegion(IdString name, BelId bel) { region[name]->bels.insert(bel); } void BaseCtx::constrainCellToRegion(IdString cell, IdString region_name) { - cells[cell]->region = region[region_name].get(); + // Support hierarchical cells as well as leaf ones + if (hierarchy.count(cell)) { + auto &hc = hierarchy.at(cell); + for (auto &lc : hc.leaf_cells) + constrainCellToRegion(lc.second, region_name); + for (auto &hsc : hc.hier_cells) + constrainCellToRegion(hsc.second, region_name); + } + if (cells.count(cell)) + cells.at(cell)->region = region[region_name].get(); } DecalXY BaseCtx::constructDecalXY(DecalId decal, float x, float y) { @@ -723,4 +733,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 24f6948b..61e04415 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -387,7 +387,7 @@ struct ClockConstraint; struct NetInfo : ArchNetInfo { - IdString name; + IdString name, hierpath; int32_t udata = 0; PortRef driver; @@ -397,6 +397,8 @@ struct NetInfo : ArchNetInfo // wire -> uphill_pip std::unordered_map<WireId, PipMap> wires; + std::vector<IdString> aliases; // entries in net_aliases that point to this net + std::unique_ptr<ClockConstraint> clkconstr; TimingConstrObjectId tmg_id; @@ -421,7 +423,7 @@ struct PortInfo struct CellInfo : ArchCellInfo { - IdString name, type; + IdString name, type, hierpath; int32_t udata; std::unordered_map<IdString, PortInfo> ports; @@ -525,6 +527,31 @@ struct TimingConstraint std::unordered_set<TimingConstrObjectId> to; }; +// Represents the contents of a non-leaf cell in a design +// with hierarchy + +struct HierarchicalPort +{ + IdString name; + PortType dir; + std::vector<IdString> nets; + int offset; + bool upto; +}; + +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; +}; + inline bool operator==(const std::pair<const TimingConstrObjectId, TimingConstraint *> &a, const std::pair<TimingConstrObjectId, TimingConstraint *> &b) { @@ -618,6 +645,11 @@ struct BaseCtx std::unordered_map<IdString, std::unique_ptr<NetInfo>> nets; std::unordered_map<IdString, std::unique_ptr<CellInfo>> cells; + // Hierarchical (non-leaf) cells by full path + std::unordered_map<IdString, HierarchicalCell> hierarchy; + // This is the root of the above structure + IdString top_module; + // Aliases for nets, which may have more than one name due to assignments and hierarchy std::unordered_map<IdString, IdString> net_aliases; @@ -807,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/common/pybindings.cc b/common/pybindings.cc index 03979233..3b2a3744 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -22,7 +22,7 @@ #include "pybindings.h" #include "arch_pybindings.h" -#include "jsonparse.h" +#include "json_frontend.h" #include "log.h" #include "nextpnr.h" @@ -53,7 +53,7 @@ void parse_json_shim(std::string filename, Context &d) std::ifstream inf(filename); if (!inf) throw std::runtime_error("failed to open file " + filename); - parse_json_file(inf, filename, &d); + parse_json(inf, filename, &d); } // Create a new Chip and load design from json file @@ -131,7 +131,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) typedef std::unordered_map<IdString, Property> AttrMap; typedef std::unordered_map<IdString, PortInfo> PortMap; - typedef std::unordered_map<IdString, IdString> PinMap; + typedef std::unordered_map<IdString, IdString> IdIdMap; typedef std::unordered_map<IdString, std::unique_ptr<Region>> RegionMap; class_<BaseCtx, BaseCtx *, boost::noncopyable>("BaseCtx", no_init); @@ -157,8 +157,8 @@ BOOST_PYTHON_MODULE(MODULE_NAME) conv_from_str<BelId>>::def_wrap(ci_cls, "bel"); readwrite_wrapper<CellInfo &, decltype(&CellInfo::belStrength), &CellInfo::belStrength, pass_through<PlaceStrength>, pass_through<PlaceStrength>>::def_wrap(ci_cls, "belStrength"); - readonly_wrapper<CellInfo &, decltype(&CellInfo::pins), &CellInfo::pins, wrap_context<PinMap &>>::def_wrap(ci_cls, - "pins"); + readonly_wrapper<CellInfo &, decltype(&CellInfo::pins), &CellInfo::pins, wrap_context<IdIdMap &>>::def_wrap(ci_cls, + "pins"); fn_wrapper_1a_v<CellInfo &, decltype(&CellInfo::addInput), &CellInfo::addInput, conv_from_str<IdString>>::def_wrap( ci_cls, "addInput"); @@ -230,9 +230,25 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readonly_wrapper<Region &, decltype(&Region::wires), &Region::wires, wrap_context<WireSet &>>::def_wrap(region_cls, "wires"); + auto hierarchy_cls = class_<ContextualWrapper<HierarchicalCell &>>("HierarchicalCell", no_init); + readwrite_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::name), &HierarchicalCell::name, + conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(hierarchy_cls, "name"); + readwrite_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::type), &HierarchicalCell::type, + conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(hierarchy_cls, "type"); + readwrite_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::parent), &HierarchicalCell::parent, + conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(hierarchy_cls, "parent"); + readwrite_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::fullpath), &HierarchicalCell::fullpath, + conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(hierarchy_cls, "fullpath"); + + readonly_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::leaf_cells), &HierarchicalCell::leaf_cells, + wrap_context<IdIdMap &>>::def_wrap(hierarchy_cls, "leaf_cells"); + readonly_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::nets), &HierarchicalCell::nets, + wrap_context<IdIdMap &>>::def_wrap(hierarchy_cls, "nets"); + readonly_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::hier_cells), &HierarchicalCell::hier_cells, + wrap_context<IdIdMap &>>::def_wrap(hierarchy_cls, "hier_cells"); WRAP_MAP(AttrMap, conv_to_str<Property>, "AttrMap"); WRAP_MAP(PortMap, wrap_context<PortInfo &>, "PortMap"); - WRAP_MAP(PinMap, conv_to_str<IdString>, "PinMap"); + WRAP_MAP(IdIdMap, conv_to_str<IdString>, "IdIdMap"); WRAP_MAP(WireMap, wrap_context<PipMap &>, "WireMap"); WRAP_MAP_UPTR(RegionMap, "RegionMap"); |