diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.cc b/himbaechel/uarch/ng-ultra/ng_ultra.cc index bb83785a..9fa7aa0f 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.cc +++ b/himbaechel/uarch/ng-ultra/ng_ultra.cc @@ -54,8 +54,8 @@ void NgUltraImpl::init(Context *ctx) HimbaechelAPI::init(ctx); for (auto bel : ctx->getBels()) { if (ctx->getBelType(bel) == id_IOM) { - std::deque wfgs; - std::deque plls; + pool wfgs; + pool plls; IdString bank = tile_name_id(bel.tile); iom_bels.emplace(bank,bel); WireId belpin = ctx->getBelPinWire(bel,id_CKO1); @@ -63,10 +63,12 @@ void NgUltraImpl::init(Context *ctx) WireId pip_dst = ctx->getPipDstWire(dh); for (const auto &item : ctx->getWireBelPins(pip_dst)) { if (boost::contains(ctx->nameOfBel(item.bel),"WFG_C")) { - wfgs.push_back(item.bel); + wfgs.emplace(item.bel); + unused_wfg.emplace(item.bel); } else if (boost::contains(ctx->nameOfBel(item.bel),"PLL")) { - plls.push_back(item.bel); + plls.emplace(item.bel); + unused_pll.emplace(item.bel); } } } diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.h b/himbaechel/uarch/ng-ultra/ng_ultra.h index 8376ead7..3d6647f6 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.h +++ b/himbaechel/uarch/ng-ultra/ng_ultra.h @@ -74,8 +74,10 @@ public: dict> gck_per_lobe; pool blocked_pips; - dict> wfg_c_per_bank; - dict> pll_per_bank; + dict> wfg_c_per_bank; + dict> pll_per_bank; + std::set unused_wfg; + std::set unused_pll; private: void write_bitstream_json(const std::string &filename); diff --git a/himbaechel/uarch/ng-ultra/pack.cc b/himbaechel/uarch/ng-ultra/pack.cc index 9940706c..09f0b5b8 100644 --- a/himbaechel/uarch/ng-ultra/pack.cc +++ b/himbaechel/uarch/ng-ultra/pack.cc @@ -48,6 +48,9 @@ inline bool is_fe(const BaseCtx *ctx, const CellInfo *cell) { return cell->type // Return true if a cell is a DFR inline bool is_dfr(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_NX_DFR; } +// Return true if a cell is a WFG/WFB +inline bool is_wfg(const BaseCtx *ctx, const CellInfo *cell) { return cell->type.in(id_WFB, id_WFG); } + // Process the contents of packed_cells void NgUltraPacker::flush_cells() { @@ -1052,19 +1055,34 @@ void NgUltraPacker::insert_ioms() ctx->cells.erase(bfr->name); } } - - for (auto &cell : ctx->cells) { - CellInfo &ci = *cell.second; - if (!ci.type.in(id_IOM)) - continue; - insert_wfb(&ci, id_CKO1); - insert_wfb(&ci, id_CKO2); - } - if (bfr_removed) log_info(" Removed %d unused BFR\n", bfr_removed); } +void NgUltraPacker::insert_wfbs() +{ + log_info("Inserting WFBs for IOMs...\n"); + for (auto &cell : ctx->cells) { + CellInfo &ci = *cell.second; + if (ci.type.in(id_IOM)) { + insert_wfb(&ci, id_CKO1); + insert_wfb(&ci, id_CKO2); + } else if (ci.type.in(id_PLL)) { + insert_wfb(&ci, id_VCO); + insert_wfb(&ci, id_REFO); + insert_wfb(&ci, id_LDFO); + insert_wfb(&ci, id_CLK_DIV1); + insert_wfb(&ci, id_CLK_DIV2); + insert_wfb(&ci, id_CLK_DIV3); + insert_wfb(&ci, id_CLK_DIVD1); + insert_wfb(&ci, id_CLK_DIVD2); + insert_wfb(&ci, id_CLK_DIVD3); + insert_wfb(&ci, id_CLK_DIVD4); + insert_wfb(&ci, id_CLK_DIVD5); + } + } +} + void NgUltraPacker::mandatory_param(CellInfo *cell, IdString param) { if (!cell->params.count(param)) @@ -1121,13 +1139,9 @@ void NgUltraPacker::insert_wfb(CellInfo *cell, IdString port) { NetInfo *net = cell->getPort(port); if (!net) return; - IdString bank; - if (cell->type == id_IOM) { - bank = uarch->tile_name_id(cell->bel.tile); - log("bank:%s\n",bank.c_str(ctx)); - } - BelId bel = uarch->wfg_c_per_bank[bank].back(); - uarch->wfg_c_per_bank[bank].pop_back(); + + CellInfo *wfg = net_only_drives(ctx, net, is_wfg, id_ZI, true); + if (wfg) return; log_info(" Inserting WFB for cell '%s' port '%s'\n", cell->name.c_str(ctx), port.c_str(ctx)); CellInfo *wfb = create_cell_ptr(id_WFB, ctx->id(std::string(cell->name.c_str(ctx)) + "$" + port.c_str(ctx))); cell->disconnectPort(port); @@ -1135,7 +1149,6 @@ void NgUltraPacker::insert_wfb(CellInfo *cell, IdString port) NetInfo *new_out = ctx->createNet(ctx->id(net->name.str(ctx) + "$" + port.c_str(ctx))); cell->connectPort(port, new_out); wfb->connectPort(id_ZI, new_out); - ctx->bindBel(bel, wfb, PlaceStrength::STRENGTH_LOCKED); } void NgUltraPacker::constrain_location(CellInfo *cell) @@ -1180,17 +1193,6 @@ void NgUltraPacker::pack_plls(void) disconnect_if_gnd(&ci, id_EXT_CAL5); disconnect_if_gnd(&ci, id_EXT_CAL_LOCKED); disconnect_if_gnd(&ci, id_ARST_CAL); - insert_wfb(&ci, id_VCO); - insert_wfb(&ci, id_REFO); - insert_wfb(&ci, id_LDFO); - insert_wfb(&ci, id_CLK_DIV1); - insert_wfb(&ci, id_CLK_DIV2); - insert_wfb(&ci, id_CLK_DIV3); - insert_wfb(&ci, id_CLK_DIVD1); - insert_wfb(&ci, id_CLK_DIVD2); - insert_wfb(&ci, id_CLK_DIVD3); - insert_wfb(&ci, id_CLK_DIVD4); - insert_wfb(&ci, id_CLK_DIVD5); } } @@ -1363,7 +1365,7 @@ void NgUltraPacker::setup() // clock_sinks[id_XWFIFO].insert(id_WCK1); // clock_sinks[id_XWFIFO].insert(id_WCK2); - // clock_sinks[id_DSP].insert(id_CK); + clock_sinks[id_DSP].insert(id_CK); clock_sinks[id_PLL].insert(id_CLK_CAL); clock_sinks[id_PLL].insert(id_FBK); @@ -1403,26 +1405,96 @@ void NgUltraImpl::pack() if (args.options.count("csv")) { parse_csv(args.options.at("csv")); } + + // Setup NgUltraPacker packer(ctx, this); packer.setup(); packer.pack_constants(); packer.update_lut_init(); packer.update_dffs(); - packer.pack_iobs(); - packer.pack_ioms(); - packer.pack_gcks(); - packer.pack_plls(); - packer.pack_wfgs(); + + // CGB packer.pack_rams(); packer.pack_dsps(); + + // TILE packer.pack_rfs(); packer.pack_cys(); packer.pack_lut_dffs(); packer.pack_dffs(); + + // Tube + packer.pack_gcks(); + + // Ring + packer.pack_iobs(); + packer.pack_ioms(); + packer.pack_plls(); + packer.pack_wfgs(); packer.insert_ioms(); + packer.insert_wfbs(); + + packer.pre_place(); } +void NgUltraPacker::pre_place(void) +{ + log_info("Pre-placing PLLs..\n"); + + for (auto &cell : ctx->cells) { + CellInfo &ci = *cell.second; + if (!ci.type.in(id_PLL)) + continue; + // Remove from list those that are used + if (ci.bel != BelId()) { + uarch->unused_pll.erase(ci.bel); + } + } + // First process those on dedicated clock pins + for (auto &cell : ctx->cells) { + CellInfo &ci = *cell.second; + if (!ci.type.in(id_PLL) || ci.bel != BelId()) + continue; + + NetInfo *ref = ci.getPort(id_REF); + if (ref && ref->driver.cell && ref->driver.cell->type == id_IOM) { + IdString bank= uarch->tile_name_id(ref->driver.cell->bel.tile); + bool found = false; + for (auto &bel : uarch->pll_per_bank[bank]) { + if (uarch->unused_pll.count(bel)) { + uarch->unused_pll.erase(bel); + log_info(" Using PLL in '%s' for cell '%s'.\n", uarch->tile_name(bel.tile).c_str(), ci.name.c_str(ctx)); + ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_LOCKED); + found = true; + break; + } + } + if (!found) + log_error(" No more available PLLs for driving '%s'.\n", ci.name.c_str(ctx)); + } + } + for (auto &cell : ctx->cells) { + CellInfo &ci = *cell.second; + if (!ci.type.in(id_PLL) || ci.bel != BelId()) + continue; + log_warning(" PLL '%s' is not driven by clock dedicated pin.\n", ci.name.c_str(ctx)); + if (uarch->unused_pll.empty()) + log_error(" No more available PLLs for driving '%s'.\n", ci.name.c_str(ctx)); + BelId bel = *uarch->unused_pll.begin(); + uarch->unused_pll.erase(bel); + log_info(" Using PLL in '%s' for cell '%s'.\n", uarch->tile_name(bel.tile).c_str(), ci.name.c_str(ctx)); + ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_LOCKED); + } + + log_info("Pre-placing WFB/WFGs..\n"); + for (auto &cell : ctx->cells) { + CellInfo &ci = *cell.second; + if (!ci.type.in(id_WFG, id_WFB)) + continue; + } +} + void NgUltraImpl::postPlace() { log_break(); diff --git a/himbaechel/uarch/ng-ultra/pack.h b/himbaechel/uarch/ng-ultra/pack.h index 2c8ee60a..a3504e00 100644 --- a/himbaechel/uarch/ng-ultra/pack.h +++ b/himbaechel/uarch/ng-ultra/pack.h @@ -60,8 +60,10 @@ struct NgUltraPacker void pack_gcks(); void pack_plls(); void pack_wfgs(); + void pre_place(); void insert_ioms(); + void insert_wfbs(); void setup();