Merge pull request #1055 from yrabbit/pll-pins

gowin: add PLL pins processing
This commit is contained in:
myrtle 2022-12-06 21:20:59 +01:00 committed by GitHub
commit a342b96bb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 140 additions and 16 deletions

View File

@ -23,6 +23,7 @@
#include <iostream> #include <iostream>
#include <math.h> #include <math.h>
#include <regex> #include <regex>
#include "design_utils.h"
#include "embed.h" #include "embed.h"
#include "gfx.h" #include "gfx.h"
#include "nextpnr.h" #include "nextpnr.h"
@ -1575,6 +1576,24 @@ Arch::Arch(ArchArgs args) : args(args)
} }
} }
} }
// IO pin configs
for (unsigned int i = 0; i < package->num_pins; i++) {
const PinPOD *pin = &package->pins[i];
if (pin->num_cfgs == 0) {
continue;
}
auto b = bels.find(IdString(pin->loc_id));
if (b == bels.end()) {
// Not all pins are transmitted, e.g. MODE, DONE etc.
continue;
}
std::vector<IdString> &cfgs = b->second.pin_cfgs;
for (unsigned int j = 0; j < pin->num_cfgs; ++j) {
cfgs.push_back(IdString(pin->cfgs[j]));
}
}
// setup pips // setup pips
for (int i = 0; i < db->rows * db->cols; i++) { for (int i = 0; i < db->rows * db->cols; i++) {
int row = i / db->cols; int row = i / db->cols;
@ -1958,26 +1977,128 @@ bool Arch::place()
return retVal; return retVal;
} }
static bool is_spec_iob(const Context *ctx, const CellInfo *cell, IdString pin_name)
{
if (!is_iob(ctx, cell)) {
return false;
}
std::vector<IdString> const &cfgs = ctx->bels.at(cell->bel).pin_cfgs;
bool have_pin = std::find(cfgs.begin(), cfgs.end(), pin_name) != cfgs.end();
return have_pin;
}
static bool is_PLL_T_IN_iob(const Context *ctx, const CellInfo *cell)
{
return is_spec_iob(ctx, cell, ctx->id("RPLL_T_IN"));
}
static bool is_PLL_T_FB_iob(const Context *ctx, const CellInfo *cell)
{
return is_spec_iob(ctx, cell, ctx->id("RPLL_T_FB"));
}
// If the PLL input can be connected using a direct wire, then do so,
// bypassing conventional routing.
void Arch::fix_pll_nets(Context *ctx)
{
for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get();
if (ci->type != id_RPLLA) {
continue;
}
// *** CLKIN
do {
if (!port_used(ci, id_CLKIN)) {
ci->setParam(id_INSEL, Property("UNKNOWN"));
break;
}
NetInfo *net = ci->getPort(id_CLKIN);
if (net->name == id("$PACKER_VCC_NET") || net->name == id("$PACKER_GND_NET")) {
ci->setParam(id_INSEL, Property("UNKNOWN"));
break;
}
if (net_driven_by(ctx, net, is_PLL_T_IN_iob, id_O) != nullptr) {
ci->disconnectPort(id_CLKIN);
ci->setParam(id_INSEL, Property("CLKIN0"));
break;
}
// XXX do special bels (HCLK etc)
// This is general routing through CLK0 pip
ci->setParam(id_INSEL, Property("CLKIN1"));
} while (0);
do {
// *** CLKFB
if (str_or_default(ci->params, id_CLKFB_SEL, "internal") == "internal") {
ci->setParam(id_FBSEL, Property("CLKFB3"));
continue;
}
if (!port_used(ci, id_CLKFB)) {
ci->setParam(id_FBSEL, Property("UNKNOWN"));
continue;
}
NetInfo *net = ci->getPort(id_CLKFB);
if (net->name == id("$PACKER_VCC_NET") || net->name == id("$PACKER_GND_NET")) {
ci->setParam(id_FBSEL, Property("UNKNOWN"));
continue;
}
if (net_driven_by(ctx, net, is_PLL_T_FB_iob, id_O) != nullptr) {
ci->disconnectPort(id_CLKFB);
ci->setParam(id_FBSEL, Property("CLKFB2"));
break;
}
// XXX do special bels (HCLK etc)
// This is general routing through CLK2 pip
ci->setParam(id_FBSEL, Property("CLKFB0"));
} while (0);
// resets
Property pr_enable("ENABLE"), pr_disable("DISABLE");
NetInfo *net = ci->getPort(id_RESET);
ci->setParam(id_RSTEN, pr_enable);
if (!port_used(ci, id_RESET) || net->name == id("$PACKER_VCC_NET") || net->name == id("$PACKER_GND_NET")) {
ci->setParam(id_RSTEN, pr_disable);
}
ci->setParam(id_PWDEN, pr_enable);
net = ci->getPort(id_RESET_P);
if (!port_used(ci, id_RESET_P) || net->name == id("$PACKER_VCC_NET") || net->name == id("$PACKER_GND_NET")) {
ci->setParam(id_PWDEN, pr_disable);
}
}
}
void Arch::pre_route(Context *ctx)
{
fix_pll_nets(ctx);
if (bool_or_default(settings, id("arch.enable-globals"))) {
mark_gowin_globals(ctx);
}
}
void Arch::post_route(Context *ctx) { fix_longwire_bels(); }
bool Arch::route() bool Arch::route()
{ {
std::string router = str_or_default(settings, id_router, defaultRouter); std::string router = str_or_default(settings, id_router, defaultRouter);
Context *ctx = getCtx();
pre_route(ctx);
if (bool_or_default(settings, id("arch.enable-globals"))) { if (bool_or_default(settings, id("arch.enable-globals"))) {
route_gowin_globals(getCtx()); route_gowin_globals(ctx);
} }
bool result; bool result;
if (router == "router1") { if (router == "router1") {
result = router1(getCtx(), Router1Cfg(getCtx())); result = router1(ctx, Router1Cfg(ctx));
} else if (router == "router2") { } else if (router == "router2") {
router2(getCtx(), Router2Cfg(getCtx())); router2(ctx, Router2Cfg(ctx));
result = true; result = true;
} else { } else {
log_error("Gowin architecture does not support router '%s'\n", router.c_str()); log_error("Gowin architecture does not support router '%s'\n", router.c_str());
} }
getCtx()->settings[id_route] = 1; getCtx()->settings[id_route] = 1;
archInfoToAttributes(); archInfoToAttributes();
fix_longwire_bels(); post_route(ctx);
return result; return result;
} }
@ -2174,11 +2295,6 @@ void Arch::pre_pack(Context *ctx)
} }
} }
void Arch::post_pack(Context *ctx) void Arch::post_pack(Context *ctx) {}
{
if (bool_or_default(settings, id("arch.enable-globals"))) {
mark_gowin_globals(ctx);
}
}
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -227,6 +227,7 @@ struct BelInfo
std::map<IdString, std::string> attrs; std::map<IdString, std::string> attrs;
CellInfo *bound_cell; CellInfo *bound_cell;
dict<IdString, PinInfo> pins; dict<IdString, PinInfo> pins;
std::vector<IdString> pin_cfgs;
DecalXY decalxy_active, decalxy_inactive; DecalXY decalxy_active, decalxy_inactive;
int x, y, z; int x, y, z;
bool gb; bool gb;
@ -474,8 +475,11 @@ struct Arch : BaseArch<ArchRanges>
void fix_longwire_bels(); void fix_longwire_bels();
void pre_pack(Context *ctx); void pre_pack(Context *ctx);
void post_pack(Context *ctx); void post_pack(Context *ctx);
void pre_route(Context *ctx);
void post_route(Context *ctx);
void auto_longwires(); void auto_longwires();
void add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col); void add_plla_ports(BelsPOD const *bel, IdString belname, int row, int col);
void fix_pll_nets(Context *ctx);
GowinGlobalRouter globals_router; GowinGlobalRouter globals_router;
void mark_gowin_globals(Context *ctx); void mark_gowin_globals(Context *ctx);

View File

@ -105,6 +105,8 @@ inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type
inline bool is_sram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_RAM16SDP4; } inline bool is_sram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_RAM16SDP4; }
inline bool is_iob(const Context *ctx, const CellInfo *cell) { return (cell->type.index == ID_IOB); }
// Convert a LUT primitive to (part of) an GENERIC_SLICE, swapping ports // Convert a LUT primitive to (part of) an GENERIC_SLICE, swapping ports
// as needed. Set no_dff if a DFF is not being used, so that the output // as needed. Set no_dff if a DFF is not being used, so that the output
// can be reconnected // can be reconnected

View File

@ -938,6 +938,9 @@ X(CLKOUTDIV3)
X(PWDEN) X(PWDEN)
X(RSTEN) X(RSTEN)
X(FLOCK) X(FLOCK)
X(INSEL)
X(FBSEL)
X(CLKFB_SEL)
// timing // timing
X(X0) X(X0)

View File

@ -820,8 +820,6 @@ static bool is_gowin_iologic(const Context *ctx, const CellInfo *cell)
} }
} }
static bool is_iob(const Context *ctx, const CellInfo *cell) { return (cell->type.index == ID_IOB); }
// Pack IO logic // Pack IO logic
static void pack_iologic(Context *ctx) static void pack_iologic(Context *ctx)
{ {
@ -1021,10 +1019,11 @@ static void pack_plls(Context *ctx)
if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1") { if (parm_device == "GW1N-1" || parm_device == "GW1NZ-1") {
// Unused ports will be disabled during image generation. Here we add flags for such ports. // Unused ports will be disabled during image generation. Here we add flags for such ports.
Property pr_enable("ENABLE"), pr_disable("DISABLE"); Property pr_enable("ENABLE"), pr_disable("DISABLE");
IdString ports[][2] = {{id_CLKOUTP, id_CLKOUTPS}, {id_CLKOUTD, id_CLKOUTDIV}, IdString ports[][2] = {{id_CLKOUTP, id_CLKOUTPS},
{id_CLKOUTD3, id_CLKOUTDIV3}, {id_LOCK, id_FLOCK}, {id_CLKOUTD, id_CLKOUTDIV},
{id_RESET_P, id_PWDEN}, {id_RESET, id_RSTEN}}; {id_CLKOUTD3, id_CLKOUTDIV3},
for (int i = 0; i < 6; ++i) { {id_LOCK, id_FLOCK}};
for (int i = 0; i < 4; ++i) {
ci->setParam(ports[i][1], port_used(ci, ports[i][0]) ? pr_enable : pr_disable); ci->setParam(ports[i][1], port_used(ci, ports[i][0]) ? pr_enable : pr_disable);
} }
// B half // B half