aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/arch.h
diff options
context:
space:
mode:
authorSergiusz Bazanski <q3k@q3k.org>2018-07-13 12:35:39 +0100
committerSergiusz Bazanski <q3k@q3k.org>2018-07-13 12:35:39 +0100
commit0816f447b768ebe0632f419e9b696714dda4e860 (patch)
tree2001dd1ba033d8cd535c8c72a078f71b5fee757b /ice40/arch.h
parent309a533b7c5eab79addfc2b1733d39c1b48d9aae (diff)
downloadnextpnr-0816f447b768ebe0632f419e9b696714dda4e860.tar.gz
nextpnr-0816f447b768ebe0632f419e9b696714dda4e860.tar.bz2
nextpnr-0816f447b768ebe0632f419e9b696714dda4e860.zip
Make ice40::Arch thread-safe
We move all non-chip data to be private and guard them with an R/W mutex. We then modify all calls that access these fields to lock/shared_lock the mutex as required. Profiling the code before and after is an exercise left to the reader :).
Diffstat (limited to 'ice40/arch.h')
-rw-r--r--ice40/arch.h38
1 files changed, 32 insertions, 6 deletions
diff --git a/ice40/arch.h b/ice40/arch.h
index 04de5178..410df48b 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -21,6 +21,9 @@
#error Include "arch.h" via "nextpnr.h" only.
#endif
+#include <boost/thread/shared_lock_guard.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
NEXTPNR_NAMESPACE_BEGIN
/**** Everything in this section must be kept in sync with chipdb.py ****/
@@ -324,8 +327,17 @@ struct ArchArgs
std::string package;
};
-struct Arch : BaseCtx
+class Arch : public BaseCtx
{
+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;
+ // ... are guarded by the following lock:
+ mutable boost::shared_mutex mtx_;
+public:
const ChipInfoPOD *chip_info;
const PackageInfoPOD *package_info;
@@ -333,11 +345,6 @@ struct Arch : BaseCtx
mutable std::unordered_map<IdString, int> wire_by_name;
mutable std::unordered_map<IdString, int> pip_by_name;
- std::vector<IdString> bel_to_cell;
- std::vector<IdString> wire_to_net;
- std::vector<IdString> pip_to_net;
- std::vector<IdString> switches_locked;
-
ArchArgs args;
Arch(ArchArgs args);
@@ -368,6 +375,7 @@ struct Arch : BaseCtx
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] == IdString());
+ boost::lock_guard<boost::shared_mutex> lock(mtx_);
bel_to_cell[bel.index] = cell;
cells[cell]->bel = bel;
cells[cell]->belStrength = strength;
@@ -377,6 +385,7 @@ struct Arch : BaseCtx
{
NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] != IdString());
+ boost::lock_guard<boost::shared_mutex> lock(mtx_);
cells[bel_to_cell[bel.index]]->bel = BelId();
cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
bel_to_cell[bel.index] = IdString();
@@ -385,18 +394,21 @@ struct Arch : BaseCtx
bool checkBelAvail(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
return bel_to_cell[bel.index] == IdString();
}
IdString getBoundBelCell(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
return bel_to_cell[bel.index];
}
IdString getConflictingBelCell(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
return bel_to_cell[bel.index];
}
@@ -470,6 +482,8 @@ struct Arch : BaseCtx
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] == IdString());
+ boost::lock_guard<boost::shared_mutex> lock(mtx_);
+
wire_to_net[wire.index] = net;
nets[net]->wires[wire].pip = PipId();
nets[net]->wires[wire].strength = strength;
@@ -479,6 +493,7 @@ struct Arch : BaseCtx
{
NPNR_ASSERT(wire != WireId());
NPNR_ASSERT(wire_to_net[wire.index] != IdString());
+ boost::lock_guard<boost::shared_mutex> lock(mtx_);
auto &net_wires = nets[wire_to_net[wire.index]]->wires;
auto it = net_wires.find(wire);
@@ -497,18 +512,24 @@ struct Arch : BaseCtx
bool checkWireAvail(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
+
return wire_to_net[wire.index] == IdString();
}
IdString getBoundWireNet(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
+
return wire_to_net[wire.index];
}
IdString getConflictingWireNet(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
+
return wire_to_net[wire.index];
}
@@ -532,6 +553,7 @@ struct Arch : BaseCtx
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());
+ boost::lock_guard<boost::shared_mutex> lock(mtx_);
pip_to_net[pip.index] = net;
switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
@@ -549,6 +571,7 @@ struct Arch : BaseCtx
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());
+ boost::lock_guard<boost::shared_mutex> lock(mtx_);
WireId dst;
dst.index = chip_info->pip_data[pip.index].dst;
@@ -563,18 +586,21 @@ struct Arch : BaseCtx
bool checkPipAvail(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString();
}
IdString getBoundPipNet(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
return pip_to_net[pip.index];
}
IdString getConflictingPipNet(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
+ boost::shared_lock_guard<boost::shared_mutex> lock(mtx_);
return switches_locked[chip_info->pip_data[pip.index].switch_index];
}