From 9b17fe385cf7e8d3025747b5f7c7822ac2d99920 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Sat, 14 Jul 2018 11:10:31 +0100 Subject: Refactor proxies to nextpnr. --- common/nextpnr.cc | 11 ++++ common/nextpnr.h | 170 +++++++++++++++++++++++++++++++++++++++---------- common/place_common.cc | 2 +- common/place_common.h | 2 +- common/placer1.cc | 4 +- common/router1.cc | 4 +- 6 files changed, 155 insertions(+), 38 deletions(-) (limited to 'common') 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(this)); +} + +ReadContext BaseCtx::rproxy(void) const +{ + return ReadContext(reinterpret_cast(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 #include #include +#include #ifndef NEXTPNR_H #define NEXTPNR_H @@ -248,21 +249,37 @@ struct UIUpdatesRequired std::unordered_set 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 *idstring_str_to_idx; - mutable std::vector *idstring_idx_to_str; + bool allUiReload = false; + bool frameUiReload = false; + std::unordered_set belUiReload; + std::unordered_set wireUiReload; + std::unordered_set pipUiReload; + std::unordered_set 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> nets; std::unordered_map> cells; + mutable std::unordered_map *idstring_str_to_idx; + mutable std::vector *idstring_idx_to_str; BaseCtx() { @@ -286,41 +303,83 @@ struct BaseCtx // -------------------------------------------------------------- - bool allUiReload = false; - bool frameUiReload = false; - std::unordered_set belUiReload; - std::unordered_set wireUiReload; - std::unordered_set pipUiReload; - std::unordered_set 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 update; static std::vector> 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, 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 pips; @@ -115,7 +115,7 @@ struct Router delay_t maxDelay = 0.0; WireId failedDest; - void route(ArchRWProxy &proxy, const std::unordered_map &src_wires, WireId dst_wire) + void route(MutateContext &proxy, const std::unordered_map &src_wires, WireId dst_wire) { std::priority_queue, QueuedWire::Greater> queue; -- cgit v1.2.3