diff options
Diffstat (limited to 'nexus')
-rw-r--r-- | nexus/arch.cc | 8 | ||||
-rw-r--r-- | nexus/arch.h | 12 | ||||
-rw-r--r-- | nexus/arch_pybindings.cc | 8 | ||||
-rw-r--r-- | nexus/archdefs.h | 70 | ||||
-rw-r--r-- | nexus/fasm.cc | 30 | ||||
-rw-r--r-- | nexus/global.cc | 6 | ||||
-rw-r--r-- | nexus/io.cc | 2 | ||||
-rw-r--r-- | nexus/main.cc | 4 | ||||
-rw-r--r-- | nexus/pack.cc | 143 | ||||
-rw-r--r-- | nexus/pdc.cc | 2 | ||||
-rw-r--r-- | nexus/pins.cc | 2 | ||||
-rw-r--r-- | nexus/post_place.cc | 4 |
12 files changed, 117 insertions, 174 deletions
diff --git a/nexus/arch.cc b/nexus/arch.cc index d5bb9deb..d90236a8 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -667,19 +667,19 @@ bool Arch::place() void Arch::pre_routing() { - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_MULT9_CORE || ci->type == id_PREADD9_CORE || ci->type == id_MULT18_CORE || ci->type == id_MULT18X36_CORE || ci->type == id_MULT36_CORE || ci->type == id_REG18_CORE || ci->type == id_ACC54_CORE) { - for (auto port : sorted_ref(ci->ports)) { + for (auto &port : ci->ports) { WireId wire = getBelPinWire(ci->bel, port.first); if (wire != WireId()) dsp_wires.insert(wire); } } if (ci->type == id_LRAM_CORE) { - for (auto port : sorted_ref(ci->ports)) { + for (auto &port : ci->ports) { WireId wire = getBelPinWire(ci->bel, port.first); if (wire != WireId()) lram_wires.insert(wire); diff --git a/nexus/arch.h b/nexus/arch.h index b3558413..a669be0d 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -916,7 +916,7 @@ struct Arch : BaseArch<ArchRanges> // fast access to X and Y IdStrings for building object names std::vector<IdString> x_ids, y_ids; // inverse of the above for name->object mapping - std::unordered_map<IdString, int> id_to_x, id_to_y; + dict<IdString, int> id_to_x, id_to_y; // ------------------------------------------------- @@ -1181,7 +1181,7 @@ struct Arch : BaseArch<ArchRanges> // for better DSP bounding boxes void pre_routing(); - std::unordered_set<WireId> dsp_wires, lram_wires; + pool<WireId> dsp_wires, lram_wires; // ------------------------------------------------- @@ -1271,9 +1271,9 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- - typedef std::unordered_map<IdString, CellPinStyle> CellPinsData; + typedef dict<IdString, CellPinStyle> CellPinsData; - std::unordered_map<IdString, CellPinsData> cell_pins_db; + dict<IdString, CellPinsData> cell_pins_db; CellPinStyle get_cell_pin_style(const CellInfo *cell, IdString port) const; void init_cell_pin_data(); @@ -1361,7 +1361,7 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- // Data about different IO standard, mostly used by bitgen - static const std::unordered_map<std::string, IOTypeData> io_types; + static const dict<std::string, IOTypeData> io_types; int get_io_type_vcc(const std::string &io_type) const; bool is_io_type_diff(const std::string &io_type) const; bool is_io_type_ref(const std::string &io_type) const; @@ -1388,7 +1388,7 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- // List of IO constraints, used by PDC parser - std::unordered_map<IdString, std::unordered_map<IdString, Property>> io_attr; + dict<IdString, dict<IdString, Property>> io_attr; void read_pdc(std::istream &in); diff --git a/nexus/arch_pybindings.cc b/nexus/arch_pybindings.cc index a8b04ba7..d6bc7329 100644 --- a/nexus/arch_pybindings.cc +++ b/nexus/arch_pybindings.cc @@ -46,10 +46,10 @@ void arch_wrap_python(py::module &m) .def("place", &Context::place) .def("route", &Context::route); - typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap; - typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap; - typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap; - typedef std::unordered_map<IdString, IdString> AliasMap; + typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap; + typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap; + typedef dict<IdString, HierarchicalCell> HierarchyMap; + typedef dict<IdString, IdString> AliasMap; typedef UpDownhillPipRange UphillPipRange; typedef UpDownhillPipRange DownhillPipRange; diff --git a/nexus/archdefs.h b/nexus/archdefs.h index 660f166c..f2b5a45d 100644 --- a/nexus/archdefs.h +++ b/nexus/archdefs.h @@ -20,10 +20,8 @@ #ifndef NEXUS_ARCHDEFS_H #define NEXUS_ARCHDEFS_H -#include <boost/functional/hash.hpp> -#include <unordered_map> - #include "base_clusterinfo.h" +#include "hashlib.h" #include "idstring.h" #include "nextpnr_namespaces.h" @@ -62,6 +60,7 @@ struct BelId { return tile < other.tile || (tile == other.tile && index < other.index); } + unsigned int hash() const { return mkhash(tile, index); } }; struct WireId @@ -80,6 +79,7 @@ struct WireId { return tile < other.tile || (tile == other.tile && index < other.index); } + unsigned int hash() const { return mkhash(tile, index); } }; struct PipId @@ -97,6 +97,7 @@ struct PipId { return tile < other.tile || (tile == other.tile && index < other.index); } + unsigned int hash() const { return mkhash(tile, index); } }; typedef IdString BelBucketId; @@ -111,6 +112,7 @@ struct GroupId bool operator==(const GroupId &other) const { return (type == other.type) && (x == other.x) && (y == other.y); } bool operator!=(const GroupId &other) const { return (type != other.type) || (x != other.x) || (y == other.y); } + unsigned int hash() const { return mkhash(mkhash(x, y), int(type)); } }; struct DecalId @@ -134,6 +136,7 @@ struct DecalId { return (type != other.type) || (index != other.index) || (active != other.active); } + unsigned int hash() const { return mkhash(index, int(type)); } }; struct ArchNetInfo @@ -178,68 +181,9 @@ struct ArchCellInfo : BaseClusterInfo int tmg_index = -1; // Map from cell/bel ports to logical timing ports - std::unordered_map<IdString, IdString> tmg_portmap; + dict<IdString, IdString> tmg_portmap; }; NEXTPNR_NAMESPACE_END -namespace std { -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelId &bel) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(bel.tile)); - boost::hash_combine(seed, hash<int>()(bel.index)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX WireId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX WireId &wire) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(wire.tile)); - boost::hash_combine(seed, hash<int>()(wire.index)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PipId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX PipId &pip) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(pip.tile)); - boost::hash_combine(seed, hash<int>()(pip.index)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX GroupId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX GroupId &group) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(group.type)); - boost::hash_combine(seed, hash<int>()(group.x)); - boost::hash_combine(seed, hash<int>()(group.y)); - return seed; - } -}; - -template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId> -{ - std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DecalId &decal) const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, hash<int>()(decal.type)); - boost::hash_combine(seed, hash<int>()(decal.index)); - return seed; - } -}; - -} // namespace std - #endif /* NEXUS_ARCHDEFS_H */ diff --git a/nexus/fasm.cc b/nexus/fasm.cc index 0afefa4b..48483bfe 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -248,7 +248,7 @@ struct NexusFasmWriter // Write out the mux config for a cell void write_cell_muxes(const CellInfo *cell) { - for (auto port : sorted_cref(cell->ports)) { + for (auto &port : cell->ports) { // Only relevant to inputs if (port.second.type != PORT_IN) continue; @@ -336,7 +336,7 @@ struct NexusFasmWriter pop(2); } - std::unordered_set<BelId> used_io; + pool<BelId> used_io; struct BankConfig { @@ -539,7 +539,7 @@ struct NexusFasmWriter push_bel(bel); if (cell->type != id_MULT18_CORE && cell->type != id_MULT18X36_CORE && cell->type != id_MULT36_CORE) write_bit(stringf("MODE.%s", ctx->nameOf(cell->type))); - for (auto param : sorted_cref(cell->params)) { + for (auto ¶m : cell->params) { const std::string ¶m_name = param.first.str(ctx); if (is_mux_param(param_name)) continue; @@ -556,7 +556,7 @@ struct NexusFasmWriter // Which PLL params are 'word' values /* clang-format off */ - const std::unordered_map<std::string, int> pll_word_params = { + const dict<std::string, int> pll_word_params = { {"DIVA", 7}, {"DELA", 7}, {"PHIA", 3}, {"DIVB", 7}, {"DELB", 7}, {"PHIB", 3}, {"DIVC", 7}, {"DELC", 7}, {"PHIC", 3}, {"DIVD", 7}, {"DELD", 7}, {"PHID", 3}, @@ -582,7 +582,7 @@ struct NexusFasmWriter }; // Which MIPI params are 'word' values - const std::unordered_map<std::string, int> dphy_word_params = { + const dict<std::string, int> dphy_word_params = { {"CM", 8}, {"CN", 5}, {"CO", 3}, {"RSEL", 2}, {"RXCDRP", 2}, {"RXDATAWIDTHHS", 2}, {"RXLPRP", 3}, {"TEST_ENBL", 6}, {"TEST_PATTERN", 32}, {"TST", 4}, {"TXDATAWIDTHHS", 2}, @@ -601,7 +601,7 @@ struct NexusFasmWriter write_cell_muxes(cell); pop(); push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name)))); - for (auto param : sorted_cref(cell->params)) { + for (auto ¶m : cell->params) { const std::string &name = param.first.str(ctx); if (is_mux_param(name) || name == "CLKMUX_FB" || name == "SEL_FBK") continue; @@ -622,7 +622,7 @@ struct NexusFasmWriter { BelId bel = cell->bel; push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name)))); - for (auto param : sorted_cref(cell->params)) { + for (auto ¶m : cell->params) { const std::string &name = param.first.str(ctx); if (is_mux_param(name) || name == "GSR") continue; @@ -683,7 +683,7 @@ struct NexusFasmWriter write_comment("# Unused bels"); // DSP primitives are configured to a default mode; even if unused - static const std::unordered_map<IdString, std::vector<std::string>> dsp_defconf = { + static const dict<IdString, std::vector<std::string>> dsp_defconf = { {id_MULT9_CORE, { "GSR.ENABLED", @@ -733,7 +733,7 @@ struct NexusFasmWriter } } } - std::unordered_map<int, int> bank_vcco; + dict<int, int> bank_vcco; // bank VccO in mV int get_bank_vcco(const std::string &iostd) { @@ -753,8 +753,8 @@ struct NexusFasmWriter // Write out placeholder bankref config void write_bankcfg() { - for (auto c : sorted(ctx->cells)) { - const CellInfo *ci = c.second; + for (auto &c : ctx->cells) { + const CellInfo *ci = c.second.get(); if (ci->type != id_SEIO33_CORE) continue; if (!ci->attrs.count(id_IO_TYPE)) @@ -809,12 +809,12 @@ struct NexusFasmWriter write_attribute("oxide.device_variant", ctx->variant); blank(); // Write routing - for (auto n : sorted(ctx->nets)) { - write_net(n.second); + for (auto &n : ctx->nets) { + write_net(n.second.get()); } // Write cell config - for (auto c : sorted(ctx->cells)) { - const CellInfo *ci = c.second; + for (auto &c : ctx->cells) { + const CellInfo *ci = c.second.get(); write_comment(stringf("# Cell %s", ctx->nameOf(ci))); if (ci->type == id_OXIDE_COMB) write_comb(ci); diff --git a/nexus/global.cc b/nexus/global.cc index 53306e21..9a0d095b 100644 --- a/nexus/global.cc +++ b/nexus/global.cc @@ -49,7 +49,7 @@ struct NexusGlobalRouter // Queue of wires to visit std::queue<WireId> visit; // Wire -> upstream pip - std::unordered_map<WireId, PipId> backtrace; + dict<WireId, PipId> backtrace; // Lookup source and destination wires WireId src = ctx->getNetinfoSourceWire(net); @@ -155,8 +155,8 @@ struct NexusGlobalRouter void operator()() { log_info("Routing globals...\n"); - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); CellInfo *drv = ni->driver.cell; if (drv == nullptr) continue; diff --git a/nexus/io.cc b/nexus/io.cc index fd5e584f..314d80b6 100644 --- a/nexus/io.cc +++ b/nexus/io.cc @@ -23,7 +23,7 @@ NEXTPNR_NAMESPACE_BEGIN -const std::unordered_map<std::string, IOTypeData> Arch::io_types = { +const dict<std::string, IOTypeData> Arch::io_types = { {"LVCMOS33", {IOSTYLE_SE_WR, 330}}, {"LVCMOS25", {IOSTYLE_SE_WR, 250}}, {"LVCMOS18", {IOSTYLE_SE_WR, 180}}, {"LVCMOS15", {IOSTYLE_SE_WR, 150}}, {"LVCMOS12", {IOSTYLE_SE_WR, 120}}, {"LVCMOS10", {IOSTYLE_SE_WR, 120}}, diff --git a/nexus/main.cc b/nexus/main.cc index cced1b95..66b1a61e 100644 --- a/nexus/main.cc +++ b/nexus/main.cc @@ -33,7 +33,7 @@ class NexusCommandHandler : public CommandHandler public: NexusCommandHandler(int argc, char **argv); virtual ~NexusCommandHandler(){}; - std::unique_ptr<Context> createContext(std::unordered_map<std::string, Property> &values) override; + std::unique_ptr<Context> createContext(dict<std::string, Property> &values) override; void setupArchContext(Context *ctx) override{}; void customBitstream(Context *ctx) override; void customAfterLoad(Context *ctx) override; @@ -66,7 +66,7 @@ void NexusCommandHandler::customBitstream(Context *ctx) } } -std::unique_ptr<Context> NexusCommandHandler::createContext(std::unordered_map<std::string, Property> &values) +std::unique_ptr<Context> NexusCommandHandler::createContext(dict<std::string, Property> &values) { ArchArgs chipArgs; if (!vm.count("device")) { diff --git a/nexus/pack.cc b/nexus/pack.cc index 66ab4b09..1d977f2c 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -106,16 +106,16 @@ struct NexusPacker struct XFormRule { IdString new_type; - std::unordered_map<IdString, IdString> port_xform; - std::unordered_map<IdString, std::vector<IdString>> port_multixform; - std::unordered_map<IdString, IdString> param_xform; + dict<IdString, IdString> port_xform; + dict<IdString, std::vector<IdString>> port_multixform; + dict<IdString, IdString> param_xform; std::vector<std::pair<IdString, std::string>> set_attrs; std::vector<std::pair<IdString, Property>> set_params; std::vector<std::pair<IdString, Property>> default_params; std::vector<std::tuple<IdString, IdString, int, int64_t>> parse_params; }; - void xform_cell(const std::unordered_map<IdString, XFormRule> &rules, CellInfo *ci) + void xform_cell(const dict<IdString, XFormRule> &rules, CellInfo *ci) { auto &rule = rules.at(ci->type); ci->type = rule.new_type; @@ -178,12 +178,12 @@ struct NexusPacker ci->params[param.first] = param.second; } - void generic_xform(const std::unordered_map<IdString, XFormRule> &rules, bool print_summary = false) + void generic_xform(const dict<IdString, XFormRule> &rules, bool print_summary = false) { std::map<std::string, int> cell_count; std::map<std::string, int> new_types; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (rules.count(ci->type)) { cell_count[ci->type.str(ctx)]++; xform_cell(rules, ci); @@ -205,7 +205,7 @@ struct NexusPacker void pack_luts() { log_info("Packing LUTs...\n"); - std::unordered_map<IdString, XFormRule> lut_rules; + dict<IdString, XFormRule> lut_rules; lut_rules[id_LUT4].new_type = id_OXIDE_COMB; lut_rules[id_LUT4].port_xform[id_Z] = id_F; lut_rules[id_LUT4].parse_params.emplace_back(id_INIT, id_INIT, 16, 0); @@ -229,7 +229,7 @@ struct NexusPacker void pack_ffs() { log_info("Packing FFs...\n"); - std::unordered_map<IdString, XFormRule> ff_rules; + dict<IdString, XFormRule> ff_rules; for (auto type : {id_FD1P3BX, id_FD1P3DX, id_FD1P3IX, id_FD1P3JX}) { ff_rules[type].new_type = id_OXIDE_FF; ff_rules[type].port_xform[id_CK] = id_CLK; @@ -262,7 +262,7 @@ struct NexusPacker generic_xform(ff_rules, true); } - std::unordered_map<IdString, BelId> reference_bels; + dict<IdString, BelId> reference_bels; void autocreate_ports(CellInfo *cell) { @@ -303,8 +303,8 @@ struct NexusPacker { // Gets a constant net, given the driver type (VHI or VLO) // If one doesn't exist already; then create it - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != type) continue; NetInfo *z = get_net_or_empty(ci, id_Z); @@ -369,8 +369,8 @@ struct NexusPacker // Remove unused inverters and high/low drivers std::vector<IdString> trim_cells; std::vector<IdString> trim_nets; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_INV && ci->type != id_VLO && ci->type != id_VHI && ci->type != id_VCC_DRV) continue; NetInfo *z = get_net_or_empty(ci, id_Z); @@ -474,7 +474,7 @@ struct NexusPacker // Find the actual IO buffer corresponding to a port; and copy attributes across to it // Note that this relies on Yosys to do IO buffer inference, to match vendor tooling behaviour // In all cases the nextpnr-inserted IO buffers are removed as redundant. - for (auto &port : sorted_ref(ctx->ports)) { + for (auto &port : ctx->ports) { if (!ctx->cells.count(port.first)) log_error("Port '%s' doesn't seem to have a corresponding top level IO\n", ctx->nameOf(port.first)); CellInfo *ci = ctx->cells.at(port.first).get(); @@ -549,11 +549,10 @@ struct NexusPacker void pack_io() { - std::unordered_set<IdString> iob_types = {id_IB, id_OB, id_OBZ, id_BB, - id_BB_I3C_A, id_SEIO33, id_SEIO18, id_DIFFIO18, - id_SEIO33_CORE, id_SEIO18_CORE, id_DIFFIO18_CORE}; + pool<IdString> iob_types = {id_IB, id_OB, id_OBZ, id_BB, id_BB_I3C_A, id_SEIO33, + id_SEIO18, id_DIFFIO18, id_SEIO33_CORE, id_SEIO18_CORE, id_DIFFIO18_CORE}; - std::unordered_map<IdString, XFormRule> io_rules; + dict<IdString, XFormRule> io_rules; // For the low level primitives, make sure we always preserve their type io_rules[id_SEIO33_CORE].new_type = id_SEIO33_CORE; @@ -567,20 +566,20 @@ struct NexusPacker io_rules[id_SEIO33].port_xform[id_PADDT] = id_T; io_rules[id_SEIO33].port_xform[id_IOPAD] = id_B; - io_rules[id_BB_I3C_A] = io_rules[id_SEIO33]; + io_rules[id_BB_I3C_A] = XFormRule(io_rules[id_SEIO33]); - io_rules[id_SEIO18] = io_rules[id_SEIO33]; + io_rules[id_SEIO18] = XFormRule(io_rules[id_SEIO33]); io_rules[id_SEIO18].new_type = id_SEIO18_CORE; - io_rules[id_DIFFIO18] = io_rules[id_SEIO33]; + io_rules[id_DIFFIO18] = XFormRule(io_rules[id_SEIO33]); io_rules[id_DIFFIO18].new_type = id_DIFFIO18_CORE; // Stage 0: deal with top level inserted IO buffers prepare_io(); // Stage 1: setup constraints - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Iterate through all IO buffer primitives if (!iob_types.count(ci->type)) continue; @@ -625,8 +624,8 @@ struct NexusPacker // Stage 2: apply rules for primitives that need them generic_xform(io_rules, false); // Stage 3: all other IO primitives become their bel type - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Iterate through all IO buffer primitives if (!iob_types.count(ci->type)) continue; @@ -660,12 +659,12 @@ struct NexusPacker gnd_net = get_const_net(id_VLO); dedi_vcc_net = get_const_net(id_VCC_DRV); // Iterate through cells - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Skip certain cells at this point if (ci->type != id_LUT4 && ci->type != id_INV && ci->type != id_VHI && ci->type != id_VLO && ci->type != id_VCC_DRV) - process_inv_constants(cell.second); + process_inv_constants(ci); } // Remove superfluous inverters and constant drivers trim_design(); @@ -677,8 +676,8 @@ struct NexusPacker { int iter = 0; std::queue<WireId> visit; - std::unordered_set<WireId> seen_wires; - std::unordered_set<BelId> seen_bels; + pool<WireId> seen_wires; + pool<BelId> seen_bels; BelId bel = get_bel_attr(cell); if (bel == BelId()) @@ -751,7 +750,7 @@ struct NexusPacker return best_bel; } - std::unordered_set<BelId> used_bels; + pool<BelId> used_bels; // Pre-place a primitive based on routeability first and distance second bool preplace_prim(CellInfo *cell, IdString pin, bool strict_routing) @@ -854,8 +853,8 @@ struct NexusPacker { std::vector<std::pair<int, IdString>> clk_fanout; int available_globals = 16; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); // Skip undriven nets; and nets that are already global if (ni->driver.cell == nullptr) continue; @@ -894,8 +893,8 @@ struct NexusPacker bool did_something = true; while (did_something) { did_something = false; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_OSC_CORE) did_something |= preplace_singleton(ci); else if (ci->type == id_DCC) @@ -916,8 +915,8 @@ struct NexusPacker { // Do this so we don't have an iterate-and-modfiy situation std::vector<CellInfo *> lutrams; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_DPR16X4) continue; lutrams.push_back(ci); @@ -1024,15 +1023,15 @@ struct NexusPacker void convert_prims() { // Convert primitives from their non-CORE variant to their CORE variant - static const std::unordered_map<IdString, IdString> prim_map = { + static const dict<IdString, IdString> prim_map = { {id_OSCA, id_OSC_CORE}, {id_DP16K, id_DP16K_MODE}, {id_PDP16K, id_PDP16K_MODE}, {id_PDPSC16K, id_PDPSC16K_MODE}, {id_SP16K, id_SP16K_MODE}, {id_FIFO16K, id_FIFO16K_MODE}, {id_SP512K, id_SP512K_MODE}, {id_DPSC512K, id_DPSC512K_MODE}, {id_PDPSC512K, id_PDPSC512K_MODE}, {id_PLL, id_PLL_CORE}, {id_DPHY, id_DPHY_CORE}, }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (!prim_map.count(ci->type)) continue; prim_to_core(ci, prim_map.at(ci->type)); @@ -1048,7 +1047,7 @@ struct NexusPacker void pack_bram() { - std::unordered_map<IdString, XFormRule> bram_rules; + dict<IdString, XFormRule> bram_rules; bram_rules[id_DP16K_MODE].new_type = id_OXIDE_EBR; bram_rules[id_DP16K_MODE].set_params.emplace_back(id_MODE, std::string("DP16K")); bram_rules[id_DP16K_MODE].parse_params.emplace_back(id_CSDECODE_A, id_CSDECODE_A, 3, 7); @@ -1074,7 +1073,7 @@ struct NexusPacker add_bus_xform(bram_rules[id_PDP16K_MODE], "DO", "DOA", 18, 18, 0); // Pseudo dual port; single clock - bram_rules[id_PDPSC16K_MODE] = bram_rules[id_PDP16K_MODE]; + bram_rules[id_PDPSC16K_MODE] = XFormRule(bram_rules[id_PDP16K_MODE]); bram_rules[id_PDPSC16K_MODE].set_params.clear(); bram_rules[id_PDPSC16K_MODE].set_params.emplace_back(id_MODE, std::string("PDPSC16K")); bram_rules[id_PDPSC16K_MODE].set_params.emplace_back(id_WEAMUX, std::string("1")); @@ -1084,8 +1083,8 @@ struct NexusPacker generic_xform(bram_rules, true); int wid = 2; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_OXIDE_EBR) continue; if (ci->params.count(id_WID)) @@ -1096,7 +1095,7 @@ struct NexusPacker void pack_lram() { - std::unordered_map<IdString, XFormRule> lram_rules; + dict<IdString, XFormRule> lram_rules; lram_rules[id_SP512K_MODE].new_type = id_LRAM_CORE; lram_rules[id_SP512K_MODE].set_params.emplace_back(id_EBR_SP_EN, std::string("ENABLE")); lram_rules[id_SP512K_MODE].port_xform[id_CE] = id_CEA; @@ -1129,8 +1128,8 @@ struct NexusPacker log_info("Packing LRAM...\n"); generic_xform(lram_rules, true); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_LRAM_CORE) continue; if (str_or_default(ci->params, ctx->id("ECC_BYTE_SEL"), "BYTE_EN") == "BYTE_EN") @@ -1151,8 +1150,8 @@ struct NexusPacker void pack_widefn() { std::vector<CellInfo *> widefns; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_WIDEFN9) continue; widefns.push_back(ci); @@ -1200,8 +1199,8 @@ struct NexusPacker // Find root carry cells log_info("Packing carries...\n"); std::vector<CellInfo *> roots; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_CCU2) continue; if (get_net_or_empty(ci, id_CIN) != nullptr) @@ -1296,7 +1295,7 @@ struct NexusPacker // Automatically generate cascade connections downstream of a cell // using the temporary placement that we use solely to access the routing graph - void auto_cascade_cell(CellInfo *cell, BelId bel, const std::unordered_map<BelId, CellInfo *> &bel2cell) + void auto_cascade_cell(CellInfo *cell, BelId bel, const dict<BelId, CellInfo *> &bel2cell) { // Create outputs based on the actual bel for (auto bp : ctx->getBelPins(bel)) { @@ -1306,7 +1305,7 @@ struct NexusPacker continue; cell->addOutput(bp); } - for (auto port : sorted_ref(cell->ports)) { + for (auto &port : cell->ports) { // Skip if not an output, or being used already for something else if (port.second.type != PORT_OUT || port.second.net != nullptr) continue; @@ -1322,7 +1321,7 @@ struct NexusPacker // Standard BFS-type exploration std::queue<WireId> visit; - std::unordered_set<WireId> in_queue; + pool<WireId> in_queue; visit.push(start_wire); in_queue.insert(start_wire); int iter = 0; @@ -1403,8 +1402,8 @@ struct NexusPacker // We first create a temporary placement so we can access the routing graph bool found = false; - std::unordered_map<BelId, CellInfo *> bel2cell; - std::unordered_map<IdString, BelId> cell2bel; + dict<BelId, CellInfo *> bel2cell; + dict<IdString, BelId> cell2bel; for (BelId root_bel : ctx->getBels()) { if (ctx->getBelType(root_bel) != root->type) @@ -1592,7 +1591,7 @@ struct NexusPacker int wide; // DSP is a "wide" (dot-product) variant }; - const std::unordered_map<IdString, DSPMacroType> dsp_types = { + const dict<IdString, DSPMacroType> dsp_types = { {id_MULT9X9, {9, 9, 0, 18, 1, 0, 0, false, false, -1}}, {id_MULT18X18, {18, 18, 0, 36, 2, 1, 0, false, false, -1}}, {id_MULT18X36, {18, 36, 0, 54, 4, 2, 1, false, false, -1}}, @@ -1609,8 +1608,8 @@ struct NexusPacker log_info("Packing DSPs...\n"); std::vector<CellInfo *> to_remove; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (!dsp_types.count(ci->type)) continue; auto &mt = dsp_types.at(ci->type); @@ -1792,7 +1791,7 @@ struct NexusPacker } for (auto cell : to_remove) { - for (auto port : sorted_ref(cell->ports)) + for (auto &port : cell->ports) disconnect_port(ctx, cell, port.first); ctx->cells.erase(cell->name); } @@ -1805,7 +1804,7 @@ struct NexusPacker auto equals_epsilon = [](delay_t a, delay_t b) { return (std::abs(a - b) / std::max(double(b), 1.0)) < 1e-3; }; - std::unordered_set<IdString> user_constrained, changed_nets; + pool<IdString> user_constrained, changed_nets; for (auto &net : ctx->nets) { if (net.second->clkconstr != nullptr) user_constrained.insert(net.first); @@ -1883,7 +1882,7 @@ struct NexusPacker const int itermax = 5000; while (!changed_nets.empty() && iter < itermax) { ++iter; - std::unordered_set<IdString> changed_cells; + pool<IdString> changed_cells; for (auto net : changed_nets) { for (auto &user : ctx->nets.at(net)->users) if (user.port == id_CLKI || user.port == id_REFCK) @@ -1893,7 +1892,7 @@ struct NexusPacker changed_cells.insert(drv.cell->name); } changed_nets.clear(); - for (auto cell : sorted(changed_cells)) { + for (auto cell : changed_cells) { CellInfo *ci = ctx->cells.at(cell).get(); if (ci->type == id_DCC) { copy_constraint(ci, id_CLKI, id_CLKO, 1); @@ -1945,12 +1944,12 @@ struct NexusPacker void pack_plls() { - const std::unordered_map<IdString, std::string> pll_defaults = { + const dict<IdString, std::string> pll_defaults = { {id_FLOCK_CTRL, "2X"}, {id_FLOCK_EN, "ENABLED"}, {id_FLOCK_SRC_SEL, "REFCLK"}, {id_DIV_DEL, "0b0000001"}, {id_FBK_PI_RC, "0b1100"}, {id_FBK_PR_IC, "0b1000"}, }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_PLL_CORE) { // Extra log to phys rules rename_port(ctx, ci, id_PLLPOWERDOWN_N, id_PLLPDN); @@ -1966,7 +1965,7 @@ struct NexusPacker // Map LOC attribute on DPHY_CORE to a bel // TDPHY_CORE2 is Radiant 2.0 style, DPHY0 is Radiant 2.2 // TODO: LIFCL-17 (perhaps remove the hardcoded map) - const std::unordered_map<std::string, std::string> dphy_loc_map = { + const dict<std::string, std::string> dphy_loc_map = { {"TDPHY_CORE2", "X4/Y0/TDPHY_CORE2"}, {"DPHY0", "X4/Y0/TDPHY_CORE2"}, {"TDPHY_CORE26", "X28/Y0/TDPHY_CORE26"}, @@ -1975,8 +1974,8 @@ struct NexusPacker void pack_ip() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DPHY_CORE) { auto loc_attr = ci->attrs.find(id_LOC); if (loc_attr == ci->attrs.end()) @@ -2026,8 +2025,8 @@ bool Arch::pack() void Arch::assignArchInfo() { - for (auto cell : sorted(cells)) { - assignCellInfo(cell.second); + for (auto &cell : cells) { + assignCellInfo(cell.second.get()); } } diff --git a/nexus/pdc.cc b/nexus/pdc.cc index 1ffe0a64..f81bb74e 100644 --- a/nexus/pdc.cc +++ b/nexus/pdc.cc @@ -406,7 +406,7 @@ struct PDCParser TCLValue cmd_ldc_set_port(const std::vector<TCLValue> &arguments) { - std::unordered_map<IdString, Property> args; + dict<IdString, Property> args; for (int i = 1; i < int(arguments.size()); i++) { auto &arg = arguments.at(i); if (arg.is_string) { diff --git a/nexus/pins.cc b/nexus/pins.cc index a283953b..e9841f4b 100644 --- a/nexus/pins.cc +++ b/nexus/pins.cc @@ -24,7 +24,7 @@ NEXTPNR_NAMESPACE_BEGIN namespace { -static const std::unordered_map<IdString, Arch::CellPinsData> base_cell_pin_data = { +static const dict<IdString, Arch::CellPinsData> base_cell_pin_data = { {id_OXIDE_COMB, { {id_WCK, PINSTYLE_DEDI}, diff --git a/nexus/post_place.cc b/nexus/post_place.cc index b6817b57..068c013e 100644 --- a/nexus/post_place.cc +++ b/nexus/post_place.cc @@ -88,9 +88,9 @@ struct NexusPostPlaceOpt void opt_lutffs() { int moves_made = 0; - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { // Search for FF cells - CellInfo *ff = cell.second; + CellInfo *ff = cell.second.get(); if (ff->type != id_OXIDE_FF) continue; // Check M ('fabric') input net |