aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch.h26
-rw-r--r--ecp5/arch_place.cc17
-rw-r--r--ecp5/arch_pybindings.cc8
-rw-r--r--ecp5/archdefs.h77
-rw-r--r--ecp5/bitstream.cc7
-rw-r--r--ecp5/cells.cc2
-rw-r--r--ecp5/cells.h2
-rw-r--r--ecp5/globals.cc26
-rw-r--r--ecp5/lpf.cc5
-rw-r--r--ecp5/main.cc8
-rw-r--r--ecp5/pack.cc151
11 files changed, 120 insertions, 209 deletions
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 063a3df6..be1a44d8 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -419,23 +419,9 @@ struct DelayKey
{
return celltype == other.celltype && from == other.from && to == other.to;
}
+ unsigned int hash() const { return mkhash(celltype.hash(), mkhash(from.hash(), to.hash())); }
};
-NEXTPNR_NAMESPACE_END
-namespace std {
-template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DelayKey>
-{
- std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DelayKey &dk) const noexcept
- {
- std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.celltype);
- seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.from) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.to) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- return seed;
- }
-};
-} // namespace std
-NEXTPNR_NAMESPACE_BEGIN
-
struct ArchRanges : BaseArchRanges
{
using ArchArgsT = ArchArgs;
@@ -458,15 +444,15 @@ struct Arch : BaseArch<ArchRanges>
const PackageInfoPOD *package_info;
const SpeedGradePOD *speed_grade;
- mutable std::unordered_map<IdStringList, PipId> pip_by_name;
+ mutable dict<IdStringList, PipId> pip_by_name;
std::vector<CellInfo *> bel_to_cell;
- std::unordered_map<WireId, int> wire_fanout;
+ dict<WireId, int> wire_fanout;
// 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;
ArchArgs args;
Arch(ArchArgs args);
@@ -914,10 +900,10 @@ struct Arch : BaseArch<ArchRanges>
// Improves directivity of routing to DSP inputs, avoids issues
// with different routes to the same physical reset wire causing
// conflicts and slow routing
- std::unordered_map<WireId, std::pair<int, int>> wire_loc_overrides;
+ dict<WireId, std::pair<int, int>> wire_loc_overrides;
void setup_wire_locations();
- mutable std::unordered_map<DelayKey, std::pair<bool, DelayQuad>> celldelay_cache;
+ mutable dict<DelayKey, std::pair<bool, DelayQuad>> celldelay_cache;
static const std::string defaultPlacer;
static const std::vector<std::string> availablePlacers;
diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc
index 57c3b181..a98d96ec 100644
--- a/ecp5/arch_place.cc
+++ b/ecp5/arch_place.cc
@@ -98,15 +98,6 @@ void Arch::permute_luts()
TimingAnalyser tmg(getCtx());
tmg.setup();
- std::unordered_map<PortInfo *, size_t> port_to_user;
- for (auto net : sorted(nets)) {
- NetInfo *ni = net.second;
- for (size_t i = 0; i < ni->users.size(); i++) {
- auto &usr = ni->users.at(i);
- port_to_user[&(usr.cell->ports.at(usr.port))] = i;
- }
- }
-
auto proc_lut = [&](CellInfo *ci, int lut) {
std::vector<IdString> port_names;
for (int i = 0; i < 4; i++)
@@ -157,8 +148,8 @@ void Arch::permute_luts()
ci->params[id("LUT" + std::to_string(lut) + "_INITVAL")] = Property(new_init, 16);
};
- for (auto cell : sorted(cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id("MODE"), "LOGIC") == "LOGIC") {
proc_lut(ci, 0);
proc_lut(ci, 1);
@@ -169,8 +160,8 @@ void Arch::permute_luts()
void Arch::setup_wire_locations()
{
wire_loc_overrides.clear();
- for (auto cell : sorted(cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : cells) {
+ CellInfo *ci = cell.second.get();
if (ci->bel == BelId())
continue;
if (ci->type == id_MULT18X18D || ci->type == id_DCUA || ci->type == id_DDRDLL || ci->type == id_DQSBUFM ||
diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc
index 5218ce36..35660afd 100644
--- a/ecp5/arch_pybindings.cc
+++ b/ecp5/arch_pybindings.cc
@@ -44,10 +44,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, IdString> AliasMap;
- typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
+ typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
+ typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
+ typedef dict<IdString, IdString> AliasMap;
+ typedef dict<IdString, HierarchicalCell> HierarchyMap;
auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin");
readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel");
diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h
index 2b4590e5..6243a9df 100644
--- a/ecp5/archdefs.h
+++ b/ecp5/archdefs.h
@@ -21,9 +21,8 @@
#ifndef ECP5_ARCHDEFS_H
#define ECP5_ARCHDEFS_H
-#include <boost/functional/hash.hpp>
-
#include "base_clusterinfo.h"
+#include "hashlib.h"
#include "idstring.h"
#include "nextpnr_namespaces.h"
@@ -63,6 +62,7 @@ struct Location
bool operator==(const Location &other) const { return x == other.x && y == other.y; }
bool operator!=(const Location &other) const { return x != other.x || y != other.y; }
bool operator<(const Location &other) const { return y == other.y ? x < other.x : y < other.y; }
+ unsigned int hash() const { return mkhash(x, y); }
};
inline Location operator+(const Location &a, const Location &b) { return Location(a.x + b.x, a.y + b.y); }
@@ -78,6 +78,7 @@ struct BelId
{
return location == other.location ? index < other.index : location < other.location;
}
+ unsigned int hash() const { return mkhash(location.hash(), index); }
};
struct WireId
@@ -91,6 +92,7 @@ struct WireId
{
return location == other.location ? index < other.index : location < other.location;
}
+ unsigned int hash() const { return mkhash(location.hash(), index); }
};
struct PipId
@@ -104,6 +106,7 @@ struct PipId
{
return location == other.location ? index < other.index : location < other.location;
}
+ unsigned int hash() const { return mkhash(location.hash(), index); }
};
typedef IdString BelBucketId;
@@ -119,6 +122,7 @@ struct GroupId
bool operator==(const GroupId &other) const { return (type == other.type) && (location == other.location); }
bool operator!=(const GroupId &other) const { return (type != other.type) || (location != other.location); }
+ unsigned int hash() const { return mkhash(location.hash(), int(type)); }
};
struct DecalId
@@ -142,6 +146,7 @@ struct DecalId
{
return type != other.type || location != other.location || z != other.z || active != other.active;
}
+ unsigned int hash() const { return mkhash(location.hash(), mkhash(z, int(type))); }
};
struct ArchNetInfo
@@ -180,72 +185,4 @@ struct ArchCellInfo : BaseClusterInfo
};
NEXTPNR_NAMESPACE_END
-
-namespace std {
-template <> struct hash<NEXTPNR_NAMESPACE_PREFIX Location>
-{
- std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX Location &loc) const noexcept
- {
- std::size_t seed = std::hash<int>()(loc.x);
- seed ^= std::hash<int>()(loc.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- return seed;
- }
-};
-
-template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelId>
-{
- std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelId &bel) const noexcept
- {
- std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(bel.location);
- seed ^= std::hash<int>()(bel.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- 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 = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(wire.location);
- seed ^= std::hash<int>()(wire.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- 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 = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(pip.location);
- seed ^= std::hash<int>()(pip.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- 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<NEXTPNR_NAMESPACE_PREFIX Location>()(group.location));
- 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<NEXTPNR_NAMESPACE_PREFIX Location>()(decal.location));
- boost::hash_combine(seed, hash<int>()(decal.z));
- boost::hash_combine(seed, hash<bool>()(decal.active));
- return seed;
- }
-};
-
-} // namespace std
-
#endif /* ECP5_ARCHDEFS_H */
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc
index f8d11d39..ac9d4a4d 100644
--- a/ecp5/bitstream.cc
+++ b/ecp5/bitstream.cc
@@ -569,8 +569,7 @@ static std::vector<bool> parse_config_str(const Property &p, int length)
return word;
}
-std::string intstr_or_default(const std::unordered_map<IdString, Property> &ct, const IdString &key,
- std::string def = "0")
+std::string intstr_or_default(const dict<IdString, Property> &ct, const IdString &key, std::string def = "0")
{
auto found = ct.find(key);
if (found == ct.end())
@@ -670,8 +669,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
}
}
// Find bank voltages
- std::unordered_map<int, IOVoltage> bankVcc;
- std::unordered_map<int, bool> bankLvds, bankVref, bankDiff;
+ dict<int, IOVoltage> bankVcc;
+ dict<int, bool> bankLvds, bankVref, bankDiff;
for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get();
diff --git a/ecp5/cells.cc b/ecp5/cells.cc
index 7f9f1579..edc80329 100644
--- a/ecp5/cells.cc
+++ b/ecp5/cells.cc
@@ -422,7 +422,7 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw
}
void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::unique_ptr<CellInfo>> &created_cells,
- std::unordered_set<IdString> &todelete_cells)
+ pool<IdString> &todelete_cells)
{
if (nxio->type == ctx->id("$nextpnr_ibuf")) {
trio->params[ctx->id("DIR")] = std::string("INPUT");
diff --git a/ecp5/cells.h b/ecp5/cells.h
index e66f8f21..20ba97b4 100644
--- a/ecp5/cells.h
+++ b/ecp5/cells.h
@@ -65,7 +65,7 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw
// Convert a nextpnr IO buffer to a TRELLIS_IO
void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::unique_ptr<CellInfo>> &created_cells,
- std::unordered_set<IdString> &todelete_cells);
+ pool<IdString> &todelete_cells);
NEXTPNR_NAMESPACE_END
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 36bec64c..b840ac91 100644
--- a/ecp5/globals.cc
+++ b/ecp5/globals.cc
@@ -72,7 +72,7 @@ class Ecp5GlobalRouter
std::vector<NetInfo *> get_clocks()
{
- std::unordered_map<IdString, int> clockCount;
+ dict<IdString, int> clockCount;
for (auto &net : ctx->nets) {
NetInfo *ni = net.second.get();
if (ni->name == ctx->id("$PACKER_GND_NET") || ni->name == ctx->id("$PACKER_VCC_NET"))
@@ -91,8 +91,8 @@ class Ecp5GlobalRouter
}
// DCCAs must always drive globals
std::vector<NetInfo *> clocks;
- for (auto &cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_DCCA) {
NetInfo *glb = ci->ports.at(id_CLKO).net;
if (glb != nullptr) {
@@ -147,7 +147,7 @@ class Ecp5GlobalRouter
WireId globalWire;
IdString global_name = ctx->id(fmt_str("G_HPBX" << std::setw(2) << std::setfill('0') << global_index << "00"));
std::queue<WireId> upstream;
- std::unordered_map<WireId, PipId> backtrace;
+ dict<WireId, PipId> backtrace;
upstream.push(userWire);
bool already_routed = false;
WireId next;
@@ -230,7 +230,7 @@ class Ecp5GlobalRouter
bool simple_router(NetInfo *net, WireId src, WireId dst, bool allow_fail = false)
{
std::queue<WireId> visit;
- std::unordered_map<WireId, PipId> backtrace;
+ dict<WireId, PipId> backtrace;
visit.push(src);
WireId cursor;
while (true) {
@@ -340,7 +340,7 @@ class Ecp5GlobalRouter
bool has_short_route(WireId src, WireId dst, int thresh = 7)
{
std::queue<WireId> visit;
- std::unordered_map<WireId, PipId> backtrace;
+ dict<WireId, PipId> backtrace;
visit.push(src);
WireId cursor;
while (true) {
@@ -376,7 +376,7 @@ class Ecp5GlobalRouter
return length < thresh;
}
- std::unordered_set<WireId> used_pclkcib;
+ pool<WireId> used_pclkcib;
std::set<WireId> get_candidate_pclkcibs(BelId dcc)
{
@@ -535,9 +535,9 @@ class Ecp5GlobalRouter
fab_globals.insert(i);
}
std::vector<std::pair<PortRef *, int>> toroute;
- std::unordered_map<int, NetInfo *> clocks;
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ dict<int, NetInfo *> clocks;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_DCCA) {
NetInfo *clock = ci->ports.at(id_CLKO).net;
NPNR_ASSERT(clock != nullptr);
@@ -577,8 +577,8 @@ class Ecp5GlobalRouter
void route_eclk_sources()
{
// Try and use dedicated paths if possible
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF || ci->type == id_ECLKBRIDGECS) {
std::vector<IdString> pins;
if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF) {
@@ -595,7 +595,7 @@ class Ecp5GlobalRouter
WireId src = ctx->getNetinfoSourceWire(ni);
WireId dst = ctx->getBelPinWire(ci->bel, pin);
std::queue<WireId> visit;
- std::unordered_map<WireId, PipId> backtrace;
+ dict<WireId, PipId> backtrace;
visit.push(dst);
int iter = 0;
WireId cursor;
diff --git a/ecp5/lpf.cc b/ecp5/lpf.cc
index 6d134e8d..39576fcb 100644
--- a/ecp5/lpf.cc
+++ b/ecp5/lpf.cc
@@ -19,7 +19,6 @@
#include <boost/algorithm/string.hpp>
#include <sstream>
-#include <unordered_set>
#include "arch.h"
#include "log.h"
@@ -27,7 +26,7 @@
NEXTPNR_NAMESPACE_BEGIN
-static const std::unordered_set<std::string> sysconfig_keys = {
+static const pool<std::string> sysconfig_keys = {
"SLAVE_SPI_PORT", "MASTER_SPI_PORT", "SLAVE_PARALLEL_PORT",
"BACKGROUND_RECONFIG", "DONE_EX", "DONE_OD",
"DONE_PULL", "MCCLK_FREQ", "TRANSFR",
@@ -35,7 +34,7 @@ static const std::unordered_set<std::string> sysconfig_keys = {
"COMPRESS_CONFIG", "CONFIG_MODE", "INBUF",
};
-static const std::unordered_set<std::string> iobuf_keys = {
+static const pool<std::string> iobuf_keys = {
"IO_TYPE", "BANK", "BANK_VCC", "VREF", "PULLMODE", "DRIVE", "SLEWRATE",
"CLAMP", "OPENDRAIN", "DIFFRESISTOR", "DIFFDRIVE", "HYSTERESIS", "TERMINATION",
};
diff --git a/ecp5/main.cc b/ecp5/main.cc
index 5d9fc965..711c4944 100644
--- a/ecp5/main.cc
+++ b/ecp5/main.cc
@@ -34,7 +34,7 @@ class ECP5CommandHandler : public CommandHandler
public:
ECP5CommandHandler(int argc, char **argv);
virtual ~ECP5CommandHandler(){};
- 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 customAfterLoad(Context *ctx) override;
void validate() override;
@@ -132,7 +132,7 @@ static std::string speedString(ArchArgs::SpeedGrade speed)
return "";
}
-std::unique_ptr<Context> ECP5CommandHandler::createContext(std::unordered_map<std::string, Property> &values)
+std::unique_ptr<Context> ECP5CommandHandler::createContext(dict<std::string, Property> &values)
{
ArchArgs chipArgs;
chipArgs.type = ArchArgs::NONE;
@@ -270,8 +270,8 @@ void ECP5CommandHandler::customAfterLoad(Context *ctx)
log_error("failed to parse LPF file '%s'\n", filename.c_str());
}
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
ci->type == ctx->id("$nextpnr_iobuf")) {
if (!ci->attrs.count(ctx->id("LOC"))) {
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index bdf84bcf..19eda9e2 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -21,7 +21,6 @@
#include <boost/optional.hpp>
#include <iterator>
#include <queue>
-#include <unordered_set>
#include "cells.h"
#include "chain_utils.h"
#include "design_utils.h"
@@ -106,8 +105,8 @@ class Ecp5Packer
void find_lutff_pairs()
{
log_info("Finding LUTFF pairs...\n");
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_lut(ctx, ci) || is_pfumx(ctx, ci) || is_l6mux(ctx, ci)) {
NetInfo *znet = ci->ports.at(ctx->id("Z")).net;
if (znet != nullptr) {
@@ -261,9 +260,9 @@ class Ecp5Packer
void pair_luts()
{
log_info("Finding LUT-LUT pairs...\n");
- std::unordered_set<IdString> procdLuts;
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ pool<IdString> procdLuts;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_lut(ctx, ci) && procdLuts.find(cell.first) == procdLuts.end()) {
NetInfo *znet = ci->ports.at(ctx->id("Z")).net;
std::vector<NetInfo *> inpnets;
@@ -392,8 +391,8 @@ class Ecp5Packer
}
if (ctx->debug) {
log_info("Singleton LUTs (packer QoR debug): \n");
- for (auto cell : sorted(ctx->cells))
- if (is_lut(ctx, cell.second) && !procdLuts.count(cell.first))
+ for (auto &cell : ctx->cells)
+ if (is_lut(ctx, cell.second.get()) && !procdLuts.count(cell.first))
log_info(" %s\n", cell.first.c_str(ctx));
}
}
@@ -443,8 +442,8 @@ class Ecp5Packer
{
log_info("Packing IOs..\n");
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_nextpnr_iob(ctx, ci)) {
CellInfo *trio = nullptr;
NetInfo *ionet = nullptr;
@@ -536,8 +535,8 @@ class Ecp5Packer
void pack_lut5xs()
{
log_info("Packing LUT5-7s...\n");
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_pfumx(ctx, ci)) {
std::unique_ptr<CellInfo> packed =
create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE");
@@ -593,8 +592,8 @@ class Ecp5Packer
}
flush_cells();
// Pack LUT6s
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_l6mux(ctx, ci)) {
NetInfo *ofx0_0 = ci->ports.at(ctx->id("D0")).net;
if (ofx0_0 == nullptr)
@@ -651,8 +650,8 @@ class Ecp5Packer
}
flush_cells();
// Pack LUT7s
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_l6mux(ctx, ci)) {
NetInfo *ofx1_0 = ci->ports.at(ctx->id("D0")).net;
if (ofx1_0 == nullptr)
@@ -975,8 +974,8 @@ class Ecp5Packer
// Pack distributed RAM
void pack_dram()
{
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_dpram(ctx, ci)) {
// Create RAMW slice
@@ -1108,8 +1107,8 @@ class Ecp5Packer
void pack_remaining_luts()
{
log_info("Packing unpaired LUTs into a SLICE...\n");
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_lut(ctx, ci)) {
std::unique_ptr<CellInfo> slice =
create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE");
@@ -1134,7 +1133,7 @@ class Ecp5Packer
// Used for packing an FF into a nearby SLICE
template <typename TFunc> CellInfo *find_nearby_cell(CellInfo *origin, TFunc Func)
{
- std::unordered_set<CellInfo *> visited_cells;
+ pool<CellInfo *, hash_ptr_ops> visited_cells;
std::queue<CellInfo *> to_visit;
visited_cells.insert(origin);
to_visit.push(origin);
@@ -1181,8 +1180,8 @@ class Ecp5Packer
++used_slices;
log_info("Packing unpaired FFs into a SLICE...\n");
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (is_ff(ctx, ci)) {
bool pack_dense = used_slices > (dense_pack_mode_thresh * available_slices);
bool requires_m = get_net_or_empty(ci, ctx->id("M")) != nullptr;
@@ -1403,8 +1402,8 @@ class Ecp5Packer
bool gnd_used = false, vcc_used = false;
- for (auto net : sorted(ctx->nets)) {
- NetInfo *ni = net.second;
+ for (auto &net : ctx->nets) {
+ NetInfo *ni = net.second.get();
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, gnd_net.get(), false);
@@ -1461,8 +1460,8 @@ class Ecp5Packer
c->params[n] = c->params[o];
c->params.erase(o);
};
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
// Convert 36-bit PDP RAMs to regular 18-bit DP ones that match the Bel
if (ci->type == ctx->id("PDPW16KD")) {
ci->params[ctx->id("DATA_WIDTH_A")] = 36; // force PDP mode
@@ -1503,8 +1502,8 @@ class Ecp5Packer
ci->type = id_DP16KD;
}
}
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_DP16KD) {
// Add ports, even if disconnected, to ensure correct tie-offs
for (int i = 0; i < 14; i++) {
@@ -1544,8 +1543,8 @@ class Ecp5Packer
// Pack DSPs
void pack_dsps()
{
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_MULT18X18D) {
// Add ports, even if disconnected, to ensure correct tie-offs
for (auto sig : {"CLK", "CE", "RST"})
@@ -1708,8 +1707,8 @@ class Ecp5Packer
// "Pack" DCUs
void pack_dcus()
{
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_DCUA) {
if (ci->attrs.count(ctx->id("LOC"))) {
std::string loc = ci->attrs.at(ctx->id("LOC")).as_string();
@@ -1759,8 +1758,8 @@ class Ecp5Packer
}
}
}
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_EXTREFB) {
const NetInfo *refo = net_or_nullptr(ci, id_REFCLKO);
CellInfo *dcu = nullptr;
@@ -1800,8 +1799,8 @@ class Ecp5Packer
// Miscellaneous packer tasks
void pack_misc()
{
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_USRMCLK) {
rename_port(ctx, ci, ctx->id("USRMCLKI"), id_PADDO);
rename_port(ctx, ci, ctx->id("USRMCLKTS"), id_PADDT);
@@ -1829,14 +1828,14 @@ class Ecp5Packer
if (ctx->getBelType(bel) == id_EHXPLLL && ctx->checkBelAvail(bel))
available_plls.insert(bel);
}
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL")))
available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string()));
}
// Place PLL connected to fixed drivers such as IO close to their source
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) {
const NetInfo *drivernet = net_or_nullptr(ci, id_CLKI);
if (drivernet == nullptr || drivernet->driver.cell == nullptr)
@@ -1863,8 +1862,8 @@ class Ecp5Packer
}
}
// Place PLLs driven by logic, etc, randomly
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) {
if (available_plls.empty())
log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx));
@@ -1971,7 +1970,7 @@ class Ecp5Packer
IdString global_name = ctx->id("G_BANK" + std::to_string(bank) + "ECLK" + std::to_string(found_eclk));
std::queue<WireId> upstream;
- std::unordered_map<WireId, PipId> backtrace;
+ dict<WireId, PipId> backtrace;
upstream.push(userWire);
WireId next;
while (true) {
@@ -2026,12 +2025,12 @@ class Ecp5Packer
new_cells.push_back(std::move(zero_cell));
}
- std::unordered_map<IdString, std::pair<bool, int>> dqsbuf_dqsg;
+ dict<IdString, std::pair<bool, int>> dqsbuf_dqsg;
// Pack DQSBUFs
void pack_dqsbuf()
{
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_DQSBUFM) {
CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("DQSI")).net, is_trellis_io, id_O);
if (pio == nullptr || ci->ports.at(ctx->id("DQSI")).net->users.size() > 1)
@@ -2119,7 +2118,7 @@ class Ecp5Packer
// Pack IOLOGIC
void pack_iologic()
{
- std::unordered_map<IdString, CellInfo *> pio_iologic;
+ dict<IdString, CellInfo *> pio_iologic;
auto set_iologic_sclk = [&](CellInfo *iol, CellInfo *prim, IdString port, bool input, bool disconnect = true) {
NetInfo *sclk = nullptr;
@@ -2265,8 +2264,8 @@ class Ecp5Packer
}
};
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == ctx->id("DELAYF") || ci->type == ctx->id("DELAYG")) {
CellInfo *i_pio = net_driven_by(ctx, ci->ports.at(ctx->id("A")).net, is_trellis_io, id_O);
CellInfo *o_pio = net_only_drives(ctx, ci->ports.at(ctx->id("Z")).net, is_trellis_io, id_I, true);
@@ -2349,8 +2348,8 @@ class Ecp5Packer
}
}
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == ctx->id("IDDRX1F")) {
CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("D")).net, is_trellis_io, id_O);
if (pio == nullptr || ci->ports.at(ctx->id("D")).net->users.size() > 1)
@@ -2692,8 +2691,8 @@ class Ecp5Packer
}
flush_cells();
// Constrain ECLK-related cells
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_ECLKBRIDGECS) {
Loc loc;
NetInfo *i0 = get_net_or_empty(ci, id_CLK0), *i1 = get_net_or_empty(ci, id_CLK1),
@@ -2760,8 +2759,8 @@ class Ecp5Packer
}
}
// Promote/route edge clocks
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) {
if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr)
continue;
@@ -2779,9 +2778,9 @@ class Ecp5Packer
}
}
flush_cells();
- std::unordered_set<BelId> used_eclksyncb;
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ pool<BelId> used_eclksyncb;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_CLKDIVF) {
const NetInfo *clki = net_or_nullptr(ci, id_CLKI);
for (auto &eclk : eclks) {
@@ -2896,8 +2895,8 @@ class Ecp5Packer
}
}
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_ECLKSYNCB) {
// **All** ECLKSYNCBs must be constrained
// Most will be dealt with above, but there might be some rogue cases
@@ -2921,8 +2920,8 @@ class Ecp5Packer
}
}
- for (auto cell : sorted(ctx->cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_CLKDIVF) {
if (ci->attrs.count(ctx->id("BEL")))
continue;
@@ -2967,7 +2966,7 @@ class Ecp5Packer
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);
@@ -3041,7 +3040,7 @@ class Ecp5Packer
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_ECLKI || user.port == id_CLK0 || user.port == id_CLK1)
@@ -3051,7 +3050,7 @@ class Ecp5Packer
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_CLKDIVF) {
std::string div = str_or_default(ci->params, ctx->id("DIV"), "2.0");
@@ -3114,8 +3113,8 @@ class Ecp5Packer
{
// Check for legacy-style JSON (use CEMUX as a clue) and error out, avoiding a confusing assertion failure
// later
- for (auto cell : sorted(ctx->cells)) {
- if (is_ff(ctx, cell.second) && cell.second->params.count(ctx->id("CEMUX")) &&
+ for (auto &cell : ctx->cells) {
+ if (is_ff(ctx, cell.second.get()) && cell.second->params.count(ctx->id("CEMUX")) &&
!cell.second->params[ctx->id("CEMUX")].is_string)
log_error("Found netlist using legacy-style JSON parameter values, please update your Yosys.\n");
}
@@ -3152,7 +3151,7 @@ class Ecp5Packer
private:
Context *ctx;
- std::unordered_set<IdString> packed_cells;
+ pool<IdString> packed_cells;
std::vector<std::unique_ptr<CellInfo>> new_cells;
struct SliceUsage
@@ -3163,10 +3162,10 @@ class Ecp5Packer
bool mux5_used = false, muxx_used = false;
};
- std::unordered_map<IdString, SliceUsage> sliceUsage;
- std::unordered_map<IdString, IdString> lutffPairs;
- std::unordered_map<IdString, IdString> fflutPairs;
- std::unordered_map<IdString, IdString> lutPairs;
+ dict<IdString, SliceUsage> sliceUsage;
+ dict<IdString, IdString> lutffPairs;
+ dict<IdString, IdString> fflutPairs;
+ dict<IdString, IdString> lutPairs;
};
// Main pack function
bool Arch::pack()
@@ -3188,8 +3187,8 @@ bool Arch::pack()
void Arch::assignArchInfo()
{
- for (auto cell : sorted(cells)) {
- CellInfo *ci = cell.second;
+ for (auto &cell : cells) {
+ CellInfo *ci = cell.second.get();
if (ci->type == id_TRELLIS_SLICE) {
ci->sliceInfo.using_dff = false;
@@ -3301,7 +3300,7 @@ void Arch::assignArchInfo()
ci->multInfo.is_clocked = ci->multInfo.timing_id != id_MULT18X18D_REGS_NONE;
}
}
- for (auto net : sorted(nets)) {
+ for (auto &net : nets) {
net.second->is_global = bool_or_default(net.second->attrs, id("ECP5_IS_GLOBAL"));
}
}