Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rsz: extract detailed routing parasitics inside estimate_parasitics code #6068

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/rsz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[-ext_model_file]
[-ext_model_file model_file]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this handle corners? they have separate model files.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my tests, I'm using only the public PDKs available in ORFS, which use only on model file and one corner for parasitics extraction.

How are you using multiple corners in your flow? Do you loop over each corner to extract the parasitics for them?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we loop over them to generate a different spef file per corner and read them in per corner to be able to get timing across corners (it's clumsy, but it's the interface we have in OpenROAD at the moment). I think corner support is needed for this to be a complete/correct solution.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If rcx was augmented to allow us to set the model files per corner that would also allow us to avoid adding this argument and just ask rcx to generate the parasitics

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this option can be updated to take multiple files, and them the implementation will perform parasitics extraction for each of them. I believe sta have the support to have the parasitics stored for multiple corners, so when running repair_timing it would look at all of them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eder-matheus it seems to me like modifying RCX to store the model files would require a much less complex argument to this command. and yes, STA fully supports corners.

```

#### 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` | Either of these flags must be set. Parasitics are estimated based after placement stage versus after global routing stage, or extracted from the detailed routing. |
eder-matheus marked this conversation as resolved.
Show resolved Hide resolved
| `-ext_model_file` | Optional. File name to load the extraction model file for parasitics extraction from detailed routing. |
eder-matheus marked this conversation as resolved.
Show resolved Hide resolved
| `-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
Expand Down
13 changes: 10 additions & 3 deletions src/rsz/include/rsz/Resizer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class GlobalRouter;
class IncrementalGRoute;
} // namespace grt

namespace rcx {
class Ext;
} // namespace rcx

namespace stt {
class SteinerTreeBuilder;
}
Expand All @@ -77,6 +81,8 @@ using stt::SteinerTreeBuilder;
using grt::GlobalRouter;
using grt::IncrementalGRoute;

using rcx::Ext;

using sta::ArcDelay;
using sta::Cell;
using sta::Corner;
Expand Down Expand Up @@ -194,6 +200,7 @@ class Resizer : public dbStaState
SteinerTreeBuilder* stt_builder,
GlobalRouter* global_router,
dpl::Opendp* opendp,
rcx::Ext* openrcx,
std::unique_ptr<AbstractSteinerRenderer> steiner_renderer);
void setLayerRC(dbTechLayer* layer,
const Corner* corner,
Expand Down Expand Up @@ -240,9 +247,9 @@ class Resizer : public dbStaState
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<Corner*, std::ostream*>& spef_streams_);
std::map<Corner*, std::ostream*>& 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,
Expand Down Expand Up @@ -591,7 +598,6 @@ class Resizer : public dbStaState

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);
Expand Down Expand Up @@ -709,6 +715,7 @@ class Resizer : public dbStaState
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;
Expand Down
2 changes: 2 additions & 0 deletions src/rsz/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ target_link_libraries(rsz_lib
OpenSTA
dbSta_lib
grt_lib
rcx_lib
utl_lib
)

Expand All @@ -91,6 +92,7 @@ target_link_libraries(rsz
dbSta
grt
gui
rcx
utl
)

Expand Down
23 changes: 8 additions & 15 deletions src/rsz/src/EstimateWireParasitics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<Corner*, std::ostream*> spef_streams;
estimateParasitics(src, spef_streams);
}

void Resizer::estimateParasitics(ParasiticsSrc src,
std::map<Corner*, std::ostream*>& spef_streams)
std::map<Corner*, std::ostream*>& spef_streams,
const char* ext_model_path)
{
std::unique_ptr<SpefWriter> spef_writer;
if (!spef_streams.empty()) {
spef_writer = std::make_unique<SpefWriter>(logger_, sta_, spef_streams);
}

rcx::Ext::ExtractOptions ext_options;
ext_options.ext_model_file = ext_model_path;

switch (src) {
case ParasiticsSrc::placement:
estimateWireParasitics(spef_writer.get());
Expand All @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/rsz/src/MakeResizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/rsz/src/Resizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,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"
Expand Down Expand Up @@ -156,6 +157,7 @@ void Resizer::init(Logger* logger,
SteinerTreeBuilder* stt_builder,
GlobalRouter* global_router,
dpl::Opendp* opendp,
rcx::Ext* openrcx,
std::unique_ptr<AbstractSteinerRenderer> steiner_renderer)
{
opendp_ = opendp;
Expand All @@ -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_);
Expand Down
28 changes: 14 additions & 14 deletions src/rsz/src/Resizer.i
Original file line number Diff line number Diff line change
Expand Up @@ -338,40 +338,40 @@ 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<Corner*, std::ostream*> 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;
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();
Expand Down
28 changes: 18 additions & 10 deletions src/rsz/src/Resizer.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -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 filename] \
[-ext_model_file filename]}

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."
}
Expand Down Expand Up @@ -613,9 +624,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
Expand Down
1 change: 1 addition & 0 deletions src/rsz/test/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ target_link_libraries(TestBufRem1
rsz_lib
grt_lib
dpl_lib
rcx_lib
stt_lib
${TCL_LIBRARY}
)
Expand Down
4 changes: 3 additions & 1 deletion src/rsz/test/cpp/TestBufferRemoval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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_);
Expand Down
Loading