aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/nextpnr.h448
-rw-r--r--docs/archapi.md191
-rw-r--r--ecp5/arch.cc14
-rw-r--r--ecp5/arch.h339
-rw-r--r--ecp5/arch_pybindings.h12
-rw-r--r--ecp5/archdefs.h19
-rw-r--r--fpga_interchange/arch.cc4
-rw-r--r--fpga_interchange/arch.h237
-rw-r--r--generic/arch.h243
-rw-r--r--gowin/arch.cc42
-rw-r--r--gowin/arch.h220
-rw-r--r--ice40/arch.cc14
-rw-r--r--ice40/arch.h256
-rw-r--r--ice40/arch_pybindings.h12
-rw-r--r--ice40/archdefs.h19
-rw-r--r--nexus/arch.cc16
-rw-r--r--nexus/arch.h359
-rw-r--r--nexus/arch_pybindings.cc3
-rw-r--r--nexus/arch_pybindings.h12
-rw-r--r--nexus/archdefs.h19
20 files changed, 1334 insertions, 1145 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 2445bed1..2ecbaf0e 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -99,6 +99,8 @@ inline void assert_fail_impl_str(std::string message, const char *expr_str, cons
#define NPNR_ASSERT_FALSE(msg) (assert_fail_impl(msg, "false", __FILE__, __LINE__))
#define NPNR_ASSERT_FALSE_STR(msg) (assert_fail_impl_str(msg, "false", __FILE__, __LINE__))
+#define STRINGIFY(x) #x
+
struct BaseCtx;
struct Context;
@@ -841,6 +843,8 @@ struct BaseCtx
// Context meta data
std::unordered_map<IdString, Property> attrs;
+ Context *as_ctx = nullptr;
+
BaseCtx()
{
idstring_str_to_idx = new std::unordered_map<std::string, int>;
@@ -854,7 +858,7 @@ struct BaseCtx
constraintObjects.push_back(wildcard);
}
- ~BaseCtx()
+ virtual ~BaseCtx()
{
delete idstring_str_to_idx;
delete idstring_idx_to_str;
@@ -914,9 +918,9 @@ struct BaseCtx
IdString id(const char *s) const { return IdString(this, s); }
- Context *getCtx() { return reinterpret_cast<Context *>(this); }
+ Context *getCtx() { return as_ctx; }
- const Context *getCtx() const { return reinterpret_cast<const Context *>(this); }
+ const Context *getCtx() const { return as_ctx; }
const char *nameOf(IdString name) const { return name.c_str(this); }
@@ -1008,6 +1012,442 @@ struct BaseCtx
void attributesToArchInfo();
};
+namespace {
+// For several functions; such as bel/wire/pip attributes; the trivial implementation is to return an empty vector
+// But an arch might want to do something fancy with a custom range type that doesn't provide a constructor
+// So some cursed C++ is needed to return an empty object if possible; or error out if not; is needed
+template <typename Tc> typename std::enable_if<std::is_constructible<Tc>::value, Tc>::type empty_if_possible()
+{
+ return Tc();
+}
+template <typename Tc> typename std::enable_if<!std::is_constructible<Tc>::value, Tc>::type empty_if_possible()
+{
+ NPNR_ASSERT_FALSE("attempting to use default implementation of range-returning function with range type lacking "
+ "default constructor!");
+}
+
+// Provide a default implementation of bel bucket name if typedef'd to IdString
+template <typename Tbbid>
+typename std::enable_if<std::is_same<Tbbid, IdString>::value, IdString>::type bbid_to_name(Tbbid id)
+{
+ return id;
+}
+template <typename Tbbid>
+typename std::enable_if<!std::is_same<Tbbid, IdString>::value, IdString>::type bbid_to_name(Tbbid id)
+{
+ NPNR_ASSERT_FALSE("getBelBucketName must be implemented when BelBucketId is a type other than IdString!");
+}
+template <typename Tbbid>
+typename std::enable_if<std::is_same<Tbbid, IdString>::value, BelBucketId>::type bbid_from_name(IdString name)
+{
+ return name;
+}
+template <typename Tbbid>
+typename std::enable_if<!std::is_same<Tbbid, IdString>::value, BelBucketId>::type bbid_from_name(IdString name)
+{
+ NPNR_ASSERT_FALSE("getBelBucketByName must be implemented when BelBucketId is a type other than IdString!");
+}
+
+// For the cell type and bel type ranges; we want to return our stored vectors only if the type matches
+template <typename Tret, typename Tc>
+typename std::enable_if<std::is_same<Tret, Tc>::value, Tret>::type return_if_match(Tret r)
+{
+ return r;
+}
+
+template <typename Tret, typename Tc>
+typename std::enable_if<!std::is_same<Tret, Tc>::value, Tret>::type return_if_match(Tret r)
+{
+ NPNR_ASSERT_FALSE("default implementations of cell type and bel bucket range functions only available when the "
+ "respective range types are 'const std::vector&'");
+}
+
+} // namespace
+
+// The specification of the Arch API (pure virtual)
+template <typename R> struct ArchAPI : BaseCtx
+{
+ // Basic config
+ virtual IdString archId() const = 0;
+ virtual std::string getChipName() const = 0;
+ virtual typename R::ArchArgsT archArgs() const = 0;
+ virtual IdString archArgsToId(typename R::ArchArgsT args) const = 0;
+ virtual int getGridDimX() const = 0;
+ virtual int getGridDimY() const = 0;
+ virtual int getTileBelDimZ(int x, int y) const = 0;
+ virtual int getTilePipDimZ(int x, int y) const = 0;
+ virtual char getNameDelimiter() const = 0;
+ // Bel methods
+ virtual typename R::AllBelsRangeT getBels() const = 0;
+ virtual IdStringList getBelName(BelId bel) const = 0;
+ virtual BelId getBelByName(IdStringList name) const = 0;
+ virtual uint32_t getBelChecksum(BelId bel) const = 0;
+ virtual void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) = 0;
+ virtual void unbindBel(BelId bel) = 0;
+ virtual Loc getBelLocation(BelId bel) const = 0;
+ virtual BelId getBelByLocation(Loc loc) const = 0;
+ virtual typename R::TileBelsRangeT getBelsByTile(int x, int y) const = 0;
+ virtual bool getBelGlobalBuf(BelId bel) const = 0;
+ virtual bool checkBelAvail(BelId bel) const = 0;
+ virtual CellInfo *getBoundBelCell(BelId bel) const = 0;
+ virtual CellInfo *getConflictingBelCell(BelId bel) const = 0;
+ virtual IdString getBelType(BelId bel) const = 0;
+ virtual typename R::BelAttrsRangeT getBelAttrs(BelId bel) const = 0;
+ virtual WireId getBelPinWire(BelId bel, IdString pin) const = 0;
+ virtual PortType getBelPinType(BelId bel, IdString pin) const = 0;
+ virtual typename R::BelPinsRangeT getBelPins(BelId bel) const = 0;
+ // Wire methods
+ virtual typename R::AllWiresRangeT getWires() const = 0;
+ virtual WireId getWireByName(IdStringList name) const = 0;
+ virtual IdStringList getWireName(WireId wire) const = 0;
+ virtual IdString getWireType(WireId wire) const = 0;
+ virtual typename R::WireAttrsRangeT getWireAttrs(WireId) const = 0;
+ virtual typename R::DownhillPipRangeT getPipsDownhill(WireId wire) const = 0;
+ virtual typename R::UphillPipRangeT getPipsUphill(WireId wire) const = 0;
+ virtual typename R::WireBelPinRangeT getWireBelPins(WireId wire) const = 0;
+ virtual uint32_t getWireChecksum(WireId wire) const = 0;
+ virtual void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) = 0;
+ virtual void unbindWire(WireId wire) = 0;
+ virtual bool checkWireAvail(WireId wire) const = 0;
+ virtual NetInfo *getBoundWireNet(WireId wire) const = 0;
+ virtual WireId getConflictingWireWire(WireId wire) const = 0;
+ virtual NetInfo *getConflictingWireNet(WireId wire) const = 0;
+ virtual DelayInfo getWireDelay(WireId wire) const = 0;
+ // Pip methods
+ virtual typename R::AllPipsRangeT getPips() const = 0;
+ virtual PipId getPipByName(IdStringList name) const = 0;
+ virtual IdStringList getPipName(PipId pip) const = 0;
+ virtual IdString getPipType(PipId pip) const = 0;
+ virtual typename R::PipAttrsRangeT getPipAttrs(PipId) const = 0;
+ virtual uint32_t getPipChecksum(PipId pip) const = 0;
+ virtual void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) = 0;
+ virtual void unbindPip(PipId pip) = 0;
+ virtual bool checkPipAvail(PipId pip) const = 0;
+ virtual NetInfo *getBoundPipNet(PipId pip) const = 0;
+ virtual WireId getConflictingPipWire(PipId pip) const = 0;
+ virtual NetInfo *getConflictingPipNet(PipId pip) const = 0;
+ virtual WireId getPipSrcWire(PipId pip) const = 0;
+ virtual WireId getPipDstWire(PipId pip) const = 0;
+ virtual DelayInfo getPipDelay(PipId pip) const = 0;
+ virtual Loc getPipLocation(PipId pip) const = 0;
+ // Group methods
+ virtual GroupId getGroupByName(IdStringList name) const = 0;
+ virtual IdStringList getGroupName(GroupId group) const = 0;
+ virtual typename R::AllGroupsRangeT getGroups() const = 0;
+ virtual typename R::GroupBelsRangeT getGroupBels(GroupId group) const = 0;
+ virtual typename R::GroupWiresRangeT getGroupWires(GroupId group) const = 0;
+ virtual typename R::GroupPipsRangeT getGroupPips(GroupId group) const = 0;
+ virtual typename R::GroupGroupsRangeT getGroupGroups(GroupId group) const = 0;
+ // Delay Methods
+ virtual delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const = 0;
+ virtual delay_t getDelayEpsilon() const = 0;
+ virtual delay_t getRipupDelayPenalty() const = 0;
+ virtual float getDelayNS(delay_t v) const = 0;
+ virtual DelayInfo getDelayFromNS(float ns) const = 0;
+ virtual uint32_t getDelayChecksum(delay_t v) const = 0;
+ virtual bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const = 0;
+ virtual delay_t estimateDelay(WireId src, WireId dst) const = 0;
+ virtual ArcBounds getRouteBoundingBox(WireId src, WireId dst) const = 0;
+ // Decal methods
+ virtual typename R::DecalGfxRangeT getDecalGraphics(DecalId decal) const = 0;
+ virtual DecalXY getBelDecal(BelId bel) const = 0;
+ virtual DecalXY getWireDecal(WireId wire) const = 0;
+ virtual DecalXY getPipDecal(PipId pip) const = 0;
+ virtual DecalXY getGroupDecal(GroupId group) const = 0;
+ // Cell timing methods
+ virtual bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const = 0;
+ virtual TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const = 0;
+ virtual TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const = 0;
+ // Placement validity checks
+ virtual bool isValidBelForCellType(IdString cell_type, BelId bel) const = 0;
+ virtual IdString getBelBucketName(BelBucketId bucket) const = 0;
+ virtual BelBucketId getBelBucketByName(IdString name) const = 0;
+ virtual BelBucketId getBelBucketForBel(BelId bel) const = 0;
+ virtual BelBucketId getBelBucketForCellType(IdString cell_type) const = 0;
+ virtual bool isValidBelForCell(CellInfo *cell, BelId bel) const = 0;
+ virtual bool isBelLocationValid(BelId bel) const = 0;
+ virtual typename R::CellTypeRangeT getCellTypes() const = 0;
+ virtual typename R::BelBucketRangeT getBelBuckets() const = 0;
+ virtual typename R::BucketBelRangeT getBelsInBucket(BelBucketId bucket) const = 0;
+ // Flow methods
+ virtual bool pack() = 0;
+ virtual bool place() = 0;
+ virtual bool route() = 0;
+ virtual void assignArchInfo() = 0;
+};
+
+template <typename R> struct BaseArch : ArchAPI<R>
+{
+ // --------------------------------------------------------------
+ // Default, trivial, implementations of Arch API functions for arches that don't need complex behaviours
+
+ // Basic config
+ virtual IdString archId() const override { return this->id(STRINGIFY(ARCHNAME)); }
+ virtual IdString archArgsToId(typename R::ArchArgsT args) const { return IdString(); }
+ virtual int getTilePipDimZ(int x, int y) const override { return 1; }
+ virtual char getNameDelimiter() const override { return ' '; }
+
+ // Bel methods
+ virtual uint32_t getBelChecksum(BelId bel) const override { return uint32_t(std::hash<BelId>()(bel)); }
+ virtual void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) override
+ {
+ NPNR_ASSERT(bel != BelId());
+ auto &entry = base_bel2cell[bel];
+ NPNR_ASSERT(entry == nullptr);
+ cell->bel = bel;
+ cell->belStrength = strength;
+ entry = cell;
+ this->refreshUiBel(bel);
+ }
+ virtual void unbindBel(BelId bel) override
+ {
+ NPNR_ASSERT(bel != BelId());
+ auto &entry = base_bel2cell[bel];
+ NPNR_ASSERT(entry != nullptr);
+ entry->bel = BelId();
+ entry->belStrength = STRENGTH_NONE;
+ entry = nullptr;
+ this->refreshUiBel(bel);
+ }
+
+ virtual bool getBelGlobalBuf(BelId bel) const override { return false; }
+ virtual bool checkBelAvail(BelId bel) const override { return getBoundBelCell(bel) == nullptr; };
+ virtual CellInfo *getBoundBelCell(BelId bel) const override
+ {
+ auto fnd = base_bel2cell.find(bel);
+ return fnd == base_bel2cell.end() ? nullptr : fnd->second;
+ }
+ virtual CellInfo *getConflictingBelCell(BelId bel) const override { return getBoundBelCell(bel); }
+ virtual typename R::BelAttrsRangeT getBelAttrs(BelId bel) const override
+ {
+ return empty_if_possible<typename R::BelAttrsRangeT>();
+ }
+
+ // Wire methods
+ virtual IdString getWireType(WireId wire) const override { return IdString(); }
+ virtual typename R::WireAttrsRangeT getWireAttrs(WireId) const override
+ {
+ return empty_if_possible<typename R::WireAttrsRangeT>();
+ }
+ virtual uint32_t getWireChecksum(WireId wire) const override { return uint32_t(std::hash<WireId>()(wire)); }
+
+ virtual void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) override
+ {
+ NPNR_ASSERT(wire != WireId());
+ auto &w2n_entry = base_wire2net[wire];
+ NPNR_ASSERT(w2n_entry == nullptr);
+ net->wires[wire].pip = PipId();
+ net->wires[wire].strength = strength;
+ w2n_entry = net;
+ this->refreshUiWire(wire);
+ }
+ virtual void unbindWire(WireId wire) override
+ {
+ NPNR_ASSERT(wire != WireId());
+ auto &w2n_entry = base_wire2net[wire];
+ NPNR_ASSERT(w2n_entry != nullptr);
+
+ auto &net_wires = w2n_entry->wires;
+ auto it = net_wires.find(wire);
+ NPNR_ASSERT(it != net_wires.end());
+
+ auto pip = it->second.pip;
+ if (pip != PipId()) {
+ base_pip2net[pip] = nullptr;
+ }
+
+ net_wires.erase(it);
+ base_wire2net[wire] = nullptr;
+
+ w2n_entry = nullptr;
+ this->refreshUiWire(wire);
+ }
+ virtual bool checkWireAvail(WireId wire) const override { return getBoundWireNet(wire) == nullptr; }
+ virtual NetInfo *getBoundWireNet(WireId wire) const override
+ {
+ auto fnd = base_wire2net.find(wire);
+ return fnd == base_wire2net.end() ? nullptr : fnd->second;
+ }
+ virtual WireId getConflictingWireWire(WireId wire) const override { return wire; };
+ virtual NetInfo *getConflictingWireNet(WireId wire) const override { return getBoundWireNet(wire); }
+
+ // Pip methods
+ virtual IdString getPipType(PipId pip) const { return IdString(); }
+ virtual typename R::PipAttrsRangeT getPipAttrs(PipId) const override
+ {
+ return empty_if_possible<typename R::PipAttrsRangeT>();
+ }
+ virtual uint32_t getPipChecksum(PipId pip) const override { return uint32_t(std::hash<PipId>()(pip)); }
+ virtual void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) override
+ {
+ NPNR_ASSERT(pip != PipId());
+ auto &p2n_entry = base_pip2net[pip];
+ NPNR_ASSERT(p2n_entry == nullptr);
+ p2n_entry = net;
+
+ WireId dst = this->getPipDstWire(pip);
+ auto &w2n_entry = base_wire2net[dst];
+ NPNR_ASSERT(w2n_entry == nullptr);
+ w2n_entry = net;
+ net->wires[dst].pip = pip;
+ net->wires[dst].strength = strength;
+ }
+ virtual void unbindPip(PipId pip) override
+ {
+ NPNR_ASSERT(pip != PipId());
+ auto &p2n_entry = base_pip2net[pip];
+ NPNR_ASSERT(p2n_entry != nullptr);
+ WireId dst = this->getPipDstWire(pip);
+
+ auto &w2n_entry = base_wire2net[dst];
+ NPNR_ASSERT(w2n_entry != nullptr);
+ w2n_entry = nullptr;
+
+ p2n_entry->wires.erase(dst);
+ p2n_entry = nullptr;
+ }
+ virtual bool checkPipAvail(PipId pip) const override { return getBoundPipNet(pip) == nullptr; }
+ virtual NetInfo *getBoundPipNet(PipId pip) const override
+ {
+ auto fnd = base_pip2net.find(pip);
+ return fnd == base_pip2net.end() ? nullptr : fnd->second;
+ }
+ virtual WireId getConflictingPipWire(PipId pip) const override { return WireId(); }
+ virtual NetInfo *getConflictingPipNet(PipId pip) const override { return getBoundPipNet(pip); }
+
+ // Group methods
+ virtual GroupId getGroupByName(IdStringList name) const override { return GroupId(); };
+ virtual IdStringList getGroupName(GroupId group) const override { return IdStringList(); };
+ virtual typename R::AllGroupsRangeT getGroups() const override
+ {
+ return empty_if_possible<typename R::AllGroupsRangeT>();
+ }
+ // Default implementation of these assumes no groups so never called
+ virtual typename R::GroupBelsRangeT getGroupBels(GroupId group) const override
+ {
+ NPNR_ASSERT_FALSE("unreachable");
+ };
+ virtual typename R::GroupWiresRangeT getGroupWires(GroupId group) const override
+ {
+ NPNR_ASSERT_FALSE("unreachable");
+ };
+ virtual typename R::GroupPipsRangeT getGroupPips(GroupId group) const override
+ {
+ NPNR_ASSERT_FALSE("unreachable");
+ };
+ virtual typename R::GroupGroupsRangeT getGroupGroups(GroupId group) const override
+ {
+ NPNR_ASSERT_FALSE("unreachable");
+ };
+
+ // Delay methods
+ virtual bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override
+ {
+ return false;
+ }
+
+ // Decal methods
+ virtual typename R::DecalGfxRangeT getDecalGraphics(DecalId decal) const override
+ {
+ NPNR_ASSERT_FALSE("unreachable");
+ };
+ virtual DecalXY getBelDecal(BelId bel) const override { return DecalXY(); }
+ virtual DecalXY getWireDecal(WireId wire) const override { return DecalXY(); }
+ virtual DecalXY getPipDecal(PipId pip) const override { return DecalXY(); }
+ virtual DecalXY getGroupDecal(GroupId group) const override { return DecalXY(); }
+
+ // Cell timing methods
+ virtual bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override
+ {
+ return false;
+ }
+ virtual TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override
+ {
+ return TMG_IGNORE;
+ }
+ virtual TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override
+ {
+ NPNR_ASSERT_FALSE("unreachable");
+ }
+
+ // Placement validity checks
+ virtual bool isValidBelForCellType(IdString cell_type, BelId bel) const override
+ {
+ return cell_type == this->getBelType(bel);
+ }
+ virtual IdString getBelBucketName(BelBucketId bucket) const override { return bbid_to_name<BelBucketId>(bucket); }
+ virtual BelBucketId getBelBucketByName(IdString name) const override { return bbid_from_name<BelBucketId>(name); }
+ virtual BelBucketId getBelBucketForBel(BelId bel) const override
+ {
+ return getBelBucketForCellType(this->getBelType(bel));
+ };
+ virtual BelBucketId getBelBucketForCellType(IdString cell_type) const override
+ {
+ return getBelBucketByName(cell_type);
+ };
+ virtual bool isValidBelForCell(CellInfo *cell, BelId bel) const override { return true; }
+ virtual bool isBelLocationValid(BelId bel) const override { return true; }
+ virtual typename R::CellTypeRangeT getCellTypes() const override
+ {
+ NPNR_ASSERT(cell_types_initialised);
+ return return_if_match<const std::vector<IdString> &, typename R::CellTypeRangeT>(cell_types);
+ }
+ virtual typename R::BelBucketRangeT getBelBuckets() const override
+ {
+ NPNR_ASSERT(bel_buckets_initialised);
+ return return_if_match<const std::vector<BelBucketId> &, typename R::BelBucketRangeT>(bel_buckets);
+ }
+ virtual typename R::BucketBelRangeT getBelsInBucket(BelBucketId bucket) const override
+ {
+ NPNR_ASSERT(bel_buckets_initialised);
+ return return_if_match<const std::vector<BelId> &, typename R::BucketBelRangeT>(bucket_bels.at(bucket));
+ }
+
+ // Flow methods
+ virtual void assignArchInfo() override{};
+
+ // --------------------------------------------------------------
+ // These structures are used to provide default implementations of bel/wire/pip binding. Arches might want to
+ // replace them with their own, for example to use faster access structures than unordered_map. Arches might also
+ // want to add extra checks around these functions
+ std::unordered_map<BelId, CellInfo *> base_bel2cell;
+ std::unordered_map<WireId, NetInfo *> base_wire2net;
+ std::unordered_map<PipId, NetInfo *> base_pip2net;
+
+ // For the default cell/bel bucket implementations
+ std::vector<IdString> cell_types;
+ std::vector<BelBucketId> bel_buckets;
+ std::unordered_map<BelBucketId, std::vector<BelId>> bucket_bels;
+
+ // Arches that want to use the default cell types and bel buckets *must* call these functions in their constructor
+ bool cell_types_initialised = false;
+ bool bel_buckets_initialised = false;
+ void init_cell_types()
+ {
+ std::unordered_set<IdString> bel_types;
+ for (auto bel : this->getBels())
+ bel_types.insert(this->getBelType(bel));
+ std::copy(bel_types.begin(), bel_types.end(), std::back_inserter(cell_types));
+ std::sort(cell_types.begin(), cell_types.end());
+ cell_types_initialised = true;
+ }
+ void init_bel_buckets()
+ {
+ for (auto cell_type : this->getCellTypes()) {
+ auto bucket = this->getBelBucketForCellType(cell_type);
+ bucket_bels[bucket]; // create empty bucket
+ }
+ for (auto bel : this->getBels()) {
+ auto bucket = this->getBelBucketForBel(bel);
+ bucket_bels[bucket].push_back(bel);
+ }
+ for (auto &b : bucket_bels)
+ bel_buckets.push_back(b.first);
+ std::sort(bel_buckets.begin(), bel_buckets.end());
+ bel_buckets_initialised = true;
+ }
+};
+
NEXTPNR_NAMESPACE_END
#include "arch.h"
@@ -1023,7 +1463,7 @@ struct Context : Arch, DeterministicRNG
// Should we disable printing of the location of nets in the critical path?
bool disable_critical_path_source_print = false;
- Context(ArchArgs args) : Arch(args) {}
+ Context(ArchArgs args) : Arch(args) { BaseCtx::as_ctx = this; }
// --------------------------------------------------------------
diff --git a/docs/archapi.md b/docs/archapi.md
index e3c06efd..9e6b3a46 100644
--- a/docs/archapi.md
+++ b/docs/archapi.md
@@ -1,6 +1,35 @@
Each architecture must implement the following types and APIs.
-The syntax `const_range<T>` is used to denote anything that has a `begin()` and `end()` method that return const forward iterators. This can be a `std::list<T>`, `std::vector<T>`, a (const) reference to those, or anything else that behaves in a similar way.
+Architectures can either inherit from `ArchAPI<ArchRanges>`, which is a pure virtual description of the architecture API; or `BaseArch<ArchRanges>` which provides some default implementations described below.
+
+`ArchRanges` is a `struct` of `using`s that allows arches to return custom range types. These ranges can be anything that has a `begin()` and `end()` method that return const forward iterators. This can be a `std::list<T>`, `std::vector<T>`, a (const) reference to those, or anything else that behaves in a similar way.
+
+The contents of `ArchRanges` is as follows:
+
+| Type | Range of |
+|---------------------------|----------------------------------|
+|`ArchArgsT` | N/A (struct of device params) |
+|`AllBelsRangeT` | `BelId` |
+|`TileBelsRangeT` | `BelId` |
+|`BelAttrsRangeT` | std::pair<IdString, std::string> |
+|`BelPinsRangeT` | `IdString` |
+|`AllWiresRangeT` | `WireId` |
+|`DownhillPipRangeT` | `PipId` |
+|`UphillPipRangeT` | `PipId` |
+|`WireBelPinRangeT` | `BelPin` |
+|`AllPipsRangeT` | `PipId` |
+|`PipAttrsRangeT` | std::pair<IdString, std::string> |
+|`AllGroupsRangeT` | `GroupId` |
+|`GroupBelsRangeT` | `BelId` |
+|`GroupWiresRangeT` | `WireId` |
+|`GroupPipsRangeT` | `PipId` |
+|`GroupGroupsRangeT` | `GroupId` |
+|`DecalGfxRangeT` | `GraphicElement` |
+|`CellTypeRangeT` | `IdString` |
+|`BelBucketRangeT` | `BelBucketRange` |
+|`BucketBelRangeT` | `BelId` |
+
+The functions that return a particular type are described below
archdefs.h
==========
@@ -74,7 +103,17 @@ Constructor. ArchArgs is a architecture-specific type (usually a struct also def
### std::string getChipName() const
-Return a string representation of the ArchArgs that was used to construct this object.
+Return a user-friendly string representation of the ArchArgs that was used to construct this object.
+
+### ArchArgs archArgs() const
+
+Return the `ArchArgs` used to construct this object.
+
+### IdString archArgsToId(ArchArgs args) const
+
+Return an internal IdString representation of the ArchArgs that was used to construct this object.
+
+*BaseArch default: returns empty IdString*
### int getGridDimX() const
@@ -92,17 +131,23 @@ Get Z dimension for the specified tile for bels. All bels with at specified X an
Get Z dimension for the specified tile for pips. All pips with at specified X and Y coordinates must have a Z coordinate in the range `0 .. getTileDimZ(X,Y)-1` (inclusive).
+*BaseArch default: returns 1*
+
### char getNameDelimiter() const
Returns a delimiter that can be used to build up bel, wire and pip names out of hierarchical components (such as tiles and sites) to avoid the high memory usage of storing full names for every object.
+*BaseArch default: returns ' '*
+
Cell Methods
-----------
-### const\_range\<IdString\> getCellTypes() const
+### CellTypeRangeT getCellTypes() const
Get list of cell types that this architecture accepts.
+*BaseArch default: returns list derived from bel types set up by `init_cell_types()`*
+
Bel Methods
-----------
@@ -122,7 +167,7 @@ Get the X/Y/Z location of a given bel. Each bel must have a unique X/Y/Z locatio
Lookup a bel by its X/Y/Z location.
-### const\_range\<BelId\> getBelsByTile(int x, int y) const
+### TileBelsRangeT getBelsByTile(int x, int y) const
Return a list of all bels at the give X/Y location.
@@ -130,35 +175,49 @@ Return a list of all bels at the give X/Y location.
Returns true if the given bel is a global buffer. A global buffer does not "pull in" other cells it drives to be close to the location of the global buffer.
+*BaseArch default: returns false*
+
### uint32\_t getBelChecksum(BelId bel) const
Return a (preferably unique) number that represents this bel. This is used in design state checksum calculations.
+*BaseArch default: returns `std::hash` of `BelId` cast to `uint32_t`*
+
### void bindBel(BelId bel, CellInfo \*cell, PlaceStrength strength)
Bind a given bel to a given cell with the given strength.
This method must also update `cell->bel` and `cell->belStrength`.
+*BaseArch default: binds using `base_bel2cell`*
+
### void unbindBel(BelId bel)
Unbind a bel.
This method must also update `CellInfo::bel` and `CellInfo::belStrength`.
+*BaseArch default: unbinds using `base_bel2cell`*
+
### bool checkBelAvail(BelId bel) const
Returns true if the bel is available. A bel can be unavailable because it is bound, or because it is exclusive to some other resource that is bound.
+*BaseArch default: returns `getBoundBelCell(bel) == nullptr`*
+
### CellInfo \*getBoundBelCell(BelId bel) const
Return the cell the given bel is bound to, or nullptr if the bel is not bound.
+*BaseArch default: returns entry in `base_bel2cell`*
+
### CellInfo \*getConflictingBelCell(BelId bel) const
If the bel is unavailable, and unbinding a single cell would make it available, then this method must return that cell.
-### const\_range\<BelId\> getBels() const
+*BaseArch default: returns `getBoundBelCell(bel)`*
+
+### AllBelsRangeT getBels() const
Return a list of all bels on the device.
@@ -166,11 +225,13 @@ Return a list of all bels on the device.
Return the type of a given bel.
-### const\_range\<std\:\:pair\<IdString, std::string\>\> getBelAttrs(BelId bel) const
+### BelAttrsRangeT getBelAttrs(BelId bel) const
Return the attributes for that bel. Bel attributes are only informal. They are displayed by the GUI but are otherwise
unused. An implementation may simply return an empty range.
+*BaseArch default: returns default-constructed range*
+
### WireId getBelPinWire(BelId bel, IdString pin) const
Return the wire connected to the given bel pin.
@@ -179,7 +240,7 @@ Return the wire connected to the given bel pin.
Return the type (input/output/inout) of the given bel pin.
-### const\_range\<IdString\> getBelPins(BelId bel) const
+### BelPinsRangeT getBelPins(BelId bel) const
Return a list of all pins on that bel.
@@ -200,15 +261,21 @@ Get the type of a wire. The wire type is purely informal and
isn't used by any of the core algorithms. Implementations may
simply return `IdString()`.
-### const\_range\<std\:\:pair\<IdString, std::string\>\> getWireAttrs(WireId wire) const
+*BaseArch default: returns empty IdString*
+
+### WireAttrsRangeT getWireAttrs(WireId wire) const
Return the attributes for that wire. Wire attributes are only informal. They are displayed by the GUI but are otherwise
unused. An implementation may simply return an empty range.
+*BaseArch default: returns default-constructed range*
+
### uint32\_t getWireChecksum(WireId wire) const
Return a (preferably unique) number that represents this wire. This is used in design state checksum calculations.
+*BaseArch default: returns `std::hash` of `WireId` cast to `uint32_t`*
+
### void bindWire(WireId wire, NetInfo \*net, PlaceStrength strength)
Bind a wire to a net. This method must be used when binding a wire that is driven by a bel pin. Use `binPip()`
@@ -216,39 +283,51 @@ when binding a wire that is driven by a pip.
This method must also update `net->wires`.
+*BaseArch default: binds using `base_wire2net`*
+
### void unbindWire(WireId wire)
Unbind a wire. For wires that are driven by a pip, this will also unbind the driving pip.
This method must also update `NetInfo::wires`.
+*BaseArch default: unbinds using `base_wire2net`*
+
### bool checkWireAvail(WireId wire) const
Return true if the wire is available, i.e. can be bound to a net.
+*BaseArch default: returns `getBoundWireNet(wire) == nullptr`*
+
### NetInfo \*getBoundWireNet(WireId wire) const
Return the net a wire is bound to.
+*BaseArch default: returns entry in `base_wire2net`*
+
### WireId getConflictingWireWire(WireId wire) const
If this returns a non-WireId(), then unbinding that wire
will make the given wire available.
+*BaseArch default: returns `wire`*
+
### NetInfo \*getConflictingWireNet(WireId wire) const
If this returns a non-nullptr, then unbinding that entire net
will make the given wire available.
+*BaseArch default: returns `getBoundWireNet(wire)`*
+
### DelayInfo getWireDelay(WireId wire) const
Get the delay for a wire.
-### const\_range\<WireId\> getWires() const
+### AllWiresRangeT getWires() const
Get a list of all wires on the device.
-### const\_range\<BelPin\> getWireBelPins(WireId wire) const
+### WireBelPinRangeT getWireBelPins(WireId wire) const
Get a list of all bel pins attached to a given wire.
@@ -275,11 +354,15 @@ Get the name for a pip. (Pip names must be unique.)
Get the type of a pip. Pip types are purely informal and
implementations may simply return `IdString()`.
-### const\_range\<std\:\:pair\<IdString, std::string\>\> getPipAttrs(PipId pip) const
+*BaseArch default: returns empty IdString*
+
+### PipAttrsRangeT getPipAttrs(PipId pip) const
Return the attributes for that pip. Pip attributes are only informal. They are displayed by the GUI but are otherwise
unused. An implementation may simply return an empty range.
+*BaseArch default: returns default-constructed range*
+
### Loc getPipLocation(PipId pip) const
Get the X/Y/Z location of a given pip. Pip locations do not need to be unique, and in most cases they aren't. So
@@ -289,18 +372,24 @@ for pips a X/Y/Z location refers to a group of pips, not an individual pip.
Return a (preferably unique) number that represents this pip. This is used in design state checksum calculations.
+*BaseArch default: returns `std::hash` of `WireId` cast to `uint32_t`*
+
### void bindPip(PipId pip, NetInfo \*net, PlaceStrength strength)
Bid a pip to a net. This also bind the destination wire of that pip.
This method must also update `net->wires`.
+*BaseArch default: binds using `base_pip2net` and `base_wire2net`*
+
### void unbindPip(PipId pip)
Unbind a pip and the wire driven by that pip.
This method must also update `NetInfo::wires`.
+*BaseArch default: unbinds using `base_pip2net` and `base_wire2net`*
+
### bool checkPipAvail(PipId pip) const
Returns true if the given pip is available to be bound to a net.
@@ -309,21 +398,29 @@ Users must also check if the pip destination wire is available
with `checkWireAvail(getPipDstWire(pip))` before binding the
pip to a net.
+*BaseArch default: returns `getBoundPipNet(pip) == nullptr`*
+
### NetInfo \*getBoundPipNet(PipId pip) const
Return the net this pip is bound to.
+*BaseArch default: returns entry in `base_pip2net`*
+
### WireId getConflictingPipWire(PipId pip) const
If this returns a non-WireId(), then unbinding that wire
will make the given pip available.
+*BaseArch default: returns empty `WireId()`*
+
### NetInfo \*getConflictingPipNet(PipId pip) const
If this returns a non-nullptr, then unbinding that entire net
will make the given pip available.
-### const\_range\<PipId\> getPips() const
+*BaseArch default: returns empty `getBoundPipNet(pip)`*
+
+### AllPipsRangeT getPips() const
Return a list of all pips on the device.
@@ -342,11 +439,11 @@ anti-parallel pips.
Get the delay for a pip.
-### const\_range\<PipId\> getPipsDownhill(WireId wire) const
+### DownhillPipRangeT getPipsDownhill(WireId wire) const
Get all pips downhill of a wire, i.e. pips that use this wire as source wire.
-### const\_range\<PipId\> getPipsUphill(WireId wire) const
+### DownhillPipRangeT getPipsUphill(WireId wire) const
Get all pips uphill of a wire, i.e. pips that use this wire as destination wire.
@@ -357,30 +454,44 @@ Group Methods
Lookup a group by its name, which is a list of IdStrings joined by `getNameDelimiter()`.
+*BaseArch default: returns `GroupId()`*
+
### IdStringList getGroupName(GroupId group) const
Get the name for a group. (Group names must be unique.)
-### const\_range\<GroupId\> getGroups() const
+*BaseArch default: returns `IdStringList()`*
+
+### AllGroupsRangeT getGroups() const
Get a list of all groups on the device.
-### const\_range\<BelId\> getGroupBels(GroupId group) const
+*BaseArch default: returns default-constructed range*
+
+### GroupBelsRangeT getGroupBels(GroupId group) const
Get a list of all bels within a group.
-### const\_range\<WireId\> getGroupWires(GroupId group) const
+*BaseArch default: asserts false as unreachable due to there being no groups*
+
+### GroupWiresRangeT getGroupWires(GroupId group) const
Get a list of all wires within a group.
-### const\_range\<PipId\> getGroupPips(GroupId group) const
+*BaseArch default: asserts false as unreachable due to there being no groups*
+
+### GroupPipsRangeT getGroupPips(GroupId group) const
Get a list of all pips within a group.
-### const\_range\<GroupId\> getGroupGroups(GroupId group) const
+*BaseArch default: asserts false as unreachable due to there being no groups*
+
+### GroupGroupsRangeT getGroupGroups(GroupId group) const
Get a list of all groups within a group.
+*BaseArch default: asserts false as unreachable due to there being no groups*
+
Delay Methods
-------------
@@ -429,6 +540,8 @@ Convert a `delay_t` to an integer for checksum calculations.
Overwrite or modify (in-place) the timing budget for a given arc. Returns a bool to indicate whether this was done.
+*BaseArch default: returns false*
+
Flow Methods
------------
@@ -447,29 +560,39 @@ run the router.
Graphics Methods
----------------
-### const\_range\<GraphicElement\> getDecalGraphics(DecalId decal) const
+###DecalGfxRangeT getDecalGraphics(DecalId decal) const
Return the graphic elements that make up a decal.
The same decal must always produce the same list. If the graphics for
a design element changes, that element must return another decal.
+*BaseArch default: asserts false as unreachable due to there being no decals*
+
### DecalXY getBelDecal(BelId bel) const
Return the decal and X/Y position for the graphics representing a bel.
+*BaseArch default: returns `DecalXY()`*
+
### DecalXY getWireDecal(WireId wire) const
Return the decal and X/Y position for the graphics representing a wire.
+*BaseArch default: returns `DecalXY()`*
+
### DecalXY getPipDecal(PipId pip) const
Return the decal and X/Y position for the graphics representing a pip.
+*BaseArch default: returns `DecalXY()`*
+
### DecalXY getGroupDecal(GroupId group) const
Return the decal and X/Y position for the graphics representing a group.
+*BaseArch default: returns `DecalXY()`*
+
Cell Delay Methods
------------------
@@ -478,18 +601,24 @@ Cell Delay Methods
Returns the delay for the specified path through a cell in the `&delay` argument. The method returns
false if there is no timing relationship from `fromPort` to `toPort`.
+*BaseArch default: returns false*
+
### TimingPortClass getPortTimingClass(const CellInfo \*cell, IdString port, int &clockInfoCount) const
Return the _timing port class_ of a port. This can be a register or combinational input or output; clock input or
output; general startpoint or endpoint; or a port ignored for timing purposes. For register ports, clockInfoCount is set
to the number of associated _clock edges_ that can be queried by getPortClockingInfo.
+*BaseArch default: returns `TMG_IGNORE`*
+
### TimingClockingInfo getPortClockingInfo(const CellInfo \*cell, IdString port, int index) const
Return the _clocking info_ (including port name of clock, clock polarity and setup/hold/clock-to-out times) of a
port. Where ports have more than one clock edge associated with them (such as DDR outputs), `index` can be used to obtain
information for all edges. `index` must be in [0, clockInfoCount), behaviour is undefined otherwise.
+*BaseArch default: asserts false as unreachable*
+
Bel Buckets Methods
-------------------
@@ -513,30 +642,42 @@ Strict legality step will enforce those differences, along with additional
local constraints. `isValidBelForCell`, `isValidBelForCellType`, and
`isBelLocationValid` are used to enforce strict legality checks.
-### const\_range\<BelBucketId\> getBelBuckets() const
+### BelBucketRangeT getBelBuckets() const
Return a list of all bel buckets on the device.
+*BaseArch default: the list of buckets created by calling `init_bel_buckets()`, based on calls to `getBelBucketForBel` for all bels*
+
### IdString getBelBucketName(BelBucketId bucket) const
Return the name of this bel bucket.
+*BaseArch default: `bucket`, if `BelBucketId` is a typedef of `IdString`*
+
### BelBucketId getBelBucketByName(IdString bucket\_name) const
Return the BelBucketId for the specified bucket name.
+*BaseArch default: `bucket_name`, if `BelBucketId` is a typedef of `IdString`*
+
### BelBucketId getBelBucketForBel(BelId bel) const
Returns the bucket for a particular bel.
+*BaseArch default: `getBelBucketForCellType(getCellType(bel))`*
+
### BelBucketId getBelBucketForCell(IdString cell\_type) const
Returns the bel bucket for a particular cell type.
-### const\_range\<BelId\> getBelsInBucket(BelBucketId bucket) const
+*BaseArch default: `getBelBucketByName(cell_type)`*
+
+### BucketBelRangeT getBelsInBucket(BelBucketId bucket) const
Return the list of bels within a bucket.
+*BaseArch default: the list of bels in the bucket created by calling `init_bel_buckets()`*
+
Placer Methods
--------------
@@ -546,17 +687,23 @@ Returns true if the given cell can be bound to the given bel. This check
should be fast, compared with isValidBelForCell. This check should always
return the same value regardless if other cells are placed within the fabric.
+*BaseArch default: returns `cell_type == getBelType(bel)`*
+
### bool isValidBelForCell(CellInfo \*cell, BelId bel) const
Returns true if the given cell can be bound to the given bel, considering
other bound resources. For example, this can be used if there is only
a certain number of different clock signals allowed for a group of bels.
+*BaseArch default: returns true*
+
### bool isBelLocationValid(BelId bel) const
Returns true if a bell in the current configuration is valid, i.e. if
`isValidBelForCell()` would return true for the current mapping.
+*BaseArch default: returns true*
+
### static const std::string defaultPlacer
Name of the default placement algorithm for the architecture, if
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 1f19ee86..cf1745ff 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -105,18 +105,8 @@ Arch::Arch(ArchArgs args) : args(args)
bel_to_cell.resize(chip_info->height * chip_info->width * max_loc_bels, nullptr);
- std::unordered_set<IdString> bel_types;
- for (BelId bel : getBels()) {
- bel_types.insert(getBelType(bel));
- }
-
- for (IdString bel_type : bel_types) {
- cell_types.push_back(bel_type);
-
- BelBucketId bucket;
- bucket.name = bel_type;
- buckets.push_back(bucket);
- }
+ BaseArch::init_cell_types();
+ BaseArch::init_bel_buckets();
for (int i = 0; i < chip_info->width; i++)
x_ids.push_back(id(stringf("X%d", i)));
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 248c8cc4..49582a6e 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -435,7 +435,38 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DelayKey>
} // namespace std
NEXTPNR_NAMESPACE_BEGIN
-struct Arch : BaseCtx
+struct ArchRanges
+{
+ using ArchArgsT = ArchArgs;
+ // Bels
+ using AllBelsRangeT = BelRange;
+ using TileBelsRangeT = BelRange;
+ using BelAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ using BelPinsRangeT = std::vector<IdString>;
+ // Wires
+ using AllWiresRangeT = WireRange;
+ using DownhillPipRangeT = PipRange;
+ using UphillPipRangeT = PipRange;
+ using WireBelPinRangeT = BelPinRange;
+ using WireAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Pips
+ using AllPipsRangeT = AllPipRange;
+ using PipAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Groups
+ using AllGroupsRangeT = std::vector<GroupId>;
+ using GroupBelsRangeT = std::vector<BelId>;
+ using GroupWiresRangeT = std::vector<WireId>;
+ using GroupPipsRangeT = std::vector<PipId>;
+ using GroupGroupsRangeT = std::vector<GroupId>;
+ // Decals
+ using DecalGfxRangeT = std::vector<GraphicElement>;
+ // Placement validity
+ using CellTypeRangeT = const std::vector<IdString> &;
+ using BelBucketRangeT = const std::vector<BelBucketId> &;
+ using BucketBelRangeT = const std::vector<BelId> &;
+};
+
+struct Arch : BaseArch<ArchRanges>
{
const ChipInfoPOD *chip_info;
const PackageInfoPOD *package_info;
@@ -444,8 +475,6 @@ struct Arch : BaseCtx
mutable std::unordered_map<IdStringList, PipId> pip_by_name;
std::vector<CellInfo *> bel_to_cell;
- std::unordered_map<WireId, NetInfo *> wire_to_net;
- std::unordered_map<PipId, NetInfo *> pip_to_net;
std::unordered_map<WireId, int> wire_fanout;
// fast access to X and Y IdStrings for building object names
@@ -459,33 +488,32 @@ struct Arch : BaseCtx
static bool is_available(ArchArgs::ArchArgsTypes chip);
static std::vector<std::string> get_supported_packages(ArchArgs::ArchArgsTypes chip);
- std::string getChipName() const;
+ std::string getChipName() const override;
std::string get_full_chip_name() const;
- IdString archId() const { return id("ecp5"); }
- ArchArgs archArgs() const { return args; }
- IdString archArgsToId(ArchArgs args) const;
+ ArchArgs archArgs() const override { return args; }
+ IdString archArgsToId(ArchArgs args) const override;
// -------------------------------------------------
static const int max_loc_bels = 20;
- int getGridDimX() const { return chip_info->width; };
- int getGridDimY() const { return chip_info->height; };
- int getTileBelDimZ(int, int) const { return max_loc_bels; };
- int getTilePipDimZ(int, int) const { return 1; };
- char getNameDelimiter() const { return '/'; }
+ int getGridDimX() const override { return chip_info->width; };
+ int getGridDimY() const override { return chip_info->height; };
+ int getTileBelDimZ(int, int) const override { return max_loc_bels; };
+ int getTilePipDimZ(int, int) const override { return 1; };
+ char getNameDelimiter() const override { return '/'; }
// -------------------------------------------------
- BelId getBelByName(IdStringList name) const;
+ BelId getBelByName(IdStringList name) const override;
template <typename Id> const LocationTypePOD *loc_info(Id &id) const
{
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
}
- IdStringList getBelName(BelId bel) const
+ IdStringList getBelName(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
std::array<IdString, 3> ids{x_ids.at(bel.location.x), y_ids.at(bel.location.y),
@@ -493,14 +521,14 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- uint32_t getBelChecksum(BelId bel) const { return bel.index; }
+ uint32_t getBelChecksum(BelId bel) const override { return bel.index; }
int get_bel_flat_index(BelId bel) const
{
return (bel.location.y * chip_info->width + bel.location.x) * max_loc_bels + bel.index;
}
- void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
+ void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) override
{
NPNR_ASSERT(bel != BelId());
int idx = get_bel_flat_index(bel);
@@ -511,7 +539,7 @@ struct Arch : BaseCtx
refreshUiBel(bel);
}
- void unbindBel(BelId bel)
+ void unbindBel(BelId bel) override
{
NPNR_ASSERT(bel != BelId());
int idx = get_bel_flat_index(bel);
@@ -522,7 +550,7 @@ struct Arch : BaseCtx
refreshUiBel(bel);
}
- Loc getBelLocation(BelId bel) const
+ Loc getBelLocation(BelId bel) const override
{
Loc loc;
loc.x = bel.location.x;
@@ -531,30 +559,30 @@ struct Arch : BaseCtx
return loc;
}
- BelId getBelByLocation(Loc loc) const;
- BelRange getBelsByTile(int x, int y) const;
+ BelId getBelByLocation(Loc loc) const override;
+ BelRange getBelsByTile(int x, int y) const override;
- bool getBelGlobalBuf(BelId bel) const { return getBelType(bel) == id_DCCA; }
+ bool getBelGlobalBuf(BelId bel) const override { return getBelType(bel) == id_DCCA; }
- bool checkBelAvail(BelId bel) const
+ bool checkBelAvail(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[get_bel_flat_index(bel)] == nullptr;
}
- CellInfo *getBoundBelCell(BelId bel) const
+ CellInfo *getBoundBelCell(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[get_bel_flat_index(bel)];
}
- CellInfo *getConflictingBelCell(BelId bel) const
+ CellInfo *getConflictingBelCell(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[get_bel_flat_index(bel)];
}
- BelRange getBels() const
+ BelRange getBels() const override
{
BelRange range;
range.b.cursor_tile = 0;
@@ -567,7 +595,7 @@ struct Arch : BaseCtx
return range;
}
- IdString getBelType(BelId bel) const
+ IdString getBelType(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
IdString id;
@@ -575,15 +603,9 @@ struct Arch : BaseCtx
return id;
}
- std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId) const
- {
- std::vector<std::pair<IdString, std::string>> ret;
- return ret;
- }
-
- WireId getBelPinWire(BelId bel, IdString pin) const;
+ WireId getBelPinWire(BelId bel, IdString pin) const override;
- BelPinRange getWireBelPins(WireId wire) const
+ BelPinRange getWireBelPins(WireId wire) const override
{
BelPinRange range;
NPNR_ASSERT(wire != WireId());
@@ -598,9 +620,9 @@ struct Arch : BaseCtx
// -------------------------------------------------
- WireId getWireByName(IdStringList name) const;
+ WireId getWireByName(IdStringList name) const override;
- IdStringList getWireName(WireId wire) const
+ IdStringList getWireName(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
std::array<IdString, 3> ids{x_ids.at(wire.location.x), y_ids.at(wire.location.y),
@@ -608,7 +630,7 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- IdString getWireType(WireId wire) const
+ IdString getWireType(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
IdString id;
@@ -616,67 +638,27 @@ struct Arch : BaseCtx
return id;
}
- std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId) const;
+ std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId) const override;
- uint32_t getWireChecksum(WireId wire) const { return wire.index; }
+ uint32_t getWireChecksum(WireId wire) const override { return wire.index; }
- void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
+ void unbindWire(WireId wire) override
{
NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire] == nullptr);
- wire_to_net[wire] = net;
- net->wires[wire].pip = PipId();
- net->wires[wire].strength = strength;
- refreshUiWire(wire);
- }
+ NPNR_ASSERT(base_wire2net[wire] != nullptr);
- void unbindWire(WireId wire)
- {
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire] != nullptr);
-
- auto &net_wires = wire_to_net[wire]->wires;
+ auto &net_wires = base_wire2net[wire]->wires;
auto it = net_wires.find(wire);
NPNR_ASSERT(it != net_wires.end());
-
auto pip = it->second.pip;
+ // As well as the default rules; need to handle fanout counting
if (pip != PipId()) {
wire_fanout[getPipSrcWire(pip)]--;
- pip_to_net[pip] = nullptr;
}
-
- net_wires.erase(it);
- wire_to_net[wire] = nullptr;
- refreshUiWire(wire);
- }
-
- bool checkWireAvail(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == nullptr;
+ BaseArch::unbindWire(wire);
}
- NetInfo *getBoundWireNet(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- if (wire_to_net.find(wire) == wire_to_net.end())
- return nullptr;
- else
- return wire_to_net.at(wire);
- }
-
- WireId getConflictingWireWire(WireId wire) const { return wire; }
-
- NetInfo *getConflictingWireNet(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- if (wire_to_net.find(wire) == wire_to_net.end())
- return nullptr;
- else
- return wire_to_net.at(wire);
- }
-
- DelayInfo getWireDelay(WireId wire) const
+ DelayInfo getWireDelay(WireId wire) const override
{
DelayInfo delay;
delay.min_delay = 0;
@@ -684,7 +666,7 @@ struct Arch : BaseCtx
return delay;
}
- WireRange getWires() const
+ WireRange getWires() const override
{
WireRange range;
range.b.cursor_tile = 0;
@@ -714,79 +696,24 @@ struct Arch : BaseCtx
// -------------------------------------------------
- PipId getPipByName(IdStringList name) const;
- IdStringList getPipName(PipId pip) const;
+ PipId getPipByName(IdStringList name) const override;
+ IdStringList getPipName(PipId pip) const override;
- IdString getPipType(PipId pip) const { return IdString(); }
+ uint32_t getPipChecksum(PipId pip) const override { return pip.index; }
- std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId) const
+ void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) override
{
- std::vector<std::pair<IdString, std::string>> ret;
- return ret;
- }
-
- uint32_t getPipChecksum(PipId pip) const { return pip.index; }
-
- void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
- {
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip] == nullptr);
-
- pip_to_net[pip] = net;
wire_fanout[getPipSrcWire(pip)]++;
-
- WireId dst;
- dst.index = loc_info(pip)->pip_data[pip.index].dst_idx;
- dst.location = pip.location + loc_info(pip)->pip_data[pip.index].rel_dst_loc;
- NPNR_ASSERT(wire_to_net[dst] == nullptr);
- wire_to_net[dst] = net;
- net->wires[dst].pip = pip;
- net->wires[dst].strength = strength;
+ BaseArch::bindPip(pip, net, strength);
}
- void unbindPip(PipId pip)
+ void unbindPip(PipId pip) override
{
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip] != nullptr);
wire_fanout[getPipSrcWire(pip)]--;
-
- WireId dst;
- dst.index = loc_info(pip)->pip_data[pip.index].dst_idx;
- dst.location = pip.location + loc_info(pip)->pip_data[pip.index].rel_dst_loc;
- NPNR_ASSERT(wire_to_net[dst] != nullptr);
- wire_to_net[dst] = nullptr;
- pip_to_net[pip]->wires.erase(dst);
-
- pip_to_net[pip] = nullptr;
+ BaseArch::unbindPip(pip);
}
- bool checkPipAvail(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == nullptr;
- }
-
- NetInfo *getBoundPipNet(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- if (pip_to_net.find(pip) == pip_to_net.end())
- return nullptr;
- else
- return pip_to_net.at(pip);
- }
-
- WireId getConflictingPipWire(PipId pip) const { return WireId(); }
-
- NetInfo *getConflictingPipNet(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- if (pip_to_net.find(pip) == pip_to_net.end())
- return nullptr;
- else
- return pip_to_net.at(pip);
- }
-
- AllPipRange getPips() const
+ AllPipRange getPips() const override
{
AllPipRange range;
range.b.cursor_tile = 0;
@@ -799,7 +726,7 @@ struct Arch : BaseCtx
return range;
}
- WireId getPipSrcWire(PipId pip) const
+ WireId getPipSrcWire(PipId pip) const override
{
WireId wire;
NPNR_ASSERT(pip != PipId());
@@ -808,7 +735,7 @@ struct Arch : BaseCtx
return wire;
}
- WireId getPipDstWire(PipId pip) const
+ WireId getPipDstWire(PipId pip) const override
{
WireId wire;
NPNR_ASSERT(pip != PipId());
@@ -817,7 +744,7 @@ struct Arch : BaseCtx
return wire;
}
- DelayInfo getPipDelay(PipId pip) const
+ DelayInfo getPipDelay(PipId pip) const override
{
DelayInfo delay;
NPNR_ASSERT(pip != PipId());
@@ -834,7 +761,7 @@ struct Arch : BaseCtx
return delay;
}
- PipRange getPipsDownhill(WireId wire) const
+ PipRange getPipsDownhill(WireId wire) const override
{
PipRange range;
NPNR_ASSERT(wire != WireId());
@@ -845,7 +772,7 @@ struct Arch : BaseCtx
return range;
}
- PipRange getPipsUphill(WireId wire) const
+ PipRange getPipsUphill(WireId wire) const override
{
PipRange range;
NPNR_ASSERT(wire != WireId());
@@ -871,7 +798,7 @@ struct Arch : BaseCtx
return chip_info->tiletype_names[loc_info(pip)->pip_data[pip.index].tile_type].get();
}
- Loc getPipLocation(PipId pip) const
+ Loc getPipLocation(PipId pip) const override
{
Loc loc;
loc.x = pip.location.x;
@@ -889,60 +816,60 @@ struct Arch : BaseCtx
std::string get_pio_function_name(BelId bel) const;
BelId get_pio_by_function_name(const std::string &name) const;
- PortType getBelPinType(BelId bel, IdString pin) const;
+ PortType getBelPinType(BelId bel, IdString pin) const override;
// -------------------------------------------------
- GroupId getGroupByName(IdStringList name) const;
- IdStringList getGroupName(GroupId group) const;
- std::vector<GroupId> getGroups() const;
- std::vector<BelId> getGroupBels(GroupId group) const;
- std::vector<WireId> getGroupWires(GroupId group) const;
- std::vector<PipId> getGroupPips(GroupId group) const;
- std::vector<GroupId> getGroupGroups(GroupId group) const;
+ GroupId getGroupByName(IdStringList name) const override;
+ IdStringList getGroupName(GroupId group) const override;
+ std::vector<GroupId> getGroups() const override;
+ std::vector<BelId> getGroupBels(GroupId group) const override;
+ std::vector<WireId> getGroupWires(GroupId group) const override;
+ std::vector<PipId> getGroupPips(GroupId group) const override;
+ std::vector<GroupId> getGroupGroups(GroupId group) const override;
// -------------------------------------------------
- delay_t estimateDelay(WireId src, WireId dst) const;
- ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
- delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
- delay_t getDelayEpsilon() const { return 20; }
- delay_t getRipupDelayPenalty() const;
- float getDelayNS(delay_t v) const { return v * 0.001; }
- DelayInfo getDelayFromNS(float ns) const
+ delay_t estimateDelay(WireId src, WireId dst) const override;
+ ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
+ delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
+ delay_t getDelayEpsilon() const override { return 20; }
+ delay_t getRipupDelayPenalty() const override;
+ float getDelayNS(delay_t v) const override { return v * 0.001; }
+ DelayInfo getDelayFromNS(float ns) const override
{
DelayInfo del;
del.min_delay = delay_t(ns * 1000);
del.max_delay = delay_t(ns * 1000);
return del;
}
- uint32_t getDelayChecksum(delay_t v) const { return v; }
- bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
+ uint32_t getDelayChecksum(delay_t v) const override { return v; }
+ bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override;
// -------------------------------------------------
- bool pack();
- bool place();
- bool route();
+ bool pack() override;
+ bool place() override;
+ bool route() override;
// -------------------------------------------------
- std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const override;
- DecalXY getBelDecal(BelId bel) const;
- DecalXY getWireDecal(WireId wire) const;
- DecalXY getPipDecal(PipId pip) const;
- DecalXY getGroupDecal(GroupId group) const;
+ DecalXY getBelDecal(BelId bel) const override;
+ DecalXY getWireDecal(WireId wire) const override;
+ DecalXY getPipDecal(PipId pip) const override;
+ DecalXY getGroupDecal(GroupId group) const override;
// -------------------------------------------------
// Get the delay through a cell from one port to another, returning false
// if no path exists
- bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
+ bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override;
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
- TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override;
// Get the TimingClockingInfo of a port
- TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
+ TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override;
// Return true if a port is a net
bool is_global_net(const NetInfo *net) const;
@@ -952,53 +879,13 @@ struct Arch : BaseCtx
// -------------------------------------------------
// Placement validity checks
- bool isValidBelForCellType(IdString cell_type, BelId bel) const { return cell_type == getBelType(bel); }
-
- const std::vector<IdString> &getCellTypes() const { return cell_types; }
-
- std::vector<BelBucketId> getBelBuckets() const { return buckets; }
-
- IdString getBelBucketName(BelBucketId bucket) const { return bucket.name; }
-
- BelBucketId getBelBucketByName(IdString name) const
- {
- BelBucketId bucket;
- bucket.name = name;
- return bucket;
- }
-
- BelBucketId getBelBucketForBel(BelId bel) const
- {
- BelBucketId bucket;
- bucket.name = getBelType(bel);
- return bucket;
- }
-
- BelBucketId getBelBucketForCellType(IdString cell_type) const
- {
- BelBucketId bucket;
- bucket.name = cell_type;
- return bucket;
- }
-
- std::vector<BelId> getBelsInBucket(BelBucketId bucket) const
- {
- std::vector<BelId> bels;
- for (BelId bel : getBels()) {
- if (getBelType(bel) == bucket.name) {
- bels.push_back(bel);
- }
- }
- return bels;
- }
-
- bool isValidBelForCell(CellInfo *cell, BelId bel) const;
- bool isBelLocationValid(BelId bel) const;
+ bool isValidBelForCell(CellInfo *cell, BelId bel) const override;
+ bool isBelLocationValid(BelId bel) const override;
// Helper function for above
bool slices_compatible(const std::vector<const CellInfo *> &cells) const;
- void assignArchInfo();
+ void assignArchInfo() override;
void permute_luts();
diff --git a/ecp5/arch_pybindings.h b/ecp5/arch_pybindings.h
index 4228f12b..f2a7dabe 100644
--- a/ecp5/arch_pybindings.h
+++ b/ecp5/arch_pybindings.h
@@ -76,18 +76,6 @@ template <> struct string_converter<PipId>
}
};
-template <> struct string_converter<BelBucketId>
-{
- BelBucketId from_str(Context *ctx, std::string name) { return ctx->getBelBucketByName(ctx->id(name)); }
-
- std::string to_str(Context *ctx, BelBucketId id)
- {
- if (id == BelBucketId())
- throw bad_wrap();
- return ctx->getBelBucketName(id).str(ctx);
- }
-};
-
template <> struct string_converter<BelPin>
{
BelPin from_str(Context *ctx, std::string name)
diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h
index 3bc75ab4..c8fdf892 100644
--- a/ecp5/archdefs.h
+++ b/ecp5/archdefs.h
@@ -126,14 +126,7 @@ struct PipId
}
};
-struct BelBucketId
-{
- IdString name;
-
- bool operator==(const BelBucketId &other) const { return (name == other.name); }
- bool operator!=(const BelBucketId &other) const { return (name != other.name); }
- bool operator<(const BelBucketId &other) const { return name < other.name; }
-};
+typedef IdString BelBucketId;
struct GroupId
{
@@ -271,14 +264,4 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId>
}
};
-template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelBucketId>
-{
- std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelBucketId &partition) const noexcept
- {
- std::size_t seed = 0;
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(partition.name));
- return seed;
- }
-};
-
} // namespace std
diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc
index 63cf290b..583813f0 100644
--- a/fpga_interchange/arch.cc
+++ b/fpga_interchange/arch.cc
@@ -483,8 +483,6 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
return {x0, y0, x1, y1};
}
-delay_t Arch::getWireRipupDelayPenalty(WireId wire) const { return getRipupDelayPenalty(); }
-
bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; }
// -----------------------------------------------------------------------
@@ -529,7 +527,7 @@ DecalXY Arch::getGroupDecal(GroupId pip) const { return {}; };
// -----------------------------------------------------------------------
-delay_t Arch::estimateDelay(WireId src, WireId dst, bool debug) const
+delay_t Arch::estimateDelay(WireId src, WireId dst) const
{
// FIXME: Implement something to push the A* router in the right direction.
return 0;
diff --git a/fpga_interchange/arch.h b/fpga_interchange/arch.h
index 12c30c3d..fd2d16a2 100644
--- a/fpga_interchange/arch.h
+++ b/fpga_interchange/arch.h
@@ -652,7 +652,38 @@ struct ArchArgs
std::string chipdb;
};
-struct Arch : BaseCtx
+struct ArchRanges
+{
+ using ArchArgsT = ArchArgs;
+ // Bels
+ using AllBelsRangeT = BelRange;
+ using TileBelsRangeT = BelRange;
+ using BelAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ using BelPinsRangeT = IdStringRange;
+ // Wires
+ using AllWiresRangeT = WireRange;
+ using DownhillPipRangeT = DownhillPipRange;
+ using UphillPipRangeT = UphillPipRange;
+ using WireBelPinRangeT = BelPinRange;
+ using WireAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Pips
+ using AllPipsRangeT = AllPipRange;
+ using PipAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Groups
+ using AllGroupsRangeT = std::vector<GroupId>;
+ using GroupBelsRangeT = std::vector<BelId>;
+ using GroupWiresRangeT = std::vector<WireId>;
+ using GroupPipsRangeT = std::vector<PipId>;
+ using GroupGroupsRangeT = std::vector<GroupId>;
+ // Decals
+ using DecalGfxRangeT = std::vector<GraphicElement>;
+ // Placement validity
+ using CellTypeRangeT = const IdStringRange;
+ using BelBucketRangeT = const BelBucketRange;
+ using BucketBelRangeT = FilteredBelRange;
+};
+
+struct Arch : ArchAPI<ArchRanges>
{
boost::iostreams::mapped_file_source blob_file;
const ChipInfoPOD *chip_info;
@@ -675,11 +706,11 @@ struct Arch : BaseCtx
ArchArgs args;
Arch(ArchArgs args);
- std::string getChipName() const;
+ std::string getChipName() const override;
- IdString archId() const { return id(chip_info->name.get()); }
- ArchArgs archArgs() const { return args; }
- IdString archArgsToId(ArchArgs args) const;
+ IdString archId() const override { return id(chip_info->name.get()); }
+ ArchArgs archArgs() const override { return args; }
+ IdString archArgsToId(ArchArgs args) const override;
// -------------------------------------------------
@@ -697,25 +728,25 @@ struct Arch : BaseCtx
get_tile_x_y(tile_index, &loc->x, &loc->y);
}
- int getGridDimX() const { return chip_info->width; }
- int getGridDimY() const { return chip_info->height; }
- int getTileBelDimZ(int x, int y) const
+ int getGridDimX() const override { return chip_info->width; }
+ int getGridDimY() const override { return chip_info->height; }
+ int getTileBelDimZ(int x, int y) const override
{
return chip_info->tile_types[chip_info->tiles[get_tile_index(x, y)].type].bel_data.size();
}
- int getTilePipDimZ(int x, int y) const
+ int getTilePipDimZ(int x, int y) const override
{
return chip_info->tile_types[chip_info->tiles[get_tile_index(x, y)].type].number_sites;
}
- char getNameDelimiter() const { return '/'; }
+ char getNameDelimiter() const override { return '/'; }
// -------------------------------------------------
void setup_byname() const;
- BelId getBelByName(IdStringList name) const;
+ BelId getBelByName(IdStringList name) const override;
- IdStringList getBelName(BelId bel) const
+ IdStringList getBelName(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
int site_index = bel_info(chip_info, bel).site;
@@ -725,9 +756,9 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- uint32_t getBelChecksum(BelId bel) const { return bel.index; }
+ uint32_t getBelChecksum(BelId bel) const override { return bel.index; }
- void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
+ void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) override
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(tileStatus[bel.tile].boundcells[bel.index] == nullptr);
@@ -738,7 +769,7 @@ struct Arch : BaseCtx
refreshUiBel(bel);
}
- void unbindBel(BelId bel)
+ void unbindBel(BelId bel) override
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(tileStatus[bel.tile].boundcells[bel.index] != nullptr);
@@ -748,21 +779,21 @@ struct Arch : BaseCtx
refreshUiBel(bel);
}
- bool checkBelAvail(BelId bel) const { return tileStatus[bel.tile].boundcells[bel.index] == nullptr; }
+ bool checkBelAvail(BelId bel) const override { return tileStatus[bel.tile].boundcells[bel.index] == nullptr; }
- CellInfo *getBoundBelCell(BelId bel) const
+ CellInfo *getBoundBelCell(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return tileStatus[bel.tile].boundcells[bel.index];
}
- CellInfo *getConflictingBelCell(BelId bel) const
+ CellInfo *getConflictingBelCell(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return tileStatus[bel.tile].boundcells[bel.index];
}
- BelRange getBels() const
+ BelRange getBels() const override
{
BelRange range;
range.b.cursor_tile = 0;
@@ -775,7 +806,7 @@ struct Arch : BaseCtx
return range;
}
- Loc getBelLocation(BelId bel) const
+ Loc getBelLocation(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
Loc loc;
@@ -784,24 +815,25 @@ struct Arch : BaseCtx
return loc;
}
- BelId getBelByLocation(Loc loc) const;
- BelRange getBelsByTile(int x, int y) const;
+ BelId getBelByLocation(Loc loc) const override;
+ BelRange getBelsByTile(int x, int y) const override;
- bool getBelGlobalBuf(BelId bel) const
+ bool getBelGlobalBuf(BelId bel) const override
{
// FIXME: This probably needs to be fixed!
return false;
}
+ // TODO: this needs to become part of the Arch API
bool getBelHidden(BelId bel) const { return bel_info(chip_info, bel).category != BEL_CATEGORY_LOGIC; }
- IdString getBelType(BelId bel) const
+ IdString getBelType(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return IdString(bel_info(chip_info, bel).type);
}
- std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const;
+ std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const override;
int get_bel_pin_index(BelId bel, IdString pin) const
{
@@ -817,10 +849,10 @@ struct Arch : BaseCtx
return -1;
}
- WireId getBelPinWire(BelId bel, IdString pin) const;
- PortType getBelPinType(BelId bel, IdString pin) const;
+ WireId getBelPinWire(BelId bel, IdString pin) const override;
+ PortType getBelPinType(BelId bel, IdString pin) const override;
- IdStringRange getBelPins(BelId bel) const
+ IdStringRange getBelPins(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
@@ -836,7 +868,7 @@ struct Arch : BaseCtx
// -------------------------------------------------
- WireId getWireByName(IdStringList name) const;
+ WireId getWireByName(IdStringList name) const override;
const TileWireInfoPOD &wire_info(WireId wire) const
{
@@ -848,7 +880,7 @@ struct Arch : BaseCtx
}
}
- IdStringList getWireName(WireId wire) const
+ IdStringList getWireName(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
if (wire.tile != -1) {
@@ -867,12 +899,12 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- IdString getWireType(WireId wire) const;
- std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const;
+ IdString getWireType(WireId wire) const override;
+ std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const override;
- uint32_t getWireChecksum(WireId wire) const { return wire.index; }
+ uint32_t getWireChecksum(WireId wire) const override { return wire.index; }
- void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
+ void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) override
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire] == nullptr);
@@ -882,7 +914,7 @@ struct Arch : BaseCtx
refreshUiWire(wire);
}
- void unbindWire(WireId wire)
+ void unbindWire(WireId wire) override
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire] != nullptr);
@@ -901,30 +933,30 @@ struct Arch : BaseCtx
refreshUiWire(wire);
}
- bool checkWireAvail(WireId wire) const
+ bool checkWireAvail(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
auto w2n = wire_to_net.find(wire);
return w2n == wire_to_net.end() || w2n->second == nullptr;
}
- NetInfo *getBoundWireNet(WireId wire) const
+ NetInfo *getBoundWireNet(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
auto w2n = wire_to_net.find(wire);
return w2n == wire_to_net.end() ? nullptr : w2n->second;
}
- WireId getConflictingWireWire(WireId wire) const { return wire; }
+ WireId getConflictingWireWire(WireId wire) const override { return wire; }
- NetInfo *getConflictingWireNet(WireId wire) const
+ NetInfo *getConflictingWireNet(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
auto w2n = wire_to_net.find(wire);
return w2n == wire_to_net.end() ? nullptr : w2n->second;
}
- DelayInfo getWireDelay(WireId wire) const
+ DelayInfo getWireDelay(WireId wire) const override
{
DelayInfo delay;
delay.delay = 0;
@@ -949,7 +981,7 @@ struct Arch : BaseCtx
return range;
}
- BelPinRange getWireBelPins(WireId wire) const
+ BelPinRange getWireBelPins(WireId wire) const override
{
BelPinRange range;
NPNR_ASSERT(wire != WireId());
@@ -968,7 +1000,7 @@ struct Arch : BaseCtx
return range;
}
- WireRange getWires() const
+ WireRange getWires() const override
{
WireRange range;
range.b.chip = chip_info;
@@ -982,12 +1014,12 @@ struct Arch : BaseCtx
// -------------------------------------------------
- PipId getPipByName(IdStringList name) const;
- IdStringList getPipName(PipId pip) const;
- IdString getPipType(PipId pip) const;
- std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
+ PipId getPipByName(IdStringList name) const override;
+ IdStringList getPipName(PipId pip) const override;
+ IdString getPipType(PipId pip) const override;
+ std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const override;
- void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
+ void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) override
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip] == nullptr);
@@ -1007,7 +1039,7 @@ struct Arch : BaseCtx
refreshUiWire(dst);
}
- void unbindPip(PipId pip)
+ void unbindPip(PipId pip) override
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip] != nullptr);
@@ -1022,28 +1054,28 @@ struct Arch : BaseCtx
refreshUiWire(dst);
}
- bool checkPipAvail(PipId pip) const
+ bool checkPipAvail(PipId pip) const override
{
NPNR_ASSERT(pip != PipId());
return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == nullptr;
}
- NetInfo *getBoundPipNet(PipId pip) const
+ NetInfo *getBoundPipNet(PipId pip) const override
{
NPNR_ASSERT(pip != PipId());
auto p2n = pip_to_net.find(pip);
return p2n == pip_to_net.end() ? nullptr : p2n->second;
}
- WireId getConflictingPipWire(PipId pip) const { return getPipDstWire(pip); }
+ WireId getConflictingPipWire(PipId pip) const override { return getPipDstWire(pip); }
- NetInfo *getConflictingPipNet(PipId pip) const
+ NetInfo *getConflictingPipNet(PipId pip) const override
{
auto p2n = pip_to_net.find(pip);
return p2n == pip_to_net.end() ? nullptr : p2n->second;
}
- AllPipRange getPips() const
+ AllPipRange getPips() const override
{
AllPipRange range;
range.b.cursor_tile = 0;
@@ -1056,7 +1088,7 @@ struct Arch : BaseCtx
return range;
}
- Loc getPipLocation(PipId pip) const
+ Loc getPipLocation(PipId pip) const override
{
Loc loc;
get_tile_loc(pip.tile, &loc);
@@ -1064,21 +1096,21 @@ struct Arch : BaseCtx
return loc;
}
- uint32_t getPipChecksum(PipId pip) const { return pip.index; }
+ uint32_t getPipChecksum(PipId pip) const override { return pip.index; }
- WireId getPipSrcWire(PipId pip) const
+ WireId getPipSrcWire(PipId pip) const override
{
return canonical_wire(chip_info, pip.tile, loc_info(chip_info, pip).pip_data[pip.index].src_index);
}
- WireId getPipDstWire(PipId pip) const
+ WireId getPipDstWire(PipId pip) const override
{
return canonical_wire(chip_info, pip.tile, loc_info(chip_info, pip).pip_data[pip.index].dst_index);
}
- DelayInfo getPipDelay(PipId pip) const { return DelayInfo(); }
+ DelayInfo getPipDelay(PipId pip) const override { return DelayInfo(); }
- DownhillPipRange getPipsDownhill(WireId wire) const
+ DownhillPipRange getPipsDownhill(WireId wire) const override
{
DownhillPipRange range;
NPNR_ASSERT(wire != WireId());
@@ -1095,7 +1127,7 @@ struct Arch : BaseCtx
return range;
}
- UphillPipRange getPipsUphill(WireId wire) const
+ UphillPipRange getPipsUphill(WireId wire) const override
{
UphillPipRange range;
NPNR_ASSERT(wire != WireId());
@@ -1115,58 +1147,57 @@ struct Arch : BaseCtx
// -------------------------------------------------
// FIXME: Use groups to get access to sites.
- GroupId getGroupByName(IdStringList name) const { return GroupId(); }
- IdStringList getGroupName(GroupId group) const { return IdStringList(); }
- std::vector<GroupId> getGroups() const { return {}; }
- std::vector<BelId> getGroupBels(GroupId group) const { return {}; }
- std::vector<WireId> getGroupWires(GroupId group) const { return {}; }
- std::vector<PipId> getGroupPips(GroupId group) const { return {}; }
- std::vector<GroupId> getGroupGroups(GroupId group) const { return {}; }
+ GroupId getGroupByName(IdStringList name) const override { return GroupId(); }
+ IdStringList getGroupName(GroupId group) const override { return IdStringList(); }
+ std::vector<GroupId> getGroups() const override { return {}; }
+ std::vector<BelId> getGroupBels(GroupId group) const override { return {}; }
+ std::vector<WireId> getGroupWires(GroupId group) const override { return {}; }
+ std::vector<PipId> getGroupPips(GroupId group) const override { return {}; }
+ std::vector<GroupId> getGroupGroups(GroupId group) const override { return {}; }
// -------------------------------------------------
- delay_t estimateDelay(WireId src, WireId dst, bool debug = false) const;
- delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
- ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
- delay_t getDelayEpsilon() const { return 20; }
- delay_t getRipupDelayPenalty() const { return 120; }
- delay_t getWireRipupDelayPenalty(WireId wire) const;
- float getDelayNS(delay_t v) const { return v * 0.001; }
- DelayInfo getDelayFromNS(float ns) const
+ delay_t estimateDelay(WireId src, WireId dst) const override;
+ delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
+ ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
+ delay_t getDelayEpsilon() const override { return 20; }
+ delay_t getRipupDelayPenalty() const override { return 120; }
+ float getDelayNS(delay_t v) const override { return v * 0.001; }
+ DelayInfo getDelayFromNS(float ns) const override
{
DelayInfo del;
del.delay = delay_t(ns * 1000);
return del;
}
- uint32_t getDelayChecksum(delay_t v) const { return v; }
- bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
+ uint32_t getDelayChecksum(delay_t v) const override { return v; }
+ bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override;
// -------------------------------------------------
- bool pack();
- bool place();
- bool route();
+ bool pack() override;
+ bool place() override;
+ bool route() override;
// -------------------------------------------------
- std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const override;
- DecalXY getBelDecal(BelId bel) const;
- DecalXY getWireDecal(WireId wire) const;
- DecalXY getPipDecal(PipId pip) const;
- DecalXY getGroupDecal(GroupId group) const;
+ DecalXY getBelDecal(BelId bel) const override;
+ DecalXY getWireDecal(WireId wire) const override;
+ DecalXY getPipDecal(PipId pip) const override;
+ DecalXY getGroupDecal(GroupId group) const override;
// -------------------------------------------------
// Get the delay through a cell from one port to another, returning false
// if no path exists. This only considers combinational delays, as required by the Arch API
- bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
+ bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override;
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
- TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override;
// Get the TimingClockingInfo of a port
- TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
+ TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override;
// -------------------------------------------------
- const BelBucketRange getBelBuckets() const
+ const BelBucketRange getBelBuckets() const override
{
BelBucketRange bel_bucket_range;
bel_bucket_range.b.cursor.cursor = chip_info->bel_buckets.begin();
@@ -1174,14 +1205,14 @@ struct Arch : BaseCtx
return bel_bucket_range;
}
- BelBucketId getBelBucketForBel(BelId bel) const
+ BelBucketId getBelBucketForBel(BelId bel) const override
{
BelBucketId bel_bucket;
bel_bucket.name = IdString(bel_info(chip_info, bel).bel_bucket);
return bel_bucket;
}
- const IdStringRange getCellTypes() const
+ const IdStringRange getCellTypes() const override
{
const CellMapPOD &cell_map = *chip_info->cell_map;
@@ -1192,9 +1223,9 @@ struct Arch : BaseCtx
return id_range;
}
- IdString getBelBucketName(BelBucketId bucket) const { return bucket.name; }
+ IdString getBelBucketName(BelBucketId bucket) const override { return bucket.name; }
- BelBucketId getBelBucketByName(IdString name) const
+ BelBucketId getBelBucketByName(IdString name) const override
{
for (BelBucketId bel_bucket : getBelBuckets()) {
if (bel_bucket.name == name) {
@@ -1206,7 +1237,7 @@ struct Arch : BaseCtx
return BelBucketId();
}
- size_t getCellTypeIndex(IdString cell_type) const
+ size_t get_cell_type_index(IdString cell_type) const
{
const CellMapPOD &cell_map = *chip_info->cell_map;
int cell_offset = cell_type.index - cell_map.cell_names[0];
@@ -1216,15 +1247,15 @@ struct Arch : BaseCtx
return cell_offset;
}
- BelBucketId getBelBucketForCellType(IdString cell_type) const
+ BelBucketId getBelBucketForCellType(IdString cell_type) const override
{
BelBucketId bucket;
const CellMapPOD &cell_map = *chip_info->cell_map;
- bucket.name = IdString(cell_map.cell_bel_buckets[getCellTypeIndex(cell_type)]);
+ bucket.name = IdString(cell_map.cell_bel_buckets[get_cell_type_index(cell_type)]);
return bucket;
}
- FilteredBelRange getBelsInBucket(BelBucketId bucket) const
+ FilteredBelRange getBelsInBucket(BelBucketId bucket) const override
{
BelRange range = getBels();
FilteredBelRange filtered_range(range.begin(), range.end(),
@@ -1233,15 +1264,15 @@ struct Arch : BaseCtx
return filtered_range;
}
- bool isValidBelForCellType(IdString cell_type, BelId bel) const
+ bool isValidBelForCellType(IdString cell_type, BelId bel) const override
{
- return bel_info(chip_info, bel).valid_cells[getCellTypeIndex(cell_type)];
+ return bel_info(chip_info, bel).valid_cells[get_cell_type_index(cell_type)];
}
// Whether or not a given cell can be placed at a given Bel
// This is not intended for Bel type checks, but finer-grained constraints
// such as conflicting set/reset signals, etc
- bool isValidBelForCell(CellInfo *cell, BelId bel) const
+ bool isValidBelForCell(CellInfo *cell, BelId bel) const override
{
NPNR_ASSERT(isValidBelForCellType(cell->type, bel));
@@ -1250,17 +1281,17 @@ struct Arch : BaseCtx
}
// Return true whether all Bels at a given location are valid
- bool isBelLocationValid(BelId bel) const
+ bool isBelLocationValid(BelId bel) const override
{
// FIXME: Implement this
return true;
}
- IdString getBelTileType(BelId bel) const { return IdString(loc_info(chip_info, bel).name); }
+ IdString get_bel_tiletype(BelId bel) const { return IdString(loc_info(chip_info, bel).name); }
std::unordered_map<WireId, Loc> sink_locs, source_locs;
// -------------------------------------------------
- void assignArchInfo() {}
+ void assignArchInfo() override {}
// -------------------------------------------------
diff --git a/generic/arch.h b/generic/arch.h
index d7392e41..09fd8e34 100644
--- a/generic/arch.h
+++ b/generic/arch.h
@@ -116,7 +116,38 @@ struct CellTiming
std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo;
};
-struct Arch : BaseCtx
+struct ArchRanges
+{
+ using ArchArgsT = ArchArgs;
+ // Bels
+ using AllBelsRangeT = const std::vector<BelId> &;
+ using TileBelsRangeT = const std::vector<BelId> &;
+ using BelAttrsRangeT = const std::map<IdString, std::string> &;
+ using BelPinsRangeT = std::vector<IdString>;
+ // Wires
+ using AllWiresRangeT = const std::vector<WireId> &;
+ using DownhillPipRangeT = const std::vector<PipId> &;
+ using UphillPipRangeT = const std::vector<PipId> &;
+ using WireBelPinRangeT = const std::vector<BelPin> &;
+ using WireAttrsRangeT = const std::map<IdString, std::string> &;
+ // Pips
+ using AllPipsRangeT = const std::vector<PipId> &;
+ using PipAttrsRangeT = const std::map<IdString, std::string> &;
+ // Groups
+ using AllGroupsRangeT = std::vector<GroupId>;
+ using GroupBelsRangeT = const std::vector<BelId> &;
+ using GroupWiresRangeT = const std::vector<WireId> &;
+ using GroupPipsRangeT = const std::vector<PipId> &;
+ using GroupGroupsRangeT = const std::vector<GroupId> &;
+ // Decals
+ using DecalGfxRangeT = const std::vector<GraphicElement> &;
+ // Placement validity
+ using CellTypeRangeT = std::vector<IdString>;
+ using BelBucketRangeT = std::vector<BelBucketId>;
+ using BucketBelRangeT = std::vector<BelId>;
+};
+
+struct Arch : ArchAPI<ArchRanges>
{
std::string chipName;
@@ -180,102 +211,102 @@ struct Arch : BaseCtx
ArchArgs args;
Arch(ArchArgs args);
- std::string getChipName() const { return chipName; }
-
- IdString archId() const { return id("generic"); }
- ArchArgs archArgs() const { return args; }
- IdString archArgsToId(ArchArgs args) const { return id("none"); }
-
- int getGridDimX() const { return gridDimX; }
- int getGridDimY() const { return gridDimY; }
- int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; }
- int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; }
- char getNameDelimiter() const { return '/'; }
-
- BelId getBelByName(IdStringList name) const;
- IdStringList getBelName(BelId bel) const;
- Loc getBelLocation(BelId bel) const;
- BelId getBelByLocation(Loc loc) const;
- const std::vector<BelId> &getBelsByTile(int x, int y) const;
- bool getBelGlobalBuf(BelId bel) const;
- uint32_t getBelChecksum(BelId bel) const;
- void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength);
- void unbindBel(BelId bel);
- bool checkBelAvail(BelId bel) const;
- CellInfo *getBoundBelCell(BelId bel) const;
- CellInfo *getConflictingBelCell(BelId bel) const;
- const std::vector<BelId> &getBels() const;
- IdString getBelType(BelId bel) const;
- const std::map<IdString, std::string> &getBelAttrs(BelId bel) const;
- WireId getBelPinWire(BelId bel, IdString pin) const;
- PortType getBelPinType(BelId bel, IdString pin) const;
- std::vector<IdString> getBelPins(BelId bel) const;
-
- WireId getWireByName(IdStringList name) const;
- IdStringList getWireName(WireId wire) const;
- IdString getWireType(WireId wire) const;
- const std::map<IdString, std::string> &getWireAttrs(WireId wire) const;
- uint32_t getWireChecksum(WireId wire) const;
- void bindWire(WireId wire, NetInfo *net, PlaceStrength strength);
- void unbindWire(WireId wire);
- bool checkWireAvail(WireId wire) const;
- NetInfo *getBoundWireNet(WireId wire) const;
- WireId getConflictingWireWire(WireId wire) const { return wire; }
- NetInfo *getConflictingWireNet(WireId wire) const;
- DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); }
- const std::vector<WireId> &getWires() const;
- const std::vector<BelPin> &getWireBelPins(WireId wire) const;
-
- PipId getPipByName(IdStringList name) const;
- IdStringList getPipName(PipId pip) const;
- IdString getPipType(PipId pip) const;
- const std::map<IdString, std::string> &getPipAttrs(PipId pip) const;
- uint32_t getPipChecksum(PipId pip) const;
- void bindPip(PipId pip, NetInfo *net, PlaceStrength strength);
- void unbindPip(PipId pip);
- bool checkPipAvail(PipId pip) const;
- NetInfo *getBoundPipNet(PipId pip) const;
- WireId getConflictingPipWire(PipId pip) const;
- NetInfo *getConflictingPipNet(PipId pip) const;
- const std::vector<PipId> &getPips() const;
- Loc getPipLocation(PipId pip) const;
- WireId getPipSrcWire(PipId pip) const;
- WireId getPipDstWire(PipId pip) const;
- DelayInfo getPipDelay(PipId pip) const;
- const std::vector<PipId> &getPipsDownhill(WireId wire) const;
- const std::vector<PipId> &getPipsUphill(WireId wire) const;
-
- GroupId getGroupByName(IdStringList name) const;
- IdStringList getGroupName(GroupId group) const;
- std::vector<GroupId> getGroups() const;
- const std::vector<BelId> &getGroupBels(GroupId group) const;
- const std::vector<WireId> &getGroupWires(GroupId group) const;
- const std::vector<PipId> &getGroupPips(GroupId group) const;
- const std::vector<GroupId> &getGroupGroups(GroupId group) const;
-
- delay_t estimateDelay(WireId src, WireId dst) const;
- delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
- delay_t getDelayEpsilon() const { return 0.001; }
- delay_t getRipupDelayPenalty() const { return 0.015; }
- float getDelayNS(delay_t v) const { return v; }
-
- DelayInfo getDelayFromNS(float ns) const
+ std::string getChipName() const override { return chipName; }
+
+ IdString archId() const override { return id("generic"); }
+ ArchArgs archArgs() const override { return args; }
+ IdString archArgsToId(ArchArgs args) const override { return id("none"); }
+
+ int getGridDimX() const override { return gridDimX; }
+ int getGridDimY() const override { return gridDimY; }
+ int getTileBelDimZ(int x, int y) const override { return tileBelDimZ[x][y]; }
+ int getTilePipDimZ(int x, int y) const override { return tilePipDimZ[x][y]; }
+ char getNameDelimiter() const override { return '/'; }
+
+ BelId getBelByName(IdStringList name) const override;
+ IdStringList getBelName(BelId bel) const override;
+ Loc getBelLocation(BelId bel) const override;
+ BelId getBelByLocation(Loc loc) const override;
+ const std::vector<BelId> &getBelsByTile(int x, int y) const override;
+ bool getBelGlobalBuf(BelId bel) const override;
+ uint32_t getBelChecksum(BelId bel) const override;
+ void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) override;
+ void unbindBel(BelId bel) override;
+ bool checkBelAvail(BelId bel) const override;
+ CellInfo *getBoundBelCell(BelId bel) const override;
+ CellInfo *getConflictingBelCell(BelId bel) const override;
+ const std::vector<BelId> &getBels() const override;
+ IdString getBelType(BelId bel) const override;
+ const std::map<IdString, std::string> &getBelAttrs(BelId bel) const override;
+ WireId getBelPinWire(BelId bel, IdString pin) const override;
+ PortType getBelPinType(BelId bel, IdString pin) const override;
+ std::vector<IdString> getBelPins(BelId bel) const override;
+
+ WireId getWireByName(IdStringList name) const override;
+ IdStringList getWireName(WireId wire) const override;
+ IdString getWireType(WireId wire) const override;
+ const std::map<IdString, std::string> &getWireAttrs(WireId wire) const override;
+ uint32_t getWireChecksum(WireId wire) const override;
+ void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) override;
+ void unbindWire(WireId wire) override;
+ bool checkWireAvail(WireId wire) const override;
+ NetInfo *getBoundWireNet(WireId wire) const override;
+ WireId getConflictingWireWire(WireId wire) const override { return wire; }
+ NetInfo *getConflictingWireNet(WireId wire) const override;
+ DelayInfo getWireDelay(WireId wire) const override { return DelayInfo(); }
+ const std::vector<WireId> &getWires() const override;
+ const std::vector<BelPin> &getWireBelPins(WireId wire) const override;
+
+ PipId getPipByName(IdStringList name) const override;
+ IdStringList getPipName(PipId pip) const override;
+ IdString getPipType(PipId pip) const override;
+ const std::map<IdString, std::string> &getPipAttrs(PipId pip) const override;
+ uint32_t getPipChecksum(PipId pip) const override;
+ void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) override;
+ void unbindPip(PipId pip) override;
+ bool checkPipAvail(PipId pip) const override;
+ NetInfo *getBoundPipNet(PipId pip) const override;
+ WireId getConflictingPipWire(PipId pip) const override;
+ NetInfo *getConflictingPipNet(PipId pip) const override;
+ const std::vector<PipId> &getPips() const override;
+ Loc getPipLocation(PipId pip) const override;
+ WireId getPipSrcWire(PipId pip) const override;
+ WireId getPipDstWire(PipId pip) const override;
+ DelayInfo getPipDelay(PipId pip) const override;
+ const std::vector<PipId> &getPipsDownhill(WireId wire) const override;
+ const std::vector<PipId> &getPipsUphill(WireId wire) const override;
+
+ GroupId getGroupByName(IdStringList name) const override;
+ IdStringList getGroupName(GroupId group) const override;
+ std::vector<GroupId> getGroups() const override;
+ const std::vector<BelId> &getGroupBels(GroupId group) const override;
+ const std::vector<WireId> &getGroupWires(GroupId group) const override;
+ const std::vector<PipId> &getGroupPips(GroupId group) const override;
+ const std::vector<GroupId> &getGroupGroups(GroupId group) const override;
+
+ delay_t estimateDelay(WireId src, WireId dst) const override;
+ delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
+ delay_t getDelayEpsilon() const override { return 0.001; }
+ delay_t getRipupDelayPenalty() const override { return 0.015; }
+ float getDelayNS(delay_t v) const override { return v; }
+
+ DelayInfo getDelayFromNS(float ns) const override
{
DelayInfo del;
del.delay = ns;
return del;
}
- uint32_t getDelayChecksum(delay_t v) const { return 0; }
- bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
+ uint32_t getDelayChecksum(delay_t v) const override { return 0; }
+ bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override;
- ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
+ ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
- bool pack();
- bool place();
- bool route();
+ bool pack() override;
+ bool place() override;
+ bool route() override;
- std::vector<IdString> getCellTypes() const
+ std::vector<IdString> getCellTypes() const override
{
std::unordered_set<IdString> cell_types;
for (auto bel : bels) {
@@ -285,17 +316,17 @@ struct Arch : BaseCtx
return std::vector<IdString>{cell_types.begin(), cell_types.end()};
}
- std::vector<BelBucketId> getBelBuckets() const { return getCellTypes(); }
+ std::vector<BelBucketId> getBelBuckets() const override { return getCellTypes(); }
- IdString getBelBucketName(BelBucketId bucket) const { return bucket; }
+ IdString getBelBucketName(BelBucketId bucket) const override { return bucket; }
- BelBucketId getBelBucketByName(IdString bucket) const { return bucket; }
+ BelBucketId getBelBucketByName(IdString bucket) const override { return bucket; }
- BelBucketId getBelBucketForBel(BelId bel) const { return getBelType(bel); }
+ BelBucketId getBelBucketForBel(BelId bel) const override { return getBelType(bel); }
- BelBucketId getBelBucketForCellType(IdString cell_type) const { return cell_type; }
+ BelBucketId getBelBucketForCellType(IdString cell_type) const override { return cell_type; }
- std::vector<BelId> getBelsInBucket(BelBucketId bucket) const
+ std::vector<BelId> getBelsInBucket(BelBucketId bucket) const override
{
std::vector<BelId> bels;
for (BelId bel : getBels()) {
@@ -306,21 +337,21 @@ struct Arch : BaseCtx
return bels;
}
- const std::vector<GraphicElement> &getDecalGraphics(DecalId decal) const;
- DecalXY getBelDecal(BelId bel) const;
- DecalXY getWireDecal(WireId wire) const;
- DecalXY getPipDecal(PipId pip) const;
- DecalXY getGroupDecal(GroupId group) const;
+ const std::vector<GraphicElement> &getDecalGraphics(DecalId decal) const override;
+ DecalXY getBelDecal(BelId bel) const override;
+ DecalXY getWireDecal(WireId wire) const override;
+ DecalXY getPipDecal(PipId pip) const override;
+ DecalXY getGroupDecal(GroupId group) const override;
- bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
+ bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override;
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
- TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override;
// Get the TimingClockingInfo of a port
- TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
+ TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override;
- bool isValidBelForCellType(IdString cell_type, BelId bel) const { return cell_type == getBelType(bel); }
- bool isValidBelForCell(CellInfo *cell, BelId bel) const;
- bool isBelLocationValid(BelId bel) const;
+ bool isValidBelForCellType(IdString cell_type, BelId bel) const override { return cell_type == getBelType(bel); }
+ bool isValidBelForCell(CellInfo *cell, BelId bel) const override;
+ bool isBelLocationValid(BelId bel) const override;
static const std::string defaultPlacer;
static const std::vector<std::string> availablePlacers;
@@ -329,7 +360,7 @@ struct Arch : BaseCtx
// ---------------------------------------------------------------
// Internal usage
- void assignArchInfo();
+ void assignArchInfo() override;
bool cellsCompatible(const CellInfo **cells, int count) const;
};
diff --git a/gowin/arch.cc b/gowin/arch.cc
index e266c9b5..d4e17a8a 100644
--- a/gowin/arch.cc
+++ b/gowin/arch.cc
@@ -736,17 +736,8 @@ Arch::Arch(ArchArgs args) : args(args)
}
}
}
- // Dummy for empty decals
- decal_graphics[IdString()];
-
- std::unordered_set<IdString> bel_types;
- for (BelId bel : getBels()) {
- bel_types.insert(getBelType(bel));
- }
-
- for (IdString bel_type : bel_types) {
- cell_types.push_back(bel_type);
- }
+ BaseArch::init_cell_types();
+ BaseArch::init_bel_buckets();
}
void IdString::initialize_arch(const BaseCtx *ctx)
@@ -785,8 +776,6 @@ const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const { return bels_
bool Arch::getBelGlobalBuf(BelId bel) const { return bels.at(bel).gb; }
-uint32_t Arch::getBelChecksum(BelId bel) const { return bel.index; }
-
void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
{
bels.at(bel).bound_cell = cell;
@@ -848,12 +837,6 @@ IdString Arch::getWireType(WireId wire) const { return wires.at(wire).type; }
const std::map<IdString, std::string> &Arch::getWireAttrs(WireId wire) const { return wires.at(wire).attrs; }
-uint32_t Arch::getWireChecksum(WireId wire) const
-{
- // FIXME
- return 0;
-}
-
void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
{
wires.at(wire).bound_net = net;
@@ -902,8 +885,6 @@ IdString Arch::getPipType(PipId pip) const { return pips.at(pip).type; }
const std::map<IdString, std::string> &Arch::getPipAttrs(PipId pip) const { return pips.at(pip).attrs; }
-uint32_t Arch::getPipChecksum(PipId wire) const { return wire.index; }
-
void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{
WireId wire = pips.at(pip).dstWire;
@@ -1074,25 +1055,6 @@ bool Arch::route()
// ---------------------------------------------------------------
-const std::vector<GraphicElement> &Arch::getDecalGraphics(DecalId decal) const
-{
- if (!decal_graphics.count(decal)) {
- std::cerr << "No decal named " << decal.str(this) << std::endl;
- log_error("No decal named %s!\n", decal.c_str(this));
- }
- return decal_graphics.at(decal);
-}
-
-DecalXY Arch::getBelDecal(BelId bel) const { return bels.at(bel).decalxy; }
-
-DecalXY Arch::getWireDecal(WireId wire) const { return wires.at(wire).decalxy; }
-
-DecalXY Arch::getPipDecal(PipId pip) const { return pips.at(pip).decalxy; }
-
-DecalXY Arch::getGroupDecal(GroupId group) const { return groups.at(group).decalxy; }
-
-// ---------------------------------------------------------------
-
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const
{
if (!cellTiming.count(cell->name))
diff --git a/gowin/arch.h b/gowin/arch.h
index 4754772b..c5ef0a2e 100644
--- a/gowin/arch.h
+++ b/gowin/arch.h
@@ -243,7 +243,38 @@ struct CellTiming
std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo;
};
-struct Arch : BaseCtx
+struct ArchRanges
+{
+ using ArchArgsT = ArchArgs;
+ // Bels
+ using AllBelsRangeT = const std::vector<BelId> &;
+ using TileBelsRangeT = const std::vector<BelId> &;
+ using BelAttrsRangeT = const std::map<IdString, std::string> &;
+ using BelPinsRangeT = std::vector<IdString>;
+ // Wires
+ using AllWiresRangeT = const std::vector<WireId> &;
+ using DownhillPipRangeT = const std::vector<PipId> &;
+ using UphillPipRangeT = const std::vector<PipId> &;
+ using WireBelPinRangeT = const std::vector<BelPin> &;
+ using WireAttrsRangeT = const std::map<IdString, std::string> &;
+ // Pips
+ using AllPipsRangeT = const std::vector<PipId> &;
+ using PipAttrsRangeT = const std::map<IdString, std::string> &;
+ // Groups
+ using AllGroupsRangeT = std::vector<GroupId>;
+ using GroupBelsRangeT = const std::vector<BelId> &;
+ using GroupWiresRangeT = const std::vector<WireId> &;
+ using GroupPipsRangeT = const std::vector<PipId> &;
+ using GroupGroupsRangeT = const std::vector<GroupId> &;
+ // Decals
+ using DecalGfxRangeT = const std::vector<GraphicElement> &;
+ // Placement validity
+ using CellTypeRangeT = std::vector<IdString>;
+ using BelBucketRangeT = std::vector<BelBucketId>;
+ using BucketBelRangeT = std::vector<BelId>;
+};
+
+struct Arch : BaseArch<ArchRanges>
{
std::string family;
std::string device;
@@ -313,14 +344,13 @@ struct Arch : BaseCtx
ArchArgs args;
Arch(ArchArgs args);
- std::string getChipName() const { return device; }
+ std::string getChipName() const override { return device; }
- IdString archId() const { return id("gowin"); }
- ArchArgs archArgs() const { return args; }
- IdString archArgsToId(ArchArgs args) const { return id("none"); }
+ ArchArgs archArgs() const override { return args; }
+ IdString archArgsToId(ArchArgs args) const override { return id("none"); }
- int getGridDimX() const { return gridDimX; }
- int getGridDimY() const { return gridDimY; }
+ int getGridDimX() const override { return gridDimX; }
+ int getGridDimY() const override { return gridDimY; }
int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; }
int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; }
char getNameDelimiter() const
@@ -328,74 +358,71 @@ struct Arch : BaseCtx
return ' '; /* use a non-existent delimiter as we aren't using IdStringLists yet */
}
- BelId getBelByName(IdStringList name) const;
- IdStringList getBelName(BelId bel) const;
- Loc getBelLocation(BelId bel) const;
- BelId getBelByLocation(Loc loc) const;
- const std::vector<BelId> &getBelsByTile(int x, int y) const;
- bool getBelGlobalBuf(BelId bel) const;
- uint32_t getBelChecksum(BelId bel) const;
- void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength);
- void unbindBel(BelId bel);
- bool checkBelAvail(BelId bel) const;
- CellInfo *getBoundBelCell(BelId bel) const;
- CellInfo *getConflictingBelCell(BelId bel) const;
- const std::vector<BelId> &getBels() const;
- IdString getBelType(BelId bel) const;
- const std::map<IdString, std::string> &getBelAttrs(BelId bel) const;
- WireId getBelPinWire(BelId bel, IdString pin) const;
- PortType getBelPinType(BelId bel, IdString pin) const;
- std::vector<IdString> getBelPins(BelId bel) const;
-
- WireId getWireByName(IdStringList name) const;
- IdStringList getWireName(WireId wire) const;
- IdString getWireType(WireId wire) const;
- const std::map<IdString, std::string> &getWireAttrs(WireId wire) const;
- uint32_t getWireChecksum(WireId wire) const;
- void bindWire(WireId wire, NetInfo *net, PlaceStrength strength);
- void unbindWire(WireId wire);
- bool checkWireAvail(WireId wire) const;
- NetInfo *getBoundWireNet(WireId wire) const;
- WireId getConflictingWireWire(WireId wire) const { return wire; }
- NetInfo *getConflictingWireNet(WireId wire) const;
- DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); }
- const std::vector<WireId> &getWires() const;
- const std::vector<BelPin> &getWireBelPins(WireId wire) const;
-
- PipId getPipByName(IdStringList name) const;
- IdStringList getPipName(PipId pip) const;
- IdString getPipType(PipId pip) const;
- const std::map<IdString, std::string> &getPipAttrs(PipId pip) const;
- uint32_t getPipChecksum(PipId pip) const;
- void bindPip(PipId pip, NetInfo *net, PlaceStrength strength);
- void unbindPip(PipId pip);
- bool checkPipAvail(PipId pip) const;
- NetInfo *getBoundPipNet(PipId pip) const;
- WireId getConflictingPipWire(PipId pip) const;
- NetInfo *getConflictingPipNet(PipId pip) const;
- const std::vector<PipId> &getPips() const;
- Loc getPipLocation(PipId pip) const;
- WireId getPipSrcWire(PipId pip) const;
- WireId getPipDstWire(PipId pip) const;
- DelayInfo getPipDelay(PipId pip) const;
- const std::vector<PipId> &getPipsDownhill(WireId wire) const;
- const std::vector<PipId> &getPipsUphill(WireId wire) const;
-
- GroupId getGroupByName(IdStringList name) const;
- IdStringList getGroupName(GroupId group) const;
- std::vector<GroupId> getGroups() const;
- const std::vector<BelId> &getGroupBels(GroupId group) const;
- const std::vector<WireId> &getGroupWires(GroupId group) const;
- const std::vector<PipId> &getGroupPips(GroupId group) const;
- const std::vector<GroupId> &getGroupGroups(GroupId group) const;
-
- delay_t estimateDelay(WireId src, WireId dst) const;
- delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
- delay_t getDelayEpsilon() const { return 0.01; }
- delay_t getRipupDelayPenalty() const { return 0.4; }
- float getDelayNS(delay_t v) const { return v; }
-
- DelayInfo getDelayFromNS(float ns) const
+ BelId getBelByName(IdStringList name) const override;
+ IdStringList getBelName(BelId bel) const override;
+ Loc getBelLocation(BelId bel) const override;
+ BelId getBelByLocation(Loc loc) const override;
+ const std::vector<BelId> &getBelsByTile(int x, int y) const override;
+ bool getBelGlobalBuf(BelId bel) const override;
+ void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) override;
+ void unbindBel(BelId bel) override;
+ bool checkBelAvail(BelId bel) const override;
+ CellInfo *getBoundBelCell(BelId bel) const override;
+ CellInfo *getConflictingBelCell(BelId bel) const override;
+ const std::vector<BelId> &getBels() const override;
+ IdString getBelType(BelId bel) const override;
+ const std::map<IdString, std::string> &getBelAttrs(BelId bel) const override;
+ WireId getBelPinWire(BelId bel, IdString pin) const override;
+ PortType getBelPinType(BelId bel, IdString pin) const override;
+ std::vector<IdString> getBelPins(BelId bel) const override;
+
+ WireId getWireByName(IdStringList name) const override;
+ IdStringList getWireName(WireId wire) const override;
+ IdString getWireType(WireId wire) const override;
+ const std::map<IdString, std::string> &getWireAttrs(WireId wire) const override;
+ void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) override;
+ void unbindWire(WireId wire) override;
+ bool checkWireAvail(WireId wire) const override;
+ NetInfo *getBoundWireNet(WireId wire) const override;
+ WireId getConflictingWireWire(WireId wire) const override { return wire; }
+ NetInfo *getConflictingWireNet(WireId wire) const override;
+ DelayInfo getWireDelay(WireId wire) const override { return DelayInfo(); }
+ const std::vector<WireId> &getWires() const override;
+ const std::vector<BelPin> &getWireBelPins(WireId wire) const override;
+
+ PipId getPipByName(IdStringList name) const override;
+ IdStringList getPipName(PipId pip) const override;
+ IdString getPipType(PipId pip) const override;
+ const std::map<IdString, std::string> &getPipAttrs(PipId pip) const override;
+ void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) override;
+ void unbindPip(PipId pip) override;
+ bool checkPipAvail(PipId pip) const override;
+ NetInfo *getBoundPipNet(PipId pip) const override;
+ WireId getConflictingPipWire(PipId pip) const override;
+ NetInfo *getConflictingPipNet(PipId pip) const override;
+ const std::vector<PipId> &getPips() const override;
+ Loc getPipLocation(PipId pip) const override;
+ WireId getPipSrcWire(PipId pip) const override;
+ WireId getPipDstWire(PipId pip) const override;
+ DelayInfo getPipDelay(PipId pip) const override;
+ const std::vector<PipId> &getPipsDownhill(WireId wire) const override;
+ const std::vector<PipId> &getPipsUphill(WireId wire) const override;
+
+ GroupId getGroupByName(IdStringList name) const override;
+ IdStringList getGroupName(GroupId group) const override;
+ std::vector<GroupId> getGroups() const override;
+ const std::vector<BelId> &getGroupBels(GroupId group) const override;
+ const std::vector<WireId> &getGroupWires(GroupId group) const override;
+ const std::vector<PipId> &getGroupPips(GroupId group) const override;
+ const std::vector<GroupId> &getGroupGroups(GroupId group) const override;
+
+ delay_t estimateDelay(WireId src, WireId dst) const override;
+ delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
+ delay_t getDelayEpsilon() const override { return 0.01; }
+ delay_t getRipupDelayPenalty() const override { return 0.4; }
+ float getDelayNS(delay_t v) const override { return v; }
+
+ DelayInfo getDelayFromNS(float ns) const override
{
DelayInfo del;
del.maxRaise = ns;
@@ -405,20 +432,14 @@ struct Arch : BaseCtx
return del;
}
- uint32_t getDelayChecksum(delay_t v) const { return 0; }
- bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
-
- ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
+ uint32_t getDelayChecksum(delay_t v) const override { return 0; }
+ bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override;
- bool pack();
- bool place();
- bool route();
+ ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
- const std::vector<GraphicElement> &getDecalGraphics(DecalId decal) const;
- DecalXY getBelDecal(BelId bel) const;
- DecalXY getWireDecal(WireId wire) const;
- DecalXY getPipDecal(PipId pip) const;
- DecalXY getGroupDecal(GroupId group) const;
+ bool pack() override;
+ bool place() override;
+ bool route() override;
bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
@@ -426,31 +447,6 @@ struct Arch : BaseCtx
// Get the TimingClockingInfo of a port
TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
- bool isValidBelForCellType(IdString cell_type, BelId bel) const { return cell_type == getBelType(bel); }
-
- const std::vector<IdString> &getCellTypes() const { return cell_types; }
-
- std::vector<BelBucketId> getBelBuckets() const { return cell_types; }
-
- IdString getBelBucketName(BelBucketId bucket) const { return bucket; }
-
- BelBucketId getBelBucketByName(IdString name) const { return name; }
-
- BelBucketId getBelBucketForBel(BelId bel) const { return getBelType(bel); }
-
- BelBucketId getBelBucketForCellType(IdString cell_type) const { return cell_type; }
-
- std::vector<BelId> getBelsInBucket(BelBucketId bucket) const
- {
- std::vector<BelId> bels;
- for (BelId bel : getBels()) {
- if (getBelType(bel) == bucket) {
- bels.push_back(bel);
- }
- }
- return bels;
- }
-
bool isValidBelForCell(CellInfo *cell, BelId bel) const;
bool isBelLocationValid(BelId bel) const;
diff --git a/ice40/arch.cc b/ice40/arch.cc
index b7a87842..5b59fea4 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -127,18 +127,8 @@ Arch::Arch(ArchArgs args) : args(args)
pip_to_net.resize(chip_info->pip_data.size());
switches_locked.resize(chip_info->num_switches);
- std::unordered_set<IdString> bel_types;
- for (BelId bel : getBels()) {
- bel_types.insert(getBelType(bel));
- }
-
- for (IdString bel_type : bel_types) {
- cell_types.push_back(bel_type);
-
- BelBucketId bucket;
- bucket.name = bel_type;
- buckets.push_back(bucket);
- }
+ BaseArch::init_cell_types();
+ BaseArch::init_bel_buckets();
}
// -----------------------------------------------------------------------
diff --git a/ice40/arch.h b/ice40/arch.h
index 74e835ab..85182a60 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -374,7 +374,38 @@ struct ArchArgs
std::string package;
};
-struct Arch : BaseCtx
+struct ArchRanges
+{
+ using ArchArgsT = ArchArgs;
+ // Bels
+ using AllBelsRangeT = BelRange;
+ using TileBelsRangeT = BelRange;
+ using BelAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ using BelPinsRangeT = std::vector<IdString>;
+ // Wires
+ using AllWiresRangeT = WireRange;
+ using DownhillPipRangeT = PipRange;
+ using UphillPipRangeT = PipRange;
+ using WireBelPinRangeT = BelPinRange;
+ using WireAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Pips
+ using AllPipsRangeT = AllPipRange;
+ using PipAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Groups
+ using AllGroupsRangeT = std::vector<GroupId>;
+ using GroupBelsRangeT = std::vector<BelId>;
+ using GroupWiresRangeT = std::vector<WireId>;
+ using GroupPipsRangeT = std::vector<PipId>;
+ using GroupGroupsRangeT = std::vector<GroupId>;
+ // Decals
+ using DecalGfxRangeT = std::vector<GraphicElement>;
+ // Placement validity
+ using CellTypeRangeT = const std::vector<IdString> &;
+ using BelBucketRangeT = const std::vector<BelBucketId> &;
+ using BucketBelRangeT = const std::vector<BelId> &;
+};
+
+struct Arch : BaseArch<ArchRanges>
{
bool fast_part;
const ChipInfoPOD *chip_info;
@@ -402,25 +433,24 @@ struct Arch : BaseCtx
static bool is_available(ArchArgs::ArchArgsTypes chip);
static std::vector<std::string> get_supported_packages(ArchArgs::ArchArgsTypes chip);
- std::string getChipName() const;
+ std::string getChipName() const override;
- IdString archId() const { return id("ice40"); }
- ArchArgs archArgs() const { return args; }
- IdString archArgsToId(ArchArgs args) const;
+ ArchArgs archArgs() const override { return args; }
+ IdString archArgsToId(ArchArgs args) const override;
// -------------------------------------------------
- int getGridDimX() const { return chip_info->width; }
- int getGridDimY() const { return chip_info->height; }
- int getTileBelDimZ(int, int) const { return 8; }
- int getTilePipDimZ(int, int) const { return 1; }
- char getNameDelimiter() const { return '/'; }
+ int getGridDimX() const override { return chip_info->width; }
+ int getGridDimY() const override { return chip_info->height; }
+ int getTileBelDimZ(int, int) const override { return 8; }
+ int getTilePipDimZ(int, int) const override { return 1; }
+ char getNameDelimiter() const override { return '/'; }
// -------------------------------------------------
- BelId getBelByName(IdStringList name) const;
+ BelId getBelByName(IdStringList name) const override;
- IdStringList getBelName(BelId bel) const
+ IdStringList getBelName(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
auto &data = chip_info->bel_data[bel.index];
@@ -428,9 +458,7 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- uint32_t getBelChecksum(BelId bel) const { return bel.index; }
-
- void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
+ void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) override
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] == nullptr);
@@ -442,7 +470,7 @@ struct Arch : BaseCtx
refreshUiBel(bel);
}
- void unbindBel(BelId bel)
+ void unbindBel(BelId bel) override
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] != nullptr);
@@ -453,25 +481,25 @@ struct Arch : BaseCtx
refreshUiBel(bel);
}
- bool checkBelAvail(BelId bel) const
+ bool checkBelAvail(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index] == nullptr;
}
- CellInfo *getBoundBelCell(BelId bel) const
+ CellInfo *getBoundBelCell(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index];
}
- CellInfo *getConflictingBelCell(BelId bel) const
+ CellInfo *getConflictingBelCell(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index];
}
- BelRange getBels() const
+ BelRange getBels() const override
{
BelRange range;
range.b.cursor = 0;
@@ -479,7 +507,7 @@ struct Arch : BaseCtx
return range;
}
- Loc getBelLocation(BelId bel) const
+ Loc getBelLocation(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
Loc loc;
@@ -489,30 +517,30 @@ struct Arch : BaseCtx
return loc;
}
- BelId getBelByLocation(Loc loc) const;
- BelRange getBelsByTile(int x, int y) const;
+ BelId getBelByLocation(Loc loc) const override;
+ BelRange getBelsByTile(int x, int y) const override;
- bool getBelGlobalBuf(BelId bel) const { return chip_info->bel_data[bel.index].type == ID_SB_GB; }
+ bool getBelGlobalBuf(BelId bel) const override { return chip_info->bel_data[bel.index].type == ID_SB_GB; }
- IdString getBelType(BelId bel) const
+ IdString getBelType(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return IdString(chip_info->bel_data[bel.index].type);
}
- std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const;
+ std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const override;
- WireId getBelPinWire(BelId bel, IdString pin) const;
- PortType getBelPinType(BelId bel, IdString pin) const;
- std::vector<IdString> getBelPins(BelId bel) const;
+ WireId getBelPinWire(BelId bel, IdString pin) const override;
+ PortType getBelPinType(BelId bel, IdString pin) const override;
+ std::vector<IdString> getBelPins(BelId bel) const override;
bool is_bel_locked(BelId bel) const;
// -------------------------------------------------
- WireId getWireByName(IdStringList name) const;
+ WireId getWireByName(IdStringList name) const override;
- IdStringList getWireName(WireId wire) const
+ IdStringList getWireName(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
auto &data = chip_info->wire_data[wire.index];
@@ -520,12 +548,10 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- IdString getWireType(WireId wire) const;
- std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const;
+ IdString getWireType(WireId wire) const override;
+ std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const override;
- uint32_t getWireChecksum(WireId wire) const { return wire.index; }
-
- void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
+ void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) override
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] == nullptr);
@@ -535,7 +561,7 @@ struct Arch : BaseCtx
refreshUiWire(wire);
}
- void unbindWire(WireId wire)
+ void unbindWire(WireId wire) override
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] != nullptr);
@@ -555,27 +581,19 @@ struct Arch : BaseCtx
refreshUiWire(wire);
}
- bool checkWireAvail(WireId wire) const
+ bool checkWireAvail(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index] == nullptr;
}
- NetInfo *getBoundWireNet(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- return wire_to_net[wire.index];
- }
-
- WireId getConflictingWireWire(WireId wire) const { return wire; }
-
- NetInfo *getConflictingWireNet(WireId wire) const
+ NetInfo *getBoundWireNet(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index];
}
- DelayInfo getWireDelay(WireId wire) const
+ DelayInfo getWireDelay(WireId wire) const override
{
DelayInfo delay;
NPNR_ASSERT(wire != WireId());
@@ -586,7 +604,7 @@ struct Arch : BaseCtx
return delay;
}
- BelPinRange getWireBelPins(WireId wire) const
+ BelPinRange getWireBelPins(WireId wire) const override
{
BelPinRange range;
NPNR_ASSERT(wire != WireId());
@@ -595,7 +613,7 @@ struct Arch : BaseCtx
return range;
}
- WireRange getWires() const
+ WireRange getWires() const override
{
WireRange range;
range.b.cursor = 0;
@@ -605,9 +623,9 @@ struct Arch : BaseCtx
// -------------------------------------------------
- PipId getPipByName(IdStringList name) const;
+ PipId getPipByName(IdStringList name) const override;
- void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
+ void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) override
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] == nullptr);
@@ -627,7 +645,7 @@ struct Arch : BaseCtx
refreshUiWire(dst);
}
- void unbindPip(PipId pip)
+ void unbindPip(PipId pip) override
{
NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] != nullptr);
@@ -666,7 +684,7 @@ struct Arch : BaseCtx
return false;
}
- bool checkPipAvail(PipId pip) const
+ bool checkPipAvail(PipId pip) const override
{
if (ice40_pip_hard_unavail(pip))
return false;
@@ -675,13 +693,13 @@ struct Arch : BaseCtx
return switches_locked[pi.switch_index] == WireId();
}
- NetInfo *getBoundPipNet(PipId pip) const
+ NetInfo *getBoundPipNet(PipId pip) const override
{
NPNR_ASSERT(pip != PipId());
return pip_to_net[pip.index];
}
- WireId getConflictingPipWire(PipId pip) const
+ WireId getConflictingPipWire(PipId pip) const override
{
if (ice40_pip_hard_unavail(pip))
return WireId();
@@ -689,7 +707,7 @@ struct Arch : BaseCtx
return switches_locked[chip_info->pip_data[pip.index].switch_index];
}
- NetInfo *getConflictingPipNet(PipId pip) const
+ NetInfo *getConflictingPipNet(PipId pip) const override
{
if (ice40_pip_hard_unavail(pip))
return nullptr;
@@ -698,7 +716,7 @@ struct Arch : BaseCtx
return wire == WireId() ? nullptr : wire_to_net[wire.index];
}
- AllPipRange getPips() const
+ AllPipRange getPips() const override
{
AllPipRange range;
range.b.cursor = 0;
@@ -706,7 +724,7 @@ struct Arch : BaseCtx
return range;
}
- Loc getPipLocation(PipId pip) const
+ Loc getPipLocation(PipId pip) const override
{
Loc loc;
loc.x = chip_info->pip_data[pip.index].x;
@@ -715,14 +733,12 @@ struct Arch : BaseCtx
return loc;
}
- IdStringList getPipName(PipId pip) const;
-
- IdString getPipType(PipId pip) const;
- std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
+ IdStringList getPipName(PipId pip) const override;
- uint32_t getPipChecksum(PipId pip) const { return pip.index; }
+ IdString getPipType(PipId pip) const override;
+ std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const override;
- WireId getPipSrcWire(PipId pip) const
+ WireId getPipSrcWire(PipId pip) const override
{
WireId wire;
NPNR_ASSERT(pip != PipId());
@@ -730,7 +746,7 @@ struct Arch : BaseCtx
return wire;
}
- WireId getPipDstWire(PipId pip) const
+ WireId getPipDstWire(PipId pip) const override
{
WireId wire;
NPNR_ASSERT(pip != PipId());
@@ -738,7 +754,7 @@ struct Arch : BaseCtx
return wire;
}
- DelayInfo getPipDelay(PipId pip) const
+ DelayInfo getPipDelay(PipId pip) const override
{
DelayInfo delay;
NPNR_ASSERT(pip != PipId());
@@ -749,7 +765,7 @@ struct Arch : BaseCtx
return delay;
}
- PipRange getPipsDownhill(WireId wire) const
+ PipRange getPipsDownhill(WireId wire) const override
{
PipRange range;
NPNR_ASSERT(wire != WireId());
@@ -758,7 +774,7 @@ struct Arch : BaseCtx
return range;
}
- PipRange getPipsUphill(WireId wire) const
+ PipRange getPipsUphill(WireId wire) const override
{
PipRange range;
NPNR_ASSERT(wire != WireId());
@@ -772,59 +788,59 @@ struct Arch : BaseCtx
// -------------------------------------------------
- GroupId getGroupByName(IdStringList name) const;
- IdStringList getGroupName(GroupId group) const;
- std::vector<GroupId> getGroups() const;
- std::vector<BelId> getGroupBels(GroupId group) const;
- std::vector<WireId> getGroupWires(GroupId group) const;
- std::vector<PipId> getGroupPips(GroupId group) const;
- std::vector<GroupId> getGroupGroups(GroupId group) const;
+ GroupId getGroupByName(IdStringList name) const override;
+ IdStringList getGroupName(GroupId group) const override;
+ std::vector<GroupId> getGroups() const override;
+ std::vector<BelId> getGroupBels(GroupId group) const override;
+ std::vector<WireId> getGroupWires(GroupId group) const override;
+ std::vector<PipId> getGroupPips(GroupId group) const override;
+ std::vector<GroupId> getGroupGroups(GroupId group) const override;
// -------------------------------------------------
- delay_t estimateDelay(WireId src, WireId dst) const;
- delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
- delay_t getDelayEpsilon() const { return 20; }
- delay_t getRipupDelayPenalty() const { return 200; }
- float getDelayNS(delay_t v) const { return v * 0.001; }
- DelayInfo getDelayFromNS(float ns) const
+ delay_t estimateDelay(WireId src, WireId dst) const override;
+ delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
+ delay_t getDelayEpsilon() const override { return 20; }
+ delay_t getRipupDelayPenalty() const override { return 200; }
+ float getDelayNS(delay_t v) const override { return v * 0.001; }
+ DelayInfo getDelayFromNS(float ns) const override
{
DelayInfo del;
del.delay = delay_t(ns * 1000);
return del;
}
- uint32_t getDelayChecksum(delay_t v) const { return v; }
- bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
+ uint32_t getDelayChecksum(delay_t v) const override { return v; }
+ bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override;
- ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
+ ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
// -------------------------------------------------
- bool pack();
- bool place();
- bool route();
+ bool pack() override;
+ bool place() override;
+ bool route() override;
// -------------------------------------------------
- std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const override;
- DecalXY getBelDecal(BelId bel) const;
- DecalXY getWireDecal(WireId wire) const;
- DecalXY getPipDecal(PipId pip) const;
- DecalXY getGroupDecal(GroupId group) const;
+ DecalXY getBelDecal(BelId bel) const override;
+ DecalXY getWireDecal(WireId wire) const override;
+ DecalXY getPipDecal(PipId pip) const override;
+ DecalXY getGroupDecal(GroupId group) const override;
// -------------------------------------------------
// Get the delay through a cell from one port to another, returning false
// if no path exists. This only considers combinational delays, as required by the Arch API
- bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
+ bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override;
// get_cell_delay_internal is similar to the above, but without false path checks and including clock to out delays
// for internal arch use only
bool get_cell_delay_internal(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
- TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override;
// Get the TimingClockingInfo of a port
- TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
+ TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override;
// Return true if a port is a net
bool is_global_net(const NetInfo *net) const;
@@ -833,54 +849,13 @@ struct Arch : BaseCtx
// Perform placement validity checks, returning false on failure (all
// implemented in arch_place.cc)
- // Whether this cell type can be placed at this BEL.
- bool isValidBelForCellType(IdString cell_type, BelId bel) const { return cell_type == getBelType(bel); }
-
- const std::vector<IdString> &getCellTypes() const { return cell_types; }
-
- std::vector<BelBucketId> getBelBuckets() const { return buckets; }
-
- IdString getBelBucketName(BelBucketId bucket) const { return bucket.name; }
-
- BelBucketId getBelBucketByName(IdString name) const
- {
- BelBucketId bucket;
- bucket.name = name;
- return bucket;
- }
-
- BelBucketId getBelBucketForBel(BelId bel) const
- {
- BelBucketId bucket;
- bucket.name = getBelType(bel);
- return bucket;
- }
-
- BelBucketId getBelBucketForCellType(IdString cell_type) const
- {
- BelBucketId bucket;
- bucket.name = cell_type;
- return bucket;
- }
-
- std::vector<BelId> getBelsInBucket(BelBucketId bucket) const
- {
- std::vector<BelId> bels;
- for (BelId bel : getBels()) {
- if (getBelType(bel) == bucket.name) {
- bels.push_back(bel);
- }
- }
- return bels;
- }
-
// Whether or not a given cell can be placed at a given Bel
// This is not intended for Bel type checks, but finer-grained constraints
// such as conflicting set/reset signals, etc
- bool isValidBelForCell(CellInfo *cell, BelId bel) const;
+ bool isValidBelForCell(CellInfo *cell, BelId bel) const override;
// Return true whether all Bels at a given location are valid
- bool isBelLocationValid(BelId bel) const;
+ bool isBelLocationValid(BelId bel) const override;
// Helper function for above
bool logic_cells_compatible(const CellInfo **it, const size_t size) const;
@@ -915,9 +890,6 @@ struct Arch : BaseCtx
static const std::vector<std::string> availablePlacers;
static const std::string defaultRouter;
static const std::vector<std::string> availableRouters;
-
- std::vector<IdString> cell_types;
- std::vector<BelBucketId> buckets;
};
void ice40DelayFuzzerMain(Context *ctx);
diff --git a/ice40/arch_pybindings.h b/ice40/arch_pybindings.h
index 401fae91..86c2977e 100644
--- a/ice40/arch_pybindings.h
+++ b/ice40/arch_pybindings.h
@@ -76,18 +76,6 @@ template <> struct string_converter<PipId>
}
};
-template <> struct string_converter<BelBucketId>
-{
- BelBucketId from_str(Context *ctx, std::string name) { return ctx->getBelBucketByName(ctx->id(name)); }
-
- std::string to_str(Context *ctx, BelBucketId id)
- {
- if (id == BelBucketId())
- throw bad_wrap();
- return ctx->getBelBucketName(id).str(ctx);
- }
-};
-
template <> struct string_converter<BelPin>
{
BelPin from_str(Context *ctx, std::string name)
diff --git a/ice40/archdefs.h b/ice40/archdefs.h
index c0a6ac66..33227c6c 100644
--- a/ice40/archdefs.h
+++ b/ice40/archdefs.h
@@ -170,14 +170,7 @@ struct ArchCellInfo
};
};
-struct BelBucketId
-{
- IdString name;
-
- bool operator==(const BelBucketId &other) const { return (name == other.name); }
- bool operator!=(const BelBucketId &other) const { return (name != other.name); }
- bool operator<(const BelBucketId &other) const { return name < other.name; }
-};
+typedef IdString BelBucketId;
NEXTPNR_NAMESPACE_END
@@ -223,14 +216,4 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId>
}
};
-template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelBucketId>
-{
- std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelBucketId &bucket) const noexcept
- {
- std::size_t seed = 0;
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(bucket.name));
- return seed;
- }
-};
-
} // namespace std
diff --git a/nexus/arch.cc b/nexus/arch.cc
index 93fc1d82..ff0c269f 100644
--- a/nexus/arch.cc
+++ b/nexus/arch.cc
@@ -169,18 +169,8 @@ Arch::Arch(ArchArgs args) : args(args)
if (!speed_grade)
log_error("Unknown speed grade '%s'.\n", speed.c_str());
- std::unordered_set<IdString> bel_types;
- for (BelId bel : getBels()) {
- bel_types.insert(getBelType(bel));
- }
-
- for (IdString bel_type : bel_types) {
- cell_types.push_back(bel_type);
-
- BelBucketId bucket;
- bucket.name = bel_type;
- buckets.push_back(bucket);
- }
+ BaseArch::init_cell_types();
+ BaseArch::init_bel_buckets();
}
// -----------------------------------------------------------------------
@@ -322,8 +312,6 @@ WireId Arch::getWireByName(IdStringList name) const
return WireId();
}
-IdString Arch::getWireType(WireId wire) const { return id("WIRE"); }
-
std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) const
{
std::vector<std::pair<IdString, std::string>> ret;
diff --git a/nexus/arch.h b/nexus/arch.h
index 071d4456..5d6d7d99 100644
--- a/nexus/arch.h
+++ b/nexus/arch.h
@@ -721,7 +721,7 @@ struct UpDownhillPipRange
UpDownhillPipIterator end() const { return e; }
};
-struct WireBelPinIterator
+struct BelPinIterator
{
const DatabasePOD *db;
const ChipInfoPOD *chip;
@@ -740,7 +740,7 @@ struct WireBelPinIterator
cursor = 0;
}
}
- bool operator!=(const WireBelPinIterator &other) const { return twi != other.twi || cursor != other.cursor; }
+ bool operator!=(const BelPinIterator &other) const { return twi != other.twi || cursor != other.cursor; }
BelPin operator*() const
{
@@ -754,11 +754,11 @@ struct WireBelPinIterator
}
};
-struct WireBelPinRange
+struct BelPinRange
{
- WireBelPinIterator b, e;
- WireBelPinIterator begin() const { return b; }
- WireBelPinIterator end() const { return e; }
+ BelPinIterator b, e;
+ BelPinIterator begin() const { return b; }
+ BelPinIterator end() const { return e; }
};
// -----------------------------------------------------------------------
@@ -855,7 +855,38 @@ struct ArchArgs
std::string device;
};
-struct Arch : BaseCtx
+struct ArchRanges
+{
+ using ArchArgsT = ArchArgs;
+ // Bels
+ using AllBelsRangeT = BelRange;
+ using TileBelsRangeT = std::vector<BelId>;
+ using BelAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ using BelPinsRangeT = std::vector<IdString>;
+ // Wires
+ using AllWiresRangeT = WireRange;
+ using DownhillPipRangeT = UpDownhillPipRange;
+ using UphillPipRangeT = UpDownhillPipRange;
+ using WireBelPinRangeT = BelPinRange;
+ using WireAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Pips
+ using AllPipsRangeT = AllPipRange;
+ using PipAttrsRangeT = std::vector<std::pair<IdString, std::string>>;
+ // Groups
+ using AllGroupsRangeT = std::vector<GroupId>;
+ using GroupBelsRangeT = std::vector<BelId>;
+ using GroupWiresRangeT = std::vector<WireId>;
+ using GroupPipsRangeT = std::vector<PipId>;
+ using GroupGroupsRangeT = std::vector<GroupId>;
+ // Decals
+ using DecalGfxRangeT = std::vector<GraphicElement>;
+ // Placement validity
+ using CellTypeRangeT = const std::vector<IdString> &;
+ using BelBucketRangeT = const std::vector<BelBucketId> &;
+ using BucketBelRangeT = const std::vector<BelId> &;
+};
+
+struct Arch : BaseArch<ArchRanges>
{
ArchArgs args;
std::string family, device, package, speed, rating, variant;
@@ -894,8 +925,6 @@ struct Arch : BaseCtx
};
std::vector<TileStatus> tileStatus;
- std::unordered_map<WireId, NetInfo *> wire_to_net;
- std::unordered_map<PipId, NetInfo *> pip_to_net;
// fast access to X and Y IdStrings for building object names
std::vector<IdString> x_ids, y_ids;
@@ -904,23 +933,22 @@ struct Arch : BaseCtx
// -------------------------------------------------
- std::string getChipName() const;
+ std::string getChipName() const override;
- IdString archId() const { return id("nexus"); }
- ArchArgs archArgs() const { return args; }
- IdString archArgsToId(ArchArgs args) const;
+ ArchArgs archArgs() const override { return args; }
+ IdString archArgsToId(ArchArgs args) const override;
- int getGridDimX() const { return chip_info->width; }
- int getGridDimY() const { return chip_info->height; }
- int getTileBelDimZ(int, int) const { return 256; }
- int getTilePipDimZ(int, int) const { return 1; }
- char getNameDelimiter() const { return '/'; }
+ int getGridDimX() const override { return chip_info->width; }
+ int getGridDimY() const override { return chip_info->height; }
+ int getTileBelDimZ(int, int) const override { return 256; }
+ int getTilePipDimZ(int, int) const override { return 1; }
+ char getNameDelimiter() const override { return '/'; }
// -------------------------------------------------
- BelId getBelByName(IdStringList name) const;
+ BelId getBelByName(IdStringList name) const override;
- IdStringList getBelName(BelId bel) const
+ IdStringList getBelName(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
std::array<IdString, 3> ids{x_ids.at(bel.tile % chip_info->width), y_ids.at(bel.tile / chip_info->width),
@@ -928,9 +956,7 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- uint32_t getBelChecksum(BelId bel) const { return (bel.tile << 16) ^ bel.index; }
-
- void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
+ void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) override
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(tileStatus[bel.tile].boundcells[bel.index] == nullptr);
@@ -943,7 +969,7 @@ struct Arch : BaseCtx
update_logic_bel(bel, cell);
}
- void unbindBel(BelId bel)
+ void unbindBel(BelId bel) override
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(tileStatus[bel.tile].boundcells[bel.index] != nullptr);
@@ -957,25 +983,19 @@ struct Arch : BaseCtx
refreshUiBel(bel);
}
- bool checkBelAvail(BelId bel) const
+ bool checkBelAvail(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return tileStatus[bel.tile].boundcells[bel.index] == nullptr;
}
- CellInfo *getBoundBelCell(BelId bel) const
+ CellInfo *getBoundBelCell(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return tileStatus[bel.tile].boundcells[bel.index];
}
- CellInfo *getConflictingBelCell(BelId bel) const
- {
- NPNR_ASSERT(bel != BelId());
- return tileStatus[bel.tile].boundcells[bel.index];
- }
-
- BelRange getBels() const
+ BelRange getBels() const override
{
BelRange range;
range.b.cursor_tile = 0;
@@ -990,7 +1010,7 @@ struct Arch : BaseCtx
return range;
}
- Loc getBelLocation(BelId bel) const
+ Loc getBelLocation(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
Loc loc;
@@ -1000,7 +1020,7 @@ struct Arch : BaseCtx
return loc;
}
- BelId getBelByLocation(Loc loc) const
+ BelId getBelByLocation(Loc loc) const override
{
auto &t = tileStatus.at(loc.y * chip_info->width + loc.x);
if (loc.z >= int(t.bels_by_z.size()))
@@ -1008,26 +1028,26 @@ struct Arch : BaseCtx
return t.bels_by_z.at(loc.z);
}
- std::vector<BelId> getBelsByTile(int x, int y) const;
+ std::vector<BelId> getBelsByTile(int x, int y) const override;
- bool getBelGlobalBuf(BelId bel) const { return false; }
+ bool getBelGlobalBuf(BelId bel) const override { return false; }
- IdString getBelType(BelId bel) const
+ IdString getBelType(BelId bel) const override
{
NPNR_ASSERT(bel != BelId());
return IdString(bel_data(bel).type);
}
- std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const;
+ std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const override;
- WireId getBelPinWire(BelId bel, IdString pin) const;
- PortType getBelPinType(BelId bel, IdString pin) const;
- std::vector<IdString> getBelPins(BelId bel) const;
+ WireId getBelPinWire(BelId bel, IdString pin) const override;
+ PortType getBelPinType(BelId bel, IdString pin) const override;
+ std::vector<IdString> getBelPins(BelId bel) const override;
// -------------------------------------------------
- WireId getWireByName(IdStringList name) const;
- IdStringList getWireName(WireId wire) const
+ WireId getWireByName(IdStringList name) const override;
+ IdStringList getWireName(WireId wire) const override
{
NPNR_ASSERT(wire != WireId());
std::array<IdString, 3> ids{x_ids.at(wire.tile % chip_info->width), y_ids.at(wire.tile / chip_info->width),
@@ -1035,64 +1055,9 @@ struct Arch : BaseCtx
return IdStringList(ids);
}
- IdString getWireType(WireId wire) const;
- std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const;
-
- uint32_t getWireChecksum(WireId wire) const { return (wire.tile << 16) ^ wire.index; }
-
- void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
- {
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire] == nullptr);
- wire_to_net[wire] = net;
- net->wires[wire].pip = PipId();
- net->wires[wire].strength = strength;
- refreshUiWire(wire);
- }
-
- void unbindWire(WireId wire)
- {
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire] != nullptr);
-
- auto &net_wires = wire_to_net[wire]->wires;
- auto it = net_wires.find(wire);
- NPNR_ASSERT(it != net_wires.end());
-
- auto pip = it->second.pip;
- if (pip != PipId()) {
- pip_to_net[pip] = nullptr;
- }
-
- net_wires.erase(it);
- wire_to_net[wire] = nullptr;
- refreshUiWire(wire);
- }
+ std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const override;
- bool checkWireAvail(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- auto w2n = wire_to_net.find(wire);
- return w2n == wire_to_net.end() || w2n->second == nullptr;
- }
-
- NetInfo *getBoundWireNet(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- auto w2n = wire_to_net.find(wire);
- return w2n == wire_to_net.end() ? nullptr : w2n->second;
- }
-
- NetInfo *getConflictingWireNet(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- auto w2n = wire_to_net.find(wire);
- return w2n == wire_to_net.end() ? nullptr : w2n->second;
- }
-
- WireId getConflictingWireWire(WireId wire) const { return wire; }
-
- DelayInfo getWireDelay(WireId wire) const
+ DelayInfo getWireDelay(WireId wire) const override
{
DelayInfo delay;
delay.min_delay = 0;
@@ -1100,9 +1065,9 @@ struct Arch : BaseCtx
return delay;
}
- WireBelPinRange getWireBelPins(WireId wire) const
+ BelPinRange getWireBelPins(WireId wire) const override
{
- WireBelPinRange range;
+ BelPinRange range;
NPNR_ASSERT(wire != WireId());
NeighWireRange nwr = neigh_wire_range(wire);
range.b.chip = chip_info;
@@ -1119,7 +1084,7 @@ struct Arch : BaseCtx
return range;
}
- WireRange getWires() const
+ WireRange getWires() const override
{
WireRange range;
range.b.chip = chip_info;
@@ -1136,64 +1101,10 @@ struct Arch : BaseCtx
// -------------------------------------------------
- PipId getPipByName(IdStringList name) const;
- IdStringList getPipName(PipId pip) const;
-
- void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
- {
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip] == nullptr);
-
- WireId dst = canonical_wire(pip.tile, pip_data(pip).to_wire);
- NPNR_ASSERT(wire_to_net[dst] == nullptr || wire_to_net[dst] == net);
+ PipId getPipByName(IdStringList name) const override;
+ IdStringList getPipName(PipId pip) const override;
- pip_to_net[pip] = net;
-
- wire_to_net[dst] = net;
- net->wires[dst].pip = pip;
- net->wires[dst].strength = strength;
- refreshUiPip(pip);
- refreshUiWire(dst);
- }
-
- void unbindPip(PipId pip)
- {
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip] != nullptr);
-
- WireId dst = canonical_wire(pip.tile, pip_data(pip).to_wire);
- NPNR_ASSERT(wire_to_net[dst] != nullptr);
- wire_to_net[dst] = nullptr;
- pip_to_net[pip]->wires.erase(dst);
-
- pip_to_net[pip] = nullptr;
- refreshUiPip(pip);
- refreshUiWire(dst);
- }
-
- bool checkPipAvail(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == nullptr;
- }
-
- NetInfo *getBoundPipNet(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- auto p2n = pip_to_net.find(pip);
- return p2n == pip_to_net.end() ? nullptr : p2n->second;
- }
-
- WireId getConflictingPipWire(PipId pip) const { return getPipDstWire(pip); }
-
- NetInfo *getConflictingPipNet(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- auto p2n = pip_to_net.find(pip);
- return p2n == pip_to_net.end() ? nullptr : p2n->second;
- }
-
- AllPipRange getPips() const
+ AllPipRange getPips() const override
{
AllPipRange range;
range.b.cursor_tile = 0;
@@ -1208,7 +1119,7 @@ struct Arch : BaseCtx
return range;
}
- Loc getPipLocation(PipId pip) const
+ Loc getPipLocation(PipId pip) const override
{
Loc loc;
loc.x = pip.tile % chip_info->width;
@@ -1217,16 +1128,14 @@ struct Arch : BaseCtx
return loc;
}
- IdString getPipType(PipId pip) const;
- std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
-
- uint32_t getPipChecksum(PipId pip) const { return pip.tile << 16 | pip.index; }
+ IdString getPipType(PipId pip) const override;
+ std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const override;
- WireId getPipSrcWire(PipId pip) const { return canonical_wire(pip.tile, pip_data(pip).from_wire); }
+ WireId getPipSrcWire(PipId pip) const override { return canonical_wire(pip.tile, pip_data(pip).from_wire); }
WireId getPipDstWire(PipId pip) const { return canonical_wire(pip.tile, pip_data(pip).to_wire); }
- DelayInfo getPipDelay(PipId pip) const
+ DelayInfo getPipDelay(PipId pip) const override
{
DelayInfo delay;
auto &cls = speed_grade->pip_classes[pip_data(pip).timing_class];
@@ -1235,7 +1144,7 @@ struct Arch : BaseCtx
return delay;
}
- UpDownhillPipRange getPipsDownhill(WireId wire) const
+ UpDownhillPipRange getPipsDownhill(WireId wire) const override
{
UpDownhillPipRange range;
NPNR_ASSERT(wire != WireId());
@@ -1256,7 +1165,7 @@ struct Arch : BaseCtx
return range;
}
- UpDownhillPipRange getPipsUphill(WireId wire) const
+ UpDownhillPipRange getPipsUphill(WireId wire) const override
{
UpDownhillPipRange range;
NPNR_ASSERT(wire != WireId());
@@ -1277,44 +1186,24 @@ struct Arch : BaseCtx
return range;
}
- UpDownhillPipRange getWireAliases(WireId wire) const
- {
- UpDownhillPipRange range;
- range.b.cursor = 0;
- range.b.twi.cursor = 0;
- range.e.cursor = 0;
- range.e.twi.cursor = 0;
- return range;
- }
-
- // -------------------------------------------------
-
- GroupId getGroupByName(IdStringList name) const { return GroupId(); }
- IdStringList getGroupName(GroupId group) const { return IdStringList(); }
- std::vector<GroupId> getGroups() const { return {}; }
- std::vector<BelId> getGroupBels(GroupId group) const { return {}; }
- std::vector<WireId> getGroupWires(GroupId group) const { return {}; }
- std::vector<PipId> getGroupPips(GroupId group) const { return {}; }
- std::vector<GroupId> getGroupGroups(GroupId group) const { return {}; }
-
// -------------------------------------------------
- delay_t estimateDelay(WireId src, WireId dst) const;
- delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
- delay_t getDelayEpsilon() const { return 20; }
- delay_t getRipupDelayPenalty() const { return 120; }
+ delay_t estimateDelay(WireId src, WireId dst) const override;
+ delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
+ delay_t getDelayEpsilon() const override { return 20; }
+ delay_t getRipupDelayPenalty() const override { return 120; }
delay_t getWireRipupDelayPenalty(WireId wire) const;
- float getDelayNS(delay_t v) const { return v * 0.001; }
- DelayInfo getDelayFromNS(float ns) const
+ float getDelayNS(delay_t v) const override { return v * 0.001; }
+ DelayInfo getDelayFromNS(float ns) const override
{
DelayInfo del;
del.min_delay = delay_t(ns * 1000);
del.max_delay = delay_t(ns * 1000);
return del;
}
- uint32_t getDelayChecksum(delay_t v) const { return v; }
- bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
- ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
+ uint32_t getDelayChecksum(delay_t v) const override { return v; }
+ bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const override;
+ ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
// for better DSP bounding boxes
void pre_routing();
@@ -1324,71 +1213,30 @@ struct Arch : BaseCtx
// Get the delay through a cell from one port to another, returning false
// if no path exists. This only considers combinational delays, as required by the Arch API
- bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
+ bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const override;
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
- TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
+ TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override;
// Get the TimingClockingInfo of a port
- TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
+ TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override;
// -------------------------------------------------
// Perform placement validity checks, returning false on failure (all
// implemented in arch_place.cc)
- // Whether this cell type can be placed at this BEL.
- bool isValidBelForCellType(IdString cell_type, BelId bel) const { return cell_type == getBelType(bel); }
-
- const std::vector<IdString> &getCellTypes() const { return cell_types; }
-
- std::vector<BelBucketId> getBelBuckets() const { return buckets; }
-
- IdString getBelBucketName(BelBucketId bucket) const { return bucket.name; }
-
- BelBucketId getBelBucketByName(IdString name) const
- {
- BelBucketId bucket;
- bucket.name = name;
- return bucket;
- }
-
- BelBucketId getBelBucketForBel(BelId bel) const
- {
- BelBucketId bucket;
- bucket.name = getBelType(bel);
- return bucket;
- }
-
- BelBucketId getBelBucketForCellType(IdString cell_type) const
- {
- BelBucketId bucket;
- bucket.name = cell_type;
- return bucket;
- }
-
- std::vector<BelId> getBelsInBucket(BelBucketId bucket) const
- {
- std::vector<BelId> bels;
- for (BelId bel : getBels()) {
- if (getBelType(bel) == bucket.name) {
- bels.push_back(bel);
- }
- }
- return bels;
- }
-
// Whether or not a given cell can be placed at a given Bel
// This is not intended for Bel type checks, but finer-grained constraints
// such as conflicting set/reset signals, etc
- bool isValidBelForCell(CellInfo *cell, BelId bel) const;
+ bool isValidBelForCell(CellInfo *cell, BelId bel) const override;
// Return true whether all Bels at a given location are valid
- bool isBelLocationValid(BelId bel) const;
+ bool isBelLocationValid(BelId bel) const override;
// -------------------------------------------------
- bool pack();
- bool place();
- bool route();
+ bool pack() override;
+ bool place() override;
+ bool route() override;
// arch-specific post-placement optimisations
void post_place_opt();
@@ -1397,7 +1245,7 @@ struct Arch : BaseCtx
// Assign architecture-specific arguments to nets and cells, which must be
// called between packing or further
// netlist modifications, and validity checks
- void assignArchInfo();
+ void assignArchInfo() override;
void assignCellInfo(CellInfo *cell);
// -------------------------------------------------
@@ -1406,12 +1254,12 @@ struct Arch : BaseCtx
// -------------------------------------------------
- std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const override;
- DecalXY getBelDecal(BelId bel) const;
- DecalXY getWireDecal(WireId wire) const;
- DecalXY getPipDecal(PipId pip) const;
- DecalXY getGroupDecal(GroupId group) const;
+ DecalXY getBelDecal(BelId bel) const override;
+ DecalXY getWireDecal(WireId wire) const override;
+ DecalXY getPipDecal(PipId pip) const override;
+ DecalXY getGroupDecal(GroupId group) const override;
// -------------------------------------------------
@@ -1577,9 +1425,6 @@ struct Arch : BaseCtx
// -------------------------------------------------
void write_fasm(std::ostream &out) const;
-
- std::vector<IdString> cell_types;
- std::vector<BelBucketId> buckets;
};
NEXTPNR_NAMESPACE_END
diff --git a/nexus/arch_pybindings.cc b/nexus/arch_pybindings.cc
index b07031f7..a8b04ba7 100644
--- a/nexus/arch_pybindings.cc
+++ b/nexus/arch_pybindings.cc
@@ -53,7 +53,6 @@ void arch_wrap_python(py::module &m)
typedef UpDownhillPipRange UphillPipRange;
typedef UpDownhillPipRange DownhillPipRange;
- typedef WireBelPinRange BelPinRange;
typedef const std::vector<BelBucketId> &BelBucketRange;
typedef const std::vector<BelId> &BelRangeForBelBucket;
@@ -64,7 +63,7 @@ void arch_wrap_python(py::module &m)
WRAP_RANGE(m, Wire, conv_to_str<WireId>);
WRAP_RANGE(m, AllPip, conv_to_str<PipId>);
WRAP_RANGE(m, UpDownhillPip, conv_to_str<PipId>);
- WRAP_RANGE(m, WireBelPin, wrap_context<BelPin>);
+ WRAP_RANGE(m, BelPin, wrap_context<BelPin>);
WRAP_MAP_UPTR(m, CellMap, "IdCellMap");
WRAP_MAP_UPTR(m, NetMap, "IdNetMap");
diff --git a/nexus/arch_pybindings.h b/nexus/arch_pybindings.h
index dd41ce32..b94449ad 100644
--- a/nexus/arch_pybindings.h
+++ b/nexus/arch_pybindings.h
@@ -76,18 +76,6 @@ template <> struct string_converter<PipId>
}
};
-template <> struct string_converter<BelBucketId>
-{
- BelBucketId from_str(Context *ctx, std::string name) { return ctx->getBelBucketByName(ctx->id(name)); }
-
- std::string to_str(Context *ctx, BelBucketId id)
- {
- if (id == BelBucketId())
- throw bad_wrap();
- return ctx->getBelBucketName(id).str(ctx);
- }
-};
-
template <> struct string_converter<BelPin>
{
BelPin from_str(Context *ctx, std::string name)
diff --git a/nexus/archdefs.h b/nexus/archdefs.h
index 7e427e06..de5e17c8 100644
--- a/nexus/archdefs.h
+++ b/nexus/archdefs.h
@@ -114,14 +114,7 @@ struct PipId
}
};
-struct BelBucketId
-{
- IdString name;
-
- bool operator==(const BelBucketId &other) const { return (name == other.name); }
- bool operator!=(const BelBucketId &other) const { return (name != other.name); }
- bool operator<(const BelBucketId &other) const { return name < other.name; }
-};
+typedef IdString BelBucketId;
struct GroupId
{
@@ -260,14 +253,4 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId>
}
};
-template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelBucketId>
-{
- std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelBucketId &bucket) const noexcept
- {
- std::size_t seed = 0;
- boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(bucket.name));
- return seed;
- }
-};
-
} // namespace std