aboutsummaryrefslogtreecommitdiffstats
path: root/gowin/pack.cc
diff options
context:
space:
mode:
authorYRabbit <rabbit@yrabbit.cyou>2022-11-10 19:14:41 +1000
committerYRabbit <rabbit@yrabbit.cyou>2022-11-10 19:14:41 +1000
commita84ded4793ce66b0f4854349c929afae334d1e56 (patch)
tree53451f52123c43d3c6cf0f49c73f46627263b21e /gowin/pack.cc
parentac17c36bec5b0ae8d57b66f825acb6f21f2ca323 (diff)
downloadnextpnr-a84ded4793ce66b0f4854349c929afae334d1e56.tar.gz
nextpnr-a84ded4793ce66b0f4854349c929afae334d1e56.tar.bz2
nextpnr-a84ded4793ce66b0f4854349c929afae334d1e56.zip
gowin: add initial PLL support
The rPLL primitive for the simplest chip (GW1N-1) in the family is processed. All parameters of the primitive are passed on to gowin_pack, and general-purpose wires are used for routing outputs of the primitive. Compatible with older versions of apicula, but in this case will refuse to place the new primitive. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
Diffstat (limited to 'gowin/pack.cc')
-rw-r--r--gowin/pack.cc72
1 files changed, 72 insertions, 0 deletions
diff --git a/gowin/pack.cc b/gowin/pack.cc
index d978ac40..5260dda5 100644
--- a/gowin/pack.cc
+++ b/gowin/pack.cc
@@ -986,6 +986,77 @@ static void pack_diff_io(Context *ctx)
}
}
+static bool is_pll(const Context *ctx, const CellInfo *cell)
+{
+ switch (cell->type.hash()) {
+ case ID_rPLL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Pack PLLs
+static void pack_plls(Context *ctx)
+{
+ pool<IdString> packed_cells;
+ pool<IdString> delete_nets;
+
+ std::vector<std::unique_ptr<CellInfo>> new_cells;
+ log_info("Packing PLLs..\n");
+
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
+ 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");
+ if (parm_device != ctx->device) {
+ log_error("Wrong PLL device:%s vs %s\n", parm_device.c_str(), ctx->device.c_str());
+ continue;
+ }
+
+ switch (ci->type.hash()) {
+ case ID_rPLL: {
+ if (parm_device == "GW1N-1") {
+ // B half
+ std::unique_ptr<CellInfo> cell = create_generic_cell(ctx, id_RPLLB, ci->name.str(ctx) + "$rpllb");
+ reconnect_rpllb(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();
+
+ // need params for gowin_pack
+ for (auto &parm : ci->params) {
+ plla_cell->setParam(parm.first, parm.second);
+ pllb_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());
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+ }
+
+ for (auto pcell : packed_cells) {
+ ctx->cells.erase(pcell);
+ }
+ for (auto dnet : delete_nets) {
+ ctx->nets.erase(dnet);
+ }
+ for (auto &ncell : new_cells) {
+ ctx->cells[ncell->name] = std::move(ncell);
+ }
+}
+
// Pack IO buffers
static void pack_io(Context *ctx)
{
@@ -1108,6 +1179,7 @@ bool Arch::pack()
pack_alus(ctx);
pack_lut_lutffs(ctx);
pack_nonlut_ffs(ctx);
+ pack_plls(ctx);
post_pack(ctx);
ctx->settings[id_pack] = 1;
ctx->assignArchInfo();