aboutsummaryrefslogtreecommitdiffstats
path: root/nexus
diff options
context:
space:
mode:
Diffstat (limited to 'nexus')
-rw-r--r--nexus/arch.cc8
-rw-r--r--nexus/arch.h12
-rw-r--r--nexus/arch_pybindings.cc8
-rw-r--r--nexus/archdefs.h70
-rw-r--r--nexus/fasm.cc30
-rw-r--r--nexus/global.cc6
-rw-r--r--nexus/io.cc2
-rw-r--r--nexus/main.cc4
-rw-r--r--nexus/pack.cc143
-rw-r--r--nexus/pdc.cc2
-rw-r--r--nexus/pins.cc2
-rw-r--r--nexus/post_place.cc4
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 &param : cell->params) {
const std::string &param_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 &param : 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 &param : 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