aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-02-25 11:06:33 +0000
committerDavid Shah <dave@ds0.me>2019-02-25 11:49:25 +0000
commita0fa16439942d15e9be745ec074fc1ba3a2a7c95 (patch)
tree74c27b3a84b726ea4e8f6430bc1a07a7fc5af723 /ecp5
parentf363dd2d3c8d00b4d237208d394ed185203a6890 (diff)
downloadnextpnr-a0fa16439942d15e9be745ec074fc1ba3a2a7c95.tar.gz
nextpnr-a0fa16439942d15e9be745ec074fc1ba3a2a7c95.tar.bz2
nextpnr-a0fa16439942d15e9be745ec074fc1ba3a2a7c95.zip
ecp5: Add criticality-based LUT permutation
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch.cc12
-rw-r--r--ecp5/arch.h2
-rw-r--r--ecp5/arch_place.cc74
-rw-r--r--ecp5/pack.cc1
4 files changed, 88 insertions, 1 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index cc529df8..fdc9c8fc 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -486,7 +486,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y);
return (130 - 25 * args.speed) *
- (4 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
+ (6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
}
bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const
@@ -504,7 +504,17 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
// -----------------------------------------------------------------------
+<<<<<<< HEAD
bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); }
+=======
+bool Arch::place()
+{
+ bool result = placer_heap(getCtx());
+ if (result)
+ permute_luts();
+ return result;
+}
+>>>>>>> 136e030... lut permutation
bool Arch::route()
{
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 992bdb94..59c8638d 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -971,6 +971,8 @@ struct Arch : BaseCtx
void assignArchInfo();
+ void permute_luts();
+
std::vector<std::pair<std::string, std::string>> getTilesAtLocation(int row, int col);
std::string getTileByTypeAndLocation(int row, int col, std::string type) const
{
diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc
index ff70bb5a..e5c9b31f 100644
--- a/ecp5/arch_place.cc
+++ b/ecp5/arch_place.cc
@@ -18,8 +18,10 @@
*/
#include "cells.h"
+#include "design_utils.h"
#include "log.h"
#include "nextpnr.h"
+#include "timing.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
@@ -115,4 +117,76 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
}
}
+void Arch::permute_luts()
+{
+ NetCriticalityMap nc;
+ get_criticalities(getCtx(), &nc);
+
+ std::unordered_map<PortInfo *, size_t> port_to_user;
+ for (auto net : sorted(nets)) {
+ NetInfo *ni = net.second;
+ for (size_t i = 0; i < ni->users.size(); i++) {
+ auto &usr = ni->users.at(i);
+ port_to_user[&(usr.cell->ports.at(usr.port))] = i;
+ }
+ }
+
+ auto proc_lut = [&](CellInfo *ci, int lut) {
+ std::vector<IdString> port_names;
+ for (int i = 0; i < 4; i++)
+ port_names.push_back(id(std::string("ABCD").substr(i, 1) + std::to_string(lut)));
+
+ std::vector<std::pair<float, int>> inputs;
+ std::vector<NetInfo *> orig_nets;
+
+ for (int i = 0; i < 4; i++) {
+ auto &port = ci->ports.at(port_names.at(i));
+ float crit = 0;
+ if (port.net != nullptr && nc.count(port.net->name)) {
+ auto &n = nc.at(port.net->name);
+ size_t usr = port_to_user.at(&port);
+ if (usr < n.criticality.size())
+ crit = n.criticality.at(usr);
+ }
+ orig_nets.push_back(port.net);
+ inputs.emplace_back(crit, i);
+ }
+ // Least critical first (A input is slowest)
+ std::sort(inputs.begin(), inputs.end());
+ for (int i = 0; i < 4; i++) {
+ IdString p = port_names.at(i);
+ // log_info("%s %s %f\n", p.c_str(ctx), port_names.at(inputs.at(i).second).c_str(ctx), inputs.at(i).first);
+ disconnect_port(getCtx(), ci, p);
+ ci->ports.at(p).net = nullptr;
+ if (orig_nets.at(inputs.at(i).second) != nullptr) {
+ connect_port(getCtx(), orig_nets.at(inputs.at(i).second), ci, p);
+ ci->params[id(p.str(this) + "MUX")] = p.str(this);
+ } else {
+ ci->params[id(p.str(this) + "MUX")] = "1";
+ }
+ }
+ // Rewrite function
+ int old_init = int_or_default(ci->params, id("LUT" + std::to_string(lut) + "_INITVAL"), 0);
+ int new_init = 0;
+ for (int i = 0; i < 16; i++) {
+ int old_index = 0;
+ for (int k = 0; k < 4; k++) {
+ if (i & (1 << k))
+ old_index |= (1 << inputs.at(k).second);
+ }
+ if (old_init & (1 << old_index))
+ new_init |= (1 << i);
+ }
+ ci->params[id("LUT" + std::to_string(lut) + "_INITVAL")] = std::to_string(new_init);
+ };
+
+ for (auto cell : sorted(cells)) {
+ CellInfo *ci = cell.second;
+ if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id("MODE"), "LOGIC") == "LOGIC") {
+ proc_lut(ci, 0);
+ proc_lut(ci, 1);
+ }
+ }
+}
+
NEXTPNR_NAMESPACE_END
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index db8c4002..b05aec71 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -27,6 +27,7 @@
#include "design_utils.h"
#include "globals.h"
#include "log.h"
+#include "timing.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN