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 <rabbit@yrabbit.cyou>
This commit is contained in:
parent
f80b871dd5
commit
6a1212a1e1
@ -2108,6 +2108,47 @@ bool Arch::is_GCLKT_iob(const CellInfo *cell)
|
|||||||
return false;
|
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,
|
// If the PLL input can be connected using a direct wire, then do so,
|
||||||
// bypassing conventional routing.
|
// bypassing conventional routing.
|
||||||
void Arch::fix_pll_nets(Context *ctx)
|
void Arch::fix_pll_nets(Context *ctx)
|
||||||
@ -2129,53 +2170,12 @@ void Arch::fix_pll_nets(Context *ctx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (net_driven_by(ctx, net, is_RPLL_T_IN_iob, id_O) != nullptr) {
|
if (net_driven_by(ctx, net, is_RPLL_T_IN_iob, id_O) != nullptr) {
|
||||||
if (ci->type == id_rPLL) {
|
bind_pll_to_bel(ci, PLL::right);
|
||||||
ci->disconnectPort(id_CLKIN);
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (net_driven_by(ctx, net, is_LPLL_T_IN_iob, id_O) != nullptr) {
|
if (net_driven_by(ctx, net, is_LPLL_T_IN_iob, id_O) != nullptr) {
|
||||||
BelId bel = id("R1C28_PLLVR");
|
bind_pll_to_bel(ci, PLL::left);
|
||||||
if (ci->type == id_PLLVR) {
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// XXX do special bels (HCLK etc)
|
// XXX do special bels (HCLK etc)
|
||||||
// This is general routing through CLK0 pip
|
// This is general routing through CLK0 pip
|
||||||
|
@ -482,6 +482,7 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
void add_rpll_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);
|
void fix_pll_nets(Context *ctx);
|
||||||
bool is_GCLKT_iob(const CellInfo *cell);
|
bool is_GCLKT_iob(const CellInfo *cell);
|
||||||
|
void bind_pll_to_bel(CellInfo *ci, int loc);
|
||||||
|
|
||||||
GowinGlobalRouter globals_router;
|
GowinGlobalRouter globals_router;
|
||||||
void mark_gowin_globals(Context *ctx);
|
void mark_gowin_globals(Context *ctx);
|
||||||
@ -530,6 +531,14 @@ enum
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace PLL { // fixed PLL locations
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
left = 0,
|
||||||
|
right = 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* GOWIN_ARCH_H */
|
#endif /* GOWIN_ARCH_H */
|
||||||
|
@ -1043,7 +1043,8 @@ static void pack_plls(Context *ctx)
|
|||||||
|
|
||||||
switch (ci->type.hash()) {
|
switch (ci->type.hash()) {
|
||||||
case ID_rPLL: {
|
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);
|
pll_disable_unused_ports(ctx, ci);
|
||||||
// A cell
|
// A cell
|
||||||
std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll");
|
std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_rPLL, ci->name.str(ctx) + "$rpll");
|
||||||
|
Loading…
Reference in New Issue
Block a user