aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/arch.h
diff options
context:
space:
mode:
authorSergiusz Bazanski <q3k@q3k.org>2018-07-13 18:57:55 +0100
committerSergiusz Bazanski <q3k@q3k.org>2018-07-13 18:58:59 +0100
commit89809a8b810dd57f50f365d70a0ce547705f8dbb (patch)
tree3ae30e1c48cb71cc927ad399f31486d8273471e7 /ice40/arch.h
parent9e4f97290a50fc5d9dc0cbe6ead945840b9811b1 (diff)
downloadnextpnr-89809a8b810dd57f50f365d70a0ce547705f8dbb.tar.gz
nextpnr-89809a8b810dd57f50f365d70a0ce547705f8dbb.tar.bz2
nextpnr-89809a8b810dd57f50f365d70a0ce547705f8dbb.zip
Introduce proxies for locked access to ctx
Diffstat (limited to 'ice40/arch.h')
-rw-r--r--ice40/arch.h387
1 files changed, 148 insertions, 239 deletions
diff --git a/ice40/arch.h b/ice40/arch.h
index ab66e7d8..4462ce9e 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -2,6 +2,7 @@
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
+ * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -327,27 +328,40 @@ struct ArchArgs
std::string package;
};
+class ArchRWProxyMethods;
+class ArchRProxyMethods;
+class ArchRWProxy;
+class ArchRProxy;
+
class Arch : public BaseCtx
{
+ friend class ArchRWProxyMethods;
+ friend class ArchRProxyMethods;
+ friend class ArchRWProxy;
+ friend class ArchRProxy;
private:
// All of the following...
std::vector<IdString> bel_to_cell;
std::vector<IdString> wire_to_net;
std::vector<IdString> pip_to_net;
std::vector<IdString> switches_locked;
+ mutable std::unordered_map<IdString, int> bel_by_name;
+ mutable std::unordered_map<IdString, int> wire_by_name;
+ mutable std::unordered_map<IdString, int> pip_by_name;
+
// ... are guarded by the following lock:
mutable boost::shared_mutex mtx_;
+
public:
const ChipInfoPOD *chip_info;
const PackageInfoPOD *package_info;
- mutable std::unordered_map<IdString, int> bel_by_name;
- mutable std::unordered_map<IdString, int> wire_by_name;
- mutable std::unordered_map<IdString, int> pip_by_name;
-
ArchArgs args;
Arch(ArchArgs args);
+ ArchRWProxy rwproxy(void);
+ ArchRProxy rproxy(void) const;
+
std::string getChipName();
IdString archId() const { return id("ice40"); }
@@ -361,8 +375,33 @@ public:
// -------------------------------------------------
+ /// Wrappers around getting a r(w)proxy and calling a single method.
+ // Deprecated: please acquire a proxy yourself and call the methods
+ // you want on it.
+ void unbindWire(WireId wire);
+ void unbindPip(PipId pip);
+ void unbindBel(BelId bel);
+ void bindWire(WireId wire, IdString net, PlaceStrength strength);
+ void bindPip(PipId pip, IdString net, PlaceStrength strength);
+ void bindBel(BelId bel, IdString cell, PlaceStrength strength);
+ bool checkWireAvail(WireId wire) const;
+ bool checkPipAvail(PipId pip) const;
+ bool checkBelAvail(BelId bel) const;
+ WireId getWireByName(IdString name) const;
+ WireId getWireBelPin(BelId bel, PortPin pin) const;
+ PipId getPipByName(IdString name) const;
+ IdString getConflictingWireNet(WireId wire) const;
+ IdString getConflictingPipNet(PipId pip) const;
+ IdString getConflictingBelCell(BelId bel) const;
+ IdString getBoundWireNet(WireId wire) const;
+ IdString getBoundPipNet(PipId pip) const;
+ IdString getBoundBelCell(BelId bel) const;
BelId getBelByName(IdString name) const;
- BelId getBelByNameUnlocked(IdString name) const;
+
+ // -------------------------------------------------
+
+ /// Methods to get chip info - don't need to use a wrapper, as these are
+ /// static per lifetime of object.
IdString getBelName(BelId bel) const
{
@@ -370,71 +409,9 @@ public:
return id(chip_info->bel_data[bel.index].name.get());
}
- uint32_t getBelChecksum(BelId bel) const { return bel.index; }
-
- void bindBel(BelId bel, IdString cell, PlaceStrength strength) {
- boost::lock_guard<boost::shared_mutex> lock(mtx_);
- bindBelUnlocked(bel, cell, strength);
- }
-
- void bindBelUnlocked(BelId bel, IdString cell, PlaceStrength strength)
- {
- NPNR_ASSERT(bel != BelId());
- NPNR_ASSERT(bel_to_cell[bel.index] == IdString());
- bel_to_cell[bel.index] = cell;
- cells[cell]->bel = bel;
- cells[cell]->belStrength = strength;
- }
-
- void unbindBel(BelId bel)
+ uint32_t getBelChecksum(BelId bel) const
{
- boost::lock_guard<boost::shared_mutex> lock(mtx_);
- unbindBelUnlocked(bel);
- }
-
- void unbindBelUnlocked(BelId bel)
- {
- NPNR_ASSERT(bel != BelId());
- NPNR_ASSERT(bel_to_cell[bel.index] != IdString());
- cells[bel_to_cell[bel.index]]->bel = BelId();
- cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
- bel_to_cell[bel.index] = IdString();
- }
-
- bool checkBelAvail(BelId bel) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return checkBelAvailUnlocked(bel);
- }
-
- bool checkBelAvailUnlocked(BelId bel) const
- {
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell[bel.index] == IdString();
- }
-
- IdString getBoundBelCell(BelId bel) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return getBoundBelCellUnlocked(bel);
- }
-
- IdString getBoundBelCellUnlocked(BelId bel) const
- {
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell[bel.index];
- }
-
- IdString getConflictingBelCell(BelId bel) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return getConflictingBelCellUnlocked(bel);
- }
-
- IdString getConflictingBelCellUnlocked(BelId bel) const
- {
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell[bel.index];
+ return bel.index;
}
BelRange getBels() const
@@ -467,8 +444,6 @@ public:
return chip_info->bel_data[bel.index].type;
}
- WireId getWireBelPin(BelId bel, PortPin pin) const;
- WireId getWireBelPinUnlocked(BelId bel, PortPin pin) const;
BelPin getBelPinUphill(WireId wire) const
{
@@ -494,9 +469,6 @@ public:
// -------------------------------------------------
- WireId getWireByName(IdString name) const;
- WireId getWireByNameUnlocked(IdString name) const;
-
IdString getWireName(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
@@ -505,82 +477,6 @@ public:
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
- void bindWire(WireId wire, IdString net, PlaceStrength strength)
- {
- boost::lock_guard<boost::shared_mutex> lock(mtx_);
- bindWireUnlocked(wire, net, strength);
- }
-
- void bindWireUnlocked(WireId wire, IdString net, PlaceStrength strength)
- {
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire.index] == IdString());
-
- wire_to_net[wire.index] = net;
- nets[net]->wires[wire].pip = PipId();
- nets[net]->wires[wire].strength = strength;
- }
-
- void unbindWire(WireId wire)
- {
- boost::lock_guard<boost::shared_mutex> lock(mtx_);
- unbindWireUnlocked(wire);
- }
-
- void unbindWireUnlocked(WireId wire)
- {
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire.index] != IdString());
-
- auto &net_wires = nets[wire_to_net[wire.index]]->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.index] = IdString();
- switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
- }
-
- net_wires.erase(it);
- wire_to_net[wire.index] = IdString();
- }
-
- bool checkWireAvail(WireId wire) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return checkWireAvailUnlocked(wire);
- }
-
- bool checkWireAvailUnlocked(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- return wire_to_net[wire.index] == IdString();
- }
-
- IdString getBoundWireNet(WireId wire) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return getBoundWireNetUnlocked(wire);
- }
-
- IdString getBoundWireNetUnlocked(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- return wire_to_net[wire.index];
- }
-
- IdString getConflictingWireNet(WireId wire) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return getConflictingWireNetUnlocked(wire);
- }
-
- IdString getConflictingWireNetUnlocked(WireId wire) const
- {
- NPNR_ASSERT(wire != WireId());
- return wire_to_net[wire.index];
- }
WireRange getWires() const
{
@@ -592,93 +488,10 @@ public:
// -------------------------------------------------
- PipId getPipByName(IdString name) const;
- PipId getPipByNameUnlocked(IdString name) const;
IdString getPipName(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
- void bindPip(PipId pip, IdString net, PlaceStrength strength)
- {
- boost::lock_guard<boost::shared_mutex> lock(mtx_);
- bindPipUnlocked(pip, net, strength);
- }
-
- void bindPipUnlocked(PipId pip, IdString net, PlaceStrength strength)
- {
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip.index] == IdString());
- NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString());
-
- pip_to_net[pip.index] = net;
- switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
-
- WireId dst;
- dst.index = chip_info->pip_data[pip.index].dst;
- NPNR_ASSERT(wire_to_net[dst.index] == IdString());
- wire_to_net[dst.index] = net;
- nets[net]->wires[dst].pip = pip;
- nets[net]->wires[dst].strength = strength;
- }
-
- void unbindPip(PipId pip)
- {
- boost::lock_guard<boost::shared_mutex> lock(mtx_);
- unbindPipUnlocked(pip);
- }
-
- void unbindPipUnlocked(PipId pip)
- {
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip.index] != IdString());
- NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != IdString());
-
- WireId dst;
- dst.index = chip_info->pip_data[pip.index].dst;
- NPNR_ASSERT(wire_to_net[dst.index] != IdString());
- wire_to_net[dst.index] = IdString();
- nets[pip_to_net[pip.index]]->wires.erase(dst);
-
- pip_to_net[pip.index] = IdString();
- switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
- }
-
- bool checkPipAvail(PipId pip) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return checkPipAvailUnlocked(pip);
- }
-
- bool checkPipAvailUnlocked(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString();
- }
-
- IdString getBoundPipNet(PipId pip) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return getBoundPipNetUnlocked(pip);
- }
-
- IdString getBoundPipNetUnlocked(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- return pip_to_net[pip.index];
- }
-
- IdString getConflictingPipNet(PipId pip) const
- {
- boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
- return getConflictingPipNetUnlocked(pip);
- }
-
- IdString getConflictingPipNetUnlocked(PipId pip) const
- {
- NPNR_ASSERT(pip != PipId());
- return switches_locked[chip_info->pip_data[pip.index].switch_index];
- }
-
AllPipRange getPips() const
{
AllPipRange range;
@@ -789,7 +602,26 @@ public:
// -------------------------------------------------
- // Perform placement validity checks, returning false on failure (all implemented in arch_place.cc)
+ IdString id_glb_buf_out;
+ IdString id_icestorm_lc, id_sb_io, id_sb_gb;
+ IdString id_cen, id_clk, id_sr;
+ IdString id_i0, id_i1, id_i2, id_i3;
+ IdString id_dff_en, id_neg_clk;
+};
+
+class ArchRProxyMethods {
+ friend class ArchRProxy;
+ friend class ArchRWProxy;
+private:
+ const Arch *parent_;
+ ArchRProxyMethods(const Arch *parent) : parent_(parent) {}
+ ArchRProxyMethods(ArchRProxyMethods &&other) noexcept : parent_(other.parent_) {}
+ ArchRProxyMethods(const ArchRProxyMethods &other) : parent_(other.parent_) {}
+
+public:
+ ~ArchRProxyMethods() noexcept { }
+
+ /// Perform placement validity checks, returning false on failure (all implemented in arch_place.cc)
// 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
@@ -802,11 +634,88 @@ public:
// Helper function for above
bool logicCellsCompatible(const std::vector<const CellInfo *> &cells) const;
- IdString id_glb_buf_out;
- IdString id_icestorm_lc, id_sb_io, id_sb_gb;
- IdString id_cen, id_clk, id_sr;
- IdString id_i0, id_i1, id_i2, id_i3;
- IdString id_dff_en, id_neg_clk;
+ bool checkWireAvail(WireId wire) const;
+ bool checkPipAvail(PipId pip) const;
+ bool checkBelAvail(BelId bel) const;
+
+ WireId getWireByName(IdString name) const;
+ WireId getWireBelPin(BelId bel, PortPin pin) const;
+ PipId getPipByName(IdString name) const;
+
+
+ IdString getConflictingWireNet(WireId wire) const;
+ IdString getConflictingPipNet(PipId pip) const;
+ IdString getConflictingBelCell(BelId bel) const;
+
+ IdString getBoundWireNet(WireId wire) const;
+ IdString getBoundPipNet(PipId pip) const;
+ IdString getBoundBelCell(BelId bel) const;
+
+ BelId getBelByName(IdString name) const;
+};
+
+class ArchRProxy : public ArchRProxyMethods {
+ friend class Arch;
+ friend class ArchRWProxy;
+private:
+ boost::shared_mutex *lock_;
+ ArchRProxy(const Arch *parent) : ArchRProxyMethods(parent), lock_(&parent->mtx_)
+ {
+ lock_->lock_shared();
+ }
+
+public:
+ ~ArchRProxy() {
+ if (lock_ != nullptr) {
+ lock_->unlock_shared();
+ }
+ }
+ ArchRProxy(ArchRProxy &&other) : ArchRProxyMethods(other), lock_(other.lock_)
+ {
+ other.lock_ = nullptr;
+ }
+};
+
+class ArchRWProxyMethods {
+ friend class ArchRWProxy;
+private:
+ Arch *parent_;
+ ArchRWProxyMethods(Arch *parent) : parent_(parent) {}
+ ArchRWProxyMethods(ArchRWProxyMethods &&other) : parent_(other.parent_) {}
+ ArchRWProxyMethods(const ArchRWProxyMethods &other) : parent_(other.parent_) {}
+public:
+ ~ArchRWProxyMethods() {}
+
+ void unbindWire(WireId wire);
+ void unbindPip(PipId pip);
+ void unbindBel(BelId bel);
+ void bindWire(WireId wire, IdString net, PlaceStrength strength);
+ void bindPip(PipId pip, IdString net, PlaceStrength strength);
+ void bindBel(BelId bel, IdString cell, PlaceStrength strength);
+ CellInfo *getCell(IdString cell);
+};
+
+class ArchRWProxy : public ArchRProxyMethods, public ArchRWProxyMethods {
+ friend class Arch;
+private:
+ boost::shared_mutex *lock_;
+ ArchRWProxy(Arch *parent) : ArchRProxyMethods(parent), ArchRWProxyMethods(parent), lock_(&parent->mtx_) {
+ lock_->lock();
+ }
+
+public:
+ ArchRWProxy(ArchRWProxy &&other) : ArchRProxyMethods(other), ArchRWProxyMethods(other), lock_(other.lock_)
+ {
+ other.lock_ = nullptr;
+ }
+ ~ArchRWProxy()
+ {
+ if (lock_ != nullptr) {
+ lock_->unlock();
+ }
+ }
+
+
};
NEXTPNR_NAMESPACE_END