Refactor proxies to nextpnr.
This commit is contained in:
parent
a38b4fa173
commit
9b17fe385c
@ -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)
|
||||
|
168
common/nextpnr.h
168
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; }
|
||||
};
|
||||
|
||||
void refreshUiFrame() { frameUiReload = 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) {}
|
||||
};
|
||||
|
||||
void refreshUiBel(BelId bel) { belUiReload.insert(bel); }
|
||||
// State-accesssing read/write methods that every architecture object should
|
||||
// contain.
|
||||
class BaseMutateCtx
|
||||
{
|
||||
protected:
|
||||
BaseCtx *base_;
|
||||
|
||||
void refreshUiWire(WireId wire) { wireUiReload.insert(wire); }
|
||||
public:
|
||||
BaseMutateCtx(BaseCtx *base) : base_(base) {}
|
||||
|
||||
void refreshUiPip(PipId pip) { pipUiReload.insert(pip); }
|
||||
void refreshUi(void)
|
||||
{
|
||||
base_->allUiReload = true;
|
||||
}
|
||||
|
||||
void refreshUiGroup(GroupId group) { groupUiReload.insert(group); }
|
||||
void refreshUiFrame(void)
|
||||
{
|
||||
base_->frameUiReload = true;
|
||||
}
|
||||
|
||||
void refreshUiBel(BelId bel)
|
||||
{
|
||||
base_->belUiReload.insert(bel);
|
||||
}
|
||||
|
||||
void refreshUiWire(WireId wire)
|
||||
{
|
||||
base_->wireUiReload.insert(wire);
|
||||
}
|
||||
|
||||
void refreshUiPip(PipId pip)
|
||||
{
|
||||
base_->pipUiReload.insert(pip);
|
||||
}
|
||||
|
||||
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;
|
||||
req.allUIReload = base_->allUiReload;
|
||||
req.frameUIReload = base_->frameUiReload;
|
||||
req.belUIReload = base_->belUiReload;
|
||||
req.wireUIReload = base_->wireUiReload;
|
||||
req.pipUIReload = base_->pipUiReload;
|
||||
req.groupUIReload = base_->groupUiReload;
|
||||
|
||||
allUiReload = false;
|
||||
frameUiReload = false;
|
||||
belUiReload.clear();
|
||||
wireUiReload.clear();
|
||||
pipUiReload.clear();
|
||||
groupUiReload.clear();
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -29,18 +29,6 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
ArchRWProxy Arch::rwproxy(void) {
|
||||
ArchRWProxy res(this);
|
||||
return res;
|
||||
}
|
||||
|
||||
ArchRProxy Arch::rproxy(void) const {
|
||||
ArchRProxy res(this);
|
||||
return res;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
IdString Arch::belTypeToId(BelType type) const
|
||||
{
|
||||
if (type == TYPE_ICESTORM_LC)
|
||||
@ -534,7 +522,7 @@ DecalXY Arch::getGroupDecal(GroupId group) const
|
||||
return decalxy;
|
||||
};
|
||||
|
||||
std::vector<GraphicElement> ArchRProxyMethods::getDecalGraphics(DecalId decal) const
|
||||
std::vector<GraphicElement> ArchReadMethods::getDecalGraphics(DecalId decal) const
|
||||
{
|
||||
std::vector<GraphicElement> ret;
|
||||
|
||||
@ -732,25 +720,25 @@ bool Arch::isGlobalNet(const NetInfo *net) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
bool ArchRProxyMethods::checkBelAvail(BelId bel) const
|
||||
bool ArchReadMethods::checkBelAvail(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return bel_to_cell[bel.index] == IdString();
|
||||
}
|
||||
|
||||
IdString ArchRProxyMethods::getBoundBelCell(BelId bel) const
|
||||
IdString ArchReadMethods::getBoundBelCell(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return bel_to_cell[bel.index];
|
||||
}
|
||||
|
||||
IdString ArchRProxyMethods::getConflictingBelCell(BelId bel) const
|
||||
IdString ArchReadMethods::getConflictingBelCell(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return bel_to_cell[bel.index];
|
||||
}
|
||||
|
||||
WireId ArchRProxyMethods::getWireBelPin(BelId bel, PortPin pin) const
|
||||
WireId ArchReadMethods::getWireBelPin(BelId bel, PortPin pin) const
|
||||
{
|
||||
WireId ret;
|
||||
|
||||
@ -768,7 +756,7 @@ WireId ArchRProxyMethods::getWireBelPin(BelId bel, PortPin pin) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
WireId ArchRProxyMethods::getWireByName(IdString name) const
|
||||
WireId ArchReadMethods::getWireByName(IdString name) const
|
||||
{
|
||||
WireId ret;
|
||||
|
||||
@ -784,25 +772,25 @@ WireId ArchRProxyMethods::getWireByName(IdString name) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ArchRProxyMethods::checkWireAvail(WireId wire) const
|
||||
bool ArchReadMethods::checkWireAvail(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return wire_to_net[wire.index] == IdString();
|
||||
}
|
||||
|
||||
IdString ArchRProxyMethods::getBoundWireNet(WireId wire) const
|
||||
IdString ArchReadMethods::getBoundWireNet(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return wire_to_net[wire.index];
|
||||
}
|
||||
|
||||
IdString ArchRProxyMethods::getConflictingWireNet(WireId wire) const
|
||||
IdString ArchReadMethods::getConflictingWireNet(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return wire_to_net[wire.index];
|
||||
}
|
||||
|
||||
PipId ArchRProxyMethods::getPipByName(IdString name) const
|
||||
PipId ArchReadMethods::getPipByName(IdString name) const
|
||||
{
|
||||
PipId ret;
|
||||
|
||||
@ -821,25 +809,25 @@ PipId ArchRProxyMethods::getPipByName(IdString name) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ArchRProxyMethods::checkPipAvail(PipId pip) const
|
||||
bool ArchReadMethods::checkPipAvail(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString();
|
||||
}
|
||||
|
||||
IdString ArchRProxyMethods::getBoundPipNet(PipId pip) const
|
||||
IdString ArchReadMethods::getBoundPipNet(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return pip_to_net[pip.index];
|
||||
}
|
||||
|
||||
IdString ArchRProxyMethods::getConflictingPipNet(PipId pip) const
|
||||
IdString ArchReadMethods::getConflictingPipNet(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return switches_locked[chip_info->pip_data[pip.index].switch_index];
|
||||
}
|
||||
|
||||
BelId ArchRProxyMethods::getBelByName(IdString name) const
|
||||
BelId ArchReadMethods::getBelByName(IdString name) const
|
||||
{
|
||||
BelId ret;
|
||||
|
||||
@ -857,27 +845,27 @@ BelId ArchRProxyMethods::getBelByName(IdString name) const
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void ArchRWProxyMethods::bindBel(BelId bel, IdString cell, PlaceStrength strength)
|
||||
void ArchMutateMethods::bindBel(BelId bel, IdString cell, PlaceStrength strength)
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
NPNR_ASSERT(bel_to_cell[bel.index] == IdString());
|
||||
bel_to_cell[bel.index] = cell;
|
||||
parent_->cells[cell]->bel = bel;
|
||||
parent_->cells[cell]->belStrength = strength;
|
||||
parent_->refreshUiBel(bel);
|
||||
refreshUiBel(bel);
|
||||
}
|
||||
|
||||
void ArchRWProxyMethods::unbindBel(BelId bel)
|
||||
void ArchMutateMethods::unbindBel(BelId bel)
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
NPNR_ASSERT(bel_to_cell[bel.index] != IdString());
|
||||
parent_->cells[bel_to_cell[bel.index]]->bel = BelId();
|
||||
parent_->cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
|
||||
bel_to_cell[bel.index] = IdString();
|
||||
parent_->refreshUiBel(bel);
|
||||
refreshUiBel(bel);
|
||||
}
|
||||
|
||||
void ArchRWProxyMethods::bindWire(WireId wire, IdString net, PlaceStrength strength)
|
||||
void ArchMutateMethods::bindWire(WireId wire, IdString net, PlaceStrength strength)
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
NPNR_ASSERT(wire_to_net[wire.index] == IdString());
|
||||
@ -885,10 +873,10 @@ void ArchRWProxyMethods::bindWire(WireId wire, IdString net, PlaceStrength stren
|
||||
wire_to_net[wire.index] = net;
|
||||
parent_->nets[net]->wires[wire].pip = PipId();
|
||||
parent_->nets[net]->wires[wire].strength = strength;
|
||||
parent_->refreshUiWire(wire);
|
||||
refreshUiWire(wire);
|
||||
}
|
||||
|
||||
void ArchRWProxyMethods::unbindWire(WireId wire)
|
||||
void ArchMutateMethods::unbindWire(WireId wire)
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
NPNR_ASSERT(wire_to_net[wire.index] != IdString());
|
||||
@ -901,15 +889,15 @@ void ArchRWProxyMethods::unbindWire(WireId wire)
|
||||
if (pip != PipId()) {
|
||||
pip_to_net[pip.index] = IdString();
|
||||
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
|
||||
parent_->refreshUiPip(pip);
|
||||
refreshUiPip(pip);
|
||||
}
|
||||
|
||||
net_wires.erase(it);
|
||||
wire_to_net[wire.index] = IdString();
|
||||
parent_->refreshUiWire(wire);
|
||||
refreshUiWire(wire);
|
||||
}
|
||||
|
||||
void ArchRWProxyMethods::bindPip(PipId pip, IdString net, PlaceStrength strength)
|
||||
void ArchMutateMethods::bindPip(PipId pip, IdString net, PlaceStrength strength)
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
NPNR_ASSERT(pip_to_net[pip.index] == IdString());
|
||||
@ -925,11 +913,11 @@ void ArchRWProxyMethods::bindPip(PipId pip, IdString net, PlaceStrength strength
|
||||
parent_->nets[net]->wires[dst].pip = pip;
|
||||
parent_->nets[net]->wires[dst].strength = strength;
|
||||
|
||||
parent_->refreshUiPip(pip);
|
||||
parent_->refreshUiWire(dst);
|
||||
refreshUiPip(pip);
|
||||
refreshUiWire(dst);
|
||||
}
|
||||
|
||||
void ArchRWProxyMethods::unbindPip(PipId pip)
|
||||
void ArchMutateMethods::unbindPip(PipId pip)
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
NPNR_ASSERT(pip_to_net[pip.index] != IdString());
|
||||
@ -944,18 +932,13 @@ void ArchRWProxyMethods::unbindPip(PipId pip)
|
||||
pip_to_net[pip.index] = IdString();
|
||||
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
|
||||
|
||||
parent_->refreshUiPip(pip);
|
||||
parent_->refreshUiWire(dst);
|
||||
refreshUiPip(pip);
|
||||
refreshUiWire(dst);
|
||||
}
|
||||
|
||||
CellInfo *ArchRWProxyMethods::getCell(IdString cell)
|
||||
CellInfo *ArchMutateMethods::getCell(IdString cell)
|
||||
{
|
||||
return parent_->cells.at(cell).get();
|
||||
}
|
||||
|
||||
UIUpdatesRequired ArchRWProxyMethods::getUIUpdatesRequired(void)
|
||||
{
|
||||
return parent_->getUIUpdatesRequired();
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
130
ice40/arch.h
130
ice40/arch.h
@ -22,9 +22,6 @@
|
||||
#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 ****/
|
||||
@ -330,11 +327,8 @@ struct ArchArgs
|
||||
|
||||
/// Forward declare proxy classes for Arch.
|
||||
|
||||
class ArchRWProxyMethods;
|
||||
class ArchRProxyMethods;
|
||||
class ArchRWProxy;
|
||||
class ArchRProxy;
|
||||
|
||||
class ArchMutateMethods;
|
||||
class ArchReadMethods;
|
||||
|
||||
/// Arch/Context
|
||||
// Arch is the main state class of the PnR algorithms. It keeps note of mapped
|
||||
@ -347,11 +341,8 @@ class ArchRProxy;
|
||||
class Arch : public BaseCtx
|
||||
{
|
||||
// We let proxy methods access our state.
|
||||
friend class ArchRWProxyMethods;
|
||||
friend class ArchRProxyMethods;
|
||||
// We let proxy objects access our mutex.
|
||||
friend class ArchRWProxy;
|
||||
friend class ArchRProxy;
|
||||
friend class ArchMutateMethods;
|
||||
friend class ArchReadMethods;
|
||||
private:
|
||||
// All of the following...
|
||||
std::vector<IdString> bel_to_cell;
|
||||
@ -362,9 +353,6 @@ private:
|
||||
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;
|
||||
@ -372,15 +360,6 @@ public:
|
||||
ArchArgs args;
|
||||
Arch(ArchArgs args);
|
||||
|
||||
// Get a readwrite proxy to arch - this will keep a readwrite lock on the
|
||||
// entire architecture until the proxy object goes out of scope.
|
||||
ArchRWProxy 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.
|
||||
ArchRProxy rproxy(void) const;
|
||||
|
||||
std::string getChipName();
|
||||
|
||||
IdString archId() const { return id("ice40"); }
|
||||
@ -632,22 +611,9 @@ public:
|
||||
};
|
||||
|
||||
// Read-only methods on Arch that require state access.
|
||||
class ArchRProxyMethods {
|
||||
// We let proxy objects access our private constructors.
|
||||
friend class ArchRProxy;
|
||||
friend class ArchRWProxy;
|
||||
class ArchReadMethods : public BaseReadCtx {
|
||||
private:
|
||||
const Arch *parent_;
|
||||
ArchRProxyMethods(const Arch *parent) : parent_(parent), chip_info(parent->chip_info),
|
||||
bel_to_cell(parent->bel_to_cell), wire_to_net(parent->wire_to_net),
|
||||
pip_to_net(parent->pip_to_net), switches_locked(parent->switches_locked),
|
||||
bel_by_name(parent->bel_by_name), wire_by_name(parent->wire_by_name),
|
||||
pip_by_name(parent->pip_by_name) {}
|
||||
ArchRProxyMethods(ArchRProxyMethods &&other) noexcept : ArchRProxyMethods(other.parent_) {}
|
||||
ArchRProxyMethods(const ArchRProxyMethods &other) : ArchRProxyMethods(other.parent_) {}
|
||||
|
||||
// Let methods access hot members directly without having to go through
|
||||
// parent_.
|
||||
const ChipInfoPOD *chip_info;
|
||||
const std::vector<IdString> &bel_to_cell;
|
||||
const std::vector<IdString> &wire_to_net;
|
||||
@ -656,8 +622,17 @@ private:
|
||||
std::unordered_map<IdString, int> &bel_by_name;
|
||||
std::unordered_map<IdString, int> &wire_by_name;
|
||||
std::unordered_map<IdString, int> &pip_by_name;
|
||||
|
||||
public:
|
||||
~ArchRProxyMethods() noexcept { }
|
||||
~ArchReadMethods() noexcept { }
|
||||
ArchReadMethods(const Arch *parent) : BaseReadCtx(parent), parent_(parent),
|
||||
chip_info(parent->chip_info), bel_to_cell(parent->bel_to_cell),
|
||||
wire_to_net(parent->wire_to_net), pip_to_net(parent->pip_to_net),
|
||||
switches_locked(parent->switches_locked),
|
||||
bel_by_name(parent->bel_by_name), wire_by_name(parent->wire_by_name),
|
||||
pip_by_name(parent->pip_by_name) {}
|
||||
ArchReadMethods(ArchReadMethods &&other) noexcept : ArchReadMethods(other.parent_) {}
|
||||
ArchReadMethods(const ArchReadMethods &other) : ArchReadMethods(other.parent_) {}
|
||||
|
||||
/// Perform placement validity checks, returning false on failure (all implemented in arch_place.cc)
|
||||
|
||||
@ -693,44 +668,11 @@ public:
|
||||
std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
|
||||
};
|
||||
|
||||
// A proxy object that keeps an Arch shared/readonly lock until it goes out
|
||||
// of scope. All const/read-only ArchRProxyMethods are available on it.
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
// State mutating methods on Arch.
|
||||
class ArchRWProxyMethods {
|
||||
// We let proxy objects access our private constructors.
|
||||
friend class ArchRWProxy;
|
||||
class ArchMutateMethods : public BaseMutateCtx {
|
||||
friend class MutateContext;
|
||||
private:
|
||||
Arch *parent_;
|
||||
ArchRWProxyMethods(Arch *parent) : parent_(parent), chip_info(parent->chip_info),
|
||||
bel_to_cell(parent->bel_to_cell), wire_to_net(parent->wire_to_net),
|
||||
pip_to_net(parent->pip_to_net), switches_locked(parent->switches_locked),
|
||||
bel_by_name(parent->bel_by_name), wire_by_name(parent->wire_by_name),
|
||||
pip_by_name(parent->pip_by_name) {}
|
||||
ArchRWProxyMethods(ArchRWProxyMethods &&other) : ArchRWProxyMethods(other.parent_) {}
|
||||
ArchRWProxyMethods(const ArchRWProxyMethods &other) : ArchRWProxyMethods(other.parent_) {}
|
||||
|
||||
const ChipInfoPOD *chip_info;
|
||||
std::vector<IdString> &bel_to_cell;
|
||||
std::vector<IdString> &wire_to_net;
|
||||
@ -739,8 +681,17 @@ private:
|
||||
std::unordered_map<IdString, int> &bel_by_name;
|
||||
std::unordered_map<IdString, int> &wire_by_name;
|
||||
std::unordered_map<IdString, int> &pip_by_name;
|
||||
|
||||
public:
|
||||
~ArchRWProxyMethods() {}
|
||||
ArchMutateMethods(Arch *parent) : BaseMutateCtx(parent), parent_(parent),
|
||||
chip_info(parent->chip_info), bel_to_cell(parent->bel_to_cell),
|
||||
wire_to_net(parent->wire_to_net), pip_to_net(parent->pip_to_net),
|
||||
switches_locked(parent->switches_locked),
|
||||
bel_by_name(parent->bel_by_name), wire_by_name(parent->wire_by_name),
|
||||
pip_by_name(parent->pip_by_name) {}
|
||||
ArchMutateMethods(ArchMutateMethods &&other) : ArchMutateMethods(other.parent_) {}
|
||||
ArchMutateMethods(const ArchMutateMethods &other) : ArchMutateMethods(other.parent_) {}
|
||||
~ArchMutateMethods() {}
|
||||
|
||||
void unbindWire(WireId wire);
|
||||
void unbindPip(PipId pip);
|
||||
@ -750,33 +701,6 @@ public:
|
||||
void bindBel(BelId bel, IdString cell, PlaceStrength strength);
|
||||
// Returned pointer is valid as long as Proxy object exists.
|
||||
CellInfo *getCell(IdString cell);
|
||||
|
||||
|
||||
// Methods to be used by UI for detecting whether we need to redraw.
|
||||
UIUpdatesRequired getUIUpdatesRequired(void);
|
||||
};
|
||||
|
||||
// A proxy object that keeps an Arch readwrite lock until it goes out of scope.
|
||||
// All ArchRProxyMethods and ArchRWProxyMethods are available on it.
|
||||
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
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
bool ArchRProxyMethods::logicCellsCompatible(const std::vector<const CellInfo *> &cells) const
|
||||
bool ArchReadMethods::logicCellsCompatible(const std::vector<const CellInfo *> &cells) const
|
||||
{
|
||||
bool dffs_exist = false, dffs_neg = false;
|
||||
const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr;
|
||||
@ -76,7 +76,7 @@ bool ArchRProxyMethods::logicCellsCompatible(const std::vector<const CellInfo *>
|
||||
return locals_count <= 32;
|
||||
}
|
||||
|
||||
bool ArchRProxyMethods::isBelLocationValid(BelId bel) const
|
||||
bool ArchReadMethods::isBelLocationValid(BelId bel) const
|
||||
{
|
||||
if (parent_->getBelType(bel) == TYPE_ICESTORM_LC) {
|
||||
std::vector<const CellInfo *> bel_cells;
|
||||
@ -97,7 +97,7 @@ bool ArchRProxyMethods::isBelLocationValid(BelId bel) const
|
||||
}
|
||||
}
|
||||
|
||||
bool ArchRProxyMethods::isValidBelForCell(CellInfo *cell, BelId bel) const
|
||||
bool ArchReadMethods::isValidBelForCell(CellInfo *cell, BelId bel) const
|
||||
{
|
||||
if (cell->type == parent_->id_icestorm_lc) {
|
||||
NPNR_ASSERT(parent_->getBelType(bel) == TYPE_ICESTORM_LC);
|
||||
|
@ -253,7 +253,7 @@ class PlacementLegaliser
|
||||
}
|
||||
|
||||
// Find Bel closest to a location, meeting chain requirements
|
||||
std::tuple<int, int, int> find_closest_bel(ArchRWProxy &proxy, float target_x, float target_y, CellChain &chain)
|
||||
std::tuple<int, int, int> find_closest_bel(MutateContext &proxy, float target_x, float target_y, CellChain &chain)
|
||||
{
|
||||
std::tuple<int, int, int> best_origin = std::make_tuple(-1, -1, -1);
|
||||
wirelen_t best_wirelength = std::numeric_limits<wirelen_t>::max();
|
||||
@ -283,7 +283,7 @@ class PlacementLegaliser
|
||||
}
|
||||
|
||||
// Split a carry chain into multiple legal chains
|
||||
std::vector<CellChain> split_carry_chain(const ArchRProxy &proxy, CellChain &carryc)
|
||||
std::vector<CellChain> split_carry_chain(const ReadContext &proxy, CellChain &carryc)
|
||||
{
|
||||
bool start_of_chain = true;
|
||||
std::vector<CellChain> chains;
|
||||
@ -335,7 +335,7 @@ class PlacementLegaliser
|
||||
}
|
||||
|
||||
// Place a logic cell at a given grid location, handling rip-up etc
|
||||
void place_lc(ArchRWProxy &proxy, CellInfo *cell, int x, int y, int z)
|
||||
void place_lc(MutateContext &proxy, CellInfo *cell, int x, int y, int z)
|
||||
{
|
||||
auto &loc = logic_bels.at(x).at(y).at(z);
|
||||
NPNR_ASSERT(!loc.second);
|
||||
|
Loading…
Reference in New Issue
Block a user