diff options
author | YRabbit <rabbit@yrabbit.cyou> | 2022-11-10 19:14:41 +1000 |
---|---|---|
committer | YRabbit <rabbit@yrabbit.cyou> | 2022-11-10 19:14:41 +1000 |
commit | a84ded4793ce66b0f4854349c929afae334d1e56 (patch) | |
tree | 53451f52123c43d3c6cf0f49c73f46627263b21e /gowin/pack.cc | |
parent | ac17c36bec5b0ae8d57b66f825acb6f21f2ca323 (diff) | |
download | nextpnr-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.cc | 72 |
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(); |