diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 5237ec9a..91a3b224 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -83,6 +83,8 @@ using CheckErrorSeq = std::vector; enum class CmdNamespace { sta, sdc }; using ParasiticsNameMap = std::map>; using GraphLoopSeq = std::vector; +using ReportFieldGetValue = std::function; // Initialize sta functions that are not part of the Sta class. void initSta(); @@ -982,15 +984,16 @@ public: bool clk_gating_hold); void setReportPathFormat(ReportPathFormat format); void setReportPathFieldOrder(const StringSeq &field_names); - void setReportPathFields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr); + void setReportPathFields(const StringSeq &fields); ReportField *findReportPathField(std::string_view name); + ReportField *findReportPathFieldAbrev(std::string_view name); + void makeReportPathField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + Unit *unit, + const ReportFieldGetValue &get_value); void setReportPathDigits(int digits); void setReportPathNoSplit(bool no_split); void reportPathEnd(PathEnd *end); diff --git a/network/Network.i b/network/Network.i index 30cfff61..b35855c8 100644 --- a/network/Network.i +++ b/network/Network.i @@ -655,6 +655,15 @@ get_attribute(const char *key) return Sta::sta()->ensureLinked()->getAttribute(self, key); } +void +set_attribute(const char *key, + const char *value) +{ + sta::Sta *sta = Sta::sta(); + sta->ensureLinked(); + sta->networkReader()->setAttribute(self, key, value); +} + } // Instance methods %extend InstanceChildIterator { @@ -813,4 +822,3 @@ bool has_next() { return self->hasNext(); } const Pin *next() { return self->next(); } void finish() { delete self; } } // NetConnectedPinIterator methods - diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 50d05574..4b99f4a9 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -81,23 +81,22 @@ hierPinsThruEdge(const Edge *edge, const Graph *graph); ReportField::ReportField(std::string_view name, + std::string_view name_abrev, std::string_view title, size_t width, bool left_justify, Unit *unit, - bool enabled) : + ReportFieldGetValue get_value) : name_(name), + name_abrev_(name_abrev), title_(title), left_justify_(left_justify), unit_(unit), - enabled_(enabled) + get_value_(get_value) { setWidth(width); } -ReportField::~ReportField() -= default; - void ReportField::setProperties(std::string_view title, size_t width, @@ -121,72 +120,85 @@ ReportField::setEnabled(bool enabled) enabled_ = enabled; } +std::string +ReportField::value(const Path *path, + const StaState *sta) const +{ + return get_value_(path, sta); +} + //////////////////////////////////////////////////////////////// ReportPath::ReportPath(StaState *sta) : StaState(sta) { makeFields(); + setReportFields({"incr", "total", "edge", "description"}); setDigits(2); - setReportFields(false, false, false, false, false, false, false, false); } ReportPath::~ReportPath() { - delete field_description_; - delete field_total_; - delete field_incr_; - delete field_capacitance_; - delete field_slew_; - delete field_fanout_; - delete field_variation_; - delete field_src_attr_; - delete field_edge_; - delete field_case_; + deleteContents(fields_); } void ReportPath::makeFields() { // The order corresponds to the default field order. - field_fanout_ = makeField("fanout", "Fanout", 6, false, nullptr, true); - field_capacitance_ = makeField("capacitance", "Cap", 6, false, - units_->capacitanceUnit(), true); - field_slew_ = makeField("slew", "Slew", 6, false, units_->timeUnit(), - true); - field_incr_ = makeField("incr", "Delay", 6, false, units_->timeUnit(), - true); - field_variation_ = makeField("variation", "Variation", 6, false, - units_->timeUnit(), false); - field_total_ = makeField("total", "Time", 6, false, units_->timeUnit(), - true); - field_edge_ = makeField("edge", "", 1, false, nullptr, true); - field_case_ = makeField("case", "case", 11, false, nullptr, false); - field_description_ = makeField("description", "Description", 36, - true, nullptr, true); - field_src_attr_ = makeField("src_attr", "Src Attr", 40, - true, nullptr, true); + field_fanout_ = makeField("fanout", "fanout", "Fanout", 6, false, nullptr); + field_capacitance_ = makeField("capacitance", "cap", "Cap", 6, false, + units_->capacitanceUnit()); + field_slew_ = makeField("slew", "slew", "Slew", 6, false, units_->timeUnit()); + field_incr_ = makeField("incr", "incr", "Delay", 6, false, units_->timeUnit()); + field_variation_ = makeField("variation", "var", "Variation", 6, false, + units_->timeUnit()); + field_total_ = makeField("total", "total", "Time", 6, false, units_->timeUnit()); + field_edge_ = makeField("edge", "edge", "", 1, false, nullptr); + field_case_ = makeField("case", "case", "case", 11, false, nullptr); + field_description_ = makeField("description", "desc", "Description", 36, true, nullptr); + field_src_attr_ = makeField("src_attr", "src", "Src Attr", 40, true, nullptr); } ReportField * ReportPath::makeField(std::string_view name, + std::string_view name_abrev, std::string_view title, - int width, + size_t width, + bool left_justify, + Unit *unit) +{ + return makeField(name, name_abrev, title, width, left_justify, unit, nullptr); +} + +ReportField * +ReportPath::makeField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, bool left_justify, Unit *unit, - bool enabled) + ReportFieldGetValue get_value) { - ReportField *field = new ReportField(name, title, width, left_justify, - unit, enabled); + ReportField *field = new ReportField(name, name_abrev, title, width, left_justify, + unit, get_value); fields_.push_back(field); + field_map_[std::string(name)] = field; return field; } ReportField * -ReportPath::findField(std::string_view name) const +ReportPath::findField(std::string_view name) +{ + return findKey(field_map_, std::string(name)); +} + +ReportField * +ReportPath::findFieldAbrev(std::string_view name) { for (ReportField *field : fields_) { - if (field->name() == name) + const std::string &name_abrev = field->nameAbrev(); + if (name.substr(0, name_abrev.size()) == name_abrev) return field; } return nullptr; @@ -213,32 +225,38 @@ ReportPath::setReportFieldOrder(const StringSeq &field_names) next_fields.push_back(field); } - fields_.clear(); - for (ReportField *field : next_fields) - fields_.push_back(field); + fields_ = next_fields; } void -ReportPath::setReportFields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr) +ReportPath::setReportFields(const StringSeq &fields) { - report_input_pin_ = report_input_pin; - report_hier_pins_ = report_hier_pins; - report_net_ = report_net; + for (ReportField *field : fields_) + field->setEnabled(false); + field_incr_->setEnabled(true); + field_total_->setEnabled(true); + field_description_->setEnabled(true); + field_edge_->setEnabled(true); + // These are not real fields; they are flags. + report_input_pin_ = false; + report_hier_pins_ = false; + report_net_ = false; - field_capacitance_->setEnabled(report_cap); - field_slew_->setEnabled(report_slew); - field_fanout_->setEnabled(report_fanout); - field_variation_->setEnabled(report_variation); - field_src_attr_->setEnabled(report_src_attr); - // for debug - field_case_->setEnabled(false); + for (const std::string &field_name : fields) { + if (field_name == "input_pin") + report_input_pin_ = true; + else if (field_name == "hierarchical_pin") + report_hier_pins_ = true; + else if (field_name == "net") + report_net_ = true; + else { + ReportField *field = findField(field_name); + if (field) + field->setEnabled(true); + else + report_->warn(2720, "unknown path reporting field {}.", field_name); + } + } } void @@ -2454,7 +2472,7 @@ ReportPath::reportPathLine(const Path *path, // Don't show capacitance field for input pins. if (is_driver && field_capacitance_->enabled()) cap = graph_delay_calc_->loadCap(pin, rf, scene, min_max); - reportLine(what, cap, slew, field_blank_, incr, field_blank_, + reportLine(what, path, cap, slew, field_blank_, incr, field_blank_, time, false, early_late, rf, src_attr, line_case); } @@ -2823,13 +2841,13 @@ ReportPath::reportPath6(const Path *path, if (field_fanout_->enabled()) fanout = drvrFanout(vertex, scene, min_max); const std::string what = descriptionField(vertex); - reportLine(what, cap, slew, fanout, + reportLine(what, path1, cap, slew, fanout, incr, field_blank_, time, false, min_max, rf, src_attr, line_case); if (report_net_) { const std::string what2 = descriptionNet(pin); - reportLine(what2, field_blank_, field_blank_, field_blank_, + reportLine(what2, path1, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, false, min_max, nullptr, src_attr, ""); } @@ -2842,7 +2860,7 @@ ReportPath::reportPath6(const Path *path, || (i == path_last_index) || is_clk_start) { const std::string what = descriptionField(vertex); - reportLine(what, field_blank_, slew, field_blank_, + reportLine(what, path1, field_blank_, slew, field_blank_, incr, field_blank_, time, false, min_max, rf, src_attr, line_case); prev_time = time; @@ -2867,27 +2885,27 @@ ReportPath::reportVariation(const Path *path) const switch (variables_->pocvMode()) { case PocvMode::normal: { float std_dev = arc_delay.stdDev(); - reportLine("sigma", field_blank_, field_blank_, field_blank_, + reportLine("sigma", path, field_blank_, field_blank_, field_blank_, field_blank_, std_dev, field_blank_, true, min_max, nullptr, "", ""); break; } case PocvMode::skew_normal: { float mean = arc_delay.mean(); - reportLine("mean", field_blank_, field_blank_, field_blank_, + reportLine("mean", path, field_blank_, field_blank_, field_blank_, field_blank_, mean, field_blank_, true, min_max, nullptr, "", ""); float mean_shift = arc_delay.meanShift(); - reportLine("mean_shift", field_blank_, field_blank_, field_blank_, + reportLine("mean_shift", path, field_blank_, field_blank_, field_blank_, field_blank_, mean_shift, field_blank_, true, min_max, nullptr, "", ""); float std_dev = arc_delay.stdDev(); - reportLine("std_dev", field_blank_, field_blank_, field_blank_, + reportLine("std_dev", path, field_blank_, field_blank_, field_blank_, field_blank_, std_dev, field_blank_, true, min_max, nullptr, "", ""); // skewness is dimensionless, so scale it to the field's time units. float skewness = arc_delay.skewness() * units_->timeUnit()->scale(); - reportLine("skewness", field_blank_, field_blank_, field_blank_, + reportLine("skewness", path, field_blank_, field_blank_, field_blank_, field_blank_, skewness, field_blank_, true, min_max, nullptr, "", ""); break; @@ -2915,9 +2933,9 @@ ReportPath::reportHierPinsThru(const Path *path) const if (prev_edge && prev_edge->isWire()) { for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) { const std::string what = descriptionField(hpin); - reportLine(what, field_blank_, field_blank_, field_blank_, - field_blank_, field_blank_, field_blank_, false, path->minMax(this), - nullptr, "", ""); + reportLine(what, path, field_blank_, field_blank_, field_blank_, + field_blank_, field_blank_, field_blank_, false, + path->minMax(this), nullptr, "", ""); } } } @@ -3109,7 +3127,7 @@ ReportPath::reportLine(std::string_view what, Delay total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, false, early_late, nullptr, "", ""); } @@ -3119,7 +3137,7 @@ ReportPath::reportLineNegative(std::string_view what, Delay total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, true /* tota_with_minus */, early_late, nullptr, "", ""); } @@ -3131,7 +3149,7 @@ ReportPath::reportLine(std::string_view what, const EarlyLate *early_late, const RiseFall *rf) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, false, early_late, rf, "", ""); } @@ -3142,7 +3160,7 @@ ReportPath::reportLine(std::string_view what, const Delay &total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, incr, field_blank_, total, false, early_late, nullptr, "", ""); } @@ -3154,7 +3172,7 @@ ReportPath::reportLine(std::string_view what, const EarlyLate *early_late, const RiseFall *rf) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, incr, field_blank_, total, false, early_late, rf, "", ""); } @@ -3166,12 +3184,13 @@ ReportPath::reportLine(std::string_view what, const Delay &total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, slew, field_blank_, + reportLine(what, nullptr, field_blank_, slew, field_blank_, incr, field_blank_, total, false, early_late, nullptr, "", ""); } void ReportPath::reportLine(std::string_view what, + const Path *path, float cap, const Slew &slew, float fanout, @@ -3234,6 +3253,8 @@ ReportPath::reportLine(std::string_view what, } else if (field == field_case_) line += line_case; + else if (field->getValue()) + line += field->value(path, this); first_field = false; } diff --git a/search/ReportPath.hh b/search/ReportPath.hh index b8ce652d..c096e4eb 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -25,6 +25,7 @@ #pragma once #include +#include #include #include #include @@ -49,9 +50,51 @@ namespace sta { class Scene; class PathExpanded; -class ReportField; + +using ReportFieldGetValue = std::function; + +class ReportField +{ +public: + ReportField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + Unit *unit, + ReportFieldGetValue get_value); + void setProperties(std::string_view title, + size_t width, + bool left_justify); + const std::string &name() const { return name_; } + const std::string &nameAbrev() const { return name_abrev_; } + const std::string &title() const { return title_; } + size_t width() const { return width_; } + void setWidth(size_t width); + bool leftJustify() const { return left_justify_; } + Unit *unit() const { return unit_; } + const std::string &blank() const { return blank_; } + void setEnabled(bool enabled); + bool enabled() const { return enabled_; } + std::string value(const Path *path, + const StaState *sta) const; + const ReportFieldGetValue &getValue() const { return get_value_; } + +protected: + std::string name_; + std::string name_abrev_; + std::string title_; + size_t width_; + bool left_justify_; + Unit *unit_; + bool enabled_{false}; + ReportFieldGetValue get_value_; + std::string blank_; +}; using ReportFieldSeq = std::vector; +using ReportFieldMap = std::map>; class ReportPath : public StaState { @@ -61,18 +104,12 @@ public: ReportPathFormat pathFormat() const { return format_; } void setPathFormat(ReportPathFormat format); void setReportFieldOrder(const StringSeq &field_names); - void setReportFields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr); + void setReportFields(const StringSeq &fields); int digits() const { return digits_; } void setDigits(int digits); void setNoSplit(bool no_split); - ReportField *findField(std::string_view name) const; + ReportField *findField(std::string_view name); + ReportField *findFieldAbrev(std::string_view name); // Header above reportPathEnd results. void reportPathEndHeader() const; @@ -165,6 +202,15 @@ public: float slack, const Scene *scene, const MinMax *min_max) const; + + ReportField *makeField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + // nullptr for string fields. + Unit *unit, + ReportFieldGetValue get_value); ReportField *fieldSlew() const { return field_slew_; } ReportField *fieldFanout() const { return field_fanout_; } ReportField *fieldCapacitance() const { return field_capacitance_; } @@ -173,11 +219,11 @@ public: protected: void makeFields(); ReportField *makeField(std::string_view name, + std::string_view name_abrev, std::string_view title, - int width, + size_t width, bool left_justify, - Unit *unit, - bool enabled); + Unit *unit); void reportEndpointHeader(const PathEnd *end, const PathEnd *prev_end) const; void reportShort(const PathEndUnconstrained *end, @@ -370,6 +416,7 @@ protected: const Delay &total, const EarlyLate *early_late) const; void reportLine(std::string_view what, + const Path *path, float cap, const Slew &slew, float fanout, @@ -483,15 +530,14 @@ protected: // Path options. ReportPathFormat format_{ReportPathFormat::full}; - ReportFieldSeq fields_; bool report_input_pin_; bool report_hier_pins_; bool report_net_; bool no_split_{false}; int digits_; - size_t start_end_pt_width_{80}; - + ReportFieldMap field_map_; + ReportFieldSeq fields_; ReportField *field_description_; ReportField *field_total_; ReportField *field_incr_; @@ -507,41 +553,9 @@ protected: std::string minus_zero_; int field_width_extra_{5}; + size_t start_end_pt_width_{80}; static constexpr float field_blank_ = -1; static const float field_skip_; }; -class ReportField -{ -public: - ReportField(std::string_view name, - std::string_view title, - size_t width, - bool left_justify, - Unit *unit, - bool enabled); - ~ReportField(); - void setProperties(std::string_view title, - size_t width, - bool left_justify); - const std::string &name() const { return name_; } - const std::string &title() const { return title_; } - size_t width() const { return width_; } - void setWidth(size_t width); - bool leftJustify() const { return left_justify_; } - Unit *unit() const { return unit_; } - const std::string &blank() const { return blank_; } - void setEnabled(bool enabled); - bool enabled() const { return enabled_; } - -protected: - std::string name_; - std::string title_; - size_t width_; - bool left_justify_; - Unit *unit_; - bool enabled_; - std::string blank_; -}; - } // namespace sta diff --git a/search/Search.i b/search/Search.i index c378a5e8..dbf3dc0f 100644 --- a/search/Search.i +++ b/search/Search.i @@ -401,29 +401,46 @@ set_report_path_format(ReportPathFormat format) } void -set_report_path_field_order(const StringSeq &field_names) +set_report_path_field_order(StringSeq field_names) { Sta::sta()->setReportPathFieldOrder(field_names); } void -set_report_path_fields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr) +set_report_path_fields(StringSeq fields) { - Sta::sta()->setReportPathFields(report_input_pin, - report_hier_pins, - report_net, - report_cap, - report_slew, - report_fanout, - report_variation, - report_src_attr); + Sta::sta()->setReportPathFields(fields); +} + +void +make_report_path_attr_field(std::string attr_name, + int width) +{ + Sta *sta = Sta::sta(); + sta->makeReportPathField(attr_name, attr_name, attr_name, width, true, + nullptr, + [attr_name] (const Path *path, + const StaState *sta) -> std::string { + if (path) { + const Network *network = sta->network(); + const Pin *pin = path->pin(sta); + const Instance *inst = network->instance(pin); + return network->getAttribute(inst, attr_name); + } + else + return ""; + }); +} + +const char * +find_report_path_field_abrev(const char *name) +{ + Sta *sta = Sta::sta(); + ReportField *field = sta->findReportPathFieldAbrev(name); + if (field) + return field->name().c_str(); + else + return ""; } void diff --git a/search/Search.tcl b/search/Search.tcl index 11394292..6d3c7223 100644 --- a/search/Search.tcl +++ b/search/Search.tcl @@ -158,8 +158,6 @@ proc find_timing_paths_cmd { cmd args_var } { sta_error 511 "$cmd command failed." } - check_for_key_args $cmd args - if { [info exists flags(-unconstrained)] } { set unconstrained 1 } elseif { [info exists sta_report_unconstrained_paths] } { @@ -230,7 +228,6 @@ proc find_timing_paths_cmd { cmd args_var } { sta_error 515 "positional arguments not supported." } } - set path_ends [find_path_ends $from $thrus $to $unconstrained \ $scenes $min_max \ $group_path_count $endpoint_path_count \ @@ -716,41 +713,26 @@ proc parse_report_path_options { cmd args_var default_format set path_options(num_fmt) "%.${digits}f" set_report_path_digits $digits - set report_input_pin 0 - set report_hier_pins 0 - set report_cap 0 - set report_net 0 - set report_slew 0 - set report_fanout 0 - set report_variation 0 - set report_src_attr 0 + set fields {} if { [info exists path_options(-fields)] } { foreach field $path_options(-fields) { if { [string match "input*" $field] } { - set report_input_pin 1 + lappend fields "input_pin" } elseif { [string match "hier*" $field] } { - set report_hier_pins 1 - } elseif { [string match "cap*" $field] } { - set report_cap 1 + lappend fields "hierarchical_pin" } elseif { [string match "net" $field] } { - set report_net 1 - } elseif { [string match "slew" $field] } { - set report_slew 1 - } elseif { [string match "fanout" $field] } { - set report_fanout 1 - } elseif { [string match "variation" $field] } { - set report_variation 1 - } elseif { [string match "src*" $field] } { - set report_src_attr 1 + lappend fields "net" } else { - sta_warn 168 "unknown field $field." + set field_name [find_report_path_field_abrev $field] + if { $field_name != "" } { + lappend fields $field_name + } else { + sta_warn 168 "unknown field $field." + } } } } - - set_report_path_fields $report_input_pin $report_hier_pins $report_net \ - $report_cap $report_slew $report_fanout $report_variation $report_src_attr - + set_report_path_fields $fields set_report_path_no_split [info exists path_options(-no_line_splits)] } diff --git a/search/Sta.cc b/search/Sta.cc index c5a40139..5d042594 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2816,18 +2816,9 @@ Sta::setReportPathFieldOrder(const StringSeq &field_names) } void -Sta::setReportPathFields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr) +Sta::setReportPathFields(const StringSeq &fields) { - report_path_->setReportFields(report_input_pin, report_hier_pins, report_net, - report_cap, report_slew, report_fanout, - report_variation, report_src_attr); + report_path_->setReportFields(fields); } ReportField * @@ -2836,6 +2827,24 @@ Sta::findReportPathField(std::string_view name) return report_path_->findField(name); } +ReportField * +Sta::findReportPathFieldAbrev(std::string_view name) +{ + return report_path_->findFieldAbrev(name); +} + +void +Sta::makeReportPathField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + Unit *unit, + const ReportFieldGetValue &get_value) +{ + report_path_->makeField(name, name_abrev, title, width, left_justify, unit, get_value); +} + void Sta::setReportPathDigits(int digits) {