ecp5: Working on global router

Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
David Shah 2018-07-31 14:03:35 +02:00
parent d43138b022
commit bc10a5646d

View File

@ -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;
};