router1: Support for multiple bel pins per cell pin

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-02-10 14:31:16 +00:00
parent 535723f414
commit 7dafc64f78

View File

@ -32,12 +32,20 @@ USING_NEXTPNR_NAMESPACE
struct arc_key struct arc_key
{ {
NetInfo *net_info; NetInfo *net_info;
// logical user cell port index
int user_idx; int user_idx;
// physical index into cell->bel pin mapping (usually 0)
unsigned phys_idx;
bool operator==(const arc_key &other) const { return (net_info == other.net_info) && (user_idx == other.user_idx); } bool operator==(const arc_key &other) const
{
return (net_info == other.net_info) && (user_idx == other.user_idx) && (phys_idx == other.phys_idx);
}
bool operator<(const arc_key &other) const bool operator<(const arc_key &other) const
{ {
return net_info == other.net_info ? user_idx < other.user_idx : net_info->name < other.net_info->name; return net_info == other.net_info
? (user_idx == other.user_idx ? phys_idx < other.phys_idx : user_idx < other.user_idx)
: net_info->name < other.net_info->name;
} }
struct Hash struct Hash
@ -46,6 +54,7 @@ struct arc_key
{ {
std::size_t seed = std::hash<NetInfo *>()(arg.net_info); std::size_t seed = std::hash<NetInfo *>()(arg.net_info);
seed ^= std::hash<int>()(arg.user_idx) + 0x9e3779b9 + (seed << 6) + (seed >> 2); seed ^= std::hash<int>()(arg.user_idx) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= std::hash<int>()(arg.phys_idx) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed; return seed;
} }
}; };
@ -142,9 +151,10 @@ struct Router1
NetInfo *net_info = arc.net_info; NetInfo *net_info = arc.net_info;
int user_idx = arc.user_idx; int user_idx = arc.user_idx;
unsigned phys_idx = arc.phys_idx;
auto src_wire = ctx->getNetinfoSourceWire(net_info); auto src_wire = ctx->getNetinfoSourceWire(net_info);
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0); auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], phys_idx);
arc_queue_insert(arc, src_wire, dst_wire); arc_queue_insert(arc, src_wire, dst_wire);
} }
@ -302,27 +312,29 @@ struct Router1
log_assert(src_wire != WireId()); log_assert(src_wire != WireId());
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0); unsigned phys_idx = 0;
log_assert(dst_wire != WireId()); for (auto dst_wire : ctx->getNetinfoSinkWires(net_info, net_info->users[user_idx])) {
log_assert(dst_wire != WireId());
arc_key arc; arc_key arc;
arc.net_info = net_info; arc.net_info = net_info;
arc.user_idx = user_idx; arc.user_idx = user_idx;
arc.phys_idx = phys_idx++;
valid_arcs.insert(arc); valid_arcs.insert(arc);
#if 0 #if 0
if (ctx->debug) if (ctx->debug)
log("[check] arc: %s %s\n", ctx->nameOfWire(src_wire), ctx->nameOfWire(dst_wire)); log("[check] arc: %s %s\n", ctx->nameOfWire(src_wire), ctx->nameOfWire(dst_wire));
#endif #endif
for (WireId wire : arc_to_wires[arc]) { for (WireId wire : arc_to_wires[arc]) {
#if 0 #if 0
if (ctx->debug) if (ctx->debug)
log("[check] wire: %s\n", ctx->nameOfWire(wire)); log("[check] wire: %s\n", ctx->nameOfWire(wire));
#endif #endif
valid_wires_for_net.insert(wire); valid_wires_for_net.insert(wire);
log_assert(wire_to_arcs[wire].count(arc)); log_assert(wire_to_arcs[wire].count(arc));
log_assert(net_info->wires.count(wire)); log_assert(net_info->wires.count(wire));
}
} }
} }
@ -375,52 +387,55 @@ struct Router1
ctx->nameOf(dst_to_arc.at(src_wire).net_info), dst_to_arc.at(src_wire).user_idx); ctx->nameOf(dst_to_arc.at(src_wire).net_info), dst_to_arc.at(src_wire).user_idx);
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0); unsigned phys_idx = 0;
for (auto dst_wire : ctx->getNetinfoSinkWires(net_info, net_info->users[user_idx])) {
arc_key arc;
arc.net_info = net_info;
arc.user_idx = user_idx;
arc.phys_idx = phys_idx++;
if (dst_wire == WireId()) if (dst_to_arc.count(dst_wire)) {
log_error("No wire found for port %s on destination cell %s.\n", if (dst_to_arc.at(dst_wire).net_info == net_info)
ctx->nameOf(net_info->users[user_idx].port), ctx->nameOf(net_info->users[user_idx].cell)); continue;
log_error("Found two arcs with same sink wire %s: %s (%d) vs %s (%d)\n",
if (dst_to_arc.count(dst_wire)) { ctx->nameOfWire(dst_wire), ctx->nameOf(net_info), user_idx,
if (dst_to_arc.at(dst_wire).net_info == net_info) ctx->nameOf(dst_to_arc.at(dst_wire).net_info), dst_to_arc.at(dst_wire).user_idx);
continue;
log_error("Found two arcs with same sink wire %s: %s (%d) vs %s (%d)\n", ctx->nameOfWire(dst_wire),
ctx->nameOf(net_info), user_idx, ctx->nameOf(dst_to_arc.at(dst_wire).net_info),
dst_to_arc.at(dst_wire).user_idx);
}
if (src_to_net.count(dst_wire))
log_error("Wire %s is used as source and sink in different nets: %s vs %s (%d)\n",
ctx->nameOfWire(dst_wire), ctx->nameOf(src_to_net.at(dst_wire)), ctx->nameOf(net_info),
user_idx);
arc_key arc;
arc.net_info = net_info;
arc.user_idx = user_idx;
dst_to_arc[dst_wire] = arc;
if (net_info->wires.count(dst_wire) == 0) {
arc_queue_insert(arc, src_wire, dst_wire);
continue;
}
WireId cursor = dst_wire;
wire_to_arcs[cursor].insert(arc);
arc_to_wires[arc].insert(cursor);
while (src_wire != cursor) {
auto it = net_info->wires.find(cursor);
if (it == net_info->wires.end()) {
arc_queue_insert(arc, src_wire, dst_wire);
break;
} }
NPNR_ASSERT(it->second.pip != PipId()); if (src_to_net.count(dst_wire))
cursor = ctx->getPipSrcWire(it->second.pip); log_error("Wire %s is used as source and sink in different nets: %s vs %s (%d)\n",
ctx->nameOfWire(dst_wire), ctx->nameOf(src_to_net.at(dst_wire)),
ctx->nameOf(net_info), user_idx);
dst_to_arc[dst_wire] = arc;
if (net_info->wires.count(dst_wire) == 0) {
arc_queue_insert(arc, src_wire, dst_wire);
continue;
}
WireId cursor = dst_wire;
wire_to_arcs[cursor].insert(arc); wire_to_arcs[cursor].insert(arc);
arc_to_wires[arc].insert(cursor); arc_to_wires[arc].insert(cursor);
while (src_wire != cursor) {
auto it = net_info->wires.find(cursor);
if (it == net_info->wires.end()) {
arc_queue_insert(arc, src_wire, dst_wire);
break;
}
NPNR_ASSERT(it->second.pip != PipId());
cursor = ctx->getPipSrcWire(it->second.pip);
wire_to_arcs[cursor].insert(arc);
arc_to_wires[arc].insert(cursor);
}
} }
// TODO: this matches the situation before supporting multiple cell->bel pins, but do we want to keep
// this invariant?
if (phys_idx == 0)
log_error("No wires found for port %s on destination cell %s.\n",
ctx->nameOf(net_info->users[user_idx].port), ctx->nameOf(net_info->users[user_idx].cell));
} }
src_to_net[src_wire] = net_info; src_to_net[src_wire] = net_info;
@ -443,7 +458,7 @@ struct Router1
int user_idx = arc.user_idx; int user_idx = arc.user_idx;
auto src_wire = ctx->getNetinfoSourceWire(net_info); auto src_wire = ctx->getNetinfoSourceWire(net_info);
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0); auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], arc.phys_idx);
ripup_flag = false; ripup_flag = false;
if (ctx->debug) { if (ctx->debug) {
@ -934,14 +949,15 @@ bool Context::checkRoutedDesign() const
std::unordered_map<WireId, int> dest_wires; std::unordered_map<WireId, int> dest_wires;
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
auto dst_wire = ctx->getNetinfoSinkWire(net_info, net_info->users[user_idx], 0); for (auto dst_wire : ctx->getNetinfoSinkWires(net_info, net_info->users[user_idx])) {
log_assert(dst_wire != WireId()); log_assert(dst_wire != WireId());
dest_wires[dst_wire] = user_idx; dest_wires[dst_wire] = user_idx;
if (net_info->wires.count(dst_wire) == 0) { if (net_info->wires.count(dst_wire) == 0) {
if (ctx->debug) if (ctx->debug)
log(" sink %d (%s) not bound to net\n", user_idx, ctx->nameOfWire(dst_wire)); log(" sink %d (%s) not bound to net\n", user_idx, ctx->nameOfWire(dst_wire));
found_unrouted = true; found_unrouted = true;
}
} }
} }