aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5/globals.cc
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-07-31 14:03:35 +0200
committerDavid Shah <davey1576@gmail.com>2018-09-29 16:06:30 +0100
commitbc10a5646d337ef1cf412aaf58eef51e16eb4474 (patch)
treee92d5a8eee66cbc000193df66060087e2ee74ebd /ecp5/globals.cc
parentd43138b022c84efc01895f51f15244d8a42a5156 (diff)
downloadnextpnr-bc10a5646d337ef1cf412aaf58eef51e16eb4474.tar.gz
nextpnr-bc10a5646d337ef1cf412aaf58eef51e16eb4474.tar.bz2
nextpnr-bc10a5646d337ef1cf412aaf58eef51e16eb4474.zip
ecp5: Working on global router
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'ecp5/globals.cc')
-rw-r--r--ecp5/globals.cc88
1 files changed, 88 insertions, 0 deletions
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 9d51316c..453429e6 100644
--- a/ecp5/globals.cc
+++ b/ecp5/globals.cc
@@ -28,6 +28,21 @@
NEXTPNR_NAMESPACE_BEGIN
+static std::string get_quad_name(GlobalQuadrant quad)
+{
+ switch (quad) {
+ case QUAD_UL:
+ return "UL";
+ case QUAD_UR:
+ return "UR";
+ case QUAD_LL:
+ return "LL";
+ case QUAD_LR:
+ return "LR";
+ }
+ return "";
+}
+
class Ecp5GlobalRouter
{
public:
@@ -142,6 +157,79 @@ class Ecp5GlobalRouter
}
}
+ bool is_global_io(CellInfo *io, std::string &glb_name)
+ {
+ std::string func_name = ctx->getPioFunctionName(io->bel);
+ if (func_name.substr(0, 5) == "PCLKT") {
+ func_name.erase(func_name.find('_'), 1);
+ glb_name = "G_" + func_name;
+ return true;
+ }
+ return false;
+ }
+
+ WireId get_global_wire(GlobalQuadrant quad, int network)
+ {
+ return ctx->getWireByLocAndBasename(Location(0, 0), get_quad_name(quad) + "PCLK" + std::to_string(network));
+ }
+
+ void simple_router(IdString net, WireId src, WireId dst)
+ {
+ std::queue<WireId> visit;
+ std::unordered_map<WireId, PipId> backtrace;
+ visit.push(src);
+ WireId cursor;
+ while (true) {
+ if (visit.empty() || visit.size() > 50000) {
+ log_error("cannot route global from %s to %s.\n", ctx->getWireName(src).c_str(ctx),
+ ctx->getWireName(dst).c_str(ctx));
+ }
+ cursor = visit.back();
+ visit.pop();
+ IdString bound = ctx->getBoundWireNet(cursor);
+ if (bound == net) {
+ break;
+ } else if (bound != IdString()) {
+ continue;
+ }
+ if (cursor == dst)
+ break;
+ for (auto dh : ctx->getPipsDownhill(cursor)) {
+ WireId pipDst = ctx->getPipDstWire(dh);
+ if (backtrace.count(pipDst))
+ continue;
+ backtrace[pipDst] = dh;
+ visit.push(pipDst);
+ }
+ }
+ while (true) {
+ auto fnd = backtrace.find(cursor);
+ if (fnd == backtrace.end())
+ break;
+ ctx->bindPip(fnd->second, net, STRENGTH_LOCKED);
+ cursor = ctx->getPipSrcWire(fnd->second);
+ }
+ }
+
+ void 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);
+ }
+ for (int quad = QUAD_UL; quad < QUAD_LR + 1; quad++) {
+ WireId glb_dst = get_global_wire(GlobalQuadrant(quad), network);
+ simple_router(net->name, glb_src, glb_dst);
+ }
+ if (false) {
+ non_dedicated:
+ log_error("FIXME: currenly global networks can only be driven by dedicated global input pins");
+ }
+ }
+
Context *ctx;
};