From 03776796c725f315167d9a1af1b0b59b75254cd2 Mon Sep 17 00:00:00 2001 From: gatecat Date: Tue, 3 Feb 2026 18:11:42 +0100 Subject: [PATCH 1/3] gowin: Configure HeAP Signed-off-by: gatecat --- himbaechel/uarch/gowin/gowin.cc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/himbaechel/uarch/gowin/gowin.cc b/himbaechel/uarch/gowin/gowin.cc index 9b2c369e..3ca0739f 100644 --- a/himbaechel/uarch/gowin/gowin.cc +++ b/himbaechel/uarch/gowin/gowin.cc @@ -16,6 +16,8 @@ #include "gowin_utils.h" #include "pack.h" +#include "placer_heap.h" + NEXTPNR_NAMESPACE_BEGIN namespace { @@ -49,6 +51,9 @@ struct GowinImpl : HimbaechelAPI bool getClusterPlacement(ClusterId cluster, BelId root_bel, std::vector> &placement) const override; + + void configurePlacerHeap(PlacerHeapCfg &cfg) override; + private: HimbaechelHelpers h; GowinUtils gwu; @@ -1242,6 +1247,27 @@ void GowinImpl::notifyBelChange(BelId bel, CellInfo *cell) } } +void GowinImpl::configurePlacerHeap(PlacerHeapCfg &cfg) +{ + // SLICE types are closely associated with each other + cfg.cellGroups.emplace_back(); + cfg.cellGroups.back().insert(id_LUT4); + cfg.cellGroups.back().insert(id_DFF); + cfg.cellGroups.back().insert(id_ALU); + cfg.cellGroups.back().insert(id_MUX2_LUT5); + cfg.cellGroups.back().insert(id_MUX2_LUT6); + cfg.cellGroups.back().insert(id_MUX2_LUT7); + cfg.cellGroups.back().insert(id_MUX2_LUT8); + cfg.cellGroups.back().insert(id_RAM16SDP4); + + // Treat control and constants like IO buffers, because they have only one possible location + cfg.ioBufTypes.insert(id_GOWIN_VCC); + cfg.ioBufTypes.insert(id_GOWIN_GND); + cfg.ioBufTypes.insert(id_PINCFG); + cfg.ioBufTypes.insert(id_GSR); +} + + } // namespace NEXTPNR_NAMESPACE_END From d0d2862d1acc8d28f7e397e92229d206baf3b061 Mon Sep 17 00:00:00 2001 From: gatecat Date: Tue, 3 Feb 2026 19:15:42 +0100 Subject: [PATCH 2/3] gowin: Use fast constant value routing Signed-off-by: gatecat --- himbaechel/uarch/gowin/gowin_arch_gen.py | 4 ---- himbaechel/uarch/gowin/pack.cc | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/himbaechel/uarch/gowin/gowin_arch_gen.py b/himbaechel/uarch/gowin/gowin_arch_gen.py index 4cb8c095..cced755b 100644 --- a/himbaechel/uarch/gowin/gowin_arch_gen.py +++ b/himbaechel/uarch/gowin/gowin_arch_gen.py @@ -509,10 +509,6 @@ def create_nodes(chip: Chip, db: chipdb): for node in nodes: chip.add_node(node) - # VCC and VSS sources in the all tiles - global_nodes.setdefault('GND', []).append(NodeWire(x, y, 'VSS')) - global_nodes.setdefault('VCC', []).append(NodeWire(x, y, 'VCC')) - # add nodes from the apicula db for node_name, node_hdr in db.nodes.items(): wire_type, node = node_hdr diff --git a/himbaechel/uarch/gowin/pack.cc b/himbaechel/uarch/gowin/pack.cc index 47b7c26e..fd82e126 100644 --- a/himbaechel/uarch/gowin/pack.cc +++ b/himbaechel/uarch/gowin/pack.cc @@ -1740,6 +1740,7 @@ struct GowinPacker continue; } NetInfo *constnet = net->second.get(); + constnet->constant_value = (constnet->name == ctx->id("$PACKER_GND")) ? id_VSS : id_VCC; for (auto user : constnet->users) { CellInfo *uc = user.cell; if (is_lut(uc) && (user.port.str(ctx).at(0) == 'I')) { From c9ff60e3923a5bdd88fe4e35981fd662500dc177 Mon Sep 17 00:00:00 2001 From: gatecat Date: Tue, 10 Feb 2026 15:09:10 +0100 Subject: [PATCH 3/3] Support use of router2 for gowin Signed-off-by: gatecat --- common/route/router2.cc | 8 ++++++-- himbaechel/uarch/gowin/gowin.cc | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/common/route/router2.cc b/common/route/router2.cc index df1a7876..5097a62e 100644 --- a/common/route/router2.cc +++ b/common/route/router2.cc @@ -54,7 +54,7 @@ struct Router2 { WireId sink_wire; BoundingBox bb; - bool routed = false; + bool routed = false, pre_routed = false; }; // As we allow overlap at first; the nextpnr bind functions can't be used @@ -358,6 +358,9 @@ struct Router2 cursor = ctx->getPipSrcWire(pip); } ad.routed = false; + // Once we've ripped up the arc, the routing may no longer be the same as before... + // (this should only happen if it was not strongly bound) + ad.pre_routed = false; } float score_wire_for_arc(NetInfo *net, store_index user, size_t phys_pin, WireId wire, PipId pip, @@ -419,6 +422,7 @@ struct Router2 auto &nd = nets.at(net->udata); auto &ad = nd.arcs.at(usr.idx()).at(phys_pin); ad.routed = true; + ad.pre_routed = true; WireId src = nets.at(net->udata).src_wire; WireId cursor = ad.sink_wire; @@ -1141,7 +1145,7 @@ struct Router2 if (bound_net == nullptr) { to_bind.push_back(p); } - } else { + } else if (!ad.pre_routed || ctx->getBoundPipNet(p) != net) { // allow pre routing to break normal validity checking rules if (ctx->verbose) { log_info("Failed to bind pip %s to net %s\n", ctx->nameOfPip(p), net->name.c_str(ctx)); } diff --git a/himbaechel/uarch/gowin/gowin.cc b/himbaechel/uarch/gowin/gowin.cc index 3ca0739f..c5e0d76b 100644 --- a/himbaechel/uarch/gowin/gowin.cc +++ b/himbaechel/uarch/gowin/gowin.cc @@ -45,6 +45,7 @@ struct GowinImpl : HimbaechelAPI // wires bool checkPipAvail(PipId pip) const override; + bool checkPipAvailForNet(PipId pip, const NetInfo *net) const override; // Cluster bool isClusterStrict(const CellInfo *cell) const override { return true; } @@ -247,6 +248,12 @@ bool GowinImpl::checkPipAvail(PipId pip) const (!(gwu.is_global_pip(pip) || gwu.is_segment_pip(pip))); } +bool GowinImpl::checkPipAvailForNet(PipId pip, const NetInfo *net) const +{ + return (net->constant_value == IdString() && ctx->getWireConstantValue(ctx->getPipSrcWire(pip)) != IdString()) || + (!(gwu.is_global_pip(pip) || gwu.is_segment_pip(pip))); +} + void GowinImpl::pack() { if (ctx->settings.count(ctx->id("cst.filename"))) {