aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSergiusz Bazanski <q3k@q3k.org>2018-07-14 11:10:31 +0100
committerSergiusz Bazanski <q3k@q3k.org>2018-07-14 11:10:31 +0100
commit9b17fe385cf7e8d3025747b5f7c7822ac2d99920 (patch)
tree1822cebedf1e346defe28f0707de7332d45a92cc /common
parenta38b4fa1735bd0af78520f6d5320a264914fb838 (diff)
downloadnextpnr-9b17fe385cf7e8d3025747b5f7c7822ac2d99920.tar.gz
nextpnr-9b17fe385cf7e8d3025747b5f7c7822ac2d99920.tar.bz2
nextpnr-9b17fe385cf7e8d3025747b5f7c7822ac2d99920.zip
Refactor proxies to nextpnr.
Diffstat (limited to 'common')
-rw-r--r--common/nextpnr.cc11
-rw-r--r--common/nextpnr.h170
-rw-r--r--common/place_common.cc2
-rw-r--r--common/place_common.h2
-rw-r--r--common/placer1.cc4
-rw-r--r--common/router1.cc4
6 files changed, 155 insertions, 38 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 3861e5fe..54df5de1 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -21,6 +21,17 @@
NEXTPNR_NAMESPACE_BEGIN
+MutateContext BaseCtx::rwproxy(void)
+{
+ return MutateContext(reinterpret_cast<Arch *>(this));
+}
+
+ReadContext BaseCtx::rproxy(void) const
+{
+ return ReadContext(reinterpret_cast<const Arch *>(this));
+}
+
+
assertion_failure::assertion_failure(std::string msg, std::string expr_str, std::string filename, int line)
: runtime_error("Assertion failure: " + msg + " (" + filename + ":" + std::to_string(line) + ")"), msg(msg),
expr_str(expr_str), filename(filename), line(line)
diff --git a/common/nextpnr.h b/common/nextpnr.h
index efcab9fc..c3fb913c 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -26,6 +26,7 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>
+#include <boost/thread/shared_mutex.hpp>
#ifndef NEXTPNR_H
#define NEXTPNR_H
@@ -248,21 +249,37 @@ struct UIUpdatesRequired
std::unordered_set<GroupId> groupUIReload;
};
-struct BaseCtx
+class ReadContext;
+class MutateContext;
+class BaseReadCtx;
+class BaseMutateCtx;
+
+// Data that every architecture object should contain.
+class BaseCtx
{
- // --------------------------------------------------------------
+ friend class ReadContext;
+ friend class MutateContext;
+ friend class BaseReadCtx;
+ friend class BaseMutateCtx;
+private:
+ mutable boost::shared_mutex mtx_;
- mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
- mutable std::vector<const std::string *> *idstring_idx_to_str;
+ bool allUiReload = false;
+ bool frameUiReload = false;
+ std::unordered_set<BelId> belUiReload;
+ std::unordered_set<WireId> wireUiReload;
+ std::unordered_set<PipId> pipUiReload;
+ std::unordered_set<GroupId> groupUiReload;
+public:
IdString id(const std::string &s) const { return IdString(this, s); }
-
IdString id(const char *s) const { return IdString(this, s); }
- // --------------------------------------------------------------
-
+ // TODO(q3k): These need to be made private.
std::unordered_map<IdString, std::unique_ptr<NetInfo>> nets;
std::unordered_map<IdString, std::unique_ptr<CellInfo>> cells;
+ mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
+ mutable std::vector<const std::string *> *idstring_idx_to_str;
BaseCtx()
{
@@ -286,41 +303,83 @@ struct BaseCtx
// --------------------------------------------------------------
- bool allUiReload = false;
- bool frameUiReload = false;
- std::unordered_set<BelId> belUiReload;
- std::unordered_set<WireId> wireUiReload;
- std::unordered_set<PipId> pipUiReload;
- std::unordered_set<GroupId> groupUiReload;
+ // Get a readwrite proxy to arch - this will keep a readwrite lock on the
+ // entire architecture until the proxy object goes out of scope.
+ MutateContext rwproxy(void);
+ // Get a read-only proxy to arch - this will keep a read lock on the
+ // entire architecture until the proxy object goes out of scope. Other read
+ // locks can be taken while this one still exists. Ie., the UI can draw
+ // elements while the PnR is going a RO operation.
+ ReadContext rproxy(void) const;
+
+};
- void refreshUi() { allUiReload = true; }
+// State-accessing read-only methods that every architecture object should
+// contain.
+class BaseReadCtx
+{
+protected:
+ const BaseCtx *base_;
+public:
+ BaseReadCtx(const BaseCtx *base) : base_(base) {}
+};
+
+// State-accesssing read/write methods that every architecture object should
+// contain.
+class BaseMutateCtx
+{
+protected:
+ BaseCtx *base_;
+
+public:
+ BaseMutateCtx(BaseCtx *base) : base_(base) {}
+
+ void refreshUi(void)
+ {
+ base_->allUiReload = true;
+ }
- void refreshUiFrame() { frameUiReload = true; }
+ void refreshUiFrame(void)
+ {
+ base_->frameUiReload = true;
+ }
- void refreshUiBel(BelId bel) { belUiReload.insert(bel); }
+ void refreshUiBel(BelId bel)
+ {
+ base_->belUiReload.insert(bel);
+ }
- void refreshUiWire(WireId wire) { wireUiReload.insert(wire); }
+ void refreshUiWire(WireId wire)
+ {
+ base_->wireUiReload.insert(wire);
+ }
- void refreshUiPip(PipId pip) { pipUiReload.insert(pip); }
+ void refreshUiPip(PipId pip)
+ {
+ base_->pipUiReload.insert(pip);
+ }
- void refreshUiGroup(GroupId group) { groupUiReload.insert(group); }
+ void refreshUiGroup(GroupId group)
+ {
+ base_->groupUiReload.insert(group);
+ }
UIUpdatesRequired getUIUpdatesRequired(void)
{
UIUpdatesRequired req;
- req.allUIReload = allUiReload;
- req.frameUIReload = frameUiReload;
- req.belUIReload = belUiReload;
- req.wireUIReload = wireUiReload;
- req.pipUIReload = pipUiReload;
- req.groupUIReload = groupUiReload;
-
- allUiReload = false;
- frameUiReload = false;
- belUiReload.clear();
- wireUiReload.clear();
- pipUiReload.clear();
- groupUiReload.clear();
+ req.allUIReload = base_->allUiReload;
+ req.frameUIReload = base_->frameUiReload;
+ req.belUIReload = base_->belUiReload;
+ req.wireUIReload = base_->wireUiReload;
+ req.pipUIReload = base_->pipUiReload;
+ req.groupUIReload = base_->groupUiReload;
+
+ base_->allUiReload = false;
+ base_->frameUiReload = false;
+ base_->belUiReload.clear();
+ base_->wireUiReload.clear();
+ base_->pipUiReload.clear();
+ base_->groupUiReload.clear();
return req;
}
};
@@ -331,6 +390,53 @@ NEXTPNR_NAMESPACE_END
NEXTPNR_NAMESPACE_BEGIN
+// Read proxy to access ReadMethods while holding lock on underlying BaseCtx.
+class ReadContext : public ArchReadMethods
+{
+ friend class BaseCtx;
+private:
+ boost::shared_mutex *lock_;
+ ReadContext(const Arch *parent) : ArchReadMethods(parent), lock_(&parent->mtx_)
+ {
+ lock_->lock_shared();
+ }
+public:
+ ~ReadContext()
+ {
+ if (lock_ != nullptr) {
+ lock_->unlock_shared();
+ }
+ }
+ ReadContext(ReadContext &&other): ArchReadMethods(other), lock_(other.lock_)
+ {
+ other.lock_ = nullptr;
+ }
+};
+
+// Read proxy to access MutateMethods while holding lock on underlying BaseCtx.
+class MutateContext : public ArchReadMethods, public ArchMutateMethods
+{
+ friend class BaseCtx;
+private:
+ boost::shared_mutex *lock_;
+ MutateContext(Arch *parent) : ArchReadMethods(parent), ArchMutateMethods(parent), lock_(&parent->mtx_)
+ {
+ lock_->lock();
+ }
+public:
+ ~MutateContext()
+ {
+ if (lock_ != nullptr) {
+ lock_->unlock();
+ }
+ }
+ MutateContext(MutateContext &&other): ArchReadMethods(other), ArchMutateMethods(other), lock_(other.lock_)
+ {
+ other.lock_ = nullptr;
+ }
+};
+
+
struct Context : Arch
{
bool verbose = false;
diff --git a/common/place_common.cc b/common/place_common.cc
index 48416370..9694b6fe 100644
--- a/common/place_common.cc
+++ b/common/place_common.cc
@@ -26,7 +26,7 @@
NEXTPNR_NAMESPACE_BEGIN
// Placing a single cell
-bool place_single_cell(ArchRWProxy &proxy, Context *ctx, CellInfo *cell, bool require_legality)
+bool place_single_cell(MutateContext &proxy, Context *ctx, CellInfo *cell, bool require_legality)
{
bool all_placed = false;
int iters = 25;
diff --git a/common/place_common.h b/common/place_common.h
index 57e82510..96ac48a9 100644
--- a/common/place_common.h
+++ b/common/place_common.h
@@ -109,7 +109,7 @@ wirelen_t get_cell_wirelength_at_bel(const T &proxy, const Context *ctx, CellInf
}
// Place a single cell in the lowest wirelength Bel available, optionally requiring validity check
-bool place_single_cell(ArchRWProxy &proxy, Context *ctx, CellInfo *cell, bool require_legality);
+bool place_single_cell(MutateContext &proxy, Context *ctx, CellInfo *cell, bool require_legality);
NEXTPNR_NAMESPACE_END
diff --git a/common/placer1.cc b/common/placer1.cc
index 0e3a84f7..78515ece 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -275,7 +275,7 @@ class SAPlacer
private:
// Initial random placement
- void place_initial(ArchRWProxy &proxy, CellInfo *cell)
+ void place_initial(MutateContext &proxy, CellInfo *cell)
{
bool all_placed = false;
int iters = 25;
@@ -325,7 +325,7 @@ class SAPlacer
}
// Attempt a SA position swap, return true on success or false on failure
- bool try_swap_position(ArchRWProxy &proxy, CellInfo *cell, BelId newBel)
+ bool try_swap_position(MutateContext &proxy, CellInfo *cell, BelId newBel)
{
static std::unordered_set<NetInfo *> update;
static std::vector<std::pair<IdString, wirelen_t>> new_lengths;
diff --git a/common/router1.cc b/common/router1.cc
index 0d26a36d..f7a7e8a2 100644
--- a/common/router1.cc
+++ b/common/router1.cc
@@ -74,7 +74,7 @@ struct RipupScoreboard
std::unordered_map<std::pair<IdString, PipId>, int, hash_id_pip> netPipScores;
};
-void ripup_net(ArchRWProxy &proxy, Context *ctx, IdString net_name)
+void ripup_net(MutateContext &proxy, Context *ctx, IdString net_name)
{
auto net_info = ctx->nets.at(net_name).get();
std::vector<PipId> pips;
@@ -115,7 +115,7 @@ struct Router
delay_t maxDelay = 0.0;
WireId failedDest;
- void route(ArchRWProxy &proxy, const std::unordered_map<WireId, delay_t> &src_wires, WireId dst_wire)
+ void route(MutateContext &proxy, const std::unordered_map<WireId, delay_t> &src_wires, WireId dst_wire)
{
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;