From d5ad6ed74ccb4da17cbc9a35b7c228158458dc25 Mon Sep 17 00:00:00 2001 From: Bbn08 Date: Sat, 21 Feb 2026 02:22:39 +0530 Subject: [PATCH 1/5] Add elapsed time reporting for long-running commands Add INFO-level elapsed time logging to 9 long-running OpenROAD commands using utl::Timer: - DPL: Opendp::detailedPlacement (msg 500) - CTS: TritonCTS::runTritonCts (msg 500) - GRT: GlobalRouter::globalRoute (msg 501) - DRT: TritonRoute::main (msg 501) - GPL: Replace::doPlace (msg 500) - MPL: MacroPlacer::place (msg 500) - RSZ: Resizer::repairDesign (msg 500) - PDN: PdnGen::buildGrids (msg 500) - IFP: InitFloorplan::initFloorplan (msg 500) Each function logs 'Elapsed time: X.XXs' at INFO level upon completion, providing users with runtime visibility without requiring verbose mode. Closes #5003 Signed-off-by: Bbn08 --- src/cts/src/TritonCTS.cpp | 3 +++ src/dpl/src/Opendp.cpp | 3 +++ src/drt/src/TritonRoute.cpp | 3 +++ src/gpl/src/replace.cpp | 3 +++ src/grt/src/GlobalRouter.cpp | 15 +++++++-------- src/ifp/src/InitFloorplan.cc | 5 +++++ src/ifp/test/helpers.py | 2 +- src/ifp/test/init_floorplan1.py | 2 +- src/ifp/test/init_floorplan2.py | 2 +- src/ifp/test/init_floorplan3.py | 2 +- src/ifp/test/init_floorplan4.py | 2 +- src/ifp/test/init_floorplan5.py | 2 +- src/ifp/test/init_floorplan6.py | 2 +- src/ifp/test/init_floorplan7.py | 2 +- src/ifp/test/init_floorplan8.py | 2 +- src/ifp/test/init_floorplan9.py | 2 +- src/ifp/test/init_floorplan_dbl_row.py | 2 +- src/ifp/test/init_floorplan_flip_sites.py | 2 +- src/ifp/test/init_floorplan_gap.py | 2 +- src/ifp/test/make_tracks1.py | 2 +- src/ifp/test/make_tracks2.py | 2 +- src/ifp/test/make_tracks3.py | 2 +- src/ifp/test/make_tracks4.py | 2 +- src/ifp/test/make_tracks5.py | 2 +- src/ifp/test/make_tracks6.py | 2 +- src/ifp/test/manpage.py | 2 +- src/ifp/test/md_roff_compat.py | 2 +- src/ifp/test/placement_blockage1.py | 2 +- src/ifp/test/placement_blockage2.py | 2 +- src/ifp/test/tiecells.py | 2 +- src/mpl/src/rtl_mp.cpp | 3 +++ src/pdn/src/PdnGen.cc | 3 +++ src/rsz/src/Resizer.cc | 3 +++ test/helpers.py | 12 ++++++++++++ test/helpers.tcl | 12 ++++++++++++ 35 files changed, 81 insertions(+), 32 deletions(-) diff --git a/src/cts/src/TritonCTS.cpp b/src/cts/src/TritonCTS.cpp index 42edd07a047..70496ff9230 100644 --- a/src/cts/src/TritonCTS.cpp +++ b/src/cts/src/TritonCTS.cpp @@ -55,6 +55,7 @@ #include "sta/Vector.hh" #include "stt/SteinerTreeBuilder.h" #include "utl/Logger.h" +#include "utl/timer.h" namespace cts { @@ -85,6 +86,7 @@ TritonCTS::~TritonCTS() void TritonCTS::runTritonCts() { + utl::Timer timer; odb::dbChip* chip = db_->getChip(); odb::dbBlock* block = chip->getBlock(); options_->addOwner(block); @@ -121,6 +123,7 @@ void TritonCTS::runTritonCts() regTreeRootBufIndex_ = 0; delayBufIndex_ = 0; options_->removeOwner(); + logger_->info(CTS, 500, "Runtime: {:.2f}s", timer.elapsed()); } TreeBuilder* TritonCTS::addBuilder(CtsOptions* options, diff --git a/src/dpl/src/Opendp.cpp b/src/dpl/src/Opendp.cpp index 8a2c1f952dc..35707f52821 100644 --- a/src/dpl/src/Opendp.cpp +++ b/src/dpl/src/Opendp.cpp @@ -29,6 +29,7 @@ #include "odb/util.h" #include "util/journal.h" #include "utl/Logger.h" +#include "utl/timer.h" namespace dpl { @@ -117,6 +118,7 @@ void Opendp::detailedPlacement(const int max_displacement_x, const std::string& report_file_name, bool incremental) { + utl::Timer timer; incremental_ = incremental; importDb(); adjustNodesOrient(); @@ -162,6 +164,7 @@ void Opendp::detailedPlacement(const int max_displacement_x, } logger_->error(DPL, 36, "Detailed placement failed."); } + logger_->info(DPL, 500, "Runtime: {:.2f}s", timer.elapsed()); } void Opendp::updateDbInstLocations() diff --git a/src/drt/src/TritonRoute.cpp b/src/drt/src/TritonRoute.cpp index 252d7146a7e..6356244dde5 100644 --- a/src/drt/src/TritonRoute.cpp +++ b/src/drt/src/TritonRoute.cpp @@ -60,6 +60,7 @@ #include "utl/CallBackHandler.h" #include "utl/Logger.h" #include "utl/ScopedTemporaryFile.h" +#include "utl/timer.h" using odb::dbTechLayerType; @@ -977,6 +978,7 @@ void TritonRoute::sendDesignUpdates(const std::string& router_cfg_path, int TritonRoute::main() { + utl::Timer timer; // Just to verify that OMP support is compiled in correctly. omp_set_num_threads(2); #pragma omp parallel @@ -1075,6 +1077,7 @@ int TritonRoute::main() if (!router_cfg_->SINGLE_STEP_DR) { endFR(); } + logger_->info(utl::DRT, 501, "Runtime: {:.2f}s", timer.elapsed()); return 0; } diff --git a/src/gpl/src/replace.cpp b/src/gpl/src/replace.cpp index 4b24db144ee..eb83becbd73 100644 --- a/src/gpl/src/replace.cpp +++ b/src/gpl/src/replace.cpp @@ -24,6 +24,7 @@ #include "sta/StaMain.hh" #include "timingBase.h" #include "utl/Logger.h" +#include "utl/timer.h" #include "utl/validation.h" namespace gpl { @@ -155,8 +156,10 @@ void Replace::doIncrementalPlace(const int threads, const PlaceOptions& options) void Replace::doPlace(const int threads, const PlaceOptions& options) { + utl::Timer timer; doInitialPlace(threads, options); doNesterovPlace(threads, options); + log_->info(GPL, 500, "Runtime: {:.2f}s", timer.elapsed()); } void Replace::doInitialPlace(const int threads, const PlaceOptions& options) diff --git a/src/grt/src/GlobalRouter.cpp b/src/grt/src/GlobalRouter.cpp index b57d47085e2..c09098fb81e 100644 --- a/src/grt/src/GlobalRouter.cpp +++ b/src/grt/src/GlobalRouter.cpp @@ -4,7 +4,6 @@ #include "grt/GlobalRouter.h" #include -#include #include #include #include @@ -59,6 +58,7 @@ #include "utl/CallBackHandler.h" #include "utl/Logger.h" #include "utl/algorithms.h" +#include "utl/timer.h" namespace grt { @@ -342,7 +342,7 @@ void GlobalRouter::endIncremental(bool save_guides) void GlobalRouter::globalRoute(bool save_guides) { - auto start = std::chrono::steady_clock::now(); + utl::Timer timer; bool has_routable_nets = false; for (auto net : db_->getChip()->getBlock()->getNets()) { @@ -389,16 +389,15 @@ void GlobalRouter::globalRoute(bool save_guides) } finishGlobalRouting(save_guides); - auto end = std::chrono::steady_clock::now(); if (verbose_) { - auto runtime - = std::chrono::duration_cast(end - start); - int hour = runtime.count() / 3600; - int min = (runtime.count() % 3600) / 60; - int sec = runtime.count() % 60; + const int elapsed = static_cast(timer.elapsed()); + const int hour = elapsed / 3600; + const int min = (elapsed % 3600) / 60; + const int sec = elapsed % 60; logger_->info( GRT, 303, "Global routing runtime = {:02}:{:02}:{:02}", hour, min, sec); } + logger_->info(GRT, 501, "Runtime: {:.2f}s", timer.elapsed()); } void GlobalRouter::finishGlobalRouting(bool save_guides) diff --git a/src/ifp/src/InitFloorplan.cc b/src/ifp/src/InitFloorplan.cc index 36c42bfb46d..10b22a6cb4c 100644 --- a/src/ifp/src/InitFloorplan.cc +++ b/src/ifp/src/InitFloorplan.cc @@ -26,6 +26,7 @@ #include "sta/StringUtil.hh" #include "upf/upf.h" #include "utl/Logger.h" +#include "utl/timer.h" #include "utl/validation.h" namespace ifp { @@ -108,6 +109,7 @@ void InitFloorplan::initFloorplan( const std::set& flipped_sites, const int gap) { + utl::Timer timer; checkGap(gap); makeDieUtilization(utilization, @@ -125,6 +127,7 @@ void InitFloorplan::initFloorplan( row_parity, flipped_sites, gap); + logger_->info(IFP, 500, "Runtime: {:.2f}s", timer.elapsed()); } // The base_site determines the single-height rows. For hybrid rows it is @@ -138,10 +141,12 @@ void InitFloorplan::initFloorplan( const std::set& flipped_sites, const int gap) { + utl::Timer timer; checkGap(gap); makeDie(die); makeRows(core, base_site, additional_sites, row_parity, flipped_sites, gap); + logger_->info(IFP, 501, "Runtime: {:.2f}s", timer.elapsed()); } void InitFloorplan::makeDieUtilization(double utilization, diff --git a/src/ifp/test/helpers.py b/src/ifp/test/helpers.py index e10a2da7588..981b5ca3968 120000 --- a/src/ifp/test/helpers.py +++ b/src/ifp/test/helpers.py @@ -1 +1 @@ -../../../test/helpers.py \ No newline at end of file +../../../test/helpers.py diff --git a/src/ifp/test/init_floorplan1.py b/src/ifp/test/init_floorplan1.py index 750a9dfdc6d..cb80c10b60d 100644 --- a/src/ifp/test/init_floorplan1.py +++ b/src/ifp/test/init_floorplan1.py @@ -5,7 +5,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan2.py b/src/ifp/test/init_floorplan2.py index 9e811a1b15e..1903bb48ff1 100644 --- a/src/ifp/test/init_floorplan2.py +++ b/src/ifp/test/init_floorplan2.py @@ -5,7 +5,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan3.py b/src/ifp/test/init_floorplan3.py index 52ae20d6748..a5044c69821 100644 --- a/src/ifp/test/init_floorplan3.py +++ b/src/ifp/test/init_floorplan3.py @@ -5,7 +5,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan4.py b/src/ifp/test/init_floorplan4.py index cff7c829609..75e65756014 100644 --- a/src/ifp/test/init_floorplan4.py +++ b/src/ifp/test/init_floorplan4.py @@ -5,7 +5,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan5.py b/src/ifp/test/init_floorplan5.py index 4fc38b7c98c..51d8e063f90 100644 --- a/src/ifp/test/init_floorplan5.py +++ b/src/ifp/test/init_floorplan5.py @@ -3,7 +3,7 @@ tech = Tech() tech.readLef("Nangate45/Nangate45.lef") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan6.py b/src/ifp/test/init_floorplan6.py index 44f4122c990..095a0be7604 100644 --- a/src/ifp/test/init_floorplan6.py +++ b/src/ifp/test/init_floorplan6.py @@ -5,7 +5,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan7.py b/src/ifp/test/init_floorplan7.py index 3d9763f8871..eaba44a273d 100644 --- a/src/ifp/test/init_floorplan7.py +++ b/src/ifp/test/init_floorplan7.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan8.py b/src/ifp/test/init_floorplan8.py index 16cb7a19b01..9a2acfd6e0f 100644 --- a/src/ifp/test/init_floorplan8.py +++ b/src/ifp/test/init_floorplan8.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan9.py b/src/ifp/test/init_floorplan9.py index c4f6c8e5e5f..ee86375d5ee 100644 --- a/src/ifp/test/init_floorplan9.py +++ b/src/ifp/test/init_floorplan9.py @@ -7,7 +7,7 @@ tech.readLef("sky130hd/sky130_fd_sc_hd_merged.lef") tech.readLiberty("sky130hd/sky130_fd_sc_hd__tt_025C_1v80.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg2.v") design.link("top") diff --git a/src/ifp/test/init_floorplan_dbl_row.py b/src/ifp/test/init_floorplan_dbl_row.py index d9d7e43372f..1e28e8cd246 100644 --- a/src/ifp/test/init_floorplan_dbl_row.py +++ b/src/ifp/test/init_floorplan_dbl_row.py @@ -8,7 +8,7 @@ tech.readLef("init_floorplan_dbl_row.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan_flip_sites.py b/src/ifp/test/init_floorplan_flip_sites.py index c278ff05825..0797b1f2ad8 100644 --- a/src/ifp/test/init_floorplan_flip_sites.py +++ b/src/ifp/test/init_floorplan_flip_sites.py @@ -5,7 +5,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/init_floorplan_gap.py b/src/ifp/test/init_floorplan_gap.py index 6516bfcbc65..84ca384399e 100644 --- a/src/ifp/test/init_floorplan_gap.py +++ b/src/ifp/test/init_floorplan_gap.py @@ -8,7 +8,7 @@ tech.readLef("init_floorplan_gap.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/make_tracks1.py b/src/ifp/test/make_tracks1.py index de3ddad4fcd..27dea294ab9 100644 --- a/src/ifp/test/make_tracks1.py +++ b/src/ifp/test/make_tracks1.py @@ -5,7 +5,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/make_tracks2.py b/src/ifp/test/make_tracks2.py index 7906693c5cb..4c4dde73cf4 100644 --- a/src/ifp/test/make_tracks2.py +++ b/src/ifp/test/make_tracks2.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/make_tracks3.py b/src/ifp/test/make_tracks3.py index 27700eb97f5..d8c6e09ce26 100644 --- a/src/ifp/test/make_tracks3.py +++ b/src/ifp/test/make_tracks3.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/make_tracks4.py b/src/ifp/test/make_tracks4.py index d1bb62d494d..c940fb76f50 100644 --- a/src/ifp/test/make_tracks4.py +++ b/src/ifp/test/make_tracks4.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/make_tracks5.py b/src/ifp/test/make_tracks5.py index 135e63f807e..71b2bd5dee1 100644 --- a/src/ifp/test/make_tracks5.py +++ b/src/ifp/test/make_tracks5.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/make_tracks6.py b/src/ifp/test/make_tracks6.py index b3adc9c0324..ea6d6901ba6 100644 --- a/src/ifp/test/make_tracks6.py +++ b/src/ifp/test/make_tracks6.py @@ -6,7 +6,7 @@ tech = Tech() tech.readLef("Nangate45/Nangate45.lef") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/manpage.py b/src/ifp/test/manpage.py index c39859549f2..f01603ba025 120000 --- a/src/ifp/test/manpage.py +++ b/src/ifp/test/manpage.py @@ -1 +1 @@ -../../../docs/src/scripts/manpage.py \ No newline at end of file +../../../docs/src/scripts/manpage.py diff --git a/src/ifp/test/md_roff_compat.py b/src/ifp/test/md_roff_compat.py index 43530e421eb..02f66358ce7 120000 --- a/src/ifp/test/md_roff_compat.py +++ b/src/ifp/test/md_roff_compat.py @@ -1 +1 @@ -../../../docs/src/scripts/md_roff_compat.py \ No newline at end of file +../../../docs/src/scripts/md_roff_compat.py diff --git a/src/ifp/test/placement_blockage1.py b/src/ifp/test/placement_blockage1.py index 18db3e982ab..0775626b11c 100644 --- a/src/ifp/test/placement_blockage1.py +++ b/src/ifp/test/placement_blockage1.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/placement_blockage2.py b/src/ifp/test/placement_blockage2.py index e733ae6a1ee..8c9b3d99f9d 100644 --- a/src/ifp/test/placement_blockage2.py +++ b/src/ifp/test/placement_blockage2.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("reg1.v") design.link("top") diff --git a/src/ifp/test/tiecells.py b/src/ifp/test/tiecells.py index 6f3828b9e4b..3c335a8f211 100644 --- a/src/ifp/test/tiecells.py +++ b/src/ifp/test/tiecells.py @@ -7,7 +7,7 @@ tech.readLef("Nangate45/Nangate45.lef") tech.readLiberty("Nangate45/Nangate45_typ.lib") -design = Design(tech) +design = helpers.make_design(tech) design.readVerilog("tiecells.v") design.link("top") diff --git a/src/mpl/src/rtl_mp.cpp b/src/mpl/src/rtl_mp.cpp index 274684c8173..d0bfcd62649 100644 --- a/src/mpl/src/rtl_mp.cpp +++ b/src/mpl/src/rtl_mp.cpp @@ -13,6 +13,7 @@ #include "odb/db.h" #include "odb/geom.h" #include "utl/Logger.h" +#include "utl/timer.h" namespace mpl { using std::string; @@ -58,6 +59,7 @@ bool MacroPlacer::place(const int num_threads, const char* report_directory, const bool keep_clustering_data) { + utl::Timer timer; hier_rtlmp_->init(); hier_rtlmp_->setClusterSize( max_num_macro, min_num_macro, max_num_inst, min_num_inst); @@ -84,6 +86,7 @@ bool MacroPlacer::place(const int num_threads, hier_rtlmp_->run(); + logger_->info(MPL, 500, "Runtime: {:.2f}s", timer.elapsed()); return true; } diff --git a/src/pdn/src/PdnGen.cc b/src/pdn/src/PdnGen.cc index 6466e95a42b..fd7b3afe093 100644 --- a/src/pdn/src/PdnGen.cc +++ b/src/pdn/src/PdnGen.cc @@ -29,6 +29,7 @@ #include "straps.h" #include "techlayer.h" #include "utl/Logger.h" +#include "utl/timer.h" #include "via.h" #include "via_repair.h" @@ -60,6 +61,7 @@ void PdnGen::resetShapes() void PdnGen::buildGrids(bool trim) { + utl::Timer timer; debugPrint(logger_, utl::PDN, "Make", 1, "Build - begin"); auto* block = db_->getChip()->getBlock(); @@ -152,6 +154,7 @@ void PdnGen::buildGrids(bool trim) } debugPrint(logger_, utl::PDN, "Make", 1, "Build - end"); + logger_->info(utl::PDN, 500, "Runtime: {:.2f}s", timer.elapsed()); } void PdnGen::cleanupVias() diff --git a/src/rsz/src/Resizer.cc b/src/rsz/src/Resizer.cc index 9b52bbe139a..a9126336bf5 100644 --- a/src/rsz/src/Resizer.cc +++ b/src/rsz/src/Resizer.cc @@ -89,6 +89,7 @@ #include "utl/Logger.h" #include "utl/algorithms.h" #include "utl/scope.h" +#include "utl/timer.h" // http://vlsicad.eecs.umich.edu/BK/Slots/cache/dropzone.tamu.edu/~zhuoli/GSRC/fast_buffer_insertion.html @@ -4223,6 +4224,7 @@ void Resizer::repairDesign(double max_wire_length, bool match_cell_footprint, bool verbose) { + utl::Timer timer; utl::SetAndRestore set_match_footprint(match_cell_footprint_, match_cell_footprint); resizePreamble(); @@ -4234,6 +4236,7 @@ void Resizer::repairDesign(double max_wire_length, } repair_design_->repairDesign( max_wire_length, slew_margin, cap_margin, buffer_gain, verbose); + logger_->info(RSZ, 500, "Runtime: {:.2f}s", timer.elapsed()); } int Resizer::repairDesignBufferCount() const diff --git a/test/helpers.py b/test/helpers.py index 41c91212d74..eec11bc6a2d 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -116,4 +116,16 @@ def make_design(tech): logger.suppressMessage(utl.GRT, 303) logger.suppressMessage(utl.GRT, 704) + # suppress elapsed time messages (non-deterministic) + logger.suppressMessage(utl.CTS, 500) + logger.suppressMessage(utl.DPL, 500) + logger.suppressMessage(utl.DRT, 501) + logger.suppressMessage(utl.GPL, 500) + logger.suppressMessage(utl.GRT, 501) + logger.suppressMessage(utl.IFP, 500) + logger.suppressMessage(utl.IFP, 501) + logger.suppressMessage(utl.MPL, 500) + logger.suppressMessage(utl.PDN, 500) + logger.suppressMessage(utl.RSZ, 500) + return design diff --git a/test/helpers.tcl b/test/helpers.tcl index 9f204442467..950d70785fa 100644 --- a/test/helpers.tcl +++ b/test/helpers.tcl @@ -297,6 +297,18 @@ suppress_message ORD 30 suppress_message GRT 303 suppress_message GRT 704 +# suppress elapsed time messages (non-deterministic) +suppress_message CTS 500 +suppress_message DPL 500 +suppress_message DRT 501 +suppress_message GPL 500 +suppress_message GRT 501 +suppress_message IFP 500 +suppress_message IFP 501 +suppress_message MPL 500 +suppress_message PDN 500 +suppress_message RSZ 500 + proc get_3dblox_marker_count { category_name } { set top_chip [[ord::get_db] getChip] if { $top_chip == "NULL" } { From 2536d627d677d0838dd206f06e4ebbf9eae51a6d Mon Sep 17 00:00:00 2001 From: Bbn08 Date: Sun, 22 Feb 2026 13:39:36 +0530 Subject: [PATCH 2/5] Fix broken symlink in src/ifp/test/helpers.py (trailing newline) Signed-off-by: Bbn08 --- src/ifp/test/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifp/test/helpers.py b/src/ifp/test/helpers.py index 981b5ca3968..e10a2da7588 120000 --- a/src/ifp/test/helpers.py +++ b/src/ifp/test/helpers.py @@ -1 +1 @@ -../../../test/helpers.py +../../../test/helpers.py \ No newline at end of file From ac877366e2ff1553a2951556ced79fe84aa41cce Mon Sep 17 00:00:00 2001 From: Bbn08 Date: Sun, 22 Feb 2026 22:02:24 +0530 Subject: [PATCH 3/5] pdn: add secondary_ground support and fix secondary power net ordering Signed-off-by: Bbn08 --- src/pdn/include/pdn/PdnGen.hh | 6 ++- src/pdn/src/PdnGen.cc | 21 +++++++--- src/pdn/src/PdnGen.i | 21 ++++++++-- src/pdn/src/domain.cpp | 42 ++++++++++++++----- src/pdn/src/domain.h | 20 +++++++-- src/pdn/src/pdn.tcl | 31 +++++++++++--- src/pdn/test/CMakeLists.txt | 2 + src/pdn/test/core_grid_secondary_ground.tcl | 34 +++++++++++++++ .../core_grid_secondary_power_ordering.tcl | 32 ++++++++++++++ 9 files changed, 178 insertions(+), 31 deletions(-) create mode 100644 src/pdn/test/core_grid_secondary_ground.tcl create mode 100644 src/pdn/test/core_grid_secondary_power_ordering.tcl diff --git a/src/pdn/include/pdn/PdnGen.hh b/src/pdn/include/pdn/PdnGen.hh index 3daa952a7b5..61cdf3ca983 100644 --- a/src/pdn/include/pdn/PdnGen.hh +++ b/src/pdn/include/pdn/PdnGen.hh @@ -72,12 +72,14 @@ class PdnGen void setCoreDomain(odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary); + const std::vector& secondary_power, + const std::vector& secondary_ground); void makeRegionVoltageDomain(const std::string& name, odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary_nets, + const std::vector& secondary_power, + const std::vector& secondary_ground, odb::dbRegion* region); // Grids diff --git a/src/pdn/src/PdnGen.cc b/src/pdn/src/PdnGen.cc index fd7b3afe093..b0a7a8d1e92 100644 --- a/src/pdn/src/PdnGen.cc +++ b/src/pdn/src/PdnGen.cc @@ -257,7 +257,7 @@ VoltageDomain* PdnGen::getCoreDomain() const void PdnGen::ensureCoreDomain() { if (core_domain_ == nullptr) { - setCoreDomain(nullptr, nullptr, nullptr, {}); + setCoreDomain(nullptr, nullptr, nullptr, {}, {}); } } @@ -294,14 +294,15 @@ VoltageDomain* PdnGen::findDomain(const std::string& name) void PdnGen::setCoreDomain(odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary) + const std::vector& secondary_power, + const std::vector& secondary_ground) { auto* block = db_->getChip()->getBlock(); if (core_domain_ != nullptr) { logger_->warn(utl::PDN, 183, "Replacing existing core voltage domain."); } core_domain_ = std::make_unique( - this, block, power, ground, secondary, logger_); + this, block, power, ground, secondary_power, secondary_ground, logger_); if (importUPF(core_domain_.get())) { if (switched_power) { @@ -318,7 +319,8 @@ void PdnGen::makeRegionVoltageDomain( odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary_nets, + const std::vector& secondary_power, + const std::vector& secondary_ground, odb::dbRegion* region) { if (region == nullptr) { @@ -334,8 +336,15 @@ void PdnGen::makeRegionVoltageDomain( } } auto* block = db_->getChip()->getBlock(); - auto domain = std::make_unique( - this, name, block, power, ground, secondary_nets, region, logger_); + auto domain = std::make_unique(this, + name, + block, + power, + ground, + secondary_power, + secondary_ground, + region, + logger_); if (importUPF(domain.get())) { if (switched_power) { diff --git a/src/pdn/src/PdnGen.i b/src/pdn/src/PdnGen.i index 4cefcd2f84f..f16ae9572a7 100644 --- a/src/pdn/src/PdnGen.i +++ b/src/pdn/src/PdnGen.i @@ -44,16 +44,29 @@ using utl::PDN; namespace pdn { -void set_core_domain(odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, const std::vector& secondary_nets) +void set_core_domain(odb::dbNet* power, + odb::dbNet* switched_power, + odb::dbNet* ground, + const std::vector& secondary_power, + const std::vector& secondary_ground) { PdnGen* pdngen = ord::getPdnGen(); - pdngen->setCoreDomain(power, switched_power, ground, secondary_nets); + pdngen->setCoreDomain( + power, switched_power, ground, secondary_power, secondary_ground); } -void make_region_domain(const char* name, odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, const std::vector& secondary_nets, odb::dbRegion* region) +void make_region_domain(const char* name, + odb::dbNet* power, + odb::dbNet* switched_power, + odb::dbNet* ground, + const std::vector& secondary_power, + const std::vector& secondary_ground, + odb::dbRegion* region) { PdnGen* pdngen = ord::getPdnGen(); - pdngen->makeRegionVoltageDomain(name, power, switched_power, ground, secondary_nets, region); + pdngen->makeRegionVoltageDomain( + name, power, switched_power, ground, secondary_power, secondary_ground, + region); } void reset() diff --git a/src/pdn/src/domain.cpp b/src/pdn/src/domain.cpp index 17bbfa693c6..8f111a99f76 100644 --- a/src/pdn/src/domain.cpp +++ b/src/pdn/src/domain.cpp @@ -22,7 +22,8 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_nets, + const std::vector& secondary_power, + const std::vector& secondary_ground, utl::Logger* logger) : name_("Core"), pdngen_(pdngen), @@ -30,7 +31,8 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, power_(power), switched_power_(nullptr), ground_(ground), - secondary_(secondary_nets), + secondary_power_(secondary_power), + secondary_ground_(secondary_ground), region_(nullptr), logger_(logger) { @@ -42,7 +44,8 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_nets, + const std::vector& secondary_power, + const std::vector& secondary_ground, odb::dbRegion* region, utl::Logger* logger) : name_(name), @@ -51,7 +54,8 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, power_(power), switched_power_(nullptr), ground_(ground), - secondary_(secondary_nets), + secondary_power_(secondary_power), + secondary_ground_(secondary_ground), region_(region), logger_(logger) { @@ -75,21 +79,31 @@ std::vector VoltageDomain::getNets(bool start_with_power) const std::vector nets; if (start_with_power) { + // Order: primary power, switched power, secondary power nets, + // secondary ground nets, primary ground. + // This groups all supply rails together before the ground rails, + // fixing the ordering issue for multi-rail designs (e.g., VDDA, VDD, VSS). nets.push_back(power_); if (switched_power_ != nullptr) { nets.push_back(switched_power_); } + nets.insert(nets.end(), secondary_power_.begin(), secondary_power_.end()); + nets.insert( + nets.end(), secondary_ground_.begin(), secondary_ground_.end()); nets.push_back(ground_); } else { + // Reverse order: primary ground, secondary ground nets, + // secondary power nets, switched power, primary power. nets.push_back(ground_); - nets.push_back(power_); + nets.insert( + nets.end(), secondary_ground_.begin(), secondary_ground_.end()); + nets.insert(nets.end(), secondary_power_.begin(), secondary_power_.end()); if (switched_power_ != nullptr) { nets.push_back(switched_power_); } + nets.push_back(power_); } - nets.insert(nets.end(), secondary_.begin(), secondary_.end()); - return nets; } @@ -210,12 +224,20 @@ void VoltageDomain::report() const logger_->report(" Switched power net: {}", switched_power_->getName()); } - if (!secondary_.empty()) { + if (!secondary_power_.empty()) { + std::string nets; + for (auto* net : secondary_power_) { + nets += net->getName() + " "; + } + logger_->report(" Secondary power nets: {}", nets); + } + + if (!secondary_ground_.empty()) { std::string nets; - for (auto* net : secondary_) { + for (auto* net : secondary_ground_) { nets += net->getName() + " "; } - logger_->report(" Secondary nets: {}", nets); + logger_->report(" Secondary ground nets: {}", nets); } for (const auto& grid : grids_) { diff --git a/src/pdn/src/domain.h b/src/pdn/src/domain.h index 39dc9572272..28c8ad5fbad 100644 --- a/src/pdn/src/domain.h +++ b/src/pdn/src/domain.h @@ -33,7 +33,8 @@ class VoltageDomain odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_nets, + const std::vector& secondary_power, + const std::vector& secondary_ground, odb::dbRegion* region, utl::Logger* logger); @@ -41,7 +42,8 @@ class VoltageDomain odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_nets, + const std::vector& secondary_power, + const std::vector& secondary_ground, utl::Logger* logger); // Core const std::string& getName() const { return name_; } @@ -54,6 +56,14 @@ class VoltageDomain odb::dbNet* getGround() const { return ground_; } odb::dbNet* getAlwaysOnPower() const { return power_; } odb::dbNet* getSwitchedPower() const { return switched_power_; } + const std::vector& getSecondaryPower() const + { + return secondary_power_; + } + const std::vector& getSecondaryGround() const + { + return secondary_ground_; + } void setSwitchedPower(odb::dbNet* switched_power) { @@ -62,6 +72,9 @@ class VoltageDomain bool hasSwitchedPower() const { return switched_power_ != nullptr; } // returns the order in which the nets should be arranged in the grid shapes + // ordering: [power, switched_power?, ...secondary_power, + // ...secondary_ground, ground] when start_with_power is true, + // and the reverse when false. std::vector getNets(bool start_with_power = true) const; bool hasRegion() const { return region_ != nullptr; } @@ -90,7 +103,8 @@ class VoltageDomain odb::dbNet* power_; odb::dbNet* switched_power_; odb::dbNet* ground_; - std::vector secondary_; + std::vector secondary_power_; + std::vector secondary_ground_; odb::dbRegion* region_; diff --git a/src/pdn/src/pdn.tcl b/src/pdn/src/pdn.tcl index a58fcabc5e3..e73d66541ce 100644 --- a/src/pdn/src/pdn.tcl +++ b/src/pdn/src/pdn.tcl @@ -71,12 +71,14 @@ sta::define_cmd_args "set_voltage_domain" {-name domain_name \ -power power_net_name \ -ground ground_net_name \ [-region region_name] \ - [-secondary_power secondary_power_net_name] \ + [-secondary_power list_of_secondary_power_nets] \ + [-secondary_ground list_of_secondary_ground_nets] \ [-switched_power switched_power_net_name]} proc set_voltage_domain { args } { sta::parse_key_args "set_voltage_domain" args \ - keys {-name -region -power -ground -secondary_power -switched_power} flags {} + keys {-name -region -power -ground -secondary_power -secondary_ground \ + -switched_power} flags {} sta::check_argc_eq0 "set_voltage_domain" $args @@ -115,14 +117,29 @@ proc set_voltage_domain { args } { } } - set secondary {} + # Collect secondary power nets (placed between primary power and ground). + set secondary_power {} if { [info exists keys(-secondary_power)] } { foreach snet $keys(-secondary_power) { set db_net [[ord::get_db_block] findNet $snet] if { $db_net == "NULL" } { utl::error PDN 1006 "Unable to find secondary power net: $snet" } else { - lappend secondary $db_net + lappend secondary_power $db_net + } + } + } + + # Collect secondary ground nets (placed between secondary power and primary + # ground). + set secondary_ground {} + if { [info exists keys(-secondary_ground)] } { + foreach snet $keys(-secondary_ground) { + set db_net [[ord::get_db_block] findNet $snet] + if { $db_net == "NULL" } { + utl::error PDN 1007 "Unable to find secondary ground net: $snet" + } else { + lappend secondary_ground $db_net } } } @@ -148,9 +165,11 @@ proc set_voltage_domain { args } { if { [info exists keys(-name)] && [pdn::modify_voltage_domain_name $keys(-name)] != "Core" } { utl::warn PDN 1042 "Core voltage domain will be named \"Core\"." } - pdn::set_core_domain $pwr $switched_power $gnd $secondary + pdn::set_core_domain $pwr $switched_power $gnd $secondary_power \ + $secondary_ground } else { - pdn::make_region_domain $name $pwr $switched_power $gnd $secondary $region + pdn::make_region_domain $name $pwr $switched_power $gnd $secondary_power \ + $secondary_ground $region } } diff --git a/src/pdn/test/CMakeLists.txt b/src/pdn/test/CMakeLists.txt index 2e98deb1164..c841d1dc162 100644 --- a/src/pdn/test/CMakeLists.txt +++ b/src/pdn/test/CMakeLists.txt @@ -65,6 +65,8 @@ or_integration_tests( core_grid_with_rings_with_straps_rings_over_core core_grid_with_routing_obstructions core_grid_with_secondary_no_shapes + core_grid_secondary_ground + core_grid_secondary_power_ordering core_grid_with_single_edge_pins core_grid_with_single_layer_rings design_width diff --git a/src/pdn/test/core_grid_secondary_ground.tcl b/src/pdn/test/core_grid_secondary_ground.tcl new file mode 100644 index 00000000000..696cf4da0e2 --- /dev/null +++ b/src/pdn/test/core_grid_secondary_ground.tcl @@ -0,0 +1,34 @@ +# Test that -secondary_ground nets are accepted and placed between the +# secondary power nets and the primary ground net. +# Strap group ordering for VDD / VDDA (secondary power) / VSSA (secondary +# ground) / VSS must be: VDD, VDDA, VSSA, VSS. +source "helpers.tcl" + +read_lef Nangate45/Nangate45.lef +read_def nangate_gcd/floorplan.def + +add_global_connection -net VDD -pin_pattern VDD -power +add_global_connection -net VSS -pin_pattern VSS -ground +add_global_connection -net VDDA -pin_pattern VDDA -power +add_global_connection -net VSSA -pin_pattern VSSA -ground + +set_voltage_domain -power VDD -ground VSS \ + -secondary_power VDDA \ + -secondary_ground VSSA + +define_pdn_grid -name "Core" +add_pdn_stripe -followpins -layer metal1 + +# All four nets participate in the metal4 straps. +add_pdn_stripe -layer metal4 -width 0.48 -pitch 20.0 -offset 2.0 +add_pdn_stripe -layer metal7 -width 1.40 -pitch 40.0 -offset 2.0 \ + -nets {VDD VSS} + +add_pdn_connect -layers {metal1 metal4} +add_pdn_connect -layers {metal4 metal7} + +pdngen + +set def_file [make_result_file core_grid_secondary_ground.def] +write_def $def_file +diff_files core_grid_secondary_ground.defok $def_file diff --git a/src/pdn/test/core_grid_secondary_power_ordering.tcl b/src/pdn/test/core_grid_secondary_power_ordering.tcl new file mode 100644 index 00000000000..ccb77b07cf6 --- /dev/null +++ b/src/pdn/test/core_grid_secondary_power_ordering.tcl @@ -0,0 +1,32 @@ +# Test that secondary power nets are ordered between primary power and ground. +# With -secondary_power VDDA, the strap group ordering must be: +# VDD (primary power), VDDA (secondary power), VSS (ground) +# rather than the old broken ordering of VDD, VSS, VDDA. +source "helpers.tcl" + +read_lef Nangate45/Nangate45.lef +read_def nangate_gcd/floorplan.def + +add_global_connection -net VDD -pin_pattern VDD -power +add_global_connection -net VSS -pin_pattern VSS -ground +add_global_connection -net VDDA -pin_pattern VDDA -power + +set_voltage_domain -power VDD -ground VSS -secondary_power VDDA + +define_pdn_grid -name "Core" +add_pdn_stripe -followpins -layer metal1 + +# All three nets participate in the metal4 straps; ordering within each +# pitch group must be VDD, VDDA, VSS (power rails first, ground last). +add_pdn_stripe -layer metal4 -width 0.48 -pitch 15.0 -offset 2.0 +add_pdn_stripe -layer metal7 -width 1.40 -pitch 20.0 -offset 2.0 \ + -nets {VDD VSS} + +add_pdn_connect -layers {metal1 metal4} +add_pdn_connect -layers {metal4 metal7} + +pdngen + +set def_file [make_result_file core_grid_secondary_power_ordering.def] +write_def $def_file +diff_files core_grid_secondary_power_ordering.defok $def_file From 124d8c3c0a1a9d1cb9771ceb4f58584101815168 Mon Sep 17 00:00:00 2001 From: Bbn08 Date: Mon, 23 Feb 2026 01:16:57 +0530 Subject: [PATCH 4/5] pdn: temporarily disable new tests until defok files are generated Signed-off-by: Bbn08 --- src/pdn/test/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pdn/test/CMakeLists.txt b/src/pdn/test/CMakeLists.txt index c841d1dc162..2e98deb1164 100644 --- a/src/pdn/test/CMakeLists.txt +++ b/src/pdn/test/CMakeLists.txt @@ -65,8 +65,6 @@ or_integration_tests( core_grid_with_rings_with_straps_rings_over_core core_grid_with_routing_obstructions core_grid_with_secondary_no_shapes - core_grid_secondary_ground - core_grid_secondary_power_ordering core_grid_with_single_edge_pins core_grid_with_single_layer_rings design_width From 4bb48f6f88ec3abbbe303636e5cea927cd6d55f6 Mon Sep 17 00:00:00 2001 From: Bbn08 Date: Mon, 23 Feb 2026 12:02:47 +0530 Subject: [PATCH 5/5] Address review: remove GRT dup timer, split PDN to separate PR Signed-off-by: Bbn08 --- src/grt/src/GlobalRouter.cpp | 1 - src/pdn/include/pdn/PdnGen.hh | 6 +-- src/pdn/src/PdnGen.cc | 24 +++-------- src/pdn/src/PdnGen.i | 21 ++-------- src/pdn/src/domain.cpp | 42 +++++-------------- src/pdn/src/domain.h | 20 ++------- src/pdn/src/pdn.tcl | 31 +++----------- src/pdn/test/core_grid_secondary_ground.tcl | 34 --------------- .../core_grid_secondary_power_ordering.tcl | 32 -------------- test/helpers.py | 2 - test/helpers.tcl | 2 - 11 files changed, 31 insertions(+), 184 deletions(-) delete mode 100644 src/pdn/test/core_grid_secondary_ground.tcl delete mode 100644 src/pdn/test/core_grid_secondary_power_ordering.tcl diff --git a/src/grt/src/GlobalRouter.cpp b/src/grt/src/GlobalRouter.cpp index c09098fb81e..8b5f74b514c 100644 --- a/src/grt/src/GlobalRouter.cpp +++ b/src/grt/src/GlobalRouter.cpp @@ -397,7 +397,6 @@ void GlobalRouter::globalRoute(bool save_guides) logger_->info( GRT, 303, "Global routing runtime = {:02}:{:02}:{:02}", hour, min, sec); } - logger_->info(GRT, 501, "Runtime: {:.2f}s", timer.elapsed()); } void GlobalRouter::finishGlobalRouting(bool save_guides) diff --git a/src/pdn/include/pdn/PdnGen.hh b/src/pdn/include/pdn/PdnGen.hh index 61cdf3ca983..3daa952a7b5 100644 --- a/src/pdn/include/pdn/PdnGen.hh +++ b/src/pdn/include/pdn/PdnGen.hh @@ -72,14 +72,12 @@ class PdnGen void setCoreDomain(odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground); + const std::vector& secondary); void makeRegionVoltageDomain(const std::string& name, odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground, + const std::vector& secondary_nets, odb::dbRegion* region); // Grids diff --git a/src/pdn/src/PdnGen.cc b/src/pdn/src/PdnGen.cc index b0a7a8d1e92..6466e95a42b 100644 --- a/src/pdn/src/PdnGen.cc +++ b/src/pdn/src/PdnGen.cc @@ -29,7 +29,6 @@ #include "straps.h" #include "techlayer.h" #include "utl/Logger.h" -#include "utl/timer.h" #include "via.h" #include "via_repair.h" @@ -61,7 +60,6 @@ void PdnGen::resetShapes() void PdnGen::buildGrids(bool trim) { - utl::Timer timer; debugPrint(logger_, utl::PDN, "Make", 1, "Build - begin"); auto* block = db_->getChip()->getBlock(); @@ -154,7 +152,6 @@ void PdnGen::buildGrids(bool trim) } debugPrint(logger_, utl::PDN, "Make", 1, "Build - end"); - logger_->info(utl::PDN, 500, "Runtime: {:.2f}s", timer.elapsed()); } void PdnGen::cleanupVias() @@ -257,7 +254,7 @@ VoltageDomain* PdnGen::getCoreDomain() const void PdnGen::ensureCoreDomain() { if (core_domain_ == nullptr) { - setCoreDomain(nullptr, nullptr, nullptr, {}, {}); + setCoreDomain(nullptr, nullptr, nullptr, {}); } } @@ -294,15 +291,14 @@ VoltageDomain* PdnGen::findDomain(const std::string& name) void PdnGen::setCoreDomain(odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground) + const std::vector& secondary) { auto* block = db_->getChip()->getBlock(); if (core_domain_ != nullptr) { logger_->warn(utl::PDN, 183, "Replacing existing core voltage domain."); } core_domain_ = std::make_unique( - this, block, power, ground, secondary_power, secondary_ground, logger_); + this, block, power, ground, secondary, logger_); if (importUPF(core_domain_.get())) { if (switched_power) { @@ -319,8 +315,7 @@ void PdnGen::makeRegionVoltageDomain( odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground, + const std::vector& secondary_nets, odb::dbRegion* region) { if (region == nullptr) { @@ -336,15 +331,8 @@ void PdnGen::makeRegionVoltageDomain( } } auto* block = db_->getChip()->getBlock(); - auto domain = std::make_unique(this, - name, - block, - power, - ground, - secondary_power, - secondary_ground, - region, - logger_); + auto domain = std::make_unique( + this, name, block, power, ground, secondary_nets, region, logger_); if (importUPF(domain.get())) { if (switched_power) { diff --git a/src/pdn/src/PdnGen.i b/src/pdn/src/PdnGen.i index f16ae9572a7..4cefcd2f84f 100644 --- a/src/pdn/src/PdnGen.i +++ b/src/pdn/src/PdnGen.i @@ -44,29 +44,16 @@ using utl::PDN; namespace pdn { -void set_core_domain(odb::dbNet* power, - odb::dbNet* switched_power, - odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground) +void set_core_domain(odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, const std::vector& secondary_nets) { PdnGen* pdngen = ord::getPdnGen(); - pdngen->setCoreDomain( - power, switched_power, ground, secondary_power, secondary_ground); + pdngen->setCoreDomain(power, switched_power, ground, secondary_nets); } -void make_region_domain(const char* name, - odb::dbNet* power, - odb::dbNet* switched_power, - odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground, - odb::dbRegion* region) +void make_region_domain(const char* name, odb::dbNet* power, odb::dbNet* switched_power, odb::dbNet* ground, const std::vector& secondary_nets, odb::dbRegion* region) { PdnGen* pdngen = ord::getPdnGen(); - pdngen->makeRegionVoltageDomain( - name, power, switched_power, ground, secondary_power, secondary_ground, - region); + pdngen->makeRegionVoltageDomain(name, power, switched_power, ground, secondary_nets, region); } void reset() diff --git a/src/pdn/src/domain.cpp b/src/pdn/src/domain.cpp index 8f111a99f76..17bbfa693c6 100644 --- a/src/pdn/src/domain.cpp +++ b/src/pdn/src/domain.cpp @@ -22,8 +22,7 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground, + const std::vector& secondary_nets, utl::Logger* logger) : name_("Core"), pdngen_(pdngen), @@ -31,8 +30,7 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, power_(power), switched_power_(nullptr), ground_(ground), - secondary_power_(secondary_power), - secondary_ground_(secondary_ground), + secondary_(secondary_nets), region_(nullptr), logger_(logger) { @@ -44,8 +42,7 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground, + const std::vector& secondary_nets, odb::dbRegion* region, utl::Logger* logger) : name_(name), @@ -54,8 +51,7 @@ VoltageDomain::VoltageDomain(PdnGen* pdngen, power_(power), switched_power_(nullptr), ground_(ground), - secondary_power_(secondary_power), - secondary_ground_(secondary_ground), + secondary_(secondary_nets), region_(region), logger_(logger) { @@ -79,31 +75,21 @@ std::vector VoltageDomain::getNets(bool start_with_power) const std::vector nets; if (start_with_power) { - // Order: primary power, switched power, secondary power nets, - // secondary ground nets, primary ground. - // This groups all supply rails together before the ground rails, - // fixing the ordering issue for multi-rail designs (e.g., VDDA, VDD, VSS). nets.push_back(power_); if (switched_power_ != nullptr) { nets.push_back(switched_power_); } - nets.insert(nets.end(), secondary_power_.begin(), secondary_power_.end()); - nets.insert( - nets.end(), secondary_ground_.begin(), secondary_ground_.end()); nets.push_back(ground_); } else { - // Reverse order: primary ground, secondary ground nets, - // secondary power nets, switched power, primary power. nets.push_back(ground_); - nets.insert( - nets.end(), secondary_ground_.begin(), secondary_ground_.end()); - nets.insert(nets.end(), secondary_power_.begin(), secondary_power_.end()); + nets.push_back(power_); if (switched_power_ != nullptr) { nets.push_back(switched_power_); } - nets.push_back(power_); } + nets.insert(nets.end(), secondary_.begin(), secondary_.end()); + return nets; } @@ -224,20 +210,12 @@ void VoltageDomain::report() const logger_->report(" Switched power net: {}", switched_power_->getName()); } - if (!secondary_power_.empty()) { - std::string nets; - for (auto* net : secondary_power_) { - nets += net->getName() + " "; - } - logger_->report(" Secondary power nets: {}", nets); - } - - if (!secondary_ground_.empty()) { + if (!secondary_.empty()) { std::string nets; - for (auto* net : secondary_ground_) { + for (auto* net : secondary_) { nets += net->getName() + " "; } - logger_->report(" Secondary ground nets: {}", nets); + logger_->report(" Secondary nets: {}", nets); } for (const auto& grid : grids_) { diff --git a/src/pdn/src/domain.h b/src/pdn/src/domain.h index 28c8ad5fbad..39dc9572272 100644 --- a/src/pdn/src/domain.h +++ b/src/pdn/src/domain.h @@ -33,8 +33,7 @@ class VoltageDomain odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground, + const std::vector& secondary_nets, odb::dbRegion* region, utl::Logger* logger); @@ -42,8 +41,7 @@ class VoltageDomain odb::dbBlock* block, odb::dbNet* power, odb::dbNet* ground, - const std::vector& secondary_power, - const std::vector& secondary_ground, + const std::vector& secondary_nets, utl::Logger* logger); // Core const std::string& getName() const { return name_; } @@ -56,14 +54,6 @@ class VoltageDomain odb::dbNet* getGround() const { return ground_; } odb::dbNet* getAlwaysOnPower() const { return power_; } odb::dbNet* getSwitchedPower() const { return switched_power_; } - const std::vector& getSecondaryPower() const - { - return secondary_power_; - } - const std::vector& getSecondaryGround() const - { - return secondary_ground_; - } void setSwitchedPower(odb::dbNet* switched_power) { @@ -72,9 +62,6 @@ class VoltageDomain bool hasSwitchedPower() const { return switched_power_ != nullptr; } // returns the order in which the nets should be arranged in the grid shapes - // ordering: [power, switched_power?, ...secondary_power, - // ...secondary_ground, ground] when start_with_power is true, - // and the reverse when false. std::vector getNets(bool start_with_power = true) const; bool hasRegion() const { return region_ != nullptr; } @@ -103,8 +90,7 @@ class VoltageDomain odb::dbNet* power_; odb::dbNet* switched_power_; odb::dbNet* ground_; - std::vector secondary_power_; - std::vector secondary_ground_; + std::vector secondary_; odb::dbRegion* region_; diff --git a/src/pdn/src/pdn.tcl b/src/pdn/src/pdn.tcl index e73d66541ce..a58fcabc5e3 100644 --- a/src/pdn/src/pdn.tcl +++ b/src/pdn/src/pdn.tcl @@ -71,14 +71,12 @@ sta::define_cmd_args "set_voltage_domain" {-name domain_name \ -power power_net_name \ -ground ground_net_name \ [-region region_name] \ - [-secondary_power list_of_secondary_power_nets] \ - [-secondary_ground list_of_secondary_ground_nets] \ + [-secondary_power secondary_power_net_name] \ [-switched_power switched_power_net_name]} proc set_voltage_domain { args } { sta::parse_key_args "set_voltage_domain" args \ - keys {-name -region -power -ground -secondary_power -secondary_ground \ - -switched_power} flags {} + keys {-name -region -power -ground -secondary_power -switched_power} flags {} sta::check_argc_eq0 "set_voltage_domain" $args @@ -117,29 +115,14 @@ proc set_voltage_domain { args } { } } - # Collect secondary power nets (placed between primary power and ground). - set secondary_power {} + set secondary {} if { [info exists keys(-secondary_power)] } { foreach snet $keys(-secondary_power) { set db_net [[ord::get_db_block] findNet $snet] if { $db_net == "NULL" } { utl::error PDN 1006 "Unable to find secondary power net: $snet" } else { - lappend secondary_power $db_net - } - } - } - - # Collect secondary ground nets (placed between secondary power and primary - # ground). - set secondary_ground {} - if { [info exists keys(-secondary_ground)] } { - foreach snet $keys(-secondary_ground) { - set db_net [[ord::get_db_block] findNet $snet] - if { $db_net == "NULL" } { - utl::error PDN 1007 "Unable to find secondary ground net: $snet" - } else { - lappend secondary_ground $db_net + lappend secondary $db_net } } } @@ -165,11 +148,9 @@ proc set_voltage_domain { args } { if { [info exists keys(-name)] && [pdn::modify_voltage_domain_name $keys(-name)] != "Core" } { utl::warn PDN 1042 "Core voltage domain will be named \"Core\"." } - pdn::set_core_domain $pwr $switched_power $gnd $secondary_power \ - $secondary_ground + pdn::set_core_domain $pwr $switched_power $gnd $secondary } else { - pdn::make_region_domain $name $pwr $switched_power $gnd $secondary_power \ - $secondary_ground $region + pdn::make_region_domain $name $pwr $switched_power $gnd $secondary $region } } diff --git a/src/pdn/test/core_grid_secondary_ground.tcl b/src/pdn/test/core_grid_secondary_ground.tcl deleted file mode 100644 index 696cf4da0e2..00000000000 --- a/src/pdn/test/core_grid_secondary_ground.tcl +++ /dev/null @@ -1,34 +0,0 @@ -# Test that -secondary_ground nets are accepted and placed between the -# secondary power nets and the primary ground net. -# Strap group ordering for VDD / VDDA (secondary power) / VSSA (secondary -# ground) / VSS must be: VDD, VDDA, VSSA, VSS. -source "helpers.tcl" - -read_lef Nangate45/Nangate45.lef -read_def nangate_gcd/floorplan.def - -add_global_connection -net VDD -pin_pattern VDD -power -add_global_connection -net VSS -pin_pattern VSS -ground -add_global_connection -net VDDA -pin_pattern VDDA -power -add_global_connection -net VSSA -pin_pattern VSSA -ground - -set_voltage_domain -power VDD -ground VSS \ - -secondary_power VDDA \ - -secondary_ground VSSA - -define_pdn_grid -name "Core" -add_pdn_stripe -followpins -layer metal1 - -# All four nets participate in the metal4 straps. -add_pdn_stripe -layer metal4 -width 0.48 -pitch 20.0 -offset 2.0 -add_pdn_stripe -layer metal7 -width 1.40 -pitch 40.0 -offset 2.0 \ - -nets {VDD VSS} - -add_pdn_connect -layers {metal1 metal4} -add_pdn_connect -layers {metal4 metal7} - -pdngen - -set def_file [make_result_file core_grid_secondary_ground.def] -write_def $def_file -diff_files core_grid_secondary_ground.defok $def_file diff --git a/src/pdn/test/core_grid_secondary_power_ordering.tcl b/src/pdn/test/core_grid_secondary_power_ordering.tcl deleted file mode 100644 index ccb77b07cf6..00000000000 --- a/src/pdn/test/core_grid_secondary_power_ordering.tcl +++ /dev/null @@ -1,32 +0,0 @@ -# Test that secondary power nets are ordered between primary power and ground. -# With -secondary_power VDDA, the strap group ordering must be: -# VDD (primary power), VDDA (secondary power), VSS (ground) -# rather than the old broken ordering of VDD, VSS, VDDA. -source "helpers.tcl" - -read_lef Nangate45/Nangate45.lef -read_def nangate_gcd/floorplan.def - -add_global_connection -net VDD -pin_pattern VDD -power -add_global_connection -net VSS -pin_pattern VSS -ground -add_global_connection -net VDDA -pin_pattern VDDA -power - -set_voltage_domain -power VDD -ground VSS -secondary_power VDDA - -define_pdn_grid -name "Core" -add_pdn_stripe -followpins -layer metal1 - -# All three nets participate in the metal4 straps; ordering within each -# pitch group must be VDD, VDDA, VSS (power rails first, ground last). -add_pdn_stripe -layer metal4 -width 0.48 -pitch 15.0 -offset 2.0 -add_pdn_stripe -layer metal7 -width 1.40 -pitch 20.0 -offset 2.0 \ - -nets {VDD VSS} - -add_pdn_connect -layers {metal1 metal4} -add_pdn_connect -layers {metal4 metal7} - -pdngen - -set def_file [make_result_file core_grid_secondary_power_ordering.def] -write_def $def_file -diff_files core_grid_secondary_power_ordering.defok $def_file diff --git a/test/helpers.py b/test/helpers.py index eec11bc6a2d..8519f90bde0 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -121,11 +121,9 @@ def make_design(tech): logger.suppressMessage(utl.DPL, 500) logger.suppressMessage(utl.DRT, 501) logger.suppressMessage(utl.GPL, 500) - logger.suppressMessage(utl.GRT, 501) logger.suppressMessage(utl.IFP, 500) logger.suppressMessage(utl.IFP, 501) logger.suppressMessage(utl.MPL, 500) - logger.suppressMessage(utl.PDN, 500) logger.suppressMessage(utl.RSZ, 500) return design diff --git a/test/helpers.tcl b/test/helpers.tcl index 950d70785fa..577880e9e5e 100644 --- a/test/helpers.tcl +++ b/test/helpers.tcl @@ -302,11 +302,9 @@ suppress_message CTS 500 suppress_message DPL 500 suppress_message DRT 501 suppress_message GPL 500 -suppress_message GRT 501 suppress_message IFP 500 suppress_message IFP 501 suppress_message MPL 500 -suppress_message PDN 500 suppress_message RSZ 500 proc get_3dblox_marker_count { category_name } {