aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormyrtle <gatecat@ds0.me>2023-02-02 08:30:56 +0000
committerGitHub <noreply@github.com>2023-02-02 08:30:56 +0000
commit48b0025732f7b5b1b7b091691bb5a26634ae5069 (patch)
tree77052038427be7cf713ba6378f01df539f2e4688
parentf328130c0a4cf562ce358d5e2a2a39f3d3dbef5e (diff)
parent2edc77836dd7686c4deabffcd7b6ebb4a75fdce1 (diff)
downloadnextpnr-48b0025732f7b5b1b7b091691bb5a26634ae5069.tar.gz
nextpnr-48b0025732f7b5b1b7b091691bb5a26634ae5069.tar.bz2
nextpnr-48b0025732f7b5b1b7b091691bb5a26634ae5069.zip
Merge pull request #1087 from yrabbit/gw1nr-9
gowin: Add PLL support for the GW1NR-9 chip
-rw-r--r--gowin/arch.cc101
-rw-r--r--gowin/arch.h7
-rw-r--r--gowin/pack.cc3
3 files changed, 65 insertions, 46 deletions
diff --git a/gowin/arch.cc b/gowin/arch.cc
index 88b9f42f..fbe26cdd 100644
--- a/gowin/arch.cc
+++ b/gowin/arch.cc
@@ -2108,6 +2108,58 @@ bool Arch::is_GCLKT_iob(const CellInfo *cell)
return false;
}
+void Arch::bind_pll_to_bel(CellInfo *ci, PLL 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 == "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;
+ }
+ if (family == "GW1NR-9C" || family == "GW1NR-9") {
+ bel = loc == PLL::left ? id("R10C1_rPLL") : id("R10C47_rPLL");
+ break;
+ }
+ return;
+ 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 +2181,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..822cdfc1 100644
--- a/gowin/arch.h
+++ b/gowin/arch.h
@@ -283,6 +283,12 @@ struct ArchRanges : BaseArchRanges
using GroupGroupsRangeT = const std::vector<GroupId> &;
};
+enum class PLL // fixed PLL locations
+{
+ left,
+ right
+};
+
struct Arch : BaseArch<ArchRanges>
{
std::string family;
@@ -482,6 +488,7 @@ struct Arch : BaseArch<ArchRanges>
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, PLL loc);
GowinGlobalRouter globals_router;
void mark_gowin_globals(Context *ctx);
diff --git a/gowin/pack.cc b/gowin/pack.cc
index cb24ac02..fc870890 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" || parm_device == "GW1N-4" || parm_device == "GW1NS-2C") {
pll_disable_unused_ports(ctx, ci);
// A cell
std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll");