aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-09-29 16:37:18 +0100
committerDavid Shah <davey1576@gmail.com>2018-09-29 16:37:18 +0100
commit4cd582478b84c5d73faf7b43452b4976a612e685 (patch)
tree99678712649755165508dbe114d9a1205e6dc917
parentf7a270a1d868b632bd178f1927d2270aa11e053d (diff)
downloadnextpnr-4cd582478b84c5d73faf7b43452b4976a612e685.tar.gz
nextpnr-4cd582478b84c5d73faf7b43452b4976a612e685.tar.bz2
nextpnr-4cd582478b84c5d73faf7b43452b4976a612e685.zip
ecp5: Adding main global promoter/router function
Signed-off-by: David Shah <davey1576@gmail.com>
-rw-r--r--ecp5/globals.cc76
-rw-r--r--ecp5/globals.h26
2 files changed, 81 insertions, 21 deletions
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 5c5c7c13..b68bed28 100644
--- a/ecp5/globals.cc
+++ b/ecp5/globals.cc
@@ -22,7 +22,7 @@
#include <queue>
#include "nextpnr.h"
#include "cells.h"
-
+#include "globals.h"
#include "log.h"
#define fmt_str(x) (static_cast<const std::ostringstream &>(std::ostringstream() << x).str())
@@ -73,7 +73,7 @@ class Ecp5GlobalRouter
auto max = std::max_element(clockCount.begin(), clockCount.end(),
[](const decltype(clockCount)::value_type &a,
const decltype(clockCount)::value_type &b) { return a.second < b.second; });
- if (max == clockCount.end() || max->second < 3)
+ if (max == clockCount.end() || max->second < 5)
break;
clocks.push_back(ctx->nets.at(max->first).get());
clockCount.erase(max->first);
@@ -190,7 +190,7 @@ class Ecp5GlobalRouter
return ctx->getWireByLocAndBasename(Location(0, 0), get_quad_name(quad) + "PCLK" + std::to_string(network));
}
- void simple_router(NetInfo *net, WireId src, WireId dst)
+ bool simple_router(NetInfo *net, WireId src, WireId dst, bool allow_fail = false)
{
std::queue<WireId> visit;
std::unordered_map<WireId, PipId> backtrace;
@@ -198,6 +198,8 @@ class Ecp5GlobalRouter
WireId cursor;
while (true) {
if (visit.empty() || visit.size() > 50000) {
+ if (allow_fail)
+ return false;
log_error("cannot route global from %s to %s.\n", ctx->getWireName(src).c_str(ctx),
ctx->getWireName(dst).c_str(ctx));
}
@@ -226,58 +228,90 @@ class Ecp5GlobalRouter
ctx->bindPip(fnd->second, net, STRENGTH_LOCKED);
cursor = ctx->getPipSrcWire(fnd->second);
}
+ return true;
}
- void route_onto_global(NetInfo *net, int network)
+ bool route_onto_global(NetInfo *net, int network)
{
WireId glb_src;
- if (net->driver.cell->type == ctx->id("TRELLIS_IO")) {
- std::string ioglb;
- if (!is_global_io(net->driver.cell, ioglb))
- goto non_dedicated;
- glb_src = ctx->getWireByLocAndBasename(Location(0, 0), ioglb);
- }
+ NPNR_ASSERT(net->driver.cell->type == id_DCCA);
+ glb_src = ctx->getNetinfoSourceWire(net);
for (int quad = QUAD_UL; quad < QUAD_LR + 1; quad++) {
WireId glb_dst = get_global_wire(GlobalQuadrant(quad), network);
- simple_router(net, glb_src, glb_dst);
- }
- if (false) {
- non_dedicated:
- log_error("FIXME: currenly global networks can only be driven by dedicated global input pins");
+ bool routed = simple_router(net, glb_src, glb_dst);
+ if (!routed)
+ return false;
}
+ return true;
}
+ // Attempt to place a DCC
+ void place_dcc(CellInfo *dcc) {
+ for (auto bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) == id_DCCA && ctx->checkBelAvail(bel)) {
+ if (ctx->isValidBelForCell(dcc, bel)) {
+ ctx->bindBel(bel, dcc, STRENGTH_LOCKED);
+ return;
+ }
+ }
+ }
+ NPNR_ASSERT_FALSE("failed to place dcca");
+ }
+
// Insert a DCC into a net to promote it to a global
NetInfo *insert_dcc(NetInfo *net)
{
- auto dcc = create_ecp5_cell(ctx, ctx->id("DCCA"), "$gbuf$" + net->name.str(ctx));
+ auto dcc = create_ecp5_cell(ctx, id_DCCA, "$gbuf$" + net->name.str(ctx));
std::unique_ptr<NetInfo> glbnet = std::unique_ptr<NetInfo>(new NetInfo);
glbnet->name = ctx->id("$glbnet$" + net->name.str(ctx));
glbnet->driver.cell = dcc.get();
- glbnet->driver.port = ctx->id("CLKO");
+ glbnet->driver.port = id_CLKO;
for (auto user : net->users) {
user.cell->ports.at(user.port).net = glbnet.get();
}
net->users.clear();
- dcc->ports[ctx->id("CLKI")].net = net;
+ dcc->ports[id_CLKI].net = net;
PortRef clki_pr;
- clki_pr.port = ctx->id("CLKI");
+ clki_pr.port = id_CLKI;
clki_pr.cell = dcc.get();
net->users.push_back(clki_pr);
+ place_dcc(dcc.get());
+
ctx->cells[dcc->name] = std::move(dcc);
NetInfo *glbptr = glbnet.get();
ctx->nets[glbnet->name] = std::move(glbnet);
return glbptr;
}
-
Context *ctx;
+
+
+public:
+ void promote_and_route_globals() {
+ log_info("Promoting and routing globals...");
+ auto clocks = get_clocks();
+ int glbid = 0;
+ for (auto clock : clocks) {
+ log_info(" promoting clock net %s to global %d\n", clock->name.c_str(ctx), glbid);
+ auto old_users = clock->users;
+ NetInfo *global = insert_dcc(clock);
+ bool routed = route_onto_global(global, glbid);
+ NPNR_ASSERT(routed);
+ for (const auto &user : global->users) {
+ route_logic_tile_global(global, glbid, user);
+ }
+ glbid++;
+ }
+ }
+
};
-void route_ecp5_globals(Context *ctx);
+void route_ecp5_globals(Context *ctx) {
+ Ecp5GlobalRouter(ctx).promote_and_route_globals();
+}
NEXTPNR_NAMESPACE_END
diff --git a/ecp5/globals.h b/ecp5/globals.h
new file mode 100644
index 00000000..23e25c8d
--- /dev/null
+++ b/ecp5/globals.h
@@ -0,0 +1,26 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2018 David Shah <david@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.
+ *
+ */
+
+#include "nextpnr.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+void route_ecp5_globals(Context *ctx);
+
+NEXTPNR_NAMESPACE_END \ No newline at end of file