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
5 changes: 5 additions & 0 deletions include/sta/SearchClass.hh
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ enum class ReportPathFormat { full,
json
};

enum class ReportDeduplicationMode { none,
keep_worst,
keep_different
};

static const TagIndex tag_index_bit_count = 28;
static const TagIndex tag_index_max = (1 << tag_index_bit_count) - 1;
static const TagIndex tag_index_null = tag_index_max;
Expand Down
10 changes: 6 additions & 4 deletions include/sta/Sta.hh
Original file line number Diff line number Diff line change
Expand Up @@ -857,16 +857,18 @@ public:
void setReportPathDigits(int digits);
void setReportPathNoSplit(bool no_split);
void setReportPathSigmas(bool report_sigmas);
void setReportDedupByWord(bool dedup_by_word);
void setReportDeduplicationMode(ReportDeduplicationMode dedup_mode);
// 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
120 changes: 112 additions & 8 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 All @@ -61,6 +62,8 @@
#include "Genclks.hh"
#include "Variables.hh"

#include <iostream>

namespace sta {

using std::string;
Expand Down Expand Up @@ -140,6 +143,8 @@ const float ReportPath::field_blank_ = -1.0;
ReportPath::ReportPath(StaState *sta) :
StaState(sta),
format_(ReportPathFormat::full),
dedup_by_word_(false),
report_dedup_mode_(ReportDeduplicationMode::none),
no_split_(false),
report_sigmas_(false),
start_end_pt_width_(80),
Expand Down Expand Up @@ -290,18 +295,26 @@ ReportPath::setReportSigmas(bool report)
report_sigmas_ = report;
}

void
ReportPath::setReportDedupByWord(bool dedup_by_word)
{
dedup_by_word_ = dedup_by_word;
ReportPath::setReportDeduplicationMode(ReportDeduplicationMode dedup_mode)
{
report_dedup_mode_ = dedup_mode;
}

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

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 +340,113 @@ 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();
if (!dedup_by_word_ || qualified_ends.count(end)) {
reportPathEnd(end, prev_end);
prev_end = end;
}
char escape = sdc_network_->pathEscape();

PathEndSeq qualified_ends;

// Keep branch/allocation penalties outside the loop
if (report_dedup_mode_ == ReportDeduplicationMode::keep_worst) {
Map<std::string, PathEnd *> worst_slack_by_bus;

while (end_iter.hasNext()) {
PathEnd *end = end_iter.next();
PathExpanded expanded(end->path(), this);
const Pin *end_pin = expanded.endPath()->vertex(this)->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) {
qualified_ends.push_back(end);
} else {
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;
}
}
}
for (auto &[_, end]: worst_slack_by_bus) {
qualified_ends.push_back(end);
}
end_iter = qualified_ends;
} else if (report_dedup_mode_ == ReportDeduplicationMode::keep_different) {
// TODO
}
while (end_iter.hasNext()) {
PathEnd *end = end_iter.next();
reportPathEnd(end, prev_end, !end_iter.hasNext());
prev_end = end;
}
}
}
else {
if (format_ != ReportPathFormat::json)
Expand Down Expand Up @@ -1080,9 +1183,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 +1251,6 @@ ReportPath::reportJson(const PathEnd *end,
delayAsFloat(end->slack(this)));
}
result += "}";
if (!last)
result += ",";
report_->reportLineString(result);
}

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

// Header above reportPathEnd results.
Expand All @@ -67,11 +69,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 +96,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 +474,8 @@ protected:
bool report_input_pin_;
bool report_hier_pins_;
bool report_net_;
bool dedup_by_word_;
ReportDeduplicationMode report_dedup_mode_;
bool no_split_;
int digits_;
bool report_sigmas_;
Expand Down
15 changes: 12 additions & 3 deletions search/Search.i
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ find_path_ends(ExceptionFrom *from,
corner, delay_min_max,
group_path_count, endpoint_path_count,
unique_pins, unique_edges,
unique_pins,
slack_min, slack_max,
sort_by_slack,
groups->size() ? groups : nullptr,
Expand Down Expand Up @@ -421,10 +422,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 +496,15 @@ 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);
set_report_path_deduplication_mode(ReportDeduplicationMode dedup_mode)
{
Sta::sta()->setReportDeduplicationMode(dedup_mode);
}

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

proc_redirect report_checks {
Expand Down Expand Up @@ -886,8 +888,9 @@ proc parse_report_path_options { cmd args_var default_format
if [info exists path_options] {
unset path_options
}
parse_key_args $cmd args path_options {-format -digits -fields} \
parse_key_args $cmd args path_options {-format -digits -fields -deduplication_mode} \
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 +962,13 @@ 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

if { [info exists path_options(-deduplication_mode)] } {
set_report_path_deduplication_mode $path_options(-deduplication_mode)
}
}

################################################################
Expand Down
18 changes: 15 additions & 3 deletions search/Sta.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,19 @@ Sta::setReportPathSigmas(bool report_sigmas)
}

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

void
Sta::setReportDeduplicationMode(ReportDeduplicationMode dedup_mode)
{
report_path_->setReportDeduplicationMode(dedup_mode);
}

void
>>>>>>> 6b6c046e (feat: bus de-duplication in reports [WIP])
Sta::reportPathEndHeader()
{
report_path_->reportPathEndHeader();
Expand All @@ -2583,10 +2596,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
16 changes: 16 additions & 0 deletions tcl/StaTclTypes.i
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,22 @@ using namespace sta;
}
}

%typemap(in) ReportDeduplicationMode {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "none"))
$1 = ReportDeduplicationMode::none;
else if (stringEq(arg, "keep_worst"))
$1 = ReportDeduplicationMode::keep_worst;
else if (stringEq(arg, "keep_different"))
$1 = ReportDeduplicationMode::keep_different;
else {
// Issue here: sometime during the sprintf arg becomes garbage
tclArgError(interp, 2172, "unknown report word deduplication mode %s.", arg);
return TCL_ERROR;
}
}

%typemap(in) ExceptionThruSeq* {
$1 = tclListSeqPtr<ExceptionThru*>($input, SWIGTYPE_p_ExceptionThru, interp);
}
Expand Down
Loading