From b8206d71ca281f00b1c681d3f7bb532eb01e030c Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 18 Aug 2018 18:14:18 +0100 Subject: [PATCH 1/3] ecp5: Speedup placement using ArchCellInfo Signed-off-by: David Shah --- ecp5/arch.h | 2 ++ ecp5/arch_place.cc | 24 ++++++++++++------------ ecp5/archdefs.h | 4 ++++ ecp5/pack.cc | 24 ++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/ecp5/arch.h b/ecp5/arch.h index 36792625..98aa6941 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -848,6 +848,8 @@ struct Arch : BaseCtx // Helper function for above bool slicesCompatible(const std::vector &cells) const; + void assignArchInfo(); + std::vector> getTilesAtLocation(int row, int col); std::string getTileByTypeAndLocation(int row, int col, std::string type) const { diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index 83af6b5a..55fff73d 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -35,26 +35,26 @@ bool Arch::slicesCompatible(const std::vector &cells) const { // TODO: allow different LSR/CLK and MUX/SRMODE settings once // routing details are worked out - NetInfo *clk_sig = nullptr, *lsr_sig = nullptr; - std::string CLKMUX, LSRMUX, SRMODE; + IdString clk_sig, lsr_sig; + IdString CLKMUX, LSRMUX, SRMODE; bool first = true; for (auto cell : cells) { if (first) { - clk_sig = port_or_nullptr(cell, id_CLK); - lsr_sig = port_or_nullptr(cell, id_LSR); - CLKMUX = str_or_default(cell->params, id_CLKMUX, "CLK"); - LSRMUX = str_or_default(cell->params, id_LSRMUX, "LSR"); - SRMODE = str_or_default(cell->params, id_SRMODE, "CE_OVER_LSR"); + clk_sig = cell->sliceInfo.clk_sig; + lsr_sig = cell->sliceInfo.lsr_sig; + CLKMUX = cell->sliceInfo.clkmux; + LSRMUX = cell->sliceInfo.lsrmux; + SRMODE = cell->sliceInfo.srmode; } else { - if (port_or_nullptr(cell, id_CLK) != clk_sig) + if (cell->sliceInfo.clk_sig != clk_sig) return false; - if (port_or_nullptr(cell, id_LSR) != lsr_sig) + if (cell->sliceInfo.lsr_sig != lsr_sig) return false; - if (str_or_default(cell->params, id_CLKMUX, "CLK") != CLKMUX) + if (cell->sliceInfo.clkmux != CLKMUX) return false; - if (str_or_default(cell->params, id_LSRMUX, "LSR") != LSRMUX) + if (cell->sliceInfo.lsrmux != LSRMUX) return false; - if (str_or_default(cell->params, id_SRMODE, "CE_OVER_LSR") != SRMODE) + if (cell->sliceInfo.srmode != SRMODE) return false; } first = false; diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h index 1493c691..c4e1413f 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -139,6 +139,10 @@ struct ArchNetInfo }; struct ArchCellInfo { + struct + { + IdString clk_sig, lsr_sig, clkmux, lsrmux, srmode; + } sliceInfo; }; NEXTPNR_NAMESPACE_END diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 786f543e..a2077204 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -536,10 +536,34 @@ bool Arch::pack() log_break(); Ecp5Packer(ctx).pack(); log_info("Checksum: 0x%08x\n", ctx->checksum()); + assignArchInfo(); return true; } catch (log_execution_error_exception) { + assignArchInfo(); return false; } } +void Arch::assignArchInfo() +{ + for (auto cell : sorted(cells)) { + CellInfo *ci = cell.second; + if (ci->type == id_TRELLIS_SLICE) { + if (ci->ports.count(id_CLK) && ci->ports[id_CLK].net != nullptr) + ci->sliceInfo.clk_sig = ci->ports[id_CLK].net->name; + else + ci->sliceInfo.clk_sig = IdString(); + + if (ci->ports.count(id_LSR) && ci->ports[id_LSR].net != nullptr) + ci->sliceInfo.lsr_sig = ci->ports[id_LSR].net->name; + else + ci->sliceInfo.lsr_sig = IdString(); + + ci->sliceInfo.clkmux = id(str_or_default(ci->params, id_CLKMUX, "CLK")); + ci->sliceInfo.lsrmux = id(str_or_default(ci->params, id_LSRMUX, "LSR")); + ci->sliceInfo.srmode = id(str_or_default(ci->params, id_SRMODE, "LSR_OVER_CE")); + } + } +} + NEXTPNR_NAMESPACE_END From 72a9a475fad693dd6e96c5fa55d02a8869e97120 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 18 Aug 2018 18:36:13 +0100 Subject: [PATCH 2/3] ecp5: Speed up Bel availability/binding checks Signed-off-by: David Shah --- ecp5/arch.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ecp5/arch.h b/ecp5/arch.h index 98aa6941..5b2738b5 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -480,25 +480,31 @@ struct Arch : BaseCtx bool checkBelAvail(BelId bel) const { NPNR_ASSERT(bel != BelId()); - return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == nullptr; + auto found = bel_to_cell.find(bel); + if (found == bel_to_cell.end()) + return true; + else + return found->second == nullptr; } CellInfo *getBoundBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); - if (bel_to_cell.find(bel) == bel_to_cell.end()) + auto found = bel_to_cell.find(bel); + if (found == bel_to_cell.end()) return nullptr; else - return bel_to_cell.at(bel); + return found->second; } CellInfo *getConflictingBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); - if (bel_to_cell.find(bel) == bel_to_cell.end()) + auto found = bel_to_cell.find(bel); + if (found == bel_to_cell.end()) return nullptr; else - return bel_to_cell.at(bel); + return found->second; } BelRange getBels() const From 0b35cb4e60c114b3d84ae39d0462a20085ef2bd4 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 18 Aug 2018 19:04:32 +0100 Subject: [PATCH 3/3] ecp5: Flatten bel_to_cell for performance Signed-off-by: David Shah --- ecp5/arch.cc | 4 +++- ecp5/arch.h | 40 ++++++++++++++++++---------------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index fec1011c..d6152e95 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -92,6 +92,8 @@ Arch::Arch(ArchArgs args) : args(args) if (!package_info) log_error("Unsupported package '%s' for '%s'.\n", args.package.c_str(), getChipName().c_str()); + + bel_to_cell.resize(chip_info->height * chip_info->width * max_loc_bels, nullptr); } // ----------------------------------------------------------------------- @@ -436,7 +438,7 @@ DecalXY Arch::getBelDecal(BelId bel) const decalxy.decal.type = DecalId::TYPE_BEL; decalxy.decal.location = bel.location; decalxy.decal.z = bel.index; - decalxy.decal.active = bel_to_cell.count(bel) && (bel_to_cell.at(bel) != nullptr); + decalxy.decal.active = (bel_to_cell.at(getBelFlatIndex(bel)) != nullptr); return decalxy; } diff --git a/ecp5/arch.h b/ecp5/arch.h index 5b2738b5..410ab15d 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -404,7 +404,7 @@ struct Arch : BaseCtx mutable std::unordered_map wire_by_name; mutable std::unordered_map pip_by_name; - std::unordered_map bel_to_cell; + std::vector bel_to_cell; std::unordered_map wire_to_net; std::unordered_map pip_to_net; @@ -443,11 +443,18 @@ struct Arch : BaseCtx uint32_t getBelChecksum(BelId bel) const { return bel.index; } + const int max_loc_bels = 20; + int getBelFlatIndex(BelId bel) const + { + return (bel.location.y * chip_info->width + bel.location.x) * max_loc_bels + bel.index; + } + void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) { NPNR_ASSERT(bel != BelId()); - NPNR_ASSERT(bel_to_cell[bel] == nullptr); - bel_to_cell[bel] = cell; + int idx = getBelFlatIndex(bel); + NPNR_ASSERT(bel_to_cell.at(idx) == nullptr); + bel_to_cell[idx] = cell; cell->bel = bel; cell->belStrength = strength; refreshUiBel(bel); @@ -456,10 +463,11 @@ struct Arch : BaseCtx void unbindBel(BelId bel) { NPNR_ASSERT(bel != BelId()); - NPNR_ASSERT(bel_to_cell[bel] != nullptr); - bel_to_cell[bel]->bel = BelId(); - bel_to_cell[bel]->belStrength = STRENGTH_NONE; - bel_to_cell[bel] = nullptr; + int idx = getBelFlatIndex(bel); + NPNR_ASSERT(bel_to_cell.at(idx) != nullptr); + bel_to_cell[idx]->bel = BelId(); + bel_to_cell[idx]->belStrength = STRENGTH_NONE; + bel_to_cell[idx] = nullptr; refreshUiBel(bel); } @@ -480,31 +488,19 @@ struct Arch : BaseCtx bool checkBelAvail(BelId bel) const { NPNR_ASSERT(bel != BelId()); - auto found = bel_to_cell.find(bel); - if (found == bel_to_cell.end()) - return true; - else - return found->second == nullptr; + return bel_to_cell[getBelFlatIndex(bel)] == nullptr; } CellInfo *getBoundBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); - auto found = bel_to_cell.find(bel); - if (found == bel_to_cell.end()) - return nullptr; - else - return found->second; + return bel_to_cell[getBelFlatIndex(bel)]; } CellInfo *getConflictingBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); - auto found = bel_to_cell.find(bel); - if (found == bel_to_cell.end()) - return nullptr; - else - return found->second; + return bel_to_cell[getBelFlatIndex(bel)]; } BelRange getBels() const