aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-08-19 16:36:18 +0100
committerGitHub <noreply@github.com>2021-08-19 16:36:18 +0100
commit897a2fccb64ac52ec4d3ce728fad91c3a5a96ff1 (patch)
tree1a89387bd5ce67c0c8c88cf72f7929b6fd6478cb /ecp5
parent6ae9b471554433f2393796d2abb42f31d4a8ccea (diff)
parente6006805cea00aa636a643def2f1c0f69bed3178 (diff)
downloadnextpnr-897a2fccb64ac52ec4d3ce728fad91c3a5a96ff1.tar.gz
nextpnr-897a2fccb64ac52ec4d3ce728fad91c3a5a96ff1.tar.bz2
nextpnr-897a2fccb64ac52ec4d3ce728fad91c3a5a96ff1.zip
Merge pull request #798 from kleinai/extref-loc
Make EXTREFB handling more robust
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/pack.cc50
1 files changed, 44 insertions, 6 deletions
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index d0077375..11d2f0ef 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -1766,6 +1766,26 @@ class Ecp5Packer
if (ci->type == id_EXTREFB) {
const NetInfo *refo = net_or_nullptr(ci, id_REFCLKO);
CellInfo *dcu = nullptr;
+ std::string loc_bel = std::string("NONE");
+ std::string dcu_bel = std::string("NONE");
+ if (ci->attrs.count(ctx->id("LOC"))) {
+ std::string loc = ci->attrs.at(ctx->id("LOC")).as_string();
+ if (loc == "EXTREF0" &&
+ (ctx->args.type == ArchArgs::LFE5UM_25F || ctx->args.type == ArchArgs::LFE5UM5G_25F))
+ loc_bel = std::string("X42/Y50/EXTREF");
+ else if (loc == "EXTREF0" &&
+ (ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F))
+ loc_bel = std::string("X42/Y71/EXTREF");
+ else if (loc == "EXTREF1" &&
+ (ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F))
+ loc_bel = std::string("X69/Y71/EXTREF");
+ else if (loc == "EXTREF0" &&
+ (ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F))
+ loc_bel = std::string("X46/Y95/EXTREF");
+ else if (loc == "EXTREF1" &&
+ (ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F))
+ loc_bel = std::string("X71/Y95/EXTREF");
+ }
if (refo == nullptr)
log_error("EXTREFB REFCLKO must not be unconnected\n");
for (auto user : refo->users) {
@@ -1775,12 +1795,30 @@ class Ecp5Packer
log_error("EXTREFB REFCLKO must only drive a single DCUA\n");
dcu = user.cell;
}
- if (!dcu->attrs.count(ctx->id("BEL")))
- log_error("DCU must be constrained to a Bel!\n");
- std::string bel = dcu->attrs.at(ctx->id("BEL")).as_string();
- NPNR_ASSERT(bel.substr(bel.length() - 3) == "DCU");
- bel.replace(bel.length() - 3, 3, "EXTREF");
- ci->attrs[ctx->id("BEL")] = bel;
+ if (dcu != nullptr) {
+ if (!dcu->attrs.count(ctx->id("BEL")))
+ log_error("DCU must be constrained to a Bel!\n");
+ dcu_bel = dcu->attrs.at(ctx->id("BEL")).as_string();
+ NPNR_ASSERT(dcu_bel.substr(dcu_bel.length() - 3) == "DCU");
+ dcu_bel.replace(dcu_bel.length() - 3, 3, "EXTREF");
+ }
+ if (dcu_bel != loc_bel) {
+ if (dcu_bel == "NONE" && loc_bel == "NONE") {
+ log_error("EXTREFB has neither a LOC or a directly associated DCUA\n");
+ } else if (dcu_bel == "NONE") {
+ ci->attrs[ctx->id("BEL")] = loc_bel;
+ dcu_bel = loc_bel;
+ } else if (loc_bel == "NONE") {
+ ci->attrs[ctx->id("BEL")] = dcu_bel;
+ } else {
+ log_error("EXTREFB has conflicting LOC '%s' and associated DCUA '%s'\n", loc_bel.c_str(),
+ dcu_bel.c_str());
+ }
+ } else {
+ if (dcu_bel == "NONE")
+ log_error("EXTREFB has no LOC or associated DCUA\n");
+ ci->attrs[ctx->id("BEL")] = dcu_bel;
+ }
} else if (ci->type == id_PCSCLKDIV) {
const NetInfo *clki = net_or_nullptr(ci, id_CLKI);
if (clki != nullptr && clki->driver.cell != nullptr && clki->driver.cell->type == id_DCUA) {