From 6a1212a1e14d19bda114317e9f544b534cbf2841 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Mon, 30 Jan 2023 12:49:57 +1000 Subject: [PATCH] gowin: Add PLL support for the GW1NR-9 chip And also unified the fixing of PLL to bels: the point is that PLL being at a certain location has the possibility to use a direct implicit wire to the clock source, but once we decide to use this direct wire, the PLL can no longer be moved. Signed-off-by: YRabbit --- gowin/arch.cc | 90 +++++++++++++++++++++++++-------------------------- gowin/arch.h | 9 ++++++ gowin/pack.cc | 3 +- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/gowin/arch.cc b/gowin/arch.cc index 88b9f42f..5ef83fbb 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -2108,6 +2108,47 @@ bool Arch::is_GCLKT_iob(const CellInfo *cell) return false; } +void Arch::bind_pll_to_bel(CellInfo *ci, int loc) +{ + BelId bel; + switch (ci->type.hash()) { + case ID_PLLVR: + bel = loc == PLL::left ? id("R1C28_PLLVR") : id("R1C37_PLLVR"); + break; + case ID_rPLL: + if (family == "GW1N-1" || family == "GW1NZ-1") { + if (loc == PLL::left) { + return; + } + bel = id("R1C18_rPLL"); + break; + } + if (family == "GW1NR-9C" || family == "GW1NR-9") { + bel = loc == PLL::left ? id("R10C1_rPLL") : id("R10C47_rPLL"); + break; + } + break; + default: + return; + } + if (checkBelAvail(bel) || ci->belStrength != STRENGTH_LOCKED) { + if (ci->bel == bel) { + unbindBel(bel); + } else { + if (!checkBelAvail(bel) && ci->belStrength != STRENGTH_LOCKED) { + CellInfo *other_ci = getBoundBelCell(bel); + unbindBel(bel); + BelId our_bel = ci->bel; + unbindBel(our_bel); + bindBel(our_bel, other_ci, STRENGTH_LOCKED); + } + } + ci->disconnectPort(id_CLKIN); + ci->setParam(id_INSEL, Property("CLKIN0")); + bindBel(bel, ci, STRENGTH_LOCKED); + } +} + // If the PLL input can be connected using a direct wire, then do so, // bypassing conventional routing. void Arch::fix_pll_nets(Context *ctx) @@ -2129,53 +2170,12 @@ void Arch::fix_pll_nets(Context *ctx) break; } if (net_driven_by(ctx, net, is_RPLL_T_IN_iob, id_O) != nullptr) { - if (ci->type == id_rPLL) { - ci->disconnectPort(id_CLKIN); - ci->setParam(id_INSEL, Property("CLKIN0")); - break; - } - BelId bel = id("R1C37_PLLVR"); - if (ci->type == id_PLLVR) { - if (checkBelAvail(bel) || ci->belStrength != STRENGTH_LOCKED) { - if (ci->bel == bel) { - unbindBel(bel); - } else { - if (!checkBelAvail(bel) && ci->belStrength != STRENGTH_LOCKED) { - CellInfo *other_ci = getBoundBelCell(bel); - unbindBel(bel); - BelId our_bel = ci->bel; - unbindBel(our_bel); - bindBel(our_bel, other_ci, STRENGTH_LOCKED); - } - } - ci->disconnectPort(id_CLKIN); - ci->setParam(id_INSEL, Property("CLKIN0")); - bindBel(bel, ci, STRENGTH_LOCKED); - break; - } - } + bind_pll_to_bel(ci, PLL::right); + break; } if (net_driven_by(ctx, net, is_LPLL_T_IN_iob, id_O) != nullptr) { - BelId bel = id("R1C28_PLLVR"); - if (ci->type == id_PLLVR) { - if (checkBelAvail(bel) || ci->belStrength != STRENGTH_LOCKED) { - if (ci->bel == bel) { - unbindBel(bel); - } else { - if (!checkBelAvail(bel) && ci->belStrength != STRENGTH_LOCKED) { - CellInfo *other_ci = getBoundBelCell(bel); - unbindBel(bel); - BelId our_bel = ci->bel; - unbindBel(our_bel); - bindBel(our_bel, other_ci, STRENGTH_LOCKED); - } - } - ci->disconnectPort(id_CLKIN); - ci->setParam(id_INSEL, Property("CLKIN0")); - bindBel(bel, ci, STRENGTH_LOCKED); - break; - } - } + bind_pll_to_bel(ci, PLL::left); + break; } // XXX do special bels (HCLK etc) // This is general routing through CLK0 pip diff --git a/gowin/arch.h b/gowin/arch.h index f060165a..6f76d577 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -482,6 +482,7 @@ struct Arch : BaseArch void add_rpll_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col); void fix_pll_nets(Context *ctx); bool is_GCLKT_iob(const CellInfo *cell); + void bind_pll_to_bel(CellInfo *ci, int loc); GowinGlobalRouter globals_router; void mark_gowin_globals(Context *ctx); @@ -530,6 +531,14 @@ enum }; } +namespace PLL { // fixed PLL locations +enum +{ + left = 0, + right = 1 +}; +} + NEXTPNR_NAMESPACE_END #endif /* GOWIN_ARCH_H */ diff --git a/gowin/pack.cc b/gowin/pack.cc index cb24ac02..09e5c880 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -1043,7 +1043,8 @@ static void pack_plls(Context *ctx) switch (ci->type.hash()) { case ID_rPLL: { - if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1" || parm_device == "GW1NR-9C") { + if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1" || parm_device == "GW1NR-9C" || + parm_device == "GW1NR-9") { pll_disable_unused_ports(ctx, ci); // A cell std::unique_ptr cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll");