Merge pull request #1087 from yrabbit/gw1nr-9
gowin: Add PLL support for the GW1NR-9 chip
This commit is contained in:
commit
48b0025732
101
gowin/arch.cc
101
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
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user