From 6a1212a1e14d19bda114317e9f544b534cbf2841 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Mon, 30 Jan 2023 12:49:57 +1000 Subject: [PATCH 1/4] 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"); From 2829a7d70af7a4cc32173cced2ebd5cb5e46cb93 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Mon, 30 Jan 2023 18:59:09 +1000 Subject: [PATCH 2/4] gowin: Proper use of the C++ mechanisms Signed-off-by: YRabbit --- gowin/arch.cc | 2 +- gowin/arch.h | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/gowin/arch.cc b/gowin/arch.cc index 5ef83fbb..1574eee3 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -2108,7 +2108,7 @@ bool Arch::is_GCLKT_iob(const CellInfo *cell) return false; } -void Arch::bind_pll_to_bel(CellInfo *ci, int loc) +void Arch::bind_pll_to_bel(CellInfo *ci, PLL loc) { BelId bel; switch (ci->type.hash()) { diff --git a/gowin/arch.h b/gowin/arch.h index 6f76d577..822cdfc1 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -283,6 +283,12 @@ struct ArchRanges : BaseArchRanges using GroupGroupsRangeT = const std::vector &; }; +enum class PLL // fixed PLL locations +{ + left, + right +}; + struct Arch : BaseArch { std::string family; @@ -482,7 +488,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); + void bind_pll_to_bel(CellInfo *ci, PLL loc); GowinGlobalRouter globals_router; void mark_gowin_globals(Context *ctx); @@ -531,14 +537,6 @@ enum }; } -namespace PLL { // fixed PLL locations -enum -{ - left = 0, - right = 1 -}; -} - NEXTPNR_NAMESPACE_END #endif /* GOWIN_ARCH_H */ From aac36ecf3f5869498876fda03d9e5f0a2ab9f2a3 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Tue, 31 Jan 2023 08:58:33 +1000 Subject: [PATCH 3/4] gowin: Add PLL support for GW1NR-4 chips Signed-off-by: YRabbit --- gowin/arch.cc | 6 +++++- gowin/pack.cc | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gowin/arch.cc b/gowin/arch.cc index 1574eee3..734ff911 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -2123,11 +2123,15 @@ void Arch::bind_pll_to_bel(CellInfo *ci, PLL loc) bel = id("R1C18_rPLL"); break; } + if (family == "GW1N-4") { + bel = loc == PLL::left ? id("R1C10_rPLL") : id("R1C28_rPLL"); + break; + } if (family == "GW1NR-9C" || family == "GW1NR-9") { bel = loc == PLL::left ? id("R10C1_rPLL") : id("R10C47_rPLL"); break; } - break; + return; default: return; } diff --git a/gowin/pack.cc b/gowin/pack.cc index 09e5c880..bed0a8df 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -1044,7 +1044,7 @@ 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" || - parm_device == "GW1NR-9") { + parm_device == "GW1NR-9" || parm_device == "GW1N-4") { pll_disable_unused_ports(ctx, ci); // A cell std::unique_ptr cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll"); From 5d5ea57e2123a6d66aa63bf82ac6110713ab8bc7 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Tue, 31 Jan 2023 18:46:38 +1000 Subject: [PATCH 4/4] gowin: Add PLL support for the GW1NS-2C chip Signed-off-by: YRabbit --- gowin/arch.cc | 7 +++++++ gowin/pack.cc | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/gowin/arch.cc b/gowin/arch.cc index 734ff911..fbe26cdd 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -2123,6 +2123,13 @@ void Arch::bind_pll_to_bel(CellInfo *ci, PLL loc) bel = id("R1C18_rPLL"); break; } + if (family == "GW1NS-2") { + if (loc == PLL::left) { + return; + } + bel = id("R10C20_rPLL"); + break; + } if (family == "GW1N-4") { bel = loc == PLL::left ? id("R1C10_rPLL") : id("R1C28_rPLL"); break; diff --git a/gowin/pack.cc b/gowin/pack.cc index bed0a8df..fc870890 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -1044,7 +1044,7 @@ 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" || - parm_device == "GW1NR-9" || parm_device == "GW1N-4") { + parm_device == "GW1NR-9" || parm_device == "GW1N-4" || parm_device == "GW1NS-2C") { pll_disable_unused_ports(ctx, ci); // A cell std::unique_ptr cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll");