From ca1cc4c5c15aed827d04e006e126651a86b4697a Mon Sep 17 00:00:00 2001 From: Dingyi Zhao Date: Sun, 29 Jun 2025 20:52:11 +0800 Subject: [PATCH 1/3] feat(sta): enhance clock tree visualization with name formatting options --- .../iSTA/source/module/sta/StaClockTree.cc | 15 ++++++++++++++- .../iSTA/source/module/sta/StaClockTree.hh | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/operation/iSTA/source/module/sta/StaClockTree.cc b/src/operation/iSTA/source/module/sta/StaClockTree.cc index 73d5cb74f..cdd1d4ad4 100644 --- a/src/operation/iSTA/source/module/sta/StaClockTree.cc +++ b/src/operation/iSTA/source/module/sta/StaClockTree.cc @@ -228,13 +228,19 @@ void StaClockTree::getChildNodeCnt(std::vector child_nodes, * format. * */ -void StaClockTree::printInstGraphViz(const char* file_path) { +void StaClockTree::printInstGraphViz(const char* file_path, + bool show_port_suffix) { auto replace_str = [](const std::string& str, const std::string& old_str, const std::string& new_str) { std::regex re(old_str); return std::regex_replace(str, re, new_str); }; + auto remove_port_suffix = [](const std::string& name) { + std::regex suffix_re(R"(_[AX]$)"); + return std::regex_replace(name, suffix_re, ""); + }; + LOG_INFO << "dump graph dotviz start"; std::ofstream dot_file; @@ -249,9 +255,16 @@ void StaClockTree::printInstGraphViz(const char* file_path) { auto from_name = net_arrive_time.get_from_name(); from_name = replace_str(from_name, R"(\/)", "_"); from_name = replace_str(from_name, R"(\:)", "_"); + from_name = replace_str(from_name, R"(\.)", "__"); auto to_name = net_arrive_time.get_to_name(); to_name = replace_str(to_name, R"(\/)", "_"); to_name = replace_str(to_name, R"(\:)", "_"); + to_name = replace_str(to_name, R"(\.)", "__"); + + if (!show_port_suffix) { + from_name = remove_port_suffix(from_name); + to_name = remove_port_suffix(to_name); + } dot_file << Str::printf("%s[label=\"%s fanout %d\" ]\n", from_name.c_str(), from_name.c_str(), diff --git a/src/operation/iSTA/source/module/sta/StaClockTree.hh b/src/operation/iSTA/source/module/sta/StaClockTree.hh index 8f15d9775..f87a7e4a2 100644 --- a/src/operation/iSTA/source/module/sta/StaClockTree.hh +++ b/src/operation/iSTA/source/module/sta/StaClockTree.hh @@ -208,7 +208,7 @@ class StaClockTree { std::vector getLevelNodeCnt(); void getChildNodeCnt(std::vector child_nodes, std::vector& child_node_size); - void printInstGraphViz(const char* file_path); + void printInstGraphViz(const char* file_path, bool show_port_suffix = true); private: StaClock* _clock; //!< The tree own clock. -- Gitee From 1b30f0dd093f4701b5507864d803726e1b232293 Mon Sep 17 00:00:00 2001 From: Dingyi Zhao Date: Mon, 30 Jun 2025 10:23:20 +0800 Subject: [PATCH 2/3] feat(ista): add JSON dump support for clock tree analysis --- .../iSTA/source/module/sta/StaClockTree.cc | 55 +++++++++++++++++++ .../iSTA/source/module/sta/StaClockTree.hh | 1 + 2 files changed, 56 insertions(+) diff --git a/src/operation/iSTA/source/module/sta/StaClockTree.cc b/src/operation/iSTA/source/module/sta/StaClockTree.cc index cdd1d4ad4..06e8de309 100644 --- a/src/operation/iSTA/source/module/sta/StaClockTree.cc +++ b/src/operation/iSTA/source/module/sta/StaClockTree.cc @@ -31,6 +31,7 @@ #include "StaClock.hh" #include "log/Log.hh" #include "string/Str.hh" +#include "json/json.hpp" namespace ista { @@ -285,4 +286,58 @@ void StaClockTree::printInstGraphViz(const char* file_path, LOG_INFO << "dump graph dotviz end"; } +void StaClockTree::printInstJson(const char* file_path, bool show_port_suffix) { + auto replace_str = [](const std::string& str, const std::string& old_str, + const std::string& new_str) { + std::regex re(old_str); + return std::regex_replace(str, re, new_str); + }; + + auto remove_port_suffix = [](const std::string& name) { + std::regex suffix_re(R"(_[AX]$)"); + return std::regex_replace(name, suffix_re, ""); + }; + + LOG_INFO << "dump graph json start"; + + nlohmann::json graph = nlohmann::json::array(); + + for (auto& child_arc : _child_arcs) { + nlohmann::json node; + auto* parent_node = child_arc->get_parent_node(); + auto* child_node = child_arc->get_child_node(); + + auto net_arrive_time = child_arc->get_net_arrive_time(); + auto from_name = net_arrive_time.get_from_name(); + from_name = replace_str(from_name, R"(\/)", "_"); + from_name = replace_str(from_name, R"(\:)", "_"); + from_name = replace_str(from_name, R"(\.)", "__"); + auto to_name = net_arrive_time.get_to_name(); + to_name = replace_str(to_name, R"(\/)", "_"); + to_name = replace_str(to_name, R"(\:)", "_"); + to_name = replace_str(to_name, R"(\.)", "__"); + + if (!show_port_suffix) { + from_name = remove_port_suffix(from_name); + to_name = remove_port_suffix(to_name); + } + + node["name"] = from_name; + node["to"] = to_name; + node["fanout"] = parent_node->get_child_nodes().size(); + node["delay"] = net_arrive_time.get_max_rise_to_arrive_time(); + + graph.push_back(node); + + if (child_node->get_inst_arrive_times().empty()) { + graph.push_back({{"name", to_name}, {"fanout", 0}}); + } + } + + std::ofstream json_file(file_path); + json_file << graph.dump(4); + json_file.close(); + LOG_INFO << "dump graph json end"; +} + } // namespace ista \ No newline at end of file diff --git a/src/operation/iSTA/source/module/sta/StaClockTree.hh b/src/operation/iSTA/source/module/sta/StaClockTree.hh index f87a7e4a2..4fab8ddfd 100644 --- a/src/operation/iSTA/source/module/sta/StaClockTree.hh +++ b/src/operation/iSTA/source/module/sta/StaClockTree.hh @@ -209,6 +209,7 @@ class StaClockTree { void getChildNodeCnt(std::vector child_nodes, std::vector& child_node_size); void printInstGraphViz(const char* file_path, bool show_port_suffix = true); + void printInstJson(const char* file_path, bool show_port_suffix = true); private: StaClock* _clock; //!< The tree own clock. -- Gitee From 60ac24bb4a81e01675c41a8099c9684ef966b7b3 Mon Sep 17 00:00:00 2001 From: Dingyi Zhao Date: Mon, 30 Jun 2025 10:27:25 +0800 Subject: [PATCH 3/3] feat(iCTS): add dump support for Skew Map --- src/operation/iCTS/api/CTSAPI.cc | 20 ++++++++++++++++++++ src/operation/iCTS/api/CTSAPI.hh | 1 + 2 files changed, 21 insertions(+) diff --git a/src/operation/iCTS/api/CTSAPI.cc b/src/operation/iCTS/api/CTSAPI.cc index 9e2ca387f..dfa84c6ce 100644 --- a/src/operation/iCTS/api/CTSAPI.cc +++ b/src/operation/iCTS/api/CTSAPI.cc @@ -48,6 +48,7 @@ #include "log/Log.hh" #include "model/ModelFactory.hh" #include "report/CtsReport.hh" +#include "sta/StaBuildClockTree.hh" #include "usage/usage.hh" namespace icts { #define DBCONFIG (dmInst->get_config()) @@ -95,6 +96,7 @@ void CTSAPI::writeDB() void CTSAPI::writeGDS() { + writeSkewMap(); GDSPloter::plotDesign(); GDSPloter::plotFlyLine(); GDSPloter::writePyDesign(); @@ -1171,4 +1173,22 @@ ieda_feature::CTSSummary CTSAPI::outputSummary() return summary; } +void CTSAPI::writeSkewMap() const +{ + auto* ista = _timing_engine->get_ista(); + auto& clocks = ista->get_clocks(); + + for (auto& clock : clocks) { + StaBuildClockTree build_clock_tree; + build_clock_tree(clock.get()); + + auto base_path = _config->get_output_def_path() + "/" + std::string(clock->get_clock_name()); + + auto& clock_trees = build_clock_tree.takeClockTrees(); + clock_trees.front()->printInstGraphViz((base_path + "_skewmap.dot").c_str(), false); + clock_trees.front()->printInstJson((base_path + "_skewmap.json").c_str(), false); + clock_trees.clear(); + } +} + } // namespace icts \ No newline at end of file diff --git a/src/operation/iCTS/api/CTSAPI.hh b/src/operation/iCTS/api/CTSAPI.hh index 5072c0623..ee561031f 100644 --- a/src/operation/iCTS/api/CTSAPI.hh +++ b/src/operation/iCTS/api/CTSAPI.hh @@ -201,6 +201,7 @@ class CTSAPI double getCapacitance(const double& wire_length, const int& level) const; double getResistance(const double& wire_length, const int& level) const; ista::TimingIDBAdapter* getStaDbAdapter() const; + void writeSkewMap() const; // variable icts::CtsConfig* _config = nullptr; -- Gitee