aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md15
-rw-r--r--common/nextpnr.cc13
-rw-r--r--common/nextpnr.h155
-rw-r--r--common/place_common.cc95
-rw-r--r--common/place_common.h81
-rw-r--r--common/placer1.cc181
-rw-r--r--common/router1.cc107
-rw-r--r--default.nix28
-rw-r--r--ecp5/arch.cc184
-rw-r--r--ecp5/arch.h263
-rw-r--r--ecp5/arch_pybindings.h18
-rw-r--r--ecp5/bitstream.cc5
-rw-r--r--gui/designwidget.cc26
-rw-r--r--gui/fpgaviewwidget.cc142
-rw-r--r--gui/fpgaviewwidget.h77
-rw-r--r--ice40/arch.cc305
-rw-r--r--ice40/arch.h309
-rw-r--r--ice40/arch_place.cc69
-rw-r--r--ice40/arch_pybindings.cc32
-rw-r--r--ice40/arch_pybindings.h18
-rw-r--r--ice40/bitstream.cc13
-rw-r--r--ice40/main.cc24
-rw-r--r--ice40/place_legaliser.cc73
-rw-r--r--nextpnr.nix53
24 files changed, 902 insertions, 1384 deletions
diff --git a/README.md b/README.md
index eb96bd1c..da38500d 100644
--- a/README.md
+++ b/README.md
@@ -78,21 +78,6 @@ Running
`./nextpnr-ecp5 --json ecp5/synth/blinky.json --basecfg ecp5/synth/ulx3s_empty.config --bit ecp5/synth/ulx3s.bit`
- Note that `ulx3s_empty.config` contains fixed/unknown bits to be copied to the output bitstream
- You can also use `--textcfg out.config` to write a text file describing the bitstream for debugging
-
-Nix
----
-
-As an alternative to getting the prerequisites yourself, you can use Nix/NixOS and run the following to get dropped into a shell with nextpnr built:
-
- nix-shell
-
-Or, you can add the `nextpnr.nix` file into your /etc/nixos/configuration.nix:
-
- environment.systemPackages = [
- ...
- ( import /home/q3k/Software/nextpnr/nextpnr.nix )
- ...
- ];
Notes
-------
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 01c1397e..3861e5fe 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -21,10 +21,6 @@
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)
@@ -170,21 +166,20 @@ uint32_t Context::checksum() const
void Context::check() const
{
- auto &&proxy = rproxy();
for (auto &n : nets) {
auto ni = n.second.get();
NPNR_ASSERT(n.first == ni->name);
for (auto &w : ni->wires) {
- NPNR_ASSERT(n.first == proxy.getBoundWireNet(w.first));
+ NPNR_ASSERT(n.first == getBoundWireNet(w.first));
if (w.second.pip != PipId()) {
NPNR_ASSERT(w.first == getPipDstWire(w.second.pip));
- NPNR_ASSERT(n.first == proxy.getBoundPipNet(w.second.pip));
+ NPNR_ASSERT(n.first == getBoundPipNet(w.second.pip));
}
}
}
for (auto w : getWires()) {
- IdString net = proxy.getBoundWireNet(w);
+ IdString net = getBoundWireNet(w);
if (net != IdString()) {
NPNR_ASSERT(nets.at(net)->wires.count(w));
}
@@ -193,7 +188,7 @@ void Context::check() const
for (auto &c : cells) {
NPNR_ASSERT(c.first == c.second->name);
if (c.second->bel != BelId())
- NPNR_ASSERT(proxy.getBoundBelCell(c.second->bel) == c.first);
+ NPNR_ASSERT(getBoundBelCell(c.second->bel) == c.first);
for (auto &port : c.second->ports) {
NetInfo *net = port.second.net;
if (net != nullptr) {
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 6228e653..50465869 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -19,7 +19,6 @@
#include <algorithm>
#include <assert.h>
-#include <boost/thread/shared_mutex.hpp>
#include <memory>
#include <stdexcept>
#include <stdint.h>
@@ -239,48 +238,21 @@ struct CellInfo
std::unordered_map<IdString, IdString> pins;
};
-struct UIUpdatesRequired
+struct BaseCtx
{
- bool allUIReload;
- bool frameUIReload;
- std::unordered_set<BelId> belUIReload;
- std::unordered_set<WireId> wireUIReload;
- std::unordered_set<PipId> pipUIReload;
- std::unordered_set<GroupId> groupUIReload;
-};
-
-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_;
+ // --------------------------------------------------------------
- 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;
+ mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
+ mutable std::vector<const std::string *> *idstring_idx_to_str;
- 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()
{
@@ -288,8 +260,6 @@ class BaseCtx
idstring_idx_to_str = new std::vector<const std::string *>;
IdString::initialize_add(this, "", 0);
IdString::initialize_arch(this);
-
- allUiReload = true;
}
~BaseCtx()
@@ -304,67 +274,24 @@ class BaseCtx
// --------------------------------------------------------------
- // 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;
-};
-
-// 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; }
+ 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;
- void refreshUiFrame(void) { base_->frameUiReload = true; }
+ void refreshUi() { allUiReload = true; }
- void refreshUiBel(BelId bel) { base_->belUiReload.insert(bel); }
+ void refreshUiFrame() { frameUiReload = true; }
- void refreshUiWire(WireId wire) { base_->wireUiReload.insert(wire); }
+ void refreshUiBel(BelId bel) { belUiReload.insert(bel); }
- void refreshUiPip(PipId pip) { base_->pipUiReload.insert(pip); }
+ void refreshUiWire(WireId wire) { wireUiReload.insert(wire); }
- void refreshUiGroup(GroupId group) { base_->groupUiReload.insert(group); }
+ void refreshUiPip(PipId pip) { pipUiReload.insert(pip); }
- UIUpdatesRequired getUIUpdatesRequired(void)
- {
- UIUpdatesRequired req;
- 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;
- }
+ void refreshUiGroup(GroupId group) { groupUiReload.insert(group); }
};
NEXTPNR_NAMESPACE_END
@@ -373,50 +300,6 @@ 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 9694b6fe..60735890 100644
--- a/common/place_common.cc
+++ b/common/place_common.cc
@@ -2,7 +2,6 @@
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 David Shah <david@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
@@ -25,8 +24,84 @@
NEXTPNR_NAMESPACE_BEGIN
+// Get the total estimated wirelength for a net
+wirelen_t get_net_wirelength(const Context *ctx, const NetInfo *net, float &tns)
+{
+ wirelen_t wirelength = 0;
+ int driver_x, driver_y;
+ bool driver_gb;
+ CellInfo *driver_cell = net->driver.cell;
+ if (!driver_cell)
+ return 0;
+ if (driver_cell->bel == BelId())
+ return 0;
+ ctx->estimatePosition(driver_cell->bel, driver_x, driver_y, driver_gb);
+ WireId drv_wire = ctx->getWireBelPin(driver_cell->bel, ctx->portPinFromId(net->driver.port));
+ if (driver_gb)
+ return 0;
+ float worst_slack = 1000;
+ int xmin = driver_x, xmax = driver_x, ymin = driver_y, ymax = driver_y;
+ for (auto load : net->users) {
+ if (load.cell == nullptr)
+ continue;
+ CellInfo *load_cell = load.cell;
+ if (load_cell->bel == BelId())
+ continue;
+ if (ctx->timing_driven) {
+ WireId user_wire = ctx->getWireBelPin(load_cell->bel, ctx->portPinFromId(load.port));
+ delay_t raw_wl = ctx->estimateDelay(drv_wire, user_wire);
+ float slack = ctx->getDelayNS(load.budget) - ctx->getDelayNS(raw_wl);
+ if (slack < 0)
+ tns += slack;
+ worst_slack = std::min(slack, worst_slack);
+ }
+
+ int load_x, load_y;
+ bool load_gb;
+ ctx->estimatePosition(load_cell->bel, load_x, load_y, load_gb);
+ if (load_gb)
+ continue;
+ xmin = std::min(xmin, load_x);
+ ymin = std::min(ymin, load_y);
+ xmax = std::max(xmax, load_x);
+ ymax = std::max(ymax, load_y);
+ }
+ if (ctx->timing_driven) {
+ wirelength = wirelen_t((((ymax - ymin) + (xmax - xmin)) * std::min(5.0, (1.0 + std::exp(-worst_slack / 5)))));
+ } else {
+ wirelength = wirelen_t((ymax - ymin) + (xmax - xmin));
+ }
+
+ return wirelength;
+}
+
+// Get the total wirelength for a cell
+wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell)
+{
+ std::set<IdString> nets;
+ for (auto p : cell->ports) {
+ if (p.second.net)
+ nets.insert(p.second.net->name);
+ }
+ wirelen_t wirelength = 0;
+ float tns = 0;
+ for (auto n : nets) {
+ wirelength += get_net_wirelength(ctx, ctx->nets.at(n).get(), tns);
+ }
+ return wirelength;
+}
+
+wirelen_t get_cell_wirelength_at_bel(const Context *ctx, CellInfo *cell, BelId bel)
+{
+ BelId oldBel = cell->bel;
+ cell->bel = bel;
+ wirelen_t wirelen = get_cell_wirelength(ctx, cell);
+ cell->bel = oldBel;
+ return wirelen;
+}
+
// Placing a single cell
-bool place_single_cell(MutateContext &proxy, Context *ctx, CellInfo *cell, bool require_legality)
+bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
{
bool all_placed = false;
int iters = 25;
@@ -37,13 +112,13 @@ bool place_single_cell(MutateContext &proxy, Context *ctx, CellInfo *cell, bool
CellInfo *ripup_target = nullptr;
BelId ripup_bel = BelId();
if (cell->bel != BelId()) {
- proxy.unbindBel(cell->bel);
+ ctx->unbindBel(cell->bel);
}
BelType targetType = ctx->belTypeFromId(cell->type);
for (auto bel : ctx->getBels()) {
- if (ctx->getBelType(bel) == targetType && (!require_legality || proxy.isValidBelForCell(cell, bel))) {
- if (proxy.checkBelAvail(bel)) {
- wirelen_t wirelen = get_cell_wirelength_at_bel(proxy, ctx, cell, bel);
+ if (ctx->getBelType(bel) == targetType && (!require_legality || ctx->isValidBelForCell(cell, bel))) {
+ if (ctx->checkBelAvail(bel)) {
+ wirelen_t wirelen = get_cell_wirelength_at_bel(ctx, cell, bel);
if (iters >= 4)
wirelen += ctx->rng(25);
if (wirelen <= best_wirelen) {
@@ -51,11 +126,11 @@ bool place_single_cell(MutateContext &proxy, Context *ctx, CellInfo *cell, bool
best_bel = bel;
}
} else {
- wirelen_t wirelen = get_cell_wirelength_at_bel(proxy, ctx, cell, bel);
+ wirelen_t wirelen = get_cell_wirelength_at_bel(ctx, cell, bel);
if (iters >= 4)
wirelen += ctx->rng(25);
if (wirelen <= best_ripup_wirelen) {
- ripup_target = proxy.getCell(proxy.getBoundBelCell(bel));
+ ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
if (ripup_target->belStrength < STRENGTH_STRONG) {
best_ripup_wirelen = wirelen;
ripup_bel = bel;
@@ -73,12 +148,12 @@ bool place_single_cell(MutateContext &proxy, Context *ctx, CellInfo *cell, bool
log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
}
--iters;
- proxy.unbindBel(ripup_target->bel);
+ ctx->unbindBel(ripup_target->bel);
best_bel = ripup_bel;
} else {
all_placed = true;
}
- proxy.bindBel(best_bel, cell->name, STRENGTH_WEAK);
+ ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
cell = ripup_target;
}
diff --git a/common/place_common.h b/common/place_common.h
index dac2e607..67956072 100644
--- a/common/place_common.h
+++ b/common/place_common.h
@@ -22,92 +22,21 @@
#include "nextpnr.h"
-#include <set>
-
NEXTPNR_NAMESPACE_BEGIN
typedef int64_t wirelen_t;
-// Get the total estimated wirelength for a net
-template <typename T> wirelen_t get_net_wirelength(const T &proxy, const Context *ctx, const NetInfo *net, float &tns)
-{
- wirelen_t wirelength = 0;
- int driver_x, driver_y;
- bool driver_gb;
- CellInfo *driver_cell = net->driver.cell;
- if (!driver_cell)
- return 0;
- if (driver_cell->bel == BelId())
- return 0;
- ctx->estimatePosition(driver_cell->bel, driver_x, driver_y, driver_gb);
- WireId drv_wire = proxy.getWireBelPin(driver_cell->bel, ctx->portPinFromId(net->driver.port));
- if (driver_gb)
- return 0;
- float worst_slack = 1000;
- int xmin = driver_x, xmax = driver_x, ymin = driver_y, ymax = driver_y;
- for (auto load : net->users) {
- if (load.cell == nullptr)
- continue;
- CellInfo *load_cell = load.cell;
- if (load_cell->bel == BelId())
- continue;
- if (ctx->timing_driven) {
- WireId user_wire = proxy.getWireBelPin(load_cell->bel, ctx->portPinFromId(load.port));
- delay_t raw_wl = ctx->estimateDelay(drv_wire, user_wire);
- float slack = ctx->getDelayNS(load.budget) - ctx->getDelayNS(raw_wl);
- if (slack < 0)
- tns += slack;
- worst_slack = std::min(slack, worst_slack);
- }
-
- int load_x, load_y;
- bool load_gb;
- ctx->estimatePosition(load_cell->bel, load_x, load_y, load_gb);
- if (load_gb)
- continue;
- xmin = std::min(xmin, load_x);
- ymin = std::min(ymin, load_y);
- xmax = std::max(xmax, load_x);
- ymax = std::max(ymax, load_y);
- }
- if (ctx->timing_driven) {
- wirelength = wirelen_t((((ymax - ymin) + (xmax - xmin)) * std::min(5.0, (1.0 + std::exp(-worst_slack / 5)))));
- } else {
- wirelength = wirelen_t((ymax - ymin) + (xmax - xmin));
- }
-
- return wirelength;
-}
+// Return the wirelength of a net
+wirelen_t get_net_wirelength(const Context *ctx, const NetInfo *net, float &tns);
// Return the wirelength of all nets connected to a cell
-template <typename T> wirelen_t get_cell_wirelength(const T &proxy, const Context *ctx, const CellInfo *cell)
-{
- std::set<IdString> nets;
- for (auto p : cell->ports) {
- if (p.second.net)
- nets.insert(p.second.net->name);
- }
- wirelen_t wirelength = 0;
- float tns = 0;
- for (auto n : nets) {
- wirelength += get_net_wirelength(proxy, ctx, ctx->nets.at(n).get(), tns);
- }
- return wirelength;
-}
+wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell);
// Return the wirelength of all nets connected to a cell, when the cell is at a given bel
-template <typename T>
-wirelen_t get_cell_wirelength_at_bel(const T &proxy, const Context *ctx, CellInfo *cell, BelId bel)
-{
- BelId oldBel = cell->bel;
- cell->bel = bel;
- wirelen_t wirelen = get_cell_wirelength(proxy, ctx, cell);
- cell->bel = oldBel;
- return wirelen;
-}
+wirelen_t get_cell_wirelength_at_bel(const Context *ctx, CellInfo *cell, BelId bel);
// Place a single cell in the lowest wirelength Bel available, optionally requiring validity check
-bool place_single_cell(MutateContext &proxy, Context *ctx, CellInfo *cell, bool require_legality);
+bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality);
NEXTPNR_NAMESPACE_END
diff --git a/common/placer1.cc b/common/placer1.cc
index 78515ece..53295a91 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -3,7 +3,6 @@
*
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
- * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
*
* Simulated annealing implementation based on arachne-pnr
* Copyright (C) 2015-2018 Cotton Seed
@@ -80,33 +79,30 @@ class SAPlacer
log_break();
size_t placed_cells = 0;
- {
- auto &&proxy = ctx->rwproxy();
- // Initial constraints placer
- for (auto &cell_entry : ctx->cells) {
- CellInfo *cell = cell_entry.second.get();
- auto loc = cell->attrs.find(ctx->id("BEL"));
- if (loc != cell->attrs.end()) {
- std::string loc_name = loc->second;
- BelId bel = proxy.getBelByName(ctx->id(loc_name));
- if (bel == BelId()) {
- log_error("No Bel named \'%s\' located for "
- "this chip (processing BEL attribute on \'%s\')\n",
- loc_name.c_str(), cell->name.c_str(ctx));
- }
-
- BelType bel_type = ctx->getBelType(bel);
- if (bel_type != ctx->belTypeFromId(cell->type)) {
- log_error("Bel \'%s\' of type \'%s\' does not match cell "
- "\'%s\' of type \'%s\'",
- loc_name.c_str(), ctx->belTypeToId(bel_type).c_str(ctx), cell->name.c_str(ctx),
- cell->type.c_str(ctx));
- }
+ // Initial constraints placer
+ for (auto &cell_entry : ctx->cells) {
+ CellInfo *cell = cell_entry.second.get();
+ auto loc = cell->attrs.find(ctx->id("BEL"));
+ if (loc != cell->attrs.end()) {
+ std::string loc_name = loc->second;
+ BelId bel = ctx->getBelByName(ctx->id(loc_name));
+ if (bel == BelId()) {
+ log_error("No Bel named \'%s\' located for "
+ "this chip (processing BEL attribute on \'%s\')\n",
+ loc_name.c_str(), cell->name.c_str(ctx));
+ }
- proxy.bindBel(bel, cell->name, STRENGTH_USER);
- locked_bels.insert(bel);
- placed_cells++;
+ BelType bel_type = ctx->getBelType(bel);
+ if (bel_type != ctx->belTypeFromId(cell->type)) {
+ log_error("Bel \'%s\' of type \'%s\' does not match cell "
+ "\'%s\' of type \'%s\'",
+ loc_name.c_str(), ctx->belTypeToId(bel_type).c_str(ctx), cell->name.c_str(ctx),
+ cell->type.c_str(ctx));
}
+
+ ctx->bindBel(bel, cell->name, STRENGTH_USER);
+ locked_bels.insert(bel);
+ placed_cells++;
}
}
int constr_placed_cells = placed_cells;
@@ -126,15 +122,12 @@ class SAPlacer
// Place cells randomly initially
log_info("Creating initial placement for remaining %d cells.\n", int(autoplaced.size()));
- {
- auto &&proxy = ctx->rwproxy();
- for (auto cell : autoplaced) {
- place_initial(proxy, cell);
- placed_cells++;
- if ((placed_cells - constr_placed_cells) % 500 == 0)
- log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells),
- int(autoplaced.size()));
- }
+ for (auto cell : autoplaced) {
+ place_initial(cell);
+ placed_cells++;
+ if ((placed_cells - constr_placed_cells) % 500 == 0)
+ log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells),
+ int(autoplaced.size()));
}
if ((placed_cells - constr_placed_cells) % 500 != 0)
log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells),
@@ -145,13 +138,10 @@ class SAPlacer
// Calculate wirelength after initial placement
curr_wirelength = 0;
curr_tns = 0;
- {
- auto &&proxy = ctx->rproxy();
- for (auto &net : ctx->nets) {
- wirelen_t wl = get_net_wirelength(proxy, ctx, net.second.get(), curr_tns);
- wirelengths[net.first] = wl;
- curr_wirelength += wl;
- }
+ for (auto &net : ctx->nets) {
+ wirelen_t wl = get_net_wirelength(ctx, net.second.get(), curr_tns);
+ wirelengths[net.first] = wl;
+ curr_wirelength += wl;
}
int n_no_progress = 0;
@@ -168,18 +158,15 @@ class SAPlacer
"%.0f, est tns = %.02fns\n",
iter, temp, double(curr_wirelength), curr_tns);
- {
- auto &&proxy = ctx->rwproxy();
- for (int m = 0; m < 15; ++m) {
- // Loop through all automatically placed cells
- for (auto cell : autoplaced) {
- // Find another random Bel for this cell
- BelId try_bel = random_bel_for_cell(cell);
- // If valid, try and swap to a new position and see if
- // the new position is valid/worthwhile
- if (try_bel != BelId() && try_bel != cell->bel)
- try_swap_position(proxy, cell, try_bel);
- }
+ for (int m = 0; m < 15; ++m) {
+ // Loop through all automatically placed cells
+ for (auto cell : autoplaced) {
+ // Find another random Bel for this cell
+ BelId try_bel = random_bel_for_cell(cell);
+ // If valid, try and swap to a new position and see if
+ // the new position is valid/worthwhile
+ if (try_bel != BelId() && try_bel != cell->bel)
+ try_swap_position(cell, try_bel);
}
}
// Heuristic to improve placement on the 8k
@@ -240,33 +227,27 @@ class SAPlacer
// accumulating over time
curr_wirelength = 0;
curr_tns = 0;
- {
- auto &&proxy = ctx->rproxy();
- for (auto &net : ctx->nets) {
- wirelen_t wl = get_net_wirelength(proxy, ctx, net.second.get(), curr_tns);
- wirelengths[net.first] = wl;
- curr_wirelength += wl;
- }
+ for (auto &net : ctx->nets) {
+ wirelen_t wl = get_net_wirelength(ctx, net.second.get(), curr_tns);
+ wirelengths[net.first] = wl;
+ curr_wirelength += wl;
}
}
- {
- // Final post-pacement validitiy check
- auto &&proxy = ctx->rproxy();
- for (auto bel : ctx->getBels()) {
- IdString cell = proxy.getBoundBelCell(bel);
- if (!proxy.isBelLocationValid(bel)) {
- std::string cell_text = "no cell";
- if (cell != IdString())
- cell_text = std::string("cell '") + cell.str(ctx) + "'";
- if (ctx->force) {
- log_warning("post-placement validity check failed for Bel '%s' "
- "(%s)\n",
- ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
- } else {
- log_error("post-placement validity check failed for Bel '%s' "
- "(%s)\n",
- ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
- }
+ // Final post-pacement validitiy check
+ for (auto bel : ctx->getBels()) {
+ IdString cell = ctx->getBoundBelCell(bel);
+ if (!ctx->isBelLocationValid(bel)) {
+ std::string cell_text = "no cell";
+ if (cell != IdString())
+ cell_text = std::string("cell '") + cell.str(ctx) + "'";
+ if (ctx->force) {
+ log_warning("post-placement validity check failed for Bel '%s' "
+ "(%s)\n",
+ ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
+ } else {
+ log_error("post-placement validity check failed for Bel '%s' "
+ "(%s)\n",
+ ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
}
}
}
@@ -275,7 +256,7 @@ class SAPlacer
private:
// Initial random placement
- void place_initial(MutateContext &proxy, CellInfo *cell)
+ void place_initial(CellInfo *cell)
{
bool all_placed = false;
int iters = 25;
@@ -286,12 +267,12 @@ class SAPlacer
CellInfo *ripup_target = nullptr;
BelId ripup_bel = BelId();
if (cell->bel != BelId()) {
- proxy.unbindBel(cell->bel);
+ ctx->unbindBel(cell->bel);
}
BelType targetType = ctx->belTypeFromId(cell->type);
for (auto bel : ctx->getBels()) {
- if (ctx->getBelType(bel) == targetType && (proxy.isValidBelForCell(cell, bel) || !require_legal)) {
- if (proxy.checkBelAvail(bel)) {
+ if (ctx->getBelType(bel) == targetType && (ctx->isValidBelForCell(cell, bel) || !require_legal)) {
+ if (ctx->checkBelAvail(bel)) {
uint64_t score = ctx->rng64();
if (score <= best_score) {
best_score = score;
@@ -301,7 +282,7 @@ class SAPlacer
uint64_t score = ctx->rng64();
if (score <= best_ripup_score) {
best_ripup_score = score;
- ripup_target = ctx->cells.at(proxy.getBoundBelCell(bel)).get();
+ ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
ripup_bel = bel;
}
}
@@ -311,12 +292,12 @@ class SAPlacer
if (iters == 0 || ripup_bel == BelId())
log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
--iters;
- proxy.unbindBel(ripup_target->bel);
+ ctx->unbindBel(ripup_target->bel);
best_bel = ripup_bel;
} else {
all_placed = true;
}
- proxy.bindBel(best_bel, cell->name, STRENGTH_WEAK);
+ ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
// Back annotate location
cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
@@ -325,14 +306,14 @@ class SAPlacer
}
// Attempt a SA position swap, return true on success or false on failure
- bool try_swap_position(MutateContext &proxy, CellInfo *cell, BelId newBel)
+ bool try_swap_position(CellInfo *cell, BelId newBel)
{
static std::unordered_set<NetInfo *> update;
static std::vector<std::pair<IdString, wirelen_t>> new_lengths;
new_lengths.clear();
update.clear();
BelId oldBel = cell->bel;
- IdString other = proxy.getBoundBelCell(newBel);
+ IdString other = ctx->getBoundBelCell(newBel);
CellInfo *other_cell = nullptr;
if (other != IdString()) {
other_cell = ctx->cells[other].get();
@@ -340,9 +321,9 @@ class SAPlacer
return false;
}
wirelen_t new_wirelength = 0, delta;
- proxy.unbindBel(oldBel);
+ ctx->unbindBel(oldBel);
if (other != IdString()) {
- proxy.unbindBel(newBel);
+ ctx->unbindBel(newBel);
}
for (const auto &port : cell->ports)
@@ -355,16 +336,16 @@ class SAPlacer
update.insert(port.second.net);
}
- proxy.bindBel(newBel, cell->name, STRENGTH_WEAK);
+ ctx->bindBel(newBel, cell->name, STRENGTH_WEAK);
if (other != IdString()) {
- proxy.bindBel(oldBel, other_cell->name, STRENGTH_WEAK);
+ ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK);
}
if (require_legal) {
- if (!proxy.isBelLocationValid(newBel) || ((other != IdString() && !proxy.isBelLocationValid(oldBel)))) {
- proxy.unbindBel(newBel);
+ if (!ctx->isBelLocationValid(newBel) || ((other != IdString() && !ctx->isBelLocationValid(oldBel)))) {
+ ctx->unbindBel(newBel);
if (other != IdString())
- proxy.unbindBel(oldBel);
+ ctx->unbindBel(oldBel);
goto swap_fail;
}
}
@@ -375,7 +356,7 @@ class SAPlacer
for (auto net : update) {
new_wirelength -= wirelengths.at(net->name);
float temp_tns = 0;
- wirelen_t net_new_wl = get_net_wirelength<>(proxy, ctx, net, temp_tns);
+ wirelen_t net_new_wl = get_net_wirelength(ctx, net, temp_tns);
new_wirelength += net_new_wl;
new_lengths.push_back(std::make_pair(net->name, net_new_wl));
}
@@ -388,8 +369,8 @@ class SAPlacer
improved = true;
} else {
if (other != IdString())
- proxy.unbindBel(oldBel);
- proxy.unbindBel(newBel);
+ ctx->unbindBel(oldBel);
+ ctx->unbindBel(newBel);
goto swap_fail;
}
curr_wirelength = new_wirelength;
@@ -398,9 +379,9 @@ class SAPlacer
return true;
swap_fail:
- proxy.bindBel(oldBel, cell->name, STRENGTH_WEAK);
+ ctx->bindBel(oldBel, cell->name, STRENGTH_WEAK);
if (other != IdString()) {
- proxy.bindBel(newBel, other, STRENGTH_WEAK);
+ ctx->bindBel(newBel, other, STRENGTH_WEAK);
}
return false;
}
diff --git a/common/router1.cc b/common/router1.cc
index dc75a153..94c7070e 100644
--- a/common/router1.cc
+++ b/common/router1.cc
@@ -2,7 +2,6 @@
* 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
@@ -74,7 +73,7 @@ struct RipupScoreboard
std::unordered_map<std::pair<IdString, PipId>, int, hash_id_pip> netPipScores;
};
-void ripup_net(MutateContext &proxy, Context *ctx, IdString net_name)
+void ripup_net(Context *ctx, IdString net_name)
{
auto net_info = ctx->nets.at(net_name).get();
std::vector<PipId> pips;
@@ -91,10 +90,10 @@ void ripup_net(MutateContext &proxy, Context *ctx, IdString net_name)
}
for (auto pip : pips)
- proxy.unbindPip(pip);
+ ctx->unbindPip(pip);
for (auto wire : wires)
- proxy.unbindWire(wire);
+ ctx->unbindWire(wire);
NPNR_ASSERT(net_info->wires.empty());
}
@@ -115,7 +114,7 @@ struct Router
delay_t maxDelay = 0.0;
WireId failedDest;
- void route(MutateContext &proxy, const std::unordered_map<WireId, delay_t> &src_wires, WireId dst_wire)
+ void route(const std::unordered_map<WireId, delay_t> &src_wires, WireId dst_wire)
{
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
@@ -149,10 +148,10 @@ struct Router
bool foundRipupNet = false;
thisVisitCnt++;
- if (!proxy.checkWireAvail(next_wire)) {
+ if (!ctx->checkWireAvail(next_wire)) {
if (!ripup)
continue;
- IdString ripupWireNet = proxy.getConflictingWireNet(next_wire);
+ IdString ripupWireNet = ctx->getConflictingWireNet(next_wire);
if (ripupWireNet == net_name || ripupWireNet == IdString())
continue;
@@ -167,10 +166,10 @@ struct Router
foundRipupNet = true;
}
- if (!proxy.checkPipAvail(pip)) {
+ if (!ctx->checkPipAvail(pip)) {
if (!ripup)
continue;
- IdString ripupPipNet = proxy.getConflictingPipNet(pip);
+ IdString ripupPipNet = ctx->getConflictingPipNet(pip);
if (ripupPipNet == net_name || ripupPipNet == IdString())
continue;
@@ -228,10 +227,7 @@ struct Router
{
std::unordered_map<WireId, delay_t> src_wires;
src_wires[src_wire] = 0;
- {
- auto &&proxy = ctx->rwproxy();
- route(proxy, src_wires, dst_wire);
- }
+ route(src_wires, dst_wire);
routedOkay = visited.count(dst_wire);
if (ctx->debug) {
@@ -276,7 +272,7 @@ struct Router
if (driver_port_it != net_info->driver.cell->pins.end())
driver_port = driver_port_it->second;
- auto src_wire = ctx->rproxy().getWireBelPin(src_bel, ctx->portPinFromId(driver_port));
+ auto src_wire = ctx->getWireBelPin(src_bel, ctx->portPinFromId(driver_port));
if (src_wire == WireId())
log_error("No wire found for port %s (pin %s) on source cell %s "
@@ -290,10 +286,8 @@ struct Router
std::unordered_map<WireId, delay_t> src_wires;
src_wires[src_wire] = 0;
- auto &&proxy = ctx->rwproxy();
-
- ripup_net(proxy, ctx, net_name);
- proxy.bindWire(src_wire, net_name, STRENGTH_WEAK);
+ ripup_net(ctx, net_name);
+ ctx->bindWire(src_wire, net_name, STRENGTH_WEAK);
std::vector<PortRef> users_array = net_info->users;
ctx->shuffle(users_array);
@@ -318,7 +312,7 @@ struct Router
if (user_port_it != user_it.cell->pins.end())
user_port = user_port_it->second;
- auto dst_wire = proxy.getWireBelPin(dst_bel, ctx->portPinFromId(user_port));
+ auto dst_wire = ctx->getWireBelPin(dst_bel, ctx->portPinFromId(user_port));
if (dst_wire == WireId())
log_error("No wire found for port %s (pin %s) on destination "
@@ -331,7 +325,7 @@ struct Router
log(" Path delay estimate: %.2f\n", float(ctx->estimateDelay(src_wire, dst_wire)));
}
- route(proxy, src_wires, dst_wire);
+ route(src_wires, dst_wire);
if (visited.count(dst_wire) == 0) {
if (ctx->debug)
@@ -340,7 +334,7 @@ struct Router
else if (ripup)
log_info("Failed to route %s -> %s.\n", ctx->getWireName(src_wire).c_str(ctx),
ctx->getWireName(dst_wire).c_str(ctx));
- ripup_net(proxy, ctx, net_name);
+ ripup_net(ctx, net_name);
failedDest = dst_wire;
return;
}
@@ -361,15 +355,15 @@ struct Router
if (src_wires.count(cursor))
break;
- IdString conflicting_wire_net = proxy.getConflictingWireNet(cursor);
+ IdString conflicting_wire_net = ctx->getConflictingWireNet(cursor);
if (conflicting_wire_net != IdString()) {
NPNR_ASSERT(ripup);
NPNR_ASSERT(conflicting_wire_net != net_name);
- proxy.unbindWire(cursor);
- if (!proxy.checkWireAvail(cursor))
- ripup_net(proxy, ctx, conflicting_wire_net);
+ ctx->unbindWire(cursor);
+ if (!ctx->checkWireAvail(cursor))
+ ripup_net(ctx, conflicting_wire_net);
rippedNets.insert(conflicting_wire_net);
scores.wireScores[cursor]++;
@@ -378,15 +372,15 @@ struct Router
}
PipId pip = visited[cursor].pip;
- IdString conflicting_pip_net = proxy.getConflictingPipNet(pip);
+ IdString conflicting_pip_net = ctx->getConflictingPipNet(pip);
if (conflicting_pip_net != IdString()) {
NPNR_ASSERT(ripup);
NPNR_ASSERT(conflicting_pip_net != net_name);
- proxy.unbindPip(pip);
- if (!proxy.checkPipAvail(pip))
- ripup_net(proxy, ctx, conflicting_pip_net);
+ ctx->unbindPip(pip);
+ if (!ctx->checkPipAvail(pip))
+ ripup_net(ctx, conflicting_pip_net);
rippedNets.insert(conflicting_pip_net);
scores.pipScores[visited[cursor].pip]++;
@@ -394,7 +388,7 @@ struct Router
scores.netPipScores[std::make_pair(conflicting_pip_net, visited[cursor].pip)]++;
}
- proxy.bindPip(visited[cursor].pip, net_name, STRENGTH_WEAK);
+ ctx->bindPip(visited[cursor].pip, net_name, STRENGTH_WEAK);
src_wires[cursor] = visited[cursor].delay;
cursor = ctx->getPipSrcWire(visited[cursor].pip);
}
@@ -443,48 +437,45 @@ bool router1(Context *ctx)
delay_t estimatedTotalDelay = 0.0;
int estimatedTotalDelayCnt = 0;
- {
- auto &&proxy = ctx->rproxy();
- for (auto net_name : netsQueue) {
- auto net_info = ctx->nets.at(net_name).get();
+ for (auto net_name : netsQueue) {
+ auto net_info = ctx->nets.at(net_name).get();
- auto src_bel = net_info->driver.cell->bel;
+ auto src_bel = net_info->driver.cell->bel;
- if (src_bel == BelId())
- continue;
+ if (src_bel == BelId())
+ continue;
- IdString driver_port = net_info->driver.port;
+ IdString driver_port = net_info->driver.port;
- auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
- if (driver_port_it != net_info->driver.cell->pins.end())
- driver_port = driver_port_it->second;
+ auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
+ if (driver_port_it != net_info->driver.cell->pins.end())
+ driver_port = driver_port_it->second;
- auto src_wire = proxy.getWireBelPin(src_bel, ctx->portPinFromId(driver_port));
+ auto src_wire = ctx->getWireBelPin(src_bel, ctx->portPinFromId(driver_port));
- if (src_wire == WireId())
- continue;
+ if (src_wire == WireId())
+ continue;
- for (auto &user_it : net_info->users) {
- auto dst_bel = user_it.cell->bel;
+ for (auto &user_it : net_info->users) {
+ auto dst_bel = user_it.cell->bel;
- if (dst_bel == BelId())
- continue;
+ if (dst_bel == BelId())
+ continue;
- IdString user_port = user_it.port;
+ IdString user_port = user_it.port;
- auto user_port_it = user_it.cell->pins.find(user_port);
+ auto user_port_it = user_it.cell->pins.find(user_port);
- if (user_port_it != user_it.cell->pins.end())
- user_port = user_port_it->second;
+ if (user_port_it != user_it.cell->pins.end())
+ user_port = user_port_it->second;
- auto dst_wire = proxy.getWireBelPin(dst_bel, ctx->portPinFromId(user_port));
+ auto dst_wire = ctx->getWireBelPin(dst_bel, ctx->portPinFromId(user_port));
- if (dst_wire == WireId())
- continue;
+ if (dst_wire == WireId())
+ continue;
- estimatedTotalDelay += ctx->estimateDelay(src_wire, dst_wire);
- estimatedTotalDelayCnt++;
- }
+ estimatedTotalDelay += ctx->estimateDelay(src_wire, dst_wire);
+ estimatedTotalDelayCnt++;
}
}
diff --git a/default.nix b/default.nix
deleted file mode 100644
index 664e3669..00000000
--- a/default.nix
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# nextpnr -- Next Generation Place and Route
-#
-# 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
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-
-with import <nixpkgs> {};
-
-stdenv.mkDerivation rec {
- name = "env";
- env = buildEnv { name = name; paths = buildInputs; };
- buildInputs = [
- ( import ./nextpnr.nix )
- ];
-}
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 1938c297..51f4db84 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -151,7 +151,7 @@ IdString Arch::archArgsToId(ArchArgs args) const
// -----------------------------------------------------------------------
-BelId ArchReadMethods::getBelByName(IdString name) const
+BelId Arch::getBelByName(IdString name) const
{
BelId ret;
auto it = bel_by_name.find(name);
@@ -160,9 +160,9 @@ BelId ArchReadMethods::getBelByName(IdString name) const
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(parent_));
+ std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
ret.location = loc;
- const LocationTypePOD *loci = parent_->locInfo(ret);
+ const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < loci->num_bels; i++) {
if (std::strcmp(loci->bel_data[i].name.get(), basename.c_str()) == 0) {
ret.index = i;
@@ -185,14 +185,14 @@ BelRange Arch::getBelsAtSameTile(BelId bel) const
return br;
}
-WireId ArchReadMethods::getWireBelPin(BelId bel, PortPin pin) const
+WireId Arch::getWireBelPin(BelId bel, PortPin pin) const
{
WireId ret;
NPNR_ASSERT(bel != BelId());
- int num_bel_wires = parent_->locInfo(bel)->bel_data[bel.index].num_bel_wires;
- const BelWirePOD *bel_wires = parent_->locInfo(bel)->bel_data[bel.index].bel_wires.get();
+ int num_bel_wires = locInfo(bel)->bel_data[bel.index].num_bel_wires;
+ const BelWirePOD *bel_wires = locInfo(bel)->bel_data[bel.index].bel_wires.get();
for (int i = 0; i < num_bel_wires; i++)
if (bel_wires[i].port == pin) {
ret.location = bel.location + bel_wires[i].rel_wire_loc;
@@ -205,7 +205,7 @@ WireId ArchReadMethods::getWireBelPin(BelId bel, PortPin pin) const
// -----------------------------------------------------------------------
-WireId ArchReadMethods::getWireByName(IdString name) const
+WireId Arch::getWireByName(IdString name) const
{
WireId ret;
auto it = wire_by_name.find(name);
@@ -214,9 +214,9 @@ WireId ArchReadMethods::getWireByName(IdString name) const
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(parent_));
+ std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
ret.location = loc;
- const LocationTypePOD *loci = parent_->locInfo(ret);
+ const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < loci->num_wires; i++) {
if (std::strcmp(loci->wire_data[i].name.get(), basename.c_str()) == 0) {
ret.index = i;
@@ -233,7 +233,7 @@ WireId ArchReadMethods::getWireByName(IdString name) const
// -----------------------------------------------------------------------
-PipId ArchReadMethods::getPipByName(IdString name) const
+PipId Arch::getPipByName(IdString name) const
{
auto it = pip_by_name.find(name);
if (it != pip_by_name.end())
@@ -242,13 +242,13 @@ PipId ArchReadMethods::getPipByName(IdString name) const
PipId ret;
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(parent_));
- const LocationTypePOD *loci = parent_->locInfo(ret);
+ std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
+ const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < loci->num_pips; i++) {
PipId curr;
curr.location = loc;
curr.index = i;
- pip_by_name[parent_->getPipName(curr)] = curr;
+ pip_by_name[getPipName(curr)] = curr;
}
return pip_by_name[name];
}
@@ -296,7 +296,7 @@ bool Arch::route() { return router1(getCtx()); }
// -----------------------------------------------------------------------
-std::vector<GraphicElement> ArchReadMethods::getDecalGraphics(DecalId decalId) const
+std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decalId) const
{
std::vector<GraphicElement> ret;
// FIXME
@@ -315,9 +315,9 @@ DecalXY Arch::getGroupDecal(GroupId pip) const { return {}; };
// -----------------------------------------------------------------------
-bool ArchReadMethods::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; }
+bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; }
-bool ArchReadMethods::isBelLocationValid(BelId bel) const { return true; }
+bool Arch::isBelLocationValid(BelId bel) const { return true; }
// -----------------------------------------------------------------------
@@ -330,156 +330,4 @@ IdString Arch::getPortClock(const CellInfo *cell, IdString port) const { return
bool Arch::isClockPort(const CellInfo *cell, IdString port) const { return false; }
-bool ArchReadMethods::checkWireAvail(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == IdString();
-}
-
-bool ArchReadMethods::checkPipAvail(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == IdString();
-}
-
-bool ArchReadMethods::checkBelAvail(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == IdString();
-}
-
-IdString ArchReadMethods::getConflictingBelCell(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- if (bel_to_cell.find(bel) == bel_to_cell.end())
- return IdString();
- else
- return bel_to_cell.at(bel);
-}
-
-IdString ArchReadMethods::getConflictingWireNet(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- if (wire_to_net.find(wire) == wire_to_net.end())
- return IdString();
- else
- return wire_to_net.at(wire);
-}
-
-IdString ArchReadMethods::getConflictingPipNet(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- if (pip_to_net.find(pip) == pip_to_net.end())
- return IdString();
- else
- return pip_to_net.at(pip);
-}
-
-IdString ArchReadMethods::getBoundWireNet(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- if (wire_to_net.find(wire) == wire_to_net.end())
- return IdString();
- else
- return wire_to_net.at(wire);
-}
-
-IdString ArchReadMethods::getBoundPipNet(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- if (pip_to_net.find(pip) == pip_to_net.end())
- return IdString();
- else
- return pip_to_net.at(pip);
-}
-
-IdString ArchReadMethods::getBoundBelCell(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- if (bel_to_cell.find(bel) == bel_to_cell.end())
- return IdString();
- else
- return bel_to_cell.at(bel);
-}
-
-void ArchMutateMethods::unbindWire(WireId wire)
-{
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire] != IdString());
-
- auto &net_wires = parent_->nets[wire_to_net[wire]]->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] = IdString();
- }
-
- net_wires.erase(it);
- wire_to_net[wire] = IdString();
-}
-
-void ArchMutateMethods::unbindPip(PipId pip)
-{
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip] != IdString());
-
- WireId dst;
- dst.index = parent_->locInfo(pip)->pip_data[pip.index].dst_idx;
- dst.location = pip.location + parent_->locInfo(pip)->pip_data[pip.index].rel_dst_loc;
- NPNR_ASSERT(wire_to_net[dst] != IdString());
- wire_to_net[dst] = IdString();
- parent_->nets[pip_to_net[pip]]->wires.erase(dst);
-
- pip_to_net[pip] = IdString();
-}
-
-void ArchMutateMethods::unbindBel(BelId bel)
-{
- NPNR_ASSERT(bel != BelId());
- NPNR_ASSERT(bel_to_cell[bel] != IdString());
- parent_->cells[bel_to_cell[bel]]->bel = BelId();
- parent_->cells[bel_to_cell[bel]]->belStrength = STRENGTH_NONE;
- bel_to_cell[bel] = IdString();
-}
-
-void ArchMutateMethods::bindWire(WireId wire, IdString net, PlaceStrength strength)
-{
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire] == IdString());
- wire_to_net[wire] = net;
- parent_->nets[net]->wires[wire].pip = PipId();
- parent_->nets[net]->wires[wire].strength = strength;
-}
-
-void ArchMutateMethods::bindPip(PipId pip, IdString net, PlaceStrength strength)
-{
- NPNR_ASSERT(pip != PipId());
- NPNR_ASSERT(pip_to_net[pip] == IdString());
-
- pip_to_net[pip] = net;
-
- WireId dst;
- dst.index = parent_->locInfo(pip)->pip_data[pip.index].dst_idx;
- dst.location = pip.location + parent_->locInfo(pip)->pip_data[pip.index].rel_dst_loc;
- NPNR_ASSERT(wire_to_net[dst] == IdString());
- wire_to_net[dst] = net;
- parent_->nets[net]->wires[dst].pip = pip;
- parent_->nets[net]->wires[dst].strength = strength;
-}
-
-void ArchMutateMethods::bindBel(BelId bel, IdString cell, PlaceStrength strength)
-{
- NPNR_ASSERT(bel != BelId());
- NPNR_ASSERT(bel_to_cell[bel] == IdString());
- bel_to_cell[bel] = cell;
- parent_->cells[cell]->bel = bel;
- parent_->cells[cell]->belStrength = strength;
-}
-
-CellInfo *ArchMutateMethods::getCell(IdString cell) { return parent_->cells.at(cell).get(); }
-
-
-
NEXTPNR_NAMESPACE_END
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 06cf6488..930c488e 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -339,10 +339,8 @@ struct ArchArgs
struct Arch : BaseCtx
{
- // We let proxy methods access our state.
- friend class ArchMutateMethods;
- friend class ArchReadMethods;
-private:
+ const ChipInfoPOD *chip_info;
+
mutable std::unordered_map<IdString, BelId> bel_by_name;
mutable std::unordered_map<IdString, WireId> wire_by_name;
mutable std::unordered_map<IdString, PipId> pip_by_name;
@@ -352,9 +350,6 @@ private:
std::unordered_map<PipId, IdString> pip_to_net;
std::unordered_map<PipId, IdString> switches_locked;
-public:
- const ChipInfoPOD *chip_info;
-
ArchArgs args;
Arch(ArchArgs args);
@@ -371,6 +366,8 @@ public:
// -------------------------------------------------
+ BelId getBelByName(IdString name) const;
+
template <typename Id> const LocationTypePOD *locInfo(Id &id) const
{
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
@@ -386,6 +383,48 @@ public:
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
+ void bindBel(BelId bel, IdString cell, PlaceStrength strength)
+ {
+ NPNR_ASSERT(bel != BelId());
+ NPNR_ASSERT(bel_to_cell[bel] == IdString());
+ bel_to_cell[bel] = cell;
+ cells[cell]->bel = bel;
+ cells[cell]->belStrength = strength;
+ }
+
+ void unbindBel(BelId bel)
+ {
+ NPNR_ASSERT(bel != BelId());
+ NPNR_ASSERT(bel_to_cell[bel] != IdString());
+ cells[bel_to_cell[bel]]->bel = BelId();
+ cells[bel_to_cell[bel]]->belStrength = STRENGTH_NONE;
+ bel_to_cell[bel] = IdString();
+ }
+
+ bool checkBelAvail(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == IdString();
+ }
+
+ IdString getBoundBelCell(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ if (bel_to_cell.find(bel) == bel_to_cell.end())
+ return IdString();
+ else
+ return bel_to_cell.at(bel);
+ }
+
+ IdString getConflictingBelCell(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ if (bel_to_cell.find(bel) == bel_to_cell.end())
+ return IdString();
+ else
+ return bel_to_cell.at(bel);
+ }
+
BelRange getBels() const
{
BelRange range;
@@ -421,6 +460,8 @@ public:
return locInfo(bel)->bel_data[bel.index].type;
}
+ WireId getWireBelPin(BelId bel, PortPin pin) const;
+
BelPin getBelPinUphill(WireId wire) const
{
BelPin ret;
@@ -448,6 +489,8 @@ public:
// -------------------------------------------------
+ WireId getWireByName(IdString name) const;
+
IdString getWireName(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
@@ -460,6 +503,57 @@ public:
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
+ void bindWire(WireId wire, IdString net, PlaceStrength strength)
+ {
+ NPNR_ASSERT(wire != WireId());
+ NPNR_ASSERT(wire_to_net[wire] == IdString());
+ wire_to_net[wire] = net;
+ nets[net]->wires[wire].pip = PipId();
+ nets[net]->wires[wire].strength = strength;
+ }
+
+ void unbindWire(WireId wire)
+ {
+ NPNR_ASSERT(wire != WireId());
+ NPNR_ASSERT(wire_to_net[wire] != IdString());
+
+ auto &net_wires = nets[wire_to_net[wire]]->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] = IdString();
+ }
+
+ net_wires.erase(it);
+ wire_to_net[wire] = IdString();
+ }
+
+ bool checkWireAvail(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == IdString();
+ }
+
+ IdString getBoundWireNet(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ if (wire_to_net.find(wire) == wire_to_net.end())
+ return IdString();
+ else
+ return wire_to_net.at(wire);
+ }
+
+ IdString getConflictingWireNet(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ if (wire_to_net.find(wire) == wire_to_net.end())
+ return IdString();
+ else
+ return wire_to_net.at(wire);
+ }
+
WireRange getWires() const
{
WireRange range;
@@ -475,10 +569,66 @@ public:
// -------------------------------------------------
+ PipId getPipByName(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)
+ {
+ NPNR_ASSERT(pip != PipId());
+ NPNR_ASSERT(pip_to_net[pip] == IdString());
+
+ pip_to_net[pip] = net;
+
+ WireId dst;
+ dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
+ dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
+ NPNR_ASSERT(wire_to_net[dst] == IdString());
+ wire_to_net[dst] = net;
+ nets[net]->wires[dst].pip = pip;
+ nets[net]->wires[dst].strength = strength;
+ }
+
+ void unbindPip(PipId pip)
+ {
+ NPNR_ASSERT(pip != PipId());
+ NPNR_ASSERT(pip_to_net[pip] != IdString());
+
+ WireId dst;
+ dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
+ dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
+ NPNR_ASSERT(wire_to_net[dst] != IdString());
+ wire_to_net[dst] = IdString();
+ nets[pip_to_net[pip]]->wires.erase(dst);
+
+ pip_to_net[pip] = IdString();
+ }
+
+ bool checkPipAvail(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == IdString();
+ }
+
+ IdString getBoundPipNet(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ if (pip_to_net.find(pip) == pip_to_net.end())
+ return IdString();
+ else
+ return pip_to_net.at(pip);
+ }
+
+ IdString getConflictingPipNet(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ if (pip_to_net.find(pip) == pip_to_net.end())
+ return IdString();
+ else
+ return pip_to_net.at(pip);
+ }
+
AllPipRange getPips() const
{
AllPipRange range;
@@ -561,7 +711,6 @@ public:
// -------------------------------------------------
- // TODO(q3k) move this to archproxies?
GroupId getGroupByName(IdString name) const { return GroupId(); }
IdString getGroupName(GroupId group) const { return IdString(); }
std::vector<GroupId> getGroups() const { return std::vector<GroupId>(); }
@@ -572,8 +721,6 @@ public:
// -------------------------------------------------
- // These are also specific to the chip and not state, so they're available
- // on arch directly.
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 20; }
@@ -589,7 +736,8 @@ public:
// -------------------------------------------------
- // TODO(q3k) move this to archproxies?
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
+
DecalXY getFrameDecal() const;
DecalXY getBelDecal(BelId bel) const;
DecalXY getWireDecal(WireId wire) const;
@@ -607,100 +755,11 @@ public:
bool isClockPort(const CellInfo *cell, IdString port) const;
// Return true if a port is a net
bool isGlobalNet(const NetInfo *net) const;
-};
-
-class ArchReadMethods : public BaseReadCtx
-{
- private:
- const Arch *parent_;
- const ChipInfoPOD *chip_info;
- const std::unordered_map<BelId, IdString> &bel_to_cell;
- const std::unordered_map<WireId, IdString> &wire_to_net;
- const std::unordered_map<PipId, IdString> &pip_to_net;
- const std::unordered_map<PipId, IdString> &switches_locked;
- std::unordered_map<IdString, BelId> &bel_by_name;
- std::unordered_map<IdString, WireId> &wire_by_name;
- std::unordered_map<IdString, PipId> &pip_by_name;
-
- public:
- ~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)
- // 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
- // such as conflicting set/reset signals, etc
+ // -------------------------------------------------
+ // Placement validity checks
bool isValidBelForCell(CellInfo *cell, BelId bel) const;
- // Return true whether all Bels at a given location are valid
bool isBelLocationValid(BelId bel) const;
-
- 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;
-
- std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
};
-class ArchMutateMethods : public BaseMutateCtx
-{
- friend class MutateContext;
-
- private:
- Arch *parent_;
- const ChipInfoPOD *chip_info;
-
- std::unordered_map<BelId, IdString> &bel_to_cell;
- std::unordered_map<WireId, IdString> &wire_to_net;
- std::unordered_map<PipId, IdString> &pip_to_net;
- std::unordered_map<PipId, IdString> &switches_locked;
- std::unordered_map<IdString, BelId> &bel_by_name;
- std::unordered_map<IdString, WireId> &wire_by_name;
- std::unordered_map<IdString, PipId> &pip_by_name;
-
- public:
- ~ArchMutateMethods() noexcept {}
- 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) noexcept : ArchMutateMethods(other.parent_) {}
- ArchMutateMethods(const ArchMutateMethods &other) : ArchMutateMethods(other.parent_) {}
-
- 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);
- // Returned pointer is valid as long as Proxy object exists.
- CellInfo *getCell(IdString cell);
-};
-
-
NEXTPNR_NAMESPACE_END
diff --git a/ecp5/arch_pybindings.h b/ecp5/arch_pybindings.h
index 6256af18..a5044f29 100644
--- a/ecp5/arch_pybindings.h
+++ b/ecp5/arch_pybindings.h
@@ -30,11 +30,7 @@ namespace PythonConversion {
template <> struct string_converter<BelId>
{
- BelId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getBelByName(ctx->id(name));
- }
+ BelId from_str(Context *ctx, std::string name) { return ctx->getBelByName(ctx->id(name)); }
std::string to_str(Context *ctx, BelId id)
{
@@ -53,22 +49,14 @@ template <> struct string_converter<BelType>
template <> struct string_converter<WireId>
{
- WireId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getWireByName(ctx->id(name));
- }
+ WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
std::string to_str(Context *ctx, WireId id) { return ctx->getWireName(id).str(ctx); }
};
template <> struct string_converter<PipId>
{
- PipId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getPipByName(ctx->id(name));
- }
+ PipId from_str(Context *ctx, std::string name) { return ctx->getPipByName(ctx->id(name)); }
std::string to_str(Context *ctx, PipId id) { return ctx->getPipName(id).str(ctx); }
};
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc
index b2376391..e70d6bb2 100644
--- a/ecp5/bitstream.cc
+++ b/ecp5/bitstream.cc
@@ -155,7 +155,6 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
{
Trellis::Chip empty_chip(ctx->getChipName());
Trellis::ChipConfig cc;
- auto &&proxy = ctx->rproxy();
std::set<std::string> cib_tiles = {"CIB", "CIB_LR", "CIB_LR_S", "CIB_EFB0", "CIB_EFB1"};
@@ -173,7 +172,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
// Add all set, configurable pips to the config
for (auto pip : ctx->getPips()) {
- if (proxy.getBoundPipNet(pip) != IdString()) {
+ if (ctx->getBoundPipNet(pip) != IdString()) {
if (ctx->getPipType(pip) == 0) { // ignore fixed pips
std::string tile = empty_chip.get_tile_by_position_and_type(pip.location.y, pip.location.x,
ctx->getPipTiletype(pip));
@@ -228,7 +227,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
(ci->ports.find(ctx->id("T")) == ci->ports.end() || ci->ports.at(ctx->id("T")).net == nullptr)) {
// Tie tristate low if unconnected for outputs or bidir
std::string jpt = fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/JPADDT" << pio.back());
- WireId jpt_wire = proxy.getWireByName(ctx->id(jpt));
+ WireId jpt_wire = ctx->getWireByName(ctx->id(jpt));
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin();
WireId cib_wire = ctx->getPipSrcWire(jpt_pip);
std::string cib_tile =
diff --git a/gui/designwidget.cc b/gui/designwidget.cc
index a6ebba5e..edf9f1ec 100644
--- a/gui/designwidget.cc
+++ b/gui/designwidget.cc
@@ -334,14 +334,12 @@ void DesignWidget::onItemSelectionChanged()
return;
}
- auto &&proxy = ctx->rproxy();
-
std::vector<DecalXY> decals;
clearProperties();
if (type == ElementType::BEL) {
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
- BelId bel = proxy.getBelByName(c);
+ BelId bel = ctx->getBelByName(c);
decals.push_back(ctx->getBelDecal(bel));
Q_EMIT selected(decals);
@@ -358,20 +356,20 @@ void DesignWidget::onItemSelectionChanged()
topItem->addSubProperty(typeItem);
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
- availItem->setValue(proxy.checkBelAvail(bel));
+ availItem->setValue(ctx->checkBelAvail(bel));
topItem->addSubProperty(availItem);
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Cell");
- cellItem->setValue(proxy.getBoundBelCell(bel).c_str(ctx));
+ cellItem->setValue(ctx->getBoundBelCell(bel).c_str(ctx));
topItem->addSubProperty(cellItem);
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Cell");
- conflictItem->setValue(proxy.getConflictingBelCell(bel).c_str(ctx));
+ conflictItem->setValue(ctx->getConflictingBelCell(bel).c_str(ctx));
topItem->addSubProperty(conflictItem);
} else if (type == ElementType::WIRE) {
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
- WireId wire = proxy.getWireByName(c);
+ WireId wire = ctx->getWireByName(c);
decals.push_back(ctx->getWireDecal(wire));
Q_EMIT selected(decals);
@@ -384,15 +382,15 @@ void DesignWidget::onItemSelectionChanged()
topItem->addSubProperty(nameItem);
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
- availItem->setValue(proxy.checkWireAvail(wire));
+ availItem->setValue(ctx->checkWireAvail(wire));
topItem->addSubProperty(availItem);
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Net");
- cellItem->setValue(proxy.getBoundWireNet(wire).c_str(ctx));
+ cellItem->setValue(ctx->getBoundWireNet(wire).c_str(ctx));
topItem->addSubProperty(cellItem);
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Net");
- conflictItem->setValue(proxy.getConflictingWireNet(wire).c_str(ctx));
+ conflictItem->setValue(ctx->getConflictingWireNet(wire).c_str(ctx));
topItem->addSubProperty(conflictItem);
BelPin uphill = ctx->getBelPinUphill(wire);
@@ -448,7 +446,7 @@ void DesignWidget::onItemSelectionChanged()
*/
} else if (type == ElementType::PIP) {
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
- PipId pip = proxy.getPipByName(c);
+ PipId pip = ctx->getPipByName(c);
decals.push_back(ctx->getPipDecal(pip));
Q_EMIT selected(decals);
@@ -461,15 +459,15 @@ void DesignWidget::onItemSelectionChanged()
topItem->addSubProperty(nameItem);
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
- availItem->setValue(proxy.checkPipAvail(pip));
+ availItem->setValue(ctx->checkPipAvail(pip));
topItem->addSubProperty(availItem);
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Net");
- cellItem->setValue(proxy.getBoundPipNet(pip).c_str(ctx));
+ cellItem->setValue(ctx->getBoundPipNet(pip).c_str(ctx));
topItem->addSubProperty(cellItem);
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Net");
- conflictItem->setValue(proxy.getConflictingPipNet(pip).c_str(ctx));
+ conflictItem->setValue(ctx->getConflictingPipNet(pip).c_str(ctx));
topItem->addSubProperty(conflictItem);
QtVariantProperty *srcWireItem = readOnlyManager->addProperty(QVariant::String, "Src Wire");
diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc
index f8fefd97..1d0e8b57 100644
--- a/gui/fpgaviewwidget.cc
+++ b/gui/fpgaviewwidget.cc
@@ -23,7 +23,6 @@
#include <QApplication>
#include <QCoreApplication>
#include <QMouseEvent>
-#include <QTimer>
#include <QWidget>
#include "fpgaviewwidget.h"
@@ -196,7 +195,7 @@ bool LineShader::compile(void)
return true;
}
-void LineShader::draw(const LineShaderData &line, const QColor &color, const float thickness, const QMatrix4x4 &projection)
+void LineShader::draw(const LineShaderData &line, const QColor &color, float thickness, const QMatrix4x4 &projection)
{
auto gl = QOpenGLContext::currentContext()->functions();
vao_.bind();
@@ -266,10 +265,6 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) : QOpenGLWidget(parent), lineSha
if (fmt.minorVersion() < 1) {
printf("Could not get OpenGL 3.1 context - trying anyway...\n ");
}
-
- QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(update()));
- timer->start(5000);
}
FPGAViewWidget::~FPGAViewWidget() {}
@@ -293,6 +288,73 @@ void FPGAViewWidget::initializeGL()
glClearColor(backgroundColor_.red() / 255, backgroundColor_.green() / 255, backgroundColor_.blue() / 255, 0.0);
}
+void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal)
+{
+ const float scale = 1.0;
+ float offsetX = 0.0, offsetY = 0.0;
+
+ for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
+ offsetX = decal.x;
+ offsetY = decal.y;
+
+ if (el.type == GraphicElement::G_BOX) {
+ auto line = PolyLine(true);
+ line.point(offsetX + scale * el.x1, offsetY + scale * el.y1);
+ line.point(offsetX + scale * el.x2, offsetY + scale * el.y1);
+ line.point(offsetX + scale * el.x2, offsetY + scale * el.y2);
+ line.point(offsetX + scale * el.x1, offsetY + scale * el.y2);
+ line.build(out);
+ }
+
+ if (el.type == GraphicElement::G_LINE) {
+ PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, offsetY + scale * el.y2)
+ .build(out);
+ }
+ }
+}
+
+void FPGAViewWidget::drawDecal(LineShaderData out[], const DecalXY &decal)
+{
+ const float scale = 1.0;
+ float offsetX = 0.0, offsetY = 0.0;
+
+ for (auto &el : ctx_->getDecalGraphics(decal.decal)) {
+ offsetX = decal.x;
+ offsetY = decal.y;
+
+ if (el.type == GraphicElement::G_BOX) {
+ auto line = PolyLine(true);
+ line.point(offsetX + scale * el.x1, offsetY + scale * el.y1);
+ line.point(offsetX + scale * el.x2, offsetY + scale * el.y1);
+ line.point(offsetX + scale * el.x2, offsetY + scale * el.y2);
+ line.point(offsetX + scale * el.x1, offsetY + scale * el.y2);
+ switch (el.style) {
+ case GraphicElement::G_FRAME:
+ case GraphicElement::G_INACTIVE:
+ case GraphicElement::G_ACTIVE:
+ line.build(out[el.style]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (el.type == GraphicElement::G_LINE) {
+ auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2,
+ offsetY + scale * el.y2);
+ switch (el.style) {
+ case GraphicElement::G_FRAME:
+ case GraphicElement::G_INACTIVE:
+ case GraphicElement::G_ACTIVE:
+ line.build(out[el.style]);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
QMatrix4x4 FPGAViewWidget::getProjection(void)
{
QMatrix4x4 matrix;
@@ -326,44 +388,27 @@ void FPGAViewWidget::paintGL()
}
lineShader_.draw(grid, gridColor_, thick1Px, matrix);
+ LineShaderData shaders[4] = {[GraphicElement::G_FRAME] = LineShaderData(),
+ [GraphicElement::G_HIDDEN] = LineShaderData(),
+ [GraphicElement::G_INACTIVE] = LineShaderData(),
+ [GraphicElement::G_ACTIVE] = LineShaderData()};
+
if (ctx_) {
- auto &&proxy = ctx_->rwproxy();
- auto updates = proxy.getUIUpdatesRequired();
-
- // Collapse all updates to a full redraw.
- // TODO(q3k) fix this.
-
- bool redraw = (updates.allUIReload
- || !updates.belUIReload.empty()
- || !updates.wireUIReload.empty()
- || !updates.pipUIReload.empty()
- || !updates.groupUIReload.empty()
- || updates.frameUIReload);
-
- if (redraw) {
- shaders_[0].clear();
- shaders_[1].clear();
- shaders_[2].clear();
- shaders_[3].clear();
-
- // Draw Bels.
- for (auto bel : ctx_->getBels()) {
- drawDecal(proxy, shaders_, ctx_->getBelDecal(bel));
- }
- // Draw Wires.
- for (auto wire : ctx_->getWires()) {
- drawDecal(proxy, shaders_, ctx_->getWireDecal(wire));
- }
- // Draw Pips.
- for (auto pip : ctx_->getPips()) {
- drawDecal(proxy, shaders_, ctx_->getPipDecal(pip));
- }
- // Draw Groups.
- for (auto group : ctx_->getGroups()) {
- drawDecal(proxy, shaders_, ctx_->getGroupDecal(group));
- }
- // Draw Frame Graphics.
- drawDecal(proxy, shaders_, ctx_->getFrameDecal());
+ // Draw Bels.
+ for (auto bel : ctx_->getBels()) {
+ drawDecal(shaders, ctx_->getBelDecal(bel));
+ }
+ // Draw Wires.
+ for (auto wire : ctx_->getWires()) {
+ drawDecal(shaders, ctx_->getWireDecal(wire));
+ }
+ // Draw Pips.
+ for (auto pip : ctx_->getPips()) {
+ drawDecal(shaders, ctx_->getPipDecal(pip));
+ }
+ // Draw Groups.
+ for (auto group : ctx_->getGroups()) {
+ drawDecal(shaders, ctx_->getGroupDecal(group));
}
if (selectedItemsChanged)
@@ -371,17 +416,16 @@ void FPGAViewWidget::paintGL()
selectedItemsChanged = false;
selectedShader_.clear();
for (auto decal : selectedItems_) {
- drawDecal(proxy, selectedShader_, decal);
+ drawDecal(selectedShader_, decal);
}
}
}
- lineShader_.draw(shaders_[0], gFrameColor_, thick11Px, matrix);
- lineShader_.draw(shaders_[1], gHiddenColor_, thick11Px, matrix);
- lineShader_.draw(shaders_[2], gInactiveColor_, thick11Px, matrix);
- lineShader_.draw(shaders_[3], gActiveColor_, thick11Px, matrix);
+ lineShader_.draw(shaders[0], gFrameColor_, thick11Px, matrix);
+ lineShader_.draw(shaders[1], gHiddenColor_, thick11Px, matrix);
+ lineShader_.draw(shaders[2], gInactiveColor_, thick11Px, matrix);
+ lineShader_.draw(shaders[3], gActiveColor_, thick11Px, matrix);
lineShader_.draw(selectedShader_, gSelectedColor_, thick11Px, matrix);
- //lineShader_.draw(frame, matrix);
}
void FPGAViewWidget::onSelectedArchItem(std::vector<DecalXY> decals)
diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h
index 0a9599c9..dd86277e 100644
--- a/gui/fpgaviewwidget.h
+++ b/gui/fpgaviewwidget.h
@@ -51,6 +51,8 @@ struct LineShaderData
std::vector<GLfloat> miters;
std::vector<GLuint> indices;
+ LineShaderData(void) {}
+
void clear(void)
{
vertices.clear();
@@ -201,7 +203,7 @@ class LineShader
bool compile(void);
// Render a LineShaderData with a given M/V/P transformation.
- void draw(const LineShaderData &data, const QColor &color, const float thickness, const QMatrix4x4 &projection);
+ void draw(const LineShaderData &data, const QColor &color, float thickness, const QMatrix4x4 &projection);
};
class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
@@ -238,76 +240,8 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
-
- template <typename T>
- void drawDecal(const T &proxy, LineShaderData &out, const DecalXY &decal)
- {
- const float scale = 1.0;
- float offsetX = 0.0, offsetY = 0.0;
-
- for (auto &el : proxy.getDecalGraphics(decal.decal)) {
- offsetX = decal.x;
- offsetY = decal.y;
-
- if (el.type == GraphicElement::G_BOX) {
- auto line = PolyLine(true);
- line.point(offsetX + scale * el.x1, offsetY + scale * el.y1);
- line.point(offsetX + scale * el.x2, offsetY + scale * el.y1);
- line.point(offsetX + scale * el.x2, offsetY + scale * el.y2);
- line.point(offsetX + scale * el.x1, offsetY + scale * el.y2);
- line.build(out);
- }
-
- if (el.type == GraphicElement::G_LINE) {
- PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, offsetY + scale * el.y2)
- .build(out);
- }
- }
- }
-
- template <typename T>
- void drawDecal(const T &proxy, LineShaderData out[], const DecalXY &decal)
- {
- const float scale = 1.0;
- float offsetX = 0.0, offsetY = 0.0;
-
- for (auto &el : proxy.getDecalGraphics(decal.decal)) {
- offsetX = decal.x;
- offsetY = decal.y;
-
- if (el.type == GraphicElement::G_BOX) {
- auto line = PolyLine(true);
- line.point(offsetX + scale * el.x1, offsetY + scale * el.y1);
- line.point(offsetX + scale * el.x2, offsetY + scale * el.y1);
- line.point(offsetX + scale * el.x2, offsetY + scale * el.y2);
- line.point(offsetX + scale * el.x1, offsetY + scale * el.y2);
- switch (el.style) {
- case GraphicElement::G_FRAME:
- case GraphicElement::G_INACTIVE:
- case GraphicElement::G_ACTIVE:
- line.build(out[el.style]);
- break;
- default:
- break;
- }
- }
-
- if (el.type == GraphicElement::G_LINE) {
- auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2,
- offsetY + scale * el.y2);
- switch (el.style) {
- case GraphicElement::G_FRAME:
- case GraphicElement::G_INACTIVE:
- case GraphicElement::G_ACTIVE:
- line.build(out[el.style]);
- break;
- default:
- break;
- }
- }
- }
- }
-
+ void drawDecal(LineShaderData &data, const DecalXY &decal);
+ void drawDecal(LineShaderData out[], const DecalXY &decal);
public Q_SLOTS:
void newContext(Context *ctx);
void onSelectedArchItem(std::vector<DecalXY> decals);
@@ -336,7 +270,6 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
QColor gSelectedColor_;
QColor frameColor_;
- LineShaderData shaders_[4];
LineShaderData selectedShader_;
std::vector<DecalXY> selectedItems_;
bool selectedItemsChanged;
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 4727597b..adc37dbd 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -2,7 +2,6 @@
* 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
@@ -29,6 +28,8 @@
NEXTPNR_NAMESPACE_BEGIN
+// -----------------------------------------------------------------------
+
IdString Arch::belTypeToId(BelType type) const
{
if (type == TYPE_ICESTORM_LC)
@@ -238,6 +239,22 @@ IdString Arch::archArgsToId(ArchArgs args) const
// -----------------------------------------------------------------------
+BelId Arch::getBelByName(IdString name) const
+{
+ BelId ret;
+
+ if (bel_by_name.empty()) {
+ for (int i = 0; i < chip_info->num_bels; i++)
+ bel_by_name[id(chip_info->bel_data[i].name.get())] = i;
+ }
+
+ auto it = bel_by_name.find(name);
+ if (it != bel_by_name.end())
+ ret.index = it->second;
+
+ return ret;
+}
+
BelRange Arch::getBelsAtSameTile(BelId bel) const
{
BelRange br;
@@ -256,8 +273,63 @@ BelRange Arch::getBelsAtSameTile(BelId bel) const
return br;
}
+WireId Arch::getWireBelPin(BelId bel, PortPin pin) const
+{
+ WireId ret;
+
+ NPNR_ASSERT(bel != BelId());
+
+ int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires;
+ const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();
+
+ for (int i = 0; i < num_bel_wires; i++)
+ if (bel_wires[i].port == pin) {
+ ret.index = bel_wires[i].wire_index;
+ break;
+ }
+
+ return ret;
+}
+
// -----------------------------------------------------------------------
+WireId Arch::getWireByName(IdString name) const
+{
+ WireId ret;
+
+ if (wire_by_name.empty()) {
+ for (int i = 0; i < chip_info->num_wires; i++)
+ wire_by_name[id(chip_info->wire_data[i].name.get())] = i;
+ }
+
+ auto it = wire_by_name.find(name);
+ if (it != wire_by_name.end())
+ ret.index = it->second;
+
+ return ret;
+}
+
+// -----------------------------------------------------------------------
+
+PipId Arch::getPipByName(IdString name) const
+{
+ PipId ret;
+
+ if (pip_by_name.empty()) {
+ for (int i = 0; i < chip_info->num_pips; i++) {
+ PipId pip;
+ pip.index = i;
+ pip_by_name[getPipName(pip)] = i;
+ }
+ }
+
+ auto it = pip_by_name.find(name);
+ if (it != pip_by_name.end())
+ ret.index = it->second;
+
+ return ret;
+}
+
IdString Arch::getPipName(PipId pip) const
{
NPNR_ASSERT(pip != PipId());
@@ -300,8 +372,6 @@ std::string Arch::getBelPackagePin(BelId bel) const
// -----------------------------------------------------------------------
-// TODO(cliffordvienna): lock all of this
-
GroupId Arch::getGroupByName(IdString name) const
{
for (auto g : getGroups())
@@ -425,7 +495,7 @@ DecalXY Arch::getGroupDecal(GroupId group) const
return decalxy;
};
-std::vector<GraphicElement> ArchReadMethods::getDecalGraphics(DecalId decal) const
+std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
{
std::vector<GraphicElement> ret;
@@ -458,7 +528,7 @@ std::vector<GraphicElement> ArchReadMethods::getDecalGraphics(DecalId decal) con
BelId bel;
bel.index = decal.index;
- auto bel_type = parent_->getBelType(bel);
+ auto bel_type = getBelType(bel);
if (bel_type == TYPE_ICESTORM_LC) {
GraphicElement el;
@@ -533,7 +603,8 @@ std::vector<GraphicElement> ArchReadMethods::getDecalGraphics(DecalId decal) con
}
if (bel_type == TYPE_ICESTORM_RAM) {
- for (int i = 0; i < 2; i++) {
+ for (int i = 0; i < 2; i++)
+ {
int tx = chip_info->bel_data[bel.index].x;
int ty = chip_info->bel_data[bel.index].y + i;
@@ -543,7 +614,7 @@ std::vector<GraphicElement> ArchReadMethods::getDecalGraphics(DecalId decal) con
el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1;
- el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + 7 * logic_cell_pitch;
+ el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + 7*logic_cell_pitch;
el.z = 0;
ret.push_back(el);
@@ -620,224 +691,4 @@ bool Arch::isGlobalNet(const NetInfo *net) const
return net->driver.cell != nullptr && net->driver.port == id_glb_buf_out;
}
-// -----------------------------------------------------------------------
-
-bool ArchReadMethods::checkBelAvail(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell[bel.index] == IdString();
-}
-
-IdString ArchReadMethods::getBoundBelCell(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell[bel.index];
-}
-
-IdString ArchReadMethods::getConflictingBelCell(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell[bel.index];
-}
-
-WireId ArchReadMethods::getWireBelPin(BelId bel, PortPin pin) const
-{
- WireId ret;
-
- NPNR_ASSERT(bel != BelId());
-
- int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires;
- const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();
-
- for (int i = 0; i < num_bel_wires; i++)
- if (bel_wires[i].port == pin) {
- ret.index = bel_wires[i].wire_index;
- break;
- }
-
- return ret;
-}
-
-WireId ArchReadMethods::getWireByName(IdString name) const
-{
- WireId ret;
-
- if (wire_by_name.empty()) {
- for (int i = 0; i < chip_info->num_wires; i++)
- wire_by_name[parent_->id(chip_info->wire_data[i].name.get())] = i;
- }
-
- auto it = wire_by_name.find(name);
- if (it != wire_by_name.end())
- ret.index = it->second;
-
- return ret;
-}
-
-bool ArchReadMethods::checkWireAvail(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- return wire_to_net[wire.index] == IdString();
-}
-
-IdString ArchReadMethods::getBoundWireNet(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- return wire_to_net[wire.index];
-}
-
-IdString ArchReadMethods::getConflictingWireNet(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- return wire_to_net[wire.index];
-}
-
-PipId ArchReadMethods::getPipByName(IdString name) const
-{
- PipId ret;
-
- if (pip_by_name.empty()) {
- for (int i = 0; i < chip_info->num_pips; i++) {
- PipId pip;
- pip.index = i;
- pip_by_name[parent_->getPipName(pip)] = i;
- }
- }
-
- auto it = pip_by_name.find(name);
- if (it != pip_by_name.end())
- ret.index = it->second;
-
- return ret;
-}
-
-bool ArchReadMethods::checkPipAvail(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString();
-}
-
-IdString ArchReadMethods::getBoundPipNet(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- return pip_to_net[pip.index];
-}
-
-IdString ArchReadMethods::getConflictingPipNet(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- return switches_locked[chip_info->pip_data[pip.index].switch_index];
-}
-
-BelId ArchReadMethods::getBelByName(IdString name) const
-{
- BelId ret;
-
- if (bel_by_name.empty()) {
- for (int i = 0; i < chip_info->num_bels; i++)
- bel_by_name[parent_->id(chip_info->bel_data[i].name.get())] = i;
- }
-
- auto it = bel_by_name.find(name);
- if (it != bel_by_name.end())
- ret.index = it->second;
-
- return ret;
-}
-
-// -----------------------------------------------------------------------
-
-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;
- refreshUiBel(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();
- refreshUiBel(bel);
-}
-
-void ArchMutateMethods::bindWire(WireId wire, IdString net, PlaceStrength strength)
-{
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire.index] == IdString());
-
- wire_to_net[wire.index] = net;
- parent_->nets[net]->wires[wire].pip = PipId();
- parent_->nets[net]->wires[wire].strength = strength;
- refreshUiWire(wire);
-}
-
-void ArchMutateMethods::unbindWire(WireId wire)
-{
- NPNR_ASSERT(wire != WireId());
- NPNR_ASSERT(wire_to_net[wire.index] != IdString());
-
- auto &net_wires = parent_->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();
- refreshUiPip(pip);
- }
-
- net_wires.erase(it);
- wire_to_net[wire.index] = IdString();
- refreshUiWire(wire);
-}
-
-void ArchMutateMethods::bindPip(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;
- parent_->nets[net]->wires[dst].pip = pip;
- parent_->nets[net]->wires[dst].strength = strength;
-
- refreshUiPip(pip);
- refreshUiWire(dst);
-}
-
-void ArchMutateMethods::unbindPip(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();
- parent_->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();
-
- refreshUiPip(pip);
- refreshUiWire(dst);
-}
-
-CellInfo *ArchMutateMethods::getCell(IdString cell) { return parent_->cells.at(cell).get(); }
-
NEXTPNR_NAMESPACE_END
diff --git a/ice40/arch.h b/ice40/arch.h
index 25ed8ebf..a02e0ced 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -2,7 +2,6 @@
* 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
@@ -325,37 +324,19 @@ struct ArchArgs
std::string package;
};
-/// Forward declare proxy classes for Arch.
-
-class ArchMutateMethods;
-class ArchReadMethods;
-
-/// Arch/Context
-// Arch is the main state class of the PnR algorithms. It keeps note of mapped
-// cells/nets, locked switches, etc.
-//
-// In order to mutate state in Arch, you can do one of two things:
-// - directly call one of the wrapper methods to mutate state
-// - get a read or readwrite proxy to the Arch, and call methods on it
-
-class Arch : public BaseCtx
+struct Arch : BaseCtx
{
- // We let proxy methods access our state.
- friend class ArchMutateMethods;
- friend class ArchReadMethods;
+ const ChipInfoPOD *chip_info;
+ const PackageInfoPOD *package_info;
- private:
- 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;
- public:
- const ChipInfoPOD *chip_info;
- const PackageInfoPOD *package_info;
+ 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);
@@ -373,8 +354,7 @@ class Arch : public BaseCtx
// -------------------------------------------------
- /// Methods to get chip info - don't need to use a wrapper, as these are
- /// static per lifetime of object.
+ BelId getBelByName(IdString name) const;
IdString getBelName(BelId bel) const
{
@@ -384,6 +364,42 @@ class Arch : public BaseCtx
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
+ void 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;
+ cells[cell]->bel = bel;
+ cells[cell]->belStrength = strength;
+ }
+
+ void unbindBel(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
+ {
+ NPNR_ASSERT(bel != BelId());
+ return bel_to_cell[bel.index] == IdString();
+ }
+
+ IdString getBoundBelCell(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ return bel_to_cell[bel.index];
+ }
+
+ IdString getConflictingBelCell(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ return bel_to_cell[bel.index];
+ }
+
BelRange getBels() const
{
BelRange range;
@@ -397,11 +413,11 @@ class Arch : public BaseCtx
BelRange range;
// FIXME
#if 0
- if (type == "TYPE_A") {
- range.b.cursor = bels_type_a_begin;
- range.e.cursor = bels_type_a_end;
- }
- ...
+ if (type == "TYPE_A") {
+ range.b.cursor = bels_type_a_begin;
+ range.e.cursor = bels_type_a_end;
+ }
+ ...
#endif
return range;
}
@@ -414,6 +430,8 @@ class Arch : public BaseCtx
return chip_info->bel_data[bel.index].type;
}
+ WireId getWireBelPin(BelId bel, PortPin pin) const;
+
BelPin getBelPinUphill(WireId wire) const
{
BelPin ret;
@@ -438,6 +456,8 @@ class Arch : public BaseCtx
// -------------------------------------------------
+ WireId getWireByName(IdString name) const;
+
IdString getWireName(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
@@ -446,6 +466,115 @@ class Arch : public BaseCtx
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
+ void bindWire(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)
+ {
+ 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
+ {
+ NPNR_ASSERT(wire != WireId());
+ return wire_to_net[wire.index] == IdString();
+ }
+
+ IdString getBoundWireNet(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ return wire_to_net[wire.index];
+ }
+
+ IdString getConflictingWireNet(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ return wire_to_net[wire.index];
+ }
+
+ WireRange getWires() const
+ {
+ WireRange range;
+ range.b.cursor = 0;
+ range.e.cursor = chip_info->num_wires;
+ return range;
+ }
+
+ // -------------------------------------------------
+
+ PipId getPipByName(IdString name) const;
+
+ void bindPip(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)
+ {
+ 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
+ {
+ NPNR_ASSERT(pip != PipId());
+ return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString();
+ }
+
+ IdString getBoundPipNet(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ return pip_to_net[pip.index];
+ }
+
+ IdString getConflictingPipNet(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ return switches_locked[chip_info->pip_data[pip.index].switch_index];
+ }
+
AllPipRange getPips() const
{
AllPipRange range;
@@ -453,7 +582,7 @@ class Arch : public BaseCtx
range.e.cursor = chip_info->num_pips;
return range;
}
-
+
IdString getPipName(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
@@ -509,20 +638,11 @@ class Arch : public BaseCtx
return range;
}
- WireRange getWires() const
- {
- WireRange range;
- range.b.cursor = 0;
- range.e.cursor = chip_info->num_wires;
- return range;
- }
-
BelId getPackagePinBel(const std::string &pin) const;
std::string getBelPackagePin(BelId bel) const;
// -------------------------------------------------
- // TODO(q3k) move this to archproxies?
GroupId getGroupByName(IdString name) const;
IdString getGroupName(GroupId group) const;
std::vector<GroupId> getGroups() const;
@@ -533,8 +653,6 @@ class Arch : public BaseCtx
// -------------------------------------------------
- // These are also specific to the chip and not state, so they're available
- // on arch directly.
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 20; }
@@ -550,7 +668,8 @@ class Arch : public BaseCtx
// -------------------------------------------------
- // TODO(q3k) move this to archproxies?
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
+
DecalXY getFrameDecal() const;
DecalXY getBelDecal(BelId bel) const;
DecalXY getWireDecal(WireId wire) const;
@@ -571,106 +690,24 @@ class Arch : public BaseCtx
// -------------------------------------------------
- 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;
-};
+ // Perform placement validity checks, returning false on failure (all implemented in arch_place.cc)
-// Read-only methods on Arch that require state access.
-class ArchReadMethods : public BaseReadCtx
-{
- private:
- const Arch *parent_;
- const ChipInfoPOD *chip_info;
- const std::vector<IdString> &bel_to_cell;
- const std::vector<IdString> &wire_to_net;
- const std::vector<IdString> &pip_to_net;
- const std::vector<IdString> &switches_locked;
- 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:
- ~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)
// 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
// such as conflicting set/reset signals, etc
bool isValidBelForCell(CellInfo *cell, BelId bel) const;
+
// Return true whether all Bels at a given location are valid
bool isBelLocationValid(BelId bel) const;
+
// Helper function for above
bool logicCellsCompatible(const std::vector<const CellInfo *> &cells) const;
- 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;
-
- std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
-};
-
-// State mutating methods on Arch.
-class ArchMutateMethods : public BaseMutateCtx
-{
- friend class MutateContext;
-
- private:
- Arch *parent_;
- const ChipInfoPOD *chip_info;
- std::vector<IdString> &bel_to_cell;
- std::vector<IdString> &wire_to_net;
- std::vector<IdString> &pip_to_net;
- std::vector<IdString> &switches_locked;
- 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:
- 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);
- 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);
- // Returned pointer is valid as long as Proxy object exists.
- CellInfo *getCell(IdString cell);
+ 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;
};
NEXTPNR_NAMESPACE_END
diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc
index 42efceab..dc1bc3eb 100644
--- a/ice40/arch_place.cc
+++ b/ice40/arch_place.cc
@@ -3,7 +3,6 @@
*
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
* Copyright (C) 2018 David Shah <david@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
@@ -25,44 +24,44 @@
NEXTPNR_NAMESPACE_BEGIN
-bool ArchReadMethods::logicCellsCompatible(const std::vector<const CellInfo *> &cells) const
+bool Arch::logicCellsCompatible(const std::vector<const CellInfo *> &cells) const
{
bool dffs_exist = false, dffs_neg = false;
const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr;
int locals_count = 0;
for (auto cell : cells) {
- if (bool_or_default(cell->params, parent_->id_dff_en)) {
+ if (bool_or_default(cell->params, id_dff_en)) {
if (!dffs_exist) {
dffs_exist = true;
- cen = get_net_or_empty(cell, parent_->id_cen);
- clk = get_net_or_empty(cell, parent_->id_clk);
- sr = get_net_or_empty(cell, parent_->id_sr);
+ cen = get_net_or_empty(cell, id_cen);
+ clk = get_net_or_empty(cell, id_clk);
+ sr = get_net_or_empty(cell, id_sr);
- if (!parent_->isGlobalNet(cen) && cen != nullptr)
+ if (!isGlobalNet(cen) && cen != nullptr)
locals_count++;
- if (!parent_->isGlobalNet(clk) && clk != nullptr)
+ if (!isGlobalNet(clk) && clk != nullptr)
locals_count++;
- if (!parent_->isGlobalNet(sr) && sr != nullptr)
+ if (!isGlobalNet(sr) && sr != nullptr)
locals_count++;
- if (bool_or_default(cell->params, parent_->id_neg_clk)) {
+ if (bool_or_default(cell->params, id_neg_clk)) {
dffs_neg = true;
}
} else {
- if (cen != get_net_or_empty(cell, parent_->id_cen))
+ if (cen != get_net_or_empty(cell, id_cen))
return false;
- if (clk != get_net_or_empty(cell, parent_->id_clk))
+ if (clk != get_net_or_empty(cell, id_clk))
return false;
- if (sr != get_net_or_empty(cell, parent_->id_sr))
+ if (sr != get_net_or_empty(cell, id_sr))
return false;
- if (dffs_neg != bool_or_default(cell->params, parent_->id_neg_clk))
+ if (dffs_neg != bool_or_default(cell->params, id_neg_clk))
return false;
}
}
- const NetInfo *i0 = get_net_or_empty(cell, parent_->id_i0), *i1 = get_net_or_empty(cell, parent_->id_i1),
- *i2 = get_net_or_empty(cell, parent_->id_i2), *i3 = get_net_or_empty(cell, parent_->id_i3);
+ const NetInfo *i0 = get_net_or_empty(cell, id_i0), *i1 = get_net_or_empty(cell, id_i1),
+ *i2 = get_net_or_empty(cell, id_i2), *i3 = get_net_or_empty(cell, id_i3);
if (i0 != nullptr)
locals_count++;
if (i1 != nullptr)
@@ -76,14 +75,14 @@ bool ArchReadMethods::logicCellsCompatible(const std::vector<const CellInfo *> &
return locals_count <= 32;
}
-bool ArchReadMethods::isBelLocationValid(BelId bel) const
+bool Arch::isBelLocationValid(BelId bel) const
{
- if (parent_->getBelType(bel) == TYPE_ICESTORM_LC) {
+ if (getBelType(bel) == TYPE_ICESTORM_LC) {
std::vector<const CellInfo *> bel_cells;
- for (auto bel_other : parent_->getBelsAtSameTile(bel)) {
+ for (auto bel_other : getBelsAtSameTile(bel)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) {
- const CellInfo *ci_other = parent_->cells.at(cell_other).get();
+ const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other);
}
}
@@ -93,40 +92,40 @@ bool ArchReadMethods::isBelLocationValid(BelId bel) const
if (cellId == IdString())
return true;
else
- return isValidBelForCell(parent_->cells.at(cellId).get(), bel);
+ return isValidBelForCell(cells.at(cellId).get(), bel);
}
}
-bool ArchReadMethods::isValidBelForCell(CellInfo *cell, BelId bel) const
+bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
{
- if (cell->type == parent_->id_icestorm_lc) {
- NPNR_ASSERT(parent_->getBelType(bel) == TYPE_ICESTORM_LC);
+ if (cell->type == id_icestorm_lc) {
+ NPNR_ASSERT(getBelType(bel) == TYPE_ICESTORM_LC);
std::vector<const CellInfo *> bel_cells;
- for (auto bel_other : parent_->getBelsAtSameTile(bel)) {
+ for (auto bel_other : getBelsAtSameTile(bel)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) {
- const CellInfo *ci_other = parent_->cells.at(cell_other).get();
+ const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other);
}
}
bel_cells.push_back(cell);
return logicCellsCompatible(bel_cells);
- } else if (cell->type == parent_->id_sb_io) {
- return parent_->getBelPackagePin(bel) != "";
- } else if (cell->type == parent_->id_sb_gb) {
+ } else if (cell->type == id_sb_io) {
+ return getBelPackagePin(bel) != "";
+ } else if (cell->type == id_sb_gb) {
bool is_reset = false, is_cen = false;
- NPNR_ASSERT(cell->ports.at(parent_->id_glb_buf_out).net != nullptr);
- for (auto user : cell->ports.at(parent_->id_glb_buf_out).net->users) {
- if (is_reset_port(parent_, user))
+ NPNR_ASSERT(cell->ports.at(id_glb_buf_out).net != nullptr);
+ for (auto user : cell->ports.at(id_glb_buf_out).net->users) {
+ if (is_reset_port(this, user))
is_reset = true;
- if (is_enable_port(parent_, user))
+ if (is_enable_port(this, user))
is_cen = true;
}
- IdString glb_net = parent_->getWireName(getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
- int glb_id = std::stoi(std::string("") + glb_net.str(parent_).back());
+ IdString glb_net = getWireName(getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
+ int glb_id = std::stoi(std::string("") + glb_net.str(this).back());
if (is_reset && is_cen)
return false;
else if (is_reset)
diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc
index a2a90191..fd5109b4 100644
--- a/ice40/arch_pybindings.cc
+++ b/ice40/arch_pybindings.cc
@@ -65,13 +65,25 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getBelType), &Context::getBelType, conv_to_str<BelType>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelType");
+ fn_wrapper_1a<Context, decltype(&Context::checkBelAvail), &Context::checkBelAvail, pass_through<bool>,
+ conv_from_str<BelId>>::def_wrap(ctx_cls, "checkBelAvail");
fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum");
+ fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>,
+ conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel");
+ fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap(
+ ctx_cls, "unbindBel");
+ fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, conv_to_str<IdString>,
+ conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell");
+ fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
+ conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
"getBels");
fn_wrapper_1a<Context, decltype(&Context::getBelsAtSameTile), &Context::getBelsAtSameTile, wrap_context<BelRange>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelsAtSameTile");
+ fn_wrapper_2a<Context, decltype(&Context::getWireBelPin), &Context::getWireBelPin, conv_to_str<WireId>,
+ conv_from_str<BelId>, conv_from_str<PortPin>>::def_wrap(ctx_cls, "getWireBelPin");
fn_wrapper_1a<Context, decltype(&Context::getBelPinUphill), &Context::getBelPinUphill, wrap_context<BelPin>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getBelPinUphill");
fn_wrapper_1a<Context, decltype(&Context::getBelPinsDownhill), &Context::getBelPinsDownhill,
@@ -79,6 +91,16 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum");
+ fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>,
+ conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire");
+ fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap(
+ ctx_cls, "unbindWire");
+ fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>,
+ conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail");
+ fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, conv_to_str<IdString>,
+ conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet");
+ fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet,
+ conv_to_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap(
ctx_cls, "getWires");
@@ -87,6 +109,16 @@ void arch_wrap_python()
ctx_cls, "getPips");
fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum");
+ fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>,
+ conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip");
+ fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap(
+ ctx_cls, "unbindPip");
+ fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>,
+ conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail");
+ fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, conv_to_str<IdString>,
+ conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet");
+ fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet,
+ conv_to_str<IdString>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet");
fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill");
diff --git a/ice40/arch_pybindings.h b/ice40/arch_pybindings.h
index 7440e29d..e502905f 100644
--- a/ice40/arch_pybindings.h
+++ b/ice40/arch_pybindings.h
@@ -31,11 +31,7 @@ namespace PythonConversion {
template <> struct string_converter<BelId>
{
- BelId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getBelByName(ctx->id(name));
- }
+ BelId from_str(Context *ctx, std::string name) { return ctx->getBelByName(ctx->id(name)); }
std::string to_str(Context *ctx, BelId id)
{
@@ -54,22 +50,14 @@ template <> struct string_converter<BelType>
template <> struct string_converter<WireId>
{
- WireId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getWireByName(ctx->id(name));
- }
+ WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
std::string to_str(Context *ctx, WireId id) { return ctx->getWireName(id).str(ctx); }
};
template <> struct string_converter<PipId>
{
- PipId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getPipByName(ctx->id(name));
- }
+ PipId from_str(Context *ctx, std::string name) { return ctx->getPipByName(ctx->id(name)); }
std::string to_str(Context *ctx, PipId id) { return ctx->getPipName(id).str(ctx); }
};
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index 87a96a22..a62c6c09 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -92,7 +92,6 @@ char get_hexdigit(int i) { return std::string("0123456789ABCDEF").at(i); }
void write_asc(const Context *ctx, std::ostream &out)
{
- auto &&proxy = ctx->rproxy();
// [y][x][row][col]
const ChipInfoPOD &ci = *ctx->chip_info;
const BitstreamInfoPOD &bi = *ci.bits_info;
@@ -129,7 +128,7 @@ void write_asc(const Context *ctx, std::ostream &out)
}
// Set pips
for (auto pip : ctx->getPips()) {
- if (proxy.getBoundPipNet(pip) != IdString()) {
+ if (ctx->pip_to_net[pip.index] != IdString()) {
const PipInfoPOD &pi = ci.pip_data[pip.index];
const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
for (int i = 0; i < swi.num_bits; i++) {
@@ -200,8 +199,8 @@ void write_asc(const Context *ctx, std::ostream &out)
NPNR_ASSERT(iez != -1);
bool input_en = false;
- if (!proxy.checkWireAvail(proxy.getWireBelPin(bel, PIN_D_IN_0)) ||
- !proxy.checkWireAvail(proxy.getWireBelPin(bel, PIN_D_IN_1))) {
+ if ((ctx->wire_to_net[ctx->getWireBelPin(bel, PIN_D_IN_0).index] != IdString()) ||
+ (ctx->wire_to_net[ctx->getWireBelPin(bel, PIN_D_IN_1).index] != IdString())) {
input_en = true;
}
@@ -272,7 +271,7 @@ void write_asc(const Context *ctx, std::ostream &out)
}
// Set config bits in unused IO and RAM
for (auto bel : ctx->getBels()) {
- if (proxy.checkBelAvail(bel) && ctx->getBelType(bel) == TYPE_SB_IO) {
+ if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_SB_IO) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z;
@@ -285,7 +284,7 @@ void write_asc(const Context *ctx, std::ostream &out)
set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false);
}
}
- } else if (proxy.checkBelAvail(bel) && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) {
+ } else if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) {
const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y;
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB];
@@ -432,7 +431,7 @@ void write_asc(const Context *ctx, std::ostream &out)
// Write symbols
// const bool write_symbols = 1;
for (auto wire : ctx->getWires()) {
- IdString net = proxy.getBoundWireNet(wire);
+ IdString net = ctx->getBoundWireNet(wire);
if (net != IdString())
out << ".sym " << wire.index << " " << net.str(ctx) << std::endl;
}
diff --git a/ice40/main.cc b/ice40/main.cc
index fdfe1f25..e77bdd34 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -51,8 +51,7 @@ void svg_dump_decal(const Context *ctx, const DecalXY &decal)
const float scale = 10.0, offset = 10.0;
const std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\"";
- auto &&proxy = ctx->rproxy();
- for (auto &el : proxy.getDecalGraphics(decal.decal)) {
+ for (auto &el : ctx->getDecalGraphics(decal.decal)) {
if (el.type == GraphicElement::G_BOX) {
std::cout << "<rect x=\"" << (offset + scale * (decal.x + el.x1)) << "\" y=\""
<< (offset + scale * (decal.y + el.y1)) << "\" height=\"" << (scale * (el.y2 - el.y1))
@@ -304,32 +303,31 @@ int main(int argc, char *argv[])
}
if (vm.count("tmfuzz")) {
- auto &&proxy = ctx->rproxy();
std::vector<WireId> src_wires, dst_wires;
/*for (auto w : ctx->getWires())
src_wires.push_back(w);*/
for (auto b : ctx->getBels()) {
if (ctx->getBelType(b) == TYPE_ICESTORM_LC) {
- src_wires.push_back(proxy.getWireBelPin(b, PIN_O));
+ src_wires.push_back(ctx->getWireBelPin(b, PIN_O));
}
if (ctx->getBelType(b) == TYPE_SB_IO) {
- src_wires.push_back(proxy.getWireBelPin(b, PIN_D_IN_0));
+ src_wires.push_back(ctx->getWireBelPin(b, PIN_D_IN_0));
}
}
for (auto b : ctx->getBels()) {
if (ctx->getBelType(b) == TYPE_ICESTORM_LC) {
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_I0));
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_I1));
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_I2));
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_I3));
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_CEN));
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_CIN));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I0));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I1));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I2));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_I3));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_CEN));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_CIN));
}
if (ctx->getBelType(b) == TYPE_SB_IO) {
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_D_OUT_0));
- dst_wires.push_back(proxy.getWireBelPin(b, PIN_OUTPUT_ENABLE));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_D_OUT_0));
+ dst_wires.push_back(ctx->getWireBelPin(b, PIN_OUTPUT_ENABLE));
}
}
diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc
index fcb47cfd..559358c7 100644
--- a/ice40/place_legaliser.cc
+++ b/ice40/place_legaliser.cc
@@ -119,17 +119,13 @@ class PlacementLegaliser
bool legalise()
{
- log_info("Legalising logic cells...\n");
+ log_info("Legalising design..\n");
init_logic_cells();
- log_info("Legalising carries...\n");
bool legalised_carries = legalise_carries();
if (!legalised_carries && !ctx->force)
return false;
- log_info("Legalising others...\n");
legalise_others();
- log_info("Legalising logic tiles...\n");
legalise_logic_tiles();
- log_info("Replacing cells...\n");
bool replaced_cells = replace_cells();
return legalised_carries && replaced_cells;
}
@@ -137,7 +133,6 @@ class PlacementLegaliser
private:
void init_logic_cells()
{
- auto &&proxy = ctx->rproxy();
for (auto bel : ctx->getBels()) {
// Initialise the logic bels vector with unavailable invalid bels, dimensions [0..width][0..height[0..7]
logic_bels.resize(ctx->chip_info->width + 1,
@@ -148,7 +143,7 @@ class PlacementLegaliser
// Using the non-standard API here to get (x, y, z) rather than just (x, y)
auto bi = ctx->chip_info->bel_data[bel.index];
int x = bi.x, y = bi.y, z = bi.z;
- IdString cell = proxy.getBoundBelCell(bel);
+ IdString cell = ctx->getBoundBelCell(bel);
if (cell != IdString() && ctx->cells.at(cell)->belStrength >= STRENGTH_FIXED)
logic_bels.at(x).at(y).at(z) = std::make_pair(bel, true); // locked out of use
else
@@ -200,33 +195,28 @@ class PlacementLegaliser
}
}
bool success = true;
-
// Find midpoints for all chains, before we start tearing them up
std::vector<CellChain> all_chains;
- {
- auto &&proxy = ctx->rproxy();
- for (auto &base_chain : carry_chains) {
- if (ctx->verbose) {
- log_info("Found carry chain: \n");
- for (auto entry : base_chain.cells)
- log_info(" %s\n", entry->name.c_str(ctx));
- log_info("\n");
- }
- std::vector<CellChain> split_chains = split_carry_chain(proxy, base_chain);
- for (auto &chain : split_chains) {
- get_chain_midpoint(ctx, chain, chain.mid_x, chain.mid_y);
- all_chains.push_back(chain);
- }
+ for (auto &base_chain : carry_chains) {
+ if (ctx->verbose) {
+ log_info("Found carry chain: \n");
+ for (auto entry : base_chain.cells)
+ log_info(" %s\n", entry->name.c_str(ctx));
+ log_info("\n");
+ }
+ std::vector<CellChain> split_chains = split_carry_chain(base_chain);
+ for (auto &chain : split_chains) {
+ get_chain_midpoint(ctx, chain, chain.mid_x, chain.mid_y);
+ all_chains.push_back(chain);
}
}
// Actual chain placement
- auto &&proxy = ctx->rwproxy();
for (auto &chain : all_chains) {
if (ctx->verbose)
log_info("Placing carry chain starting at '%s'\n", chain.cells.front()->name.c_str(ctx));
float base_x = chain.mid_x, base_y = chain.mid_y - (chain.cells.size() / 16.0f);
// Find Bel meeting requirements closest to the target base, returning location as <x, y, z>
- auto chain_origin_bel = find_closest_bel(proxy, base_x, base_y, chain);
+ auto chain_origin_bel = find_closest_bel(base_x, base_y, chain);
int place_x = std::get<0>(chain_origin_bel), place_y = std::get<1>(chain_origin_bel),
place_z = std::get<2>(chain_origin_bel);
if (place_x == -1) {
@@ -243,7 +233,7 @@ class PlacementLegaliser
// Place carry chain
for (int i = 0; i < int(chain.cells.size()); i++) {
int target_z = place_y * 8 + place_z + i;
- place_lc(proxy, chain.cells.at(i), place_x, target_z / 8, target_z % 8);
+ place_lc(chain.cells.at(i), place_x, target_z / 8, target_z % 8);
if (ctx->verbose)
log_info(" Cell '%s' placed at (%d, %d, %d)\n", chain.cells.at(i)->name.c_str(ctx), place_x,
target_z / 8, target_z % 8);
@@ -253,7 +243,7 @@ class PlacementLegaliser
}
// Find Bel closest to a location, meeting chain requirements
- std::tuple<int, int, int> find_closest_bel(MutateContext &proxy, float target_x, float target_y, CellChain &chain)
+ std::tuple<int, int, int> find_closest_bel(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();
@@ -270,7 +260,7 @@ class PlacementLegaliser
valid = false;
break;
} else {
- wirelen += get_cell_wirelength_at_bel(proxy, ctx, chain.cells.at(k), lb.first);
+ wirelen += get_cell_wirelength_at_bel(ctx, chain.cells.at(k), lb.first);
}
}
if (valid && wirelen < best_wirelength) {
@@ -283,7 +273,7 @@ class PlacementLegaliser
}
// Split a carry chain into multiple legal chains
- std::vector<CellChain> split_carry_chain(const ReadContext &proxy, CellChain &carryc)
+ std::vector<CellChain> split_carry_chain(CellChain &carryc)
{
bool start_of_chain = true;
std::vector<CellChain> chains;
@@ -308,7 +298,7 @@ class PlacementLegaliser
}
tile.push_back(cell);
chains.back().cells.push_back(cell);
- bool split_chain = (!proxy.logicCellsCompatible(tile)) || (int(chains.back().cells.size()) > max_length);
+ bool split_chain = (!ctx->logicCellsCompatible(tile)) || (int(chains.back().cells.size()) > max_length);
if (split_chain) {
CellInfo *passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT")));
tile.pop_back();
@@ -335,22 +325,22 @@ class PlacementLegaliser
}
// Place a logic cell at a given grid location, handling rip-up etc
- void place_lc(MutateContext &proxy, CellInfo *cell, int x, int y, int z)
+ void place_lc(CellInfo *cell, int x, int y, int z)
{
auto &loc = logic_bels.at(x).at(y).at(z);
NPNR_ASSERT(!loc.second);
BelId bel = loc.first;
// Check if there is a cell presently at the location, which we will need to rip up
- IdString existing = proxy.getBoundBelCell(bel);
+ IdString existing = ctx->getBoundBelCell(bel);
if (existing != IdString()) {
// TODO: keep track of the previous position of the ripped up cell, as a hint
rippedCells.insert(existing);
- proxy.unbindBel(bel);
+ ctx->unbindBel(bel);
}
if (cell->bel != BelId()) {
- proxy.unbindBel(cell->bel);
+ ctx->unbindBel(cell->bel);
}
- proxy.bindBel(bel, cell->name, STRENGTH_LOCKED);
+ ctx->bindBel(bel, cell->name, STRENGTH_LOCKED);
rippedCells.erase(cell->name); // If cell was ripped up previously, no need to re-place
loc.second = true; // Bel is now unavailable for further use
}
@@ -433,20 +423,19 @@ class PlacementLegaliser
// Legalise logic tiles
void legalise_logic_tiles()
{
- auto &&proxy = ctx->rwproxy();
int width = ctx->chip_info->width, height = ctx->chip_info->height;
for (int x = 1; x < width; x++) {
for (int y = 1; y < height; y++) {
BelId tileBel = logic_bels.at(x).at(y).at(0).first;
if (tileBel != BelId()) {
bool changed = true;
- while (!proxy.isBelLocationValid(tileBel) && changed) {
+ while (!ctx->isBelLocationValid(tileBel) && changed) {
changed = false;
int max_score = 0;
CellInfo *target = nullptr;
for (int z = 0; z < 8; z++) {
BelId bel = logic_bels.at(x).at(y).at(z).first;
- IdString cell = proxy.getBoundBelCell(bel);
+ IdString cell = ctx->getBoundBelCell(bel);
if (cell != IdString()) {
CellInfo *ci = ctx->cells.at(cell).get();
if (ci->belStrength >= STRENGTH_STRONG)
@@ -459,7 +448,7 @@ class PlacementLegaliser
}
}
if (target != nullptr) {
- proxy.unbindBel(target->bel);
+ ctx->unbindBel(target->bel);
rippedCells.insert(target->name);
changed = true;
}
@@ -472,14 +461,13 @@ class PlacementLegaliser
// Legalise other tiles
void legalise_others()
{
- auto &&proxy = ctx->rwproxy();
std::vector<CellInfo *> legalised_others;
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (!is_lc(ctx, ci)) {
if (ci->belStrength < STRENGTH_STRONG && ci->bel != BelId()) {
- if (!proxy.isValidBelForCell(ci, ci->bel)) {
- place_single_cell(proxy, ctx, ci, true);
+ if (!ctx->isValidBelForCell(ci, ci->bel)) {
+ place_single_cell(ctx, ci, true);
}
legalised_others.push_back(ci);
}
@@ -494,11 +482,10 @@ class PlacementLegaliser
// Replace ripped-up cells
bool replace_cells()
{
- auto &&proxy = ctx->rwproxy();
bool success = true;
for (auto cell : sorted(rippedCells)) {
CellInfo *ci = ctx->cells.at(cell).get();
- bool placed = place_single_cell(proxy, ctx, ci, true);
+ bool placed = place_single_cell(ctx, ci, true);
if (!placed) {
if (ctx->force) {
log_warning("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx), ci->type.c_str(ctx));
diff --git a/nextpnr.nix b/nextpnr.nix
deleted file mode 100644
index bbd2c127..00000000
--- a/nextpnr.nix
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# nextpnr -- Next Generation Place and Route
-#
-# 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
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-with import <nixpkgs> {};
-
-let
- gitRev = "a8c84e90a39c54174dd24b5b76bd17aed8311481";
- gitBranch = "master";
-in
- stdenv.mkDerivation rec {
- name = "nextpnr-${version}";
- version = "1.0.0";
-
- src = ./.;
-
- buildInputs = [
- python3 (boost.override { python = python3; })
- qt5.qtbase
- ];
-
- nativeBuildInputs = [ cmake icestorm ];
-
- cmakeFlags= [
- "-DARCH=ice40"
- "-DICEBOX_ROOT=${icestorm}/share/icebox"
- ];
-
- enableParallelBuilding = true;
-
- meta = with stdenv.lib; {
- description = "Next Generation Place-and-Route tool for FPGAs";
- homepage = "https://gitlab.com/symbioticeda/nextpnr";
- license = licenses.bsd0;
- platforms = platforms.linux;
- };
- }
-
-