Merge pull request #1085 from yrabbit/gw1nr-9c-pll
gowin: Add PLL support for the GW1NR-9C chip
This commit is contained in:
commit
d661d117af
106
gowin/arch.cc
106
gowin/arch.cc
@ -1098,23 +1098,6 @@ void Arch::addMuxBels(const DatabasePOD *db, int row, int col)
|
||||
}
|
||||
}
|
||||
|
||||
void Arch::add_plla_ports(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}) {
|
||||
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)));
|
||||
}
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString belname, int row, int col)
|
||||
{
|
||||
IdString portname;
|
||||
@ -1137,7 +1120,9 @@ 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);
|
||||
}
|
||||
@ -1146,11 +1131,69 @@ void Arch::add_pllvr_ports(DatabasePOD const *db, BelsPOD const *bel, IdString b
|
||||
addBelOutput(belname, IdString(pid), idf("R%dC%d_%s", row + 1, col + 1, portname.c_str(this)));
|
||||
}
|
||||
}
|
||||
|
||||
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_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;
|
||||
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);
|
||||
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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,36 +202,6 @@ void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &to
|
||||
}
|
||||
}
|
||||
|
||||
void reconnect_rplla(Context *ctx, CellInfo *pll, CellInfo *plla)
|
||||
{
|
||||
pll->movePortTo(id_CLKIN, plla, id_CLKIN);
|
||||
pll->movePortTo(id_CLKFB, plla, id_CLKFB);
|
||||
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));
|
||||
}
|
||||
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(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);
|
||||
}
|
||||
|
||||
void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll)
|
||||
{
|
||||
pll->movePortTo(id_CLKIN, new_pll, id_CLKIN);
|
||||
@ -260,6 +226,29 @@ void reconnect_pllvr(Context *ctx, CellInfo *pll, CellInfo *new_pll)
|
||||
pll->movePortTo(id_LOCK, new_pll, id_LOCK);
|
||||
}
|
||||
|
||||
void reconnect_rpll(Context *ctx, CellInfo *pll, CellInfo *new_pll)
|
||||
{
|
||||
pll->movePortTo(id_CLKIN, new_pll, id_CLKIN);
|
||||
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), 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), 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, 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 sram_to_ramw_split(Context *ctx, CellInfo *ram, CellInfo *ramw)
|
||||
{
|
||||
if (ramw->hierpath == IdString())
|
||||
|
@ -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);
|
||||
|
@ -855,7 +855,6 @@ X(OSCF)
|
||||
// PLLs
|
||||
X(rPLL)
|
||||
X(RPLLA)
|
||||
X(RPLLB)
|
||||
X(PLLVR)
|
||||
|
||||
// primitive attributes
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user