aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYRabbit <rabbit@yrabbit.cyou>2023-01-26 20:26:05 +1000
committerYRabbit <rabbit@yrabbit.cyou>2023-01-26 20:26:05 +1000
commit2d45d57b3246814ad20988c6ecf941180faf58a6 (patch)
tree2e7578b8e3677cd946a2cc8254dfec35ba357558
parent9b5e5f124c186942652e6be03c356cf0edf88124 (diff)
downloadnextpnr-2d45d57b3246814ad20988c6ecf941180faf58a6.tar.gz
nextpnr-2d45d57b3246814ad20988c6ecf941180faf58a6.tar.bz2
nextpnr-2d45d57b3246814ad20988c6ecf941180faf58a6.zip
gowin: Add PLL support for the GW1NR-9C chip
This chip is used in the Tangnano9k board. * all parameters of the rPLL primitive are supported; * all PLL outputs are treated as clock sources and optimized routing is applied to them; * primitive rPLL on different chips has a completely different structure: for example in GW1N-1 it takes two cells, and in GW1NR-9C as many as four, despite this unification was carried out and different chips are processed by the same functions, but this led to the fact that you can not use the PLL chip GW1N-1 with the old apicula bases - will issue a warning and refuse to encode primitive. In other cases compatibility is supported. * Cosmetic change: the usage report shows the rPLL names without any service bels. * I use ctx->idf() on occasion, it's not a total redesign. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
-rw-r--r--gowin/arch.cc98
-rw-r--r--gowin/arch.h2
-rw-r--r--gowin/cells.cc57
-rw-r--r--gowin/cells.h5
-rw-r--r--gowin/constids.inc1
-rw-r--r--gowin/globals.cc42
-rw-r--r--gowin/pack.cc24
7 files changed, 125 insertions, 104 deletions
diff --git a/gowin/arch.cc b/gowin/arch.cc
index f43cc00a..88b9f42f 100644
--- a/gowin/arch.cc
+++ b/gowin/arch.cc
@@ -1098,16 +1098,33 @@ void Arch::addMuxBels(const DatabasePOD *db, int row, int col)
}
}
-void Arch::add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col)
+void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col)
{
IdString portname;
- for (int pid : {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5,
- ID_IDSEL0, ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1,
- ID_ODSEL2, ID_ODSEL3, ID_ODSEL4, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0,
- ID_DUTYDA1, ID_DUTYDA2, ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3}) {
+ for (int pid :
+ {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5, ID_IDSEL0,
+ ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1, ID_ODSEL2, ID_ODSEL3,
+ ID_ODSEL4, ID_ODSEL5, ID_VREN, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0, ID_DUTYDA1,
+ ID_DUTYDA2, ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3, ID_RESET, ID_RESET_P}) {
portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id);
- addBelInput(belname, IdString(pid), idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this)));
+ IdString wire = idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this));
+ if (wires.count(wire) == 0) {
+ GlobalAliasPOD alias;
+ alias.dest_col = col;
+ alias.dest_row = row;
+ alias.dest_id = portname.hash();
+ auto alias_src = genericLookup(db->aliases.get(), db->num_aliases, alias, aliasCompare);
+ NPNR_ASSERT(alias_src != nullptr);
+ int srcrow = alias_src->src_row;
+ int srccol = alias_src->src_col;
+ IdString srcid = IdString(alias_src->src_id);
+ wire = wireToGlobal(srcrow, srccol, db, srcid);
+ if (wires.count(wire) == 0) {
+ addWire(wire, srcid, srccol, srcrow);
+ }
+ }
+ addBelInput(belname, IdString(pid), wire);
}
for (int pid : {ID_LOCK, ID_CLKOUT, ID_CLKOUTP, ID_CLKOUTD, ID_CLKOUTD3}) {
portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id);
@@ -1115,16 +1132,23 @@ void Arch::add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col
}
}
-void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col)
+void Arch::add_rpll_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col)
{
IdString portname;
for (int pid :
- {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5, ID_IDSEL0,
- ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1, ID_ODSEL2, ID_ODSEL3,
- ID_ODSEL4, ID_ODSEL5, ID_VREN, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0, ID_DUTYDA1,
- ID_DUTYDA2, ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3, ID_RESET, ID_RESET_P}) {
- portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id);
+ {ID_CLKIN, ID_CLKFB, ID_FBDSEL0, ID_FBDSEL1, ID_FBDSEL2, ID_FBDSEL3, ID_FBDSEL4, ID_FBDSEL5, ID_IDSEL0,
+ ID_IDSEL1, ID_IDSEL2, ID_IDSEL3, ID_IDSEL4, ID_IDSEL5, ID_ODSEL0, ID_ODSEL1, ID_ODSEL2, ID_ODSEL3,
+ ID_ODSEL4, ID_ODSEL5, ID_PSDA0, ID_PSDA1, ID_PSDA2, ID_PSDA3, ID_DUTYDA0, ID_DUTYDA1, ID_DUTYDA2,
+ ID_DUTYDA3, ID_FDLY0, ID_FDLY1, ID_FDLY2, ID_FDLY3, ID_RESET, ID_RESET_P}) {
+ const PairPOD *port = pairLookup(bel->ports.get(), bel->num_ports, pid);
+ // old base
+ if (port == nullptr) {
+ log_warning("When building nextpnr, obsolete old apicula bases were used. Probably not working properly "
+ "with PLL.\n");
+ return;
+ }
+ portname = IdString(port->src_id);
IdString wire = idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this));
if (wires.count(wire) == 0) {
GlobalAliasPOD alias;
@@ -1137,20 +1161,39 @@ void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString b
int srccol = alias_src->src_col;
IdString srcid = IdString(alias_src->src_id);
wire = wireToGlobal(srcrow, srccol, db, srcid);
- // addWire(wire, portname, srccol, srcrow);
+ if (wires.count(wire) == 0) {
+ addWire(wire, srcid, srccol, srcrow);
+ }
}
addBelInput(belname, IdString(pid), wire);
}
for (int pid : {ID_LOCK, ID_CLKOUT, ID_CLKOUTP, ID_CLKOUTD, ID_CLKOUTD3}) {
portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, pid)->src_id);
- addBelOutput(belname, IdString(pid), idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this)));
+ IdString wire = idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this));
+ if (wires.count(wire) == 0) {
+ GlobalAliasPOD alias;
+ alias.dest_col = col;
+ alias.dest_row = row;
+ alias.dest_id = portname.hash();
+ auto alias_src = genericLookup(db->aliases.get(), db->num_aliases, alias, aliasCompare);
+ NPNR_ASSERT(alias_src != nullptr);
+ int srcrow = alias_src->src_row;
+ int srccol = alias_src->src_col;
+ IdString srcid = IdString(alias_src->src_id);
+ wire = wireToGlobal(srcrow, srccol, db, srcid);
+ if (wires.count(wire) == 0) {
+ addWire(wire, srcid, srccol, srcrow);
+ }
+ }
+ addBelOutput(belname, IdString(pid), wire);
}
}
+
Arch::Arch(ArchArgs args) : args(args)
{
family = args.family;
- max_clock = 5;
+ max_clock = 6;
if (family == "GW1NZ-1") {
max_clock = 3;
}
@@ -1312,24 +1355,9 @@ Arch::Arch(ArchArgs args) : args(args)
add_pllvr_ports(db, bel, belname, row, col);
break;
case ID_RPLLA:
- snprintf(buf, 32, "R%dC%d_RPLLA", row + 1, col + 1);
- belname = id(buf);
- addBel(belname, id_RPLLA, Loc(col, row, BelZ::pll_z), false);
- add_plla_ports(bel, belname, row, col);
- break;
- case ID_RPLLB:
- snprintf(buf, 32, "R%dC%d_RPLLB", row + 1, col + 1);
- belname = id(buf);
- addBel(belname, id_RPLLB, Loc(col, row, BelZ::pll_z), false);
- portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_RESET)->src_id);
- snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this));
- addBelInput(belname, id_RESET, id(buf));
- portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_RESET_P)->src_id);
- snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this));
- addBelInput(belname, id_RESET_P, id(buf));
- portname = IdString(pairLookup(bel->ports.get(), bel->num_ports, ID_ODSEL5)->src_id);
- snprintf(buf, 32, "R%dC%d_%s", row + 1, col + 1, portname.c_str(this));
- addBelInput(belname, id_ODSEL5, id(buf));
+ belname = idf("R%dC%d_rPLL", row + 1, col + 1);
+ addBel(belname, id_rPLL, Loc(col, row, BelZ::pll_z), false);
+ add_rpll_ports(db, bel, belname, row, col);
break;
case ID_BUFS7:
z++; /* fall-through*/
@@ -2086,7 +2114,7 @@ void Arch::fix_pll_nets(Context *ctx)
{
for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get();
- if (ci->type != id_RPLLA && ci->type != id_PLLVR) {
+ if (ci->type != id_rPLL && ci->type != id_PLLVR) {
continue;
}
// *** CLKIN
@@ -2101,7 +2129,7 @@ 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_RPLLA) {
+ if (ci->type == id_rPLL) {
ci->disconnectPort(id_CLKIN);
ci->setParam(id_INSEL, Property("CLKIN0"));
break;
diff --git a/gowin/arch.h b/gowin/arch.h
index 0dd5a62b..f060165a 100644
--- a/gowin/arch.h
+++ b/gowin/arch.h
@@ -478,8 +478,8 @@ struct Arch : BaseArch<ArchRanges>
void pre_route(Context *ctx);
void post_route(Context *ctx);
void auto_longwires();
- void add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col);
void add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col);
+ 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);
diff --git a/gowin/cells.cc b/gowin/cells.cc
index ae420160..c30a4706 100644
--- a/gowin/cells.cc
+++ b/gowin/cells.cc
@@ -79,16 +79,12 @@ std::unique_ptr<CellInfo> create_generic_cell(Context *ctx, IdString type, std::
} else if (type == id_BUFS) {
new_cell->addInput(id_I);
new_cell->addOutput(id_O);
- } else if (type == id_RPLLB) {
- new_cell->addInput(id_RESET);
- new_cell->addInput(id_RESET_P);
- new_cell->addInput(id_ODSEL5);
- } else if (type == id_RPLLA) {
+ } else if (type == id_rPLL) {
for (IdString iid :
- {id_CLKIN, id_CLKFB, id_FBDSEL0, id_FBDSEL1, id_FBDSEL2, id_FBDSEL3, id_FBDSEL4, id_FBDSEL5,
- id_IDSEL0, id_IDSEL1, id_IDSEL2, id_IDSEL3, id_IDSEL4, id_IDSEL5, id_ODSEL0, id_ODSEL1,
- id_ODSEL2, id_ODSEL3, id_ODSEL4, id_PSDA0, id_PSDA1, id_PSDA2, id_PSDA3, id_DUTYDA0,
- id_DUTYDA1, id_DUTYDA2, id_DUTYDA3, id_FDLY0, id_FDLY1, id_FDLY2, id_FDLY3}) {
+ {id_CLKIN, id_CLKFB, id_FBDSEL0, id_FBDSEL1, id_FBDSEL2, id_FBDSEL3, id_FBDSEL4, id_FBDSEL5, id_IDSEL0,
+ id_IDSEL1, id_IDSEL2, id_IDSEL3, id_IDSEL4, id_IDSEL5, id_ODSEL0, id_ODSEL1, id_ODSEL2, id_ODSEL3,
+ id_ODSEL4, id_ODSEL5, id_PSDA0, id_PSDA1, id_PSDA2, id_PSDA3, id_DUTYDA0, id_DUTYDA1, id_DUTYDA2,
+ id_DUTYDA3, id_FDLY0, id_FDLY1, id_FDLY2, id_FDLY3, id_RESET, id_RESET_P}) {
new_cell->addInput(iid);
}
new_cell->addOutput(id_CLKOUT);
@@ -206,40 +202,33 @@ void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &to
}
}
-void reconnect_rplla(Context *ctx, CellInfo *pll, CellInfo *plla)
+void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll)
{
- pll->movePortTo(id_CLKIN, plla, id_CLKIN);
- pll->movePortTo(id_CLKFB, plla, id_CLKFB);
+ pll->movePortTo(id_CLKIN, new_pll, id_CLKIN);
+ pll->movePortTo(id_VREN, new_pll, id_VREN);
+ pll->movePortTo(id_CLKFB, new_pll, id_CLKFB);
+ pll->movePortTo(id_RESET, new_pll, id_RESET);
+ pll->movePortTo(id_RESET_P, new_pll, id_RESET_P);
for (int i = 0; i < 6; ++i) {
- pll->movePortTo(ctx->idf("FBDSEL[%d]", i), plla, ctx->idf("FBDSEL%d", i));
- pll->movePortTo(ctx->idf("IDSEL[%d]", i), plla, ctx->idf("IDSEL%d", i));
- if (i < 5) {
- pll->movePortTo(ctx->idf("ODSEL[%d]", i), plla, ctx->idf("ODSEL%d", i));
- }
+ pll->movePortTo(ctx->idf("FBDSEL[%d]", i), new_pll, ctx->idf("FBDSEL%d", i));
+ pll->movePortTo(ctx->idf("IDSEL[%d]", i), new_pll, ctx->idf("IDSEL%d", i));
+ pll->movePortTo(ctx->idf("ODSEL[%d]", i), new_pll, ctx->idf("ODSEL%d", i));
if (i < 4) {
- pll->movePortTo(ctx->idf("PSDA[%d]", i), plla, ctx->idf("PSDA%d", i));
- pll->movePortTo(ctx->idf("DUTYDA[%d]", i), plla, ctx->idf("DUTYDA%d", i));
- pll->movePortTo(ctx->idf("FDLY[%d]", i), plla, ctx->idf("FDLY%d", i));
+ pll->movePortTo(ctx->idf("PSDA[%d]", i), new_pll, ctx->idf("PSDA%d", i));
+ pll->movePortTo(ctx->idf("DUTYDA[%d]", i), new_pll, ctx->idf("DUTYDA%d", i));
+ pll->movePortTo(ctx->idf("FDLY[%d]", i), new_pll, ctx->idf("FDLY%d", i));
}
}
- pll->movePortTo(id_CLKOUT, plla, id_CLKOUT);
- pll->movePortTo(id_CLKOUTP, plla, id_CLKOUTP);
- pll->movePortTo(id_CLKOUTD, plla, id_CLKOUTD);
- pll->movePortTo(id_CLKOUTD3, plla, id_CLKOUTD3);
- pll->movePortTo(id_LOCK, plla, id_LOCK);
-}
-
-void reconnect_rpllb(Context *ctx, CellInfo *pll, CellInfo *pllb)
-{
- pll->movePortTo(id_RESET, pllb, id_RESET);
- pll->movePortTo(id_RESET_P, pllb, id_RESET_P);
- pll->movePortTo(ctx->id("ODSEL[5]"), pllb, id_ODSEL5);
+ pll->movePortTo(id_CLKOUT, new_pll, id_CLKOUT);
+ pll->movePortTo(id_CLKOUTP, new_pll, id_CLKOUTP);
+ pll->movePortTo(id_CLKOUTD, new_pll, id_CLKOUTD);
+ pll->movePortTo(id_CLKOUTD3, new_pll, id_CLKOUTD3);
+ pll->movePortTo(id_LOCK, new_pll, id_LOCK);
}
-void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll)
+void reconnect_rpll(Context *ctx, CellInfo *pll, CellInfo *new_pll)
{
pll->movePortTo(id_CLKIN, new_pll, id_CLKIN);
- pll->movePortTo(id_VREN, new_pll, id_VREN);
pll->movePortTo(id_CLKFB, new_pll, id_CLKFB);
pll->movePortTo(id_RESET, new_pll, id_RESET);
pll->movePortTo(id_RESET_P, new_pll, id_RESET_P);
diff --git a/gowin/cells.h b/gowin/cells.h
index 78a746f3..7aba4805 100644
--- a/gowin/cells.h
+++ b/gowin/cells.h
@@ -122,9 +122,8 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells);
// Reconnect PLL signals (B)
-void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *pllb);
-void reconnect_rplla(Context *ctx, CellInfo *pll, CellInfo *pllb);
-void reconnect_rpllb(Context *ctx, CellInfo *pll, CellInfo *pllb);
+void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll);
+void reconnect_rpll(Context *ctx, CellInfo *pll, CellInfo *new_pll);
// Convert RAM16 to write port
void sram_to_ramw_split(Context *ctx, CellInfo *ram, CellInfo *ramw);
diff --git a/gowin/constids.inc b/gowin/constids.inc
index e3e451a1..dac84a1e 100644
--- a/gowin/constids.inc
+++ b/gowin/constids.inc
@@ -855,7 +855,6 @@ X(OSCF)
// PLLs
X(rPLL)
X(RPLLA)
-X(RPLLB)
X(PLLVR)
// primitive attributes
diff --git a/gowin/globals.cc b/gowin/globals.cc
index 6ed8f770..3273191c 100644
--- a/gowin/globals.cc
+++ b/gowin/globals.cc
@@ -53,7 +53,7 @@ std::pair<WireId, BelId> GowinGlobalRouter::clock_src(Context *ctx, PortRef cons
}
return std::make_pair(WireId(), BelId());
}
- if (driver.cell->type == id_RPLLA || driver.cell->type == id_PLLVR) {
+ if (driver.cell->type == id_rPLL || driver.cell->type == id_PLLVR) {
if (driver.port == id_CLKOUT || driver.port == id_CLKOUTP || driver.port == id_CLKOUTD ||
driver.port == id_CLKOUTD3) {
wire = bel.pins[driver.port].wire;
@@ -103,12 +103,20 @@ void GowinGlobalRouter::gather_clock_nets(Context *ctx, std::vector<globalnet_t>
IdString GowinGlobalRouter::route_to_non_clock_port(Context *ctx, WireId const dstWire, int clock,
pool<IdString> &used_pips, pool<IdString> &undo_wires)
{
- static std::vector<IdString> one_hop = {id_S111, id_S121, id_N111, id_N121, id_W111, id_W121, id_E111, id_E121};
- char buf[40];
+ static std::vector<IdString> one_hop_0 = {id_W111, id_W121, id_E111, id_E121};
+ static std::vector<IdString> one_hop_4 = {id_S111, id_S121, id_N111, id_N121};
// uphill pips
for (auto const uphill : ctx->getPipsUphill(dstWire)) {
WireId srcWire = ctx->getPipSrcWire(uphill);
- if (find(one_hop.begin(), one_hop.end(), ctx->wire_info(ctx->getPipSrcWire(uphill)).type) != one_hop.end()) {
+ bool found;
+ if (clock < 4) {
+ found = find(one_hop_0.begin(), one_hop_0.end(), ctx->wire_info(ctx->getPipSrcWire(uphill)).type) !=
+ one_hop_0.end();
+ } else {
+ found = find(one_hop_4.begin(), one_hop_4.end(), ctx->wire_info(ctx->getPipSrcWire(uphill)).type) !=
+ one_hop_4.end();
+ }
+ if (found) {
// found one hop pip
if (used_wires.count(srcWire)) {
if (used_wires[srcWire] != clock) {
@@ -117,8 +125,13 @@ IdString GowinGlobalRouter::route_to_non_clock_port(Context *ctx, WireId const d
}
WireInfo wi = ctx->wire_info(srcWire);
std::string wire_alias = srcWire.str(ctx).substr(srcWire.str(ctx).rfind("_") + 1);
- snprintf(buf, sizeof(buf), "R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, clock, wire_alias.c_str());
- IdString gb = ctx->id(buf);
+ IdString gb = ctx->idf("R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, clock, wire_alias.c_str());
+ if (ctx->verbose) {
+ log_info(" 1-hop gb:%s\n", gb.c_str(ctx));
+ }
+ // sanity
+ NPNR_ASSERT(find(ctx->getPipsUphill(srcWire).begin(), ctx->getPipsUphill(srcWire).end(), gb) !=
+ ctx->getPipsUphill(srcWire).end());
auto up_pips = ctx->getPipsUphill(srcWire);
if (find(up_pips.begin(), up_pips.end(), gb) != up_pips.end()) {
if (!used_wires.count(srcWire)) {
@@ -154,11 +167,10 @@ void GowinGlobalRouter::route_net(Context *ctx, globalnet_t const &net)
char buf[30];
PipId gb_pip_id;
- if (user.port == id_CLK) {
+ if (user.port == id_CLK || user.port == id_CLKIN) {
WireInfo const wi = ctx->wire_info(dstWire);
- snprintf(buf, sizeof(buf), "R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, net.clock,
- ctx->wire_info(dstWire).type.c_str(ctx));
- gb_pip_id = ctx->id(buf);
+ gb_pip_id =
+ ctx->idf("R%dC%d_GB%d0_%s", wi.y + 1, wi.x + 1, net.clock, ctx->wire_info(dstWire).type.c_str(ctx));
// sanity
NPNR_ASSERT(find(ctx->getPipsUphill(dstWire).begin(), ctx->getPipsUphill(dstWire).end(), gb_pip_id) !=
ctx->getPipsUphill(dstWire).end());
@@ -192,11 +204,10 @@ void GowinGlobalRouter::route_net(Context *ctx, globalnet_t const &net)
dstWire = ctx->getPipSrcWire(gb_pip_id);
WireInfo dstWireInfo = ctx->wire_info(dstWire);
int branch_tap_idx = net.clock > 3 ? 1 : 0;
- snprintf(buf, sizeof(buf), "R%dC%d_GT%d0_GBO%d", dstWireInfo.y + 1, dstWireInfo.x + 1, branch_tap_idx,
- branch_tap_idx);
- PipId gt_pip_id = ctx->id(buf);
+ PipId gt_pip_id =
+ ctx->idf("R%dC%d_GT%d0_GBO%d", dstWireInfo.y + 1, dstWireInfo.x + 1, branch_tap_idx, branch_tap_idx);
if (ctx->verbose) {
- log_info(" GT Pip:%s\n", buf);
+ log_info(" GT Pip:%s\n", gt_pip_id.c_str(ctx));
}
// sanity
NPNR_ASSERT(find(ctx->getPipsUphill(dstWire).begin(), ctx->getPipsUphill(dstWire).end(), gt_pip_id) !=
@@ -251,12 +262,13 @@ void GowinGlobalRouter::route_net(Context *ctx, globalnet_t const &net)
for (auto const uphill_pip : ctx->getPipsUphill(dstWire)) {
if (ctx->getPipSrcWire(uphill_pip) == net.clock_wire) {
src_pip_id = uphill_pip;
+ break;
}
}
- NPNR_ASSERT(src_pip_id != PipId());
if (ctx->verbose) {
log_info(" Src Pip:%s\n", src_pip_id.c_str(ctx));
}
+ NPNR_ASSERT(src_pip_id != PipId());
// if already routed
if (used_pips.count(src_pip_id)) {
if (ctx->verbose) {
diff --git a/gowin/pack.cc b/gowin/pack.cc
index 1ebd5315..cb24ac02 100644
--- a/gowin/pack.cc
+++ b/gowin/pack.cc
@@ -1034,7 +1034,7 @@ static void pack_plls(Context *ctx)
if (ctx->verbose)
log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx));
if (is_pll(ctx, ci)) {
- std::string parm_device = str_or_default(ci->params, id_DEVICE, "GW1N-1");
+ std::string parm_device = str_or_default(ci->params, id_DEVICE, ctx->device.c_str());
if (parm_device != ctx->device) {
log_error("Cell '%s': wrong PLL device:%s instead of %s\n", ctx->nameOf(ci), parm_device.c_str(),
ctx->device.c_str());
@@ -1043,27 +1043,21 @@ static void pack_plls(Context *ctx)
switch (ci->type.hash()) {
case ID_rPLL: {
- if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1") {
+ if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1" || parm_device == "GW1NR-9C") {
pll_disable_unused_ports(ctx, ci);
- // B half
- std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_RPLLB, ci->name.str(ctx) + "$rpllb");
- reconnect_rpllb(ctx, ci, cell.get());
+ // A cell
+ std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll");
+ reconnect_rpll(ctx, ci, cell.get());
new_cells.push_back(std::move(cell));
- auto pllb_cell = new_cells.back().get();
- // A half
- cell = create_generic_cell(ctx, id_RPLLA, ci->name.str(ctx) + "$rplla");
- reconnect_rplla(ctx, ci, cell.get());
- new_cells.push_back(std::move(cell));
- auto plla_cell = new_cells.back().get();
+ auto pll_cell = new_cells.back().get();
// need params for gowin_pack
for (auto &parm : ci->params) {
- plla_cell->setParam(parm.first, parm.second);
- pllb_cell->setParam(parm.first, parm.second);
+ pll_cell->setParam(parm.first, parm.second);
}
packed_cells.insert(ci->name);
} else {
- log_error("PLL isn't supported for %s\n", ctx->device.c_str());
+ log_error("rPLL isn't supported for %s\n", ctx->device.c_str());
}
} break;
case ID_PLLVR: {
@@ -1080,7 +1074,7 @@ static void pack_plls(Context *ctx)
}
packed_cells.insert(ci->name);
} else {
- log_error("PLL isn't supported for %s\n", ctx->device.c_str());
+ log_error("PLLVR isn't supported for %s\n", ctx->device.c_str());
}
} break;
default: