Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 5 additions & 4 deletions include/sta/Sta.hh
Original file line number Diff line number Diff line change
Expand Up @@ -857,16 +857,17 @@ public:
void setReportPathDigits(int digits);
void setReportPathNoSplit(bool no_split);
void setReportPathSigmas(bool report_sigmas);
void setReportDedupByWord(bool dedup_by_word);
// Header above reportPathEnd results.
void reportPathEndHeader();
// Footer below reportPathEnd results.
void reportPathEndFooter();
// Format report_path_endpoint only:
// Previous path end is used to detect path group changes
// so headers are reported by group.
// Previous path end is used to:
// - detect path group changes so headers are reported by group.
// - JSON format: if not first, add a comma before appending new path
void reportPathEnd(PathEnd *end,
PathEnd *prev_end,
bool last);
PathEnd *prev_end);
void reportPathEnd(PathEnd *end);
void reportPathEnds(PathEndSeq *ends);
ReportPath *reportPath() { return report_path_; }
Expand Down
74 changes: 64 additions & 10 deletions search/ReportPath.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "GraphDelayCalc.hh"
#include "ClkInfo.hh"
#include "Tag.hh"
#include "ParseBus.hh"
#include "PathAnalysisPt.hh"
#include "PathGroup.hh"
#include "CheckMinPulseWidths.hh"
Expand Down Expand Up @@ -140,6 +141,7 @@ const float ReportPath::field_blank_ = -1.0;
ReportPath::ReportPath(StaState *sta) :
StaState(sta),
format_(ReportPathFormat::full),
dedup_by_word_(false),
no_split_(false),
report_sigmas_(false),
start_end_pt_width_(80),
Expand Down Expand Up @@ -290,18 +292,23 @@ ReportPath::setReportSigmas(bool report)
report_sigmas_ = report;
}

void
ReportPath::setReportDedupByWord(bool dedup_by_word)
{
dedup_by_word_ = dedup_by_word;
}

////////////////////////////////////////////////////////////////

void
ReportPath::reportPathEnd(const PathEnd *end) const
{
reportPathEnd(end, nullptr, true);
reportPathEnd(end, nullptr);
}

void
ReportPath::reportPathEnd(const PathEnd *end,
const PathEnd *prev_end,
bool last) const
const PathEnd *prev_end) const
{
switch (format_) {
case ReportPathFormat::full:
Expand All @@ -327,23 +334,69 @@ ReportPath::reportPathEnd(const PathEnd *end,
reportSlackOnly(end);
break;
case ReportPathFormat::json:
reportJson(end, last);
reportJson(end, prev_end);
break;
}
}

inline std::string getBusName(const StaState *state,
const sta::Network *sdc_network,
PathEnd *end) {
char escape = sdc_network->pathEscape();
PathExpanded expanded(end->path(), state);
const Pin *end_pin = expanded.endPath()->vertex(state)->pin();
const char *endpoint_name = sdc_network->pathName(end_pin);
bool is_bus;
std::string bus_name;
int index;
parseBusName(endpoint_name,
'[',
']',
escape,
is_bus,
bus_name,
index);
if (is_bus) {
return bus_name;
}
return "";
}

void
ReportPath::reportPathEnds(const PathEndSeq *ends) const
{
reportPathEndHeader();
if (ends && !ends->empty()) {
PathEnd *prev_end = nullptr;
PathEndSeq::ConstIterator end_iter(ends);
Set<PathEnd *> qualified_ends;

if (dedup_by_word_) {
Map<std::string, PathEnd *> worst_slack_by_bus;
while (end_iter.hasNext()) {
PathEnd *end = end_iter.next();
auto bus_name = getBusName(this, sdc_network_, end);
if (bus_name.length()) {
if (worst_slack_by_bus.count(bus_name) == 0 ||
worst_slack_by_bus[bus_name]->slack(this) > end->slack(this))
worst_slack_by_bus[bus_name] = end;
}
else
qualified_ends.insert(end);
}

for (auto &[_, end]: worst_slack_by_bus)
qualified_ends.insert(end);
}

end_iter = ends;
while (end_iter.hasNext()) {
PathEnd *end = end_iter.next();
reportPathEnd(end, prev_end, !end_iter.hasNext());
prev_end = end;
}
if (!dedup_by_word_ || qualified_ends.count(end)) {
reportPathEnd(end, prev_end);
prev_end = end;
}
}
}
else {
if (format_ != ReportPathFormat::json)
Expand Down Expand Up @@ -1080,9 +1133,12 @@ ReportPath::reportJsonFooter() const

void
ReportPath::reportJson(const PathEnd *end,
bool last) const
const PathEnd *prev_end) const
{
string result;
if (prev_end) {
result += ", ";
}
result += "{\n";
stringAppend(result, " \"type\": \"%s\",\n", end->typeName());
stringAppend(result, " \"path_group\": \"%s\",\n",
Expand Down Expand Up @@ -1145,8 +1201,6 @@ ReportPath::reportJson(const PathEnd *end,
delayAsFloat(end->slack(this)));
}
result += "}";
if (!last)
result += ",";
report_->reportLineString(result);
}

Expand Down
12 changes: 7 additions & 5 deletions search/ReportPath.hh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public:
void setNoSplit(bool no_split);
bool reportSigmas() const { return report_sigmas_; }
void setReportSigmas(bool report);
void setReportDedupByWord(bool dedup_by_word);
ReportField *findField(const char *name) const;

// Header above reportPathEnd results.
Expand All @@ -67,11 +68,11 @@ public:
void reportPathEndFooter() const;
void reportPathEnd(const PathEnd *end) const;
// Format report_path_endpoint only:
// Previous path end is used to detect path group changes
// so headers are reported by group.
// Previous path end is used to:
// - detect path group changes so headers are reported by group.
// - JSON format: if not first, add a comma before appending new path
void reportPathEnd(const PathEnd *end,
const PathEnd *prev_end,
bool last) const;
const PathEnd *prev_end) const;
void reportPathEnds(const PathEndSeq *ends) const;
void reportPath(const Path *path) const;

Expand All @@ -94,7 +95,7 @@ public:
void reportJsonHeader() const;
void reportJsonFooter() const;
void reportJson(const PathEnd *end,
bool last) const;
const PathEnd *prev_end) const;
void reportJson(const Path *path) const;
void reportJson(const Path *path,
const char *path_name,
Expand Down Expand Up @@ -472,6 +473,7 @@ protected:
bool report_input_pin_;
bool report_hier_pins_;
bool report_net_;
bool dedup_by_word_;
bool no_split_;
int digits_;
bool report_sigmas_;
Expand Down
11 changes: 8 additions & 3 deletions search/Search.i
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,9 @@ report_path_end(PathEnd *end)

void
report_path_end2(PathEnd *end,
PathEnd *prev_end,
bool last)
PathEnd *prev_end)
{
Sta::sta()->reportPathEnd(end, prev_end, last);
Sta::sta()->reportPathEnd(end, prev_end);
}

void
Expand Down Expand Up @@ -496,6 +495,12 @@ set_report_path_no_split(bool no_split)
Sta::sta()->setReportPathNoSplit(no_split);
}

void
set_report_path_dedup_by_word(bool dedup_by_word)
{
Sta::sta()->setReportDedupByWord(dedup_by_word);
}

void
set_report_path_sigmas(bool report_sigmas)
{
Expand Down
7 changes: 6 additions & 1 deletion search/Search.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ define_cmd_args "report_checks" \
[-fields capacitance|slew|fanout|input_pin|net|src_attr]\
[-digits digits]\
[-no_line_splits]\
[-dedup_by_word]\
[> filename] [>> filename]}

proc_redirect report_checks {
Expand Down Expand Up @@ -887,7 +888,7 @@ proc parse_report_path_options { cmd args_var default_format
unset path_options
}
parse_key_args $cmd args path_options {-format -digits -fields} \
path_options {-no_line_splits -report_sigmas} $unknown_key_is_error
path_options {-no_line_splits -report_sigmas -dedup_by_word} $unknown_key_is_error

set format $default_format
if [info exists path_options(-format)] {
Expand Down Expand Up @@ -959,6 +960,10 @@ proc parse_report_path_options { cmd args_var default_format
$report_cap $report_slew $report_fanout $report_src_attr

set_report_path_no_split [info exists path_options(-no_line_splits)]

if { [info exists path_options(-dedup_by_word)] } {
set_report_path_dedup_by_word 1
}
}

################################################################
Expand Down
11 changes: 8 additions & 3 deletions search/Sta.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2567,6 +2567,12 @@ Sta::setReportPathSigmas(bool report_sigmas)
report_path_->setReportSigmas(report_sigmas);
}

void
Sta::setReportDedupByWord(bool dedup_by_word)
{
report_path_->setReportDedupByWord(dedup_by_word);
}

void
Sta::reportPathEndHeader()
{
Expand All @@ -2587,10 +2593,9 @@ Sta::reportPathEnd(PathEnd *end)

void
Sta::reportPathEnd(PathEnd *end,
PathEnd *prev_end,
bool last)
PathEnd *prev_end)
{
report_path_->reportPathEnd(end, prev_end, last);
report_path_->reportPathEnd(end, prev_end);
}

void
Expand Down
3 changes: 3 additions & 0 deletions test/path_dedup_worst.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Warning: ../examples/gcd_sky130hd.v line 527, module sky130_fd_sc_hd__tapvpwrvgnd_1 not found. Creating black box for TAP_11.
resp_msg count: 1
resp_msg[15] count: 1
37 changes: 37 additions & 0 deletions test/path_dedup_worst.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
read_liberty ../examples/sky130hd_tt.lib.gz
read_verilog ../examples/gcd_sky130hd.v
link_design gcd
read_sdc ../examples/gcd_sky130hd.sdc

proc count_pattern {pattern filename} {
set count 0
set fh [open $filename r]
while {[gets $fh line] >= 0} {
if {[regexp $pattern $line]} {
incr count
}
}
close $fh
return $count
}

proc make_checks_rpt {args} {
set temp_file_id [file tempfile temp_filename]
close $temp_file_id

report_checks\
-format end\
{*}$args > $temp_filename

return $temp_filename
}

set checks_rpt [make_checks_rpt\
-group_path_count 999\
-fields {input_pins slew}\
-dedup_by_word]

puts "resp_msg count: [count_pattern "resp_msg" $checks_rpt]"
puts "resp_msg[15] count: [count_pattern "resp_msg\\\[15\\\]" $checks_rpt]"

file delete -force $checks_rpt
1 change: 1 addition & 0 deletions test/regression_vars.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ record_public_tests {
liberty_latch3
package_require
path_group_names
path_dedup_worst
power_json
prima3
report_checks_sorted
Expand Down