diff --git a/src/cts/src/CMakeLists.txt b/src/cts/src/CMakeLists.txt index cf626b11c65..649e6be59bc 100644 --- a/src/cts/src/CMakeLists.txt +++ b/src/cts/src/CMakeLists.txt @@ -85,6 +85,7 @@ target_link_libraries(cts_lib odb dbSta_lib OpenSTA + rcx_lib stt_lib utl_lib ) diff --git a/src/rsz/README.md b/src/rsz/README.md index 5783e326eb2..27503c51868 100644 --- a/src/rsz/README.md +++ b/src/rsz/README.md @@ -115,15 +115,17 @@ Standard Parasitic Exchange Format. ```tcl estimate_parasitics - -placement|-global_routing + -placement|-global_routing|-detailed_routing [-spef_file spef_file] + [-ext_model_file model_file] ``` #### Options | Switch Name | Description | | ----- | ----- | -| `-placement` or `-global_routing` | Either of these flags must be set. Parasitics are estimated based after placement stage versus after global routing stage. | +| `-placement` or `-global_routing` or `-detailed_routing` | One of these flags must be set. Parasitics are estimated based on placement, global routing, or detailed routing. | +| `-ext_model_file model_file` | Optional. File name to load the extraction model file for parasitics extraction from detailed routing. | | `-spef_file` | Optional. File name to write SPEF files. If more than one corner is available for the design, the files will be written as filename_corner.spef. | ### Set Don't Use diff --git a/src/rsz/include/rsz/Resizer.hh b/src/rsz/include/rsz/Resizer.hh index 8fd1e8aaa04..8e2fc1c60b2 100644 --- a/src/rsz/include/rsz/Resizer.hh +++ b/src/rsz/include/rsz/Resizer.hh @@ -52,6 +52,10 @@ class GlobalRouter; class IncrementalGRoute; } // namespace grt +namespace rcx { +class Ext; +} // namespace rcx + namespace stt { class SteinerTreeBuilder; } @@ -78,6 +82,8 @@ using stt::SteinerTreeBuilder; using grt::GlobalRouter; using grt::IncrementalGRoute; +using rcx::Ext; + using sta::ArcDelay; using sta::Cell; using sta::Corner; @@ -196,6 +202,7 @@ class Resizer : public dbStaState, public dbNetworkObserver SteinerTreeBuilder* stt_builder, GlobalRouter* global_router, dpl::Opendp* opendp, + rcx::Ext* openrcx, std::unique_ptr steiner_renderer); void setLayerRC(dbTechLayer* layer, const Corner* corner, @@ -242,9 +249,9 @@ class Resizer : public dbStaState, public dbNetworkObserver double wireClkCapacitance(const Corner* corner) const; double wireClkHCapacitance(const Corner* corner) const; double wireClkVCapacitance(const Corner* corner) const; - void estimateParasitics(ParasiticsSrc src); void estimateParasitics(ParasiticsSrc src, - std::map& spef_streams_); + std::map& spef_streams_, + const char* ext_model_path); void estimateWireParasitics(SpefWriter* spef_writer = nullptr); void estimateWireParasitic(const Net* net, SpefWriter* spef_writer = nullptr); void estimateWireParasitic(const Pin* drvr_pin, @@ -602,7 +609,6 @@ class Resizer : public dbStaState, public dbNetworkObserver void incrementalParasiticsBegin(); void incrementalParasiticsEnd(); - void ensureParasitics(); void updateParasitics(bool save_guides = false); void ensureWireParasitic(const Pin* drvr_pin); void ensureWireParasitic(const Pin* drvr_pin, const Net* net); @@ -720,6 +726,7 @@ class Resizer : public dbStaState, public dbNetworkObserver SteinerTreeBuilder* stt_builder_ = nullptr; GlobalRouter* global_router_ = nullptr; IncrementalGRoute* incr_groute_ = nullptr; + Ext* openrcx_ = nullptr; dbNetwork* db_network_ = nullptr; dbDatabase* db_ = nullptr; dbBlock* block_ = nullptr; diff --git a/src/rsz/src/CMakeLists.txt b/src/rsz/src/CMakeLists.txt index 23875cbc5b3..cdf0d1494ca 100644 --- a/src/rsz/src/CMakeLists.txt +++ b/src/rsz/src/CMakeLists.txt @@ -79,6 +79,7 @@ target_link_libraries(rsz_lib OpenSTA dbSta_lib grt_lib + rcx_lib utl_lib ) @@ -91,6 +92,7 @@ target_link_libraries(rsz dbSta grt gui + rcx utl_lib ) diff --git a/src/rsz/src/EstimateWireParasitics.cc b/src/rsz/src/EstimateWireParasitics.cc index acec51a872e..d46cfe945b8 100644 --- a/src/rsz/src/EstimateWireParasitics.cc +++ b/src/rsz/src/EstimateWireParasitics.cc @@ -36,6 +36,7 @@ #include "SteinerTree.hh" #include "db_sta/dbNetwork.hh" #include "grt/GlobalRouter.h" +#include "rcx/ext.h" #include "rsz/Resizer.hh" #include "rsz/SpefWriter.hh" #include "sta/ArcDelayCalc.hh" @@ -265,27 +266,18 @@ double Resizer::wireClkVCapacitance(const Corner* corner) const //////////////////////////////////////////////////////////////// -void Resizer::ensureParasitics() -{ - estimateParasitics(global_router_->haveRoutes() - ? ParasiticsSrc::global_routing - : ParasiticsSrc::placement); -} - -void Resizer::estimateParasitics(ParasiticsSrc src) -{ - std::map spef_streams; - estimateParasitics(src, spef_streams); -} - void Resizer::estimateParasitics(ParasiticsSrc src, - std::map& spef_streams) + std::map& spef_streams, + const char* ext_model_path) { std::unique_ptr spef_writer; if (!spef_streams.empty()) { spef_writer = std::make_unique(logger_, sta_, spef_streams); } + ExtractOptions ext_options; + ext_options.ext_model_file = ext_model_path; + switch (src) { case ParasiticsSrc::placement: estimateWireParasitics(spef_writer.get()); @@ -295,7 +287,8 @@ void Resizer::estimateParasitics(ParasiticsSrc src, parasitics_src_ = ParasiticsSrc::global_routing; break; case ParasiticsSrc::detailed_routing: - // TODO: call rcx to extract parasitics and load them to STA + openrcx_->extract(ext_options); + // TODO: load parasitics to STA parasitics_src_ = ParasiticsSrc::detailed_routing; break; case ParasiticsSrc::none: diff --git a/src/rsz/src/MakeResizer.cc b/src/rsz/src/MakeResizer.cc index 59c33e0b78d..3e7de689257 100644 --- a/src/rsz/src/MakeResizer.cc +++ b/src/rsz/src/MakeResizer.cc @@ -74,6 +74,7 @@ void initResizer(OpenRoad* openroad) openroad->getSteinerTreeBuilder(), openroad->getGlobalRouter(), openroad->getOpendp(), + openroad->getOpenRCX(), std::move(steiner_renderer)); // Define swig TCL commands. Rsz_Init(interp); diff --git a/src/rsz/src/Resizer.cc b/src/rsz/src/Resizer.cc index 6f9a6493bfa..79e81ffed54 100644 --- a/src/rsz/src/Resizer.cc +++ b/src/rsz/src/Resizer.cc @@ -48,6 +48,7 @@ #include "RepairSetup.hh" #include "boost/multi_array.hpp" #include "db_sta/dbNetwork.hh" +#include "rcx/ext.h" #include "sta/ArcDelayCalc.hh" #include "sta/Bfs.hh" #include "sta/Corner.hh" @@ -156,6 +157,7 @@ void Resizer::init(Logger* logger, SteinerTreeBuilder* stt_builder, GlobalRouter* global_router, dpl::Opendp* opendp, + rcx::Ext* openrcx, std::unique_ptr steiner_renderer) { opendp_ = opendp; @@ -166,6 +168,7 @@ void Resizer::init(Logger* logger, stt_builder_ = stt_builder; global_router_ = global_router; incr_groute_ = nullptr; + openrcx_ = openrcx; db_network_ = sta->getDbNetwork(); resized_multi_output_insts_ = InstanceSet(db_network_); inserted_buffer_set_ = InstanceSet(db_network_); diff --git a/src/rsz/src/Resizer.i b/src/rsz/src/Resizer.i index 7d936f06579..0b28f48f153 100644 --- a/src/rsz/src/Resizer.i +++ b/src/rsz/src/Resizer.i @@ -338,42 +338,42 @@ wire_clk_capacitance(const Corner *corner) } void -estimate_parasitics_cmd(ParasiticsSrc src, const char* path) +estimate_parasitics_cmd(ParasiticsSrc src, const char* spef_path, const char* ext_model_path) { ensureLinked(); Resizer* resizer = getResizer(); std::map spef_files; - if (path != nullptr && std::strlen(path) > 0) { - std::string file_path(path); - if (!file_path.empty()) { + if (spef_path != nullptr && std::strlen(spef_path) > 0) { + std::string spef_file_path(spef_path); + if (!spef_file_path.empty()) { for (Corner* corner : *resizer->getDbNetwork()->corners()) { - file_path = path; + spef_file_path = spef_path; if (resizer->getDbNetwork()->corners()->count() > 1) { std::string suffix("_"); suffix.append(corner->name()); - if (file_path.find(".spef") != std::string::npos - || file_path.find(".SPEF") != std::string::npos) { - file_path.insert(file_path.size() - 5, suffix); + if (spef_file_path.find(".spef") != std::string::npos + || spef_file_path.find(".SPEF") != std::string::npos) { + spef_file_path.insert(spef_file_path.size() - 5, suffix); } else { - file_path.append(suffix); + spef_file_path.append(suffix); } } - std::ofstream* file = new std::ofstream(file_path); + std::ofstream* spef_file = new std::ofstream(spef_file_path); - if (file->is_open()) { - spef_files[corner] = std::move(file); + if (spef_file->is_open()) { + spef_files[corner] = std::move(spef_file); } else { Logger* logger = ord::getLogger(); logger->error(utl::RSZ, 7, - "Can't open file " + file_path); + "Can't open file " + spef_file_path); } } } } - resizer->estimateParasitics(src, spef_files); + resizer->estimateParasitics(src, spef_files, ext_model_path); for (auto [_, file] : spef_files) { file->flush(); diff --git a/src/rsz/src/Resizer.tcl b/src/rsz/src/Resizer.tcl index 5b7b4d006e8..d6a0d073352 100644 --- a/src/rsz/src/Resizer.tcl +++ b/src/rsz/src/Resizer.tcl @@ -312,29 +312,40 @@ proc set_wire_rc { args } { } } -sta::define_cmd_args "estimate_parasitics" { -placement|-global_routing \ - [-spef_file filename]} +sta::define_cmd_args "estimate_parasitics" { -placement|-global_routing|-detailed_routing \ + [-spef_file spef_file] \ + [-ext_model_file model_file]} proc estimate_parasitics { args } { sta::parse_key_args "estimate_parasitics" args \ - keys {-spef_file} flags {-placement -global_routing} + keys {-spef_file -ext_model_file} flags {-placement -global_routing -detailed_routing} - set filename "" + set spef_file "" if { [info exists keys(-spef_file)] } { - set filename $keys(-spef_file) + set spef_file $keys(-spef_file) + } + + set ext_model_file "" + if { [info exists keys(-ext_model_file)] } { + set ext_model_file $keys(-ext_model_file) } if { [info exists flags(-placement)] } { if { [rsz::check_corner_wire_cap] } { - rsz::estimate_parasitics_cmd "placement" $filename + rsz::estimate_parasitics_cmd "placement" $spef_file $ext_model_file } } elseif { [info exists flags(-global_routing)] } { if { [grt::have_routes] } { # should check for layer rc - rsz::estimate_parasitics_cmd "global_routing" $filename + rsz::estimate_parasitics_cmd "global_routing" $spef_file $ext_model_file } else { utl::error RSZ 5 "Run global_route before estimating parasitics for global routing." } + } elseif { [info exists flags(-detailed_routing)] } { + if { ![design_is_routed] } { + utl::error RSZ 87 "Design is not routed." + } + rsz::estimate_parasitics_cmd "detailed_routing" $spef_file $ext_model_file } else { utl::error RSZ 3 "missing -placement or -global_routing flag." } @@ -638,9 +649,6 @@ proc repair_timing { args } { } set match_cell_footprint [info exists flags(-match_cell_footprint)] - if { [design_is_routed] } { - rsz::set_parasitics_src "detailed_routing" - } sta::check_argc_eq0 "repair_timing" $args rsz::check_parasitics diff --git a/src/rsz/test/cpp/CMakeLists.txt b/src/rsz/test/cpp/CMakeLists.txt index 93885de5a1b..7ca7df2112c 100644 --- a/src/rsz/test/cpp/CMakeLists.txt +++ b/src/rsz/test/cpp/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(TestBufRem1 rsz_lib grt_lib dpl_lib + rcx_lib stt_lib ${TCL_LIBRARY} ) diff --git a/src/rsz/test/cpp/TestBufferRemoval.cc b/src/rsz/test/cpp/TestBufferRemoval.cc index 832156aa7e1..e750aa0df49 100644 --- a/src/rsz/test/cpp/TestBufferRemoval.cc +++ b/src/rsz/test/cpp/TestBufferRemoval.cc @@ -24,6 +24,7 @@ #include "grt/GlobalRouter.h" #include "gtest/gtest.h" #include "odb/lefin.h" +#include "rcx/ext.h" #include "rsz/MakeResizer.hh" #include "rsz/Resizer.hh" #include "sta/Corner.hh" @@ -215,7 +216,8 @@ TEST_F(BufRemTest, SlackImproves) stt::SteinerTreeBuilder* stt = new stt::SteinerTreeBuilder; grt::GlobalRouter* grt = new grt::GlobalRouter; dpl::Opendp* dp = new dpl::Opendp; - resizer_->init(&logger_, db_.get(), sta_.get(), stt, grt, dp, nullptr); + rcx::Ext* rcx = new rcx::Ext; + resizer_->init(&logger_, db_.get(), sta_.get(), stt, grt, dp, rcx, nullptr); float origArrival = sta_->vertexArrival(outVertex_, sta::RiseFall::rise(), pathAnalysisPt_);