From fb4171a63dff1d91bc9da4703537abb249cef2b2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 10 Jul 2024 12:18:50 +0200 Subject: [PATCH] Support post-routing CSC and SCC --- himbaechel/uarch/ng-ultra/gen/arch_gen.py | 4 +- himbaechel/uarch/ng-ultra/ng_ultra.cc | 77 ++++++++++++++++++++--- himbaechel/uarch/ng-ultra/ng_ultra.h | 3 + himbaechel/uarch/ng-ultra/pack.cc | 63 +++++++++++++------ 4 files changed, 118 insertions(+), 29 deletions(-) diff --git a/himbaechel/uarch/ng-ultra/gen/arch_gen.py b/himbaechel/uarch/ng-ultra/gen/arch_gen.py index a63dfabf..f3f9e3f5 100644 --- a/himbaechel/uarch/ng-ultra/gen/arch_gen.py +++ b/himbaechel/uarch/ng-ultra/gen/arch_gen.py @@ -366,8 +366,8 @@ def create_tile_types(ch: Chip, bels, bel_pins, crossbars, interconnects, muxes, vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0) vi = tt.create_pip(f"{name}.DJ",f"{name}.DC","Virtual") vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0) - #vi = tt.create_pip(f"{name}.DJ",f"{name}.DS","Virtual") - #vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0) + vi = tt.create_pip(f"{name}.DJ",f"{name}.DS","Virtual") + vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0) vi = tt.create_pip(f"{name}.DJ",f"{name}.DK","Virtual") vi.extra_data = PipExtraData(ch.strs.id(name),PIP_EXTRA_VIRTUAL,0,0) # DFF bypass diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.cc b/himbaechel/uarch/ng-ultra/ng_ultra.cc index cbdff63c..0e09667f 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.cc +++ b/himbaechel/uarch/ng-ultra/ng_ultra.cc @@ -262,12 +262,60 @@ bool NgUltraImpl::get_mux_data(WireId wire, uint8_t *value) return false; } +bool NgUltraImpl::update_bff_to_csc(CellInfo *cell, BelId bel, PipId dst_pip) +{ + const auto &bel_data = chip_bel_info(ctx->chip_info, bel); + const auto &extra_data = *reinterpret_cast(bel_data.extra_data.get()); + // Check if CSC mode only if FE is capable + if (extra_data.flags & BEL_EXTRA_FE_CSC) { + WireId dwire = ctx->getPipDstWire(dst_pip); + for (PipId pip : ctx->getPipsDownhill(dwire)) { + if (!ctx->getBoundPipNet(pip)) + continue; + for (PipId pip2 : ctx->getPipsDownhill(ctx->getPipDstWire(pip))) { + if (!ctx->getBoundPipNet(pip2)) + continue; + IdString dst = ctx->getWireName(ctx->getPipDstWire(pip2))[1]; + if (boost::ends_with(dst.c_str(ctx),".DS")) { + cell->setParam(ctx->id("type"), Property("CSC")); + return true; + } + } + } + } + return false; +} + +bool NgUltraImpl::update_bff_to_scc(CellInfo *cell, BelId bel, PipId dst_pip) +{ + const auto &bel_data = chip_bel_info(ctx->chip_info, bel); + const auto &extra_data = *reinterpret_cast(bel_data.extra_data.get()); + // Check if SCC mode only if FE is capable + if (extra_data.flags & BEL_EXTRA_FE_SCC) { + WireId dwire = ctx->getPipDstWire(dst_pip); + for (PipId pip : ctx->getPipsUphill(dwire)) { + if (!ctx->getBoundPipNet(pip)) + continue; + for (PipId pip2 : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) { + if (!ctx->getBoundPipNet(pip2)) + continue; + IdString dst = ctx->getWireName(ctx->getPipSrcWire(pip2))[1]; + if (boost::starts_with(dst.c_str(ctx),"SYSTEM.ST1")) { + cell->setParam(ctx->id("type"), Property("SCC")); + return true; + } + } + } + } + return false; +} + void NgUltraImpl::postRoute() { ctx->assignArchInfo(); log_break(); log_info("Resources spent on routing:\n"); - int dff_bypass = 0, lut_bypass = 0, fe_new = 0, wfg_bypass = 0, gck_bypass = 0; + int bff_count = 0, csc_count = 0, scc_count = 0, lut_bypass = 0, fe_new = 0, wfg_bypass = 0, gck_bypass = 0; for (auto &net : ctx->nets) { NetInfo *ni = net.second.get(); for (auto &w : ni->wires) { @@ -288,10 +336,16 @@ void NgUltraImpl::postRoute() switch(type.index) { case id_BEYOND_FE.index : if (extra_data.input==0) { - dff_bypass++; // set bypass mode for DFF cell->setParam(ctx->id("type"), Property("BFF")); cell->params[id_dff_used] = Property(1,1); + // Note: no conflict, CSC and SCC modes are never available on same position + if (update_bff_to_csc(cell, bel, w.second.pip)) + csc_count++; + else if(update_bff_to_scc(cell, bel, w.second.pip)) + scc_count++; + else + bff_count++; } else { lut_bypass++; cell->params[id_lut_used] = Property(1,1); @@ -311,11 +365,20 @@ void NgUltraImpl::postRoute() } } } - log_info(" %6d DFFs used in bypass mode (BFF)\n", dff_bypass); - log_info(" %6d LUTs used in bypass mode\n", lut_bypass); - log_info(" %6d newly allocated FEs\n", fe_new); - log_info(" %6d WFGs used as WFB\n", wfg_bypass); - log_info(" %6d GCK\n", gck_bypass); + if (bff_count) + log_info(" %6d DFFs used as BFF\n", bff_count); + if (csc_count) + log_info(" %6d DFFs used as CSC\n", csc_count); + if (scc_count) + log_info(" %6d DFFs used as SCC\n", scc_count); + if(lut_bypass) + log_info(" %6d LUTs used in bypass mode\n", lut_bypass); + if (fe_new) + log_info(" %6d newly allocated FEs\n", fe_new); + if (wfg_bypass) + log_info(" %6d WFGs used as WFB\n", wfg_bypass); + if (gck_bypass) + log_info(" %6d GCK\n", gck_bypass); // Handle LUT permutation for (auto &cell : ctx->cells) { diff --git a/himbaechel/uarch/ng-ultra/ng_ultra.h b/himbaechel/uarch/ng-ultra/ng_ultra.h index 33b2af49..a5a91594 100644 --- a/himbaechel/uarch/ng-ultra/ng_ultra.h +++ b/himbaechel/uarch/ng-ultra/ng_ultra.h @@ -99,6 +99,9 @@ TESTABLE_PRIVATE: void route_lowskew(); void parse_csv(const std::string &filename); void remove_constants(); + bool update_bff_to_csc(CellInfo *cell, BelId bel, PipId dst_pip); + bool update_bff_to_scc(CellInfo *cell, BelId bel, PipId dst_pip); + void disable_beyond_fe_s_output(BelId bel); // Misc utility functions bool get_mux_data(BelId bel, IdString port, uint8_t *value); diff --git a/himbaechel/uarch/ng-ultra/pack.cc b/himbaechel/uarch/ng-ultra/pack.cc index 352f8836..b295d67e 100644 --- a/himbaechel/uarch/ng-ultra/pack.cc +++ b/himbaechel/uarch/ng-ultra/pack.cc @@ -1984,35 +1984,58 @@ void NgUltraPacker::pre_place(void) } } +void NgUltraImpl::disable_beyond_fe_s_output(BelId bel) +{ + WireId dwire = ctx->getBelPinWire(bel, id_DO); + for (PipId pip : ctx->getPipsDownhill(dwire)) { + for (PipId pip2 : ctx->getPipsDownhill(ctx->getPipDstWire(pip))) { + IdString dst = ctx->getWireName(ctx->getPipDstWire(pip2))[1]; + if (boost::ends_with(dst.c_str(ctx),".DS")) { + blocked_pips.emplace(pip2); + return; + } + } + } +} + void NgUltraImpl::postPlace() { log_break(); log_info("Limiting routing...\n"); for (auto &cell : ctx->cells) { CellInfo &ci = *cell.second; - if (!ci.type.in(id_CY)) - continue; - // In case A input is actually used, but it is connectd to GND - // it is considered that signal is comming from RI1 crossbar. - // We need to prevent router to use that crossbar output for - // any other signal. - for (int i=1;i<=4;i++) { - IdString port = ctx->idf("A%d",i); - NetInfo *net = ci.getPort(port); - if (!net) - continue; - if (net->name.in(ctx->id("$PACKER_GND"))) { - WireId dwire = ctx->getBelPinWire(ci.bel, port); - for (PipId pip : ctx->getPipsUphill(dwire)) { - WireId src = ctx->getPipSrcWire(pip); - const std::string src_name = ctx->getWireName(src)[1].str(ctx); - if (boost::starts_with(src_name,"RI1")) { - for (PipId pip2 : ctx->getPipsDownhill(src)) { - blocked_pips.emplace(pip2); + if (ci.type == id_BEYOND_FE) { + const auto &bel_data = chip_bel_info(ctx->chip_info, ci.bel); + const auto &extra_data = *reinterpret_cast(bel_data.extra_data.get()); + // Check if CSC mode only if FE is capable + if ((extra_data.flags & BEL_EXTRA_FE_CSC)) { + if (str_or_default(ci.params, ctx->id("type"), "")!="DFF") continue; + // Disable routing to S output if DFF used + disable_beyond_fe_s_output(ci.bel); + } + } else if (ci.type == id_CY) { + // In case A input is actually used, but it is connectd to GND + // it is considered that signal is comming from RI1 crossbar. + // We need to prevent router to use that crossbar output for + // any other signal. + for (int i=1;i<=4;i++) { + IdString port = ctx->idf("A%d",i); + NetInfo *net = ci.getPort(port); + if (!net) + continue; + if (net->name.in(ctx->id("$PACKER_GND"))) { + WireId dwire = ctx->getBelPinWire(ci.bel, port); + for (PipId pip : ctx->getPipsUphill(dwire)) { + WireId src = ctx->getPipSrcWire(pip); + const std::string src_name = ctx->getWireName(src)[1].str(ctx); + if (boost::starts_with(src_name,"RI1")) { + for (PipId pip2 : ctx->getPipsDownhill(src)) { + blocked_pips.emplace(pip2); + } } } + ci.disconnectPort(port); // Disconnect A } - ci.disconnectPort(port); // Disconnect A } } }