diff --git a/.gitignore b/.gitignore
index 267c23f7..1c3c92aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,5 @@ doc/messages.txt
# clangd turds
.cache/
-# test artifacts
-*/test/*.log
-**/Testing/
+# openroad ctest turds
+cmake_test*
diff --git a/include/sta/LevelizeObserver.hh b/include/sta/LevelizeObserver.hh
new file mode 100644
index 00000000..787d8054
--- /dev/null
+++ b/include/sta/LevelizeObserver.hh
@@ -0,0 +1,59 @@
+// OpenSTA, Static Timing Analyzer
+// Copyright (c) 2026, Parallax Software, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+// The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software.
+//
+// Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// This notice may not be removed or altered from any source distribution.
+
+#pragma once
+
+namespace sta {
+
+class Vertex;
+class Search;
+class GraphDelayCalc;
+
+// Observer fired by Levelize during (re)levelization. Downstream consumers
+// override the two hooks to invalidate caches that depend on vertex levels.
+class LevelizeObserver
+{
+public:
+ virtual ~LevelizeObserver() = default;
+ virtual void levelsChangedBefore() = 0;
+ virtual void levelChangedBefore(Vertex *vertex) = 0;
+};
+
+// Default observer installed by Sta::makeObservers. Forwards level-change
+// events to Search and GraphDelayCalc so their internal caches stay
+// consistent. Subclass and override to extend (call the base methods first,
+// then add your own invalidation).
+class StaLevelizeObserver : public LevelizeObserver
+{
+public:
+ StaLevelizeObserver(Search *search, GraphDelayCalc *graph_delay_calc);
+ void levelsChangedBefore() override;
+ void levelChangedBefore(Vertex *vertex) override;
+
+private:
+ Search *search_;
+ GraphDelayCalc *graph_delay_calc_;
+};
+
+} // namespace sta
diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh
index 561ce3aa..9e20bf63 100644
--- a/include/sta/Sta.hh
+++ b/include/sta/Sta.hh
@@ -73,6 +73,7 @@ class ClkSkews;
class ReportField;
class EquivCells;
class StaSimObserver;
+class LevelizeObserver;
class GraphLoop;
using ModeNameMap = std::map>;
@@ -83,6 +84,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,16 +985,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,
- bool report_orig_name);
+ 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);
@@ -1327,6 +1330,10 @@ public:
// Ensure a network has been read, linked and liberty libraries exist.
Network *ensureLibLinked();
void ensureLevelized();
+ // Replace the Levelize observer. Takes ownership; deletes any prior
+ // observer. Subclass StaLevelizeObserver to extend the default behavior
+ // (Search + GraphDelayCalc forwarding) without re-implementing it.
+ void setLevelizeObserver(LevelizeObserver *observer);
// Ensure that the timing graph has been built.
Graph *ensureGraph();
void ensureClkArrivals();
diff --git a/include/sta/StringUtil.hh b/include/sta/StringUtil.hh
index 35a8cda9..d5d2e184 100644
--- a/include/sta/StringUtil.hh
+++ b/include/sta/StringUtil.hh
@@ -91,6 +91,9 @@ stringEqual(std::string_view s1,
std::pair
stringFloat(const std::string &str);
+std::pair
+stringLong(const std::string &str,
+ int base = 10);
bool
isDigits(const char *str);
diff --git a/liberty/LibertyParse.yy b/liberty/LibertyParse.yy
index f19a7c1f..2b5ce05c 100644
--- a/liberty/LibertyParse.yy
+++ b/liberty/LibertyParse.yy
@@ -62,7 +62,7 @@ sta::LibertyParse::error(const location_type &loc,
%define api.parser.class {LibertyParse}
%define api.value.type variant
-%expect 2
+%expect 0
%token STRING KEYWORD
%token FLOAT
@@ -75,8 +75,8 @@ sta::LibertyParse::error(const location_type &loc,
%type statement complex_attr simple_attr variable group file
%type attr_values
%type attr_value
-%type string expr expr_term expr_term1 volt_expr
-%type expr_op volt_op
+%type string expr expr_term expr_term1
+%type expr_op
%start file
@@ -157,36 +157,8 @@ string:
;
attr_value:
- FLOAT
- { $$ = reader->makeAttrValueFloat($1); }
-| expr
+ expr
{ $$ = reader->makeAttrValueString(std::move($1)); }
-| volt_expr
- { $$ = reader->makeAttrValueString(std::move($1)); }
- ;
-
-/* Voltage expressions are ignored. */
-/* Crafted to avoid conflicts with expr */
-volt_expr:
- FLOAT volt_op FLOAT
- { $$ = sta::format("{}{}{}", $1, $2, $3); }
-| string volt_op FLOAT
- { $$ = sta::format("{}{}{}", $1, $2, $3); }
-| FLOAT volt_op string
- { $$ = sta::format("{}{}{}", $1, $2, $3); }
-| volt_expr volt_op FLOAT
- { $$ = sta::format("{}{}{}", $1, $2, $3); }
- ;
-
-volt_op:
- '+'
- { $$ = '+'; }
-| '-'
- { $$ = '-'; }
-| '*'
- { $$ = '*'; }
-| '/'
- { $$ = '/'; }
;
expr:
@@ -197,6 +169,8 @@ expr:
expr_term:
string
+| FLOAT
+ { $$ = sta::format("{}", $1); }
| '0'
{ $$ = std::string("0"); }
| '1'
@@ -224,6 +198,10 @@ expr_op:
{ $$ = '&'; }
| '^'
{ $$ = '^'; }
+| '-'
+ { $$ = '-'; }
+| '/'
+ { $$ = '/'; }
;
semi_opt:
diff --git a/liberty/LibertyParser.cc b/liberty/LibertyParser.cc
index ee9ef6c6..26c0fefc 100644
--- a/liberty/LibertyParser.cc
+++ b/liberty/LibertyParser.cc
@@ -513,6 +513,13 @@ LibertyGroup::findAttrInt(std::string_view attr_name,
exists = exists1;
return;
}
+ else {
+ const std::string &int_str = attr_value.stringValue();
+ auto [value1, valid1] = stringLong(int_str);
+ value = value1;
+ exists = valid1;
+ return;
+ }
}
exists = false;
}
diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc
index 991cf88e..56d64408 100644
--- a/liberty/LibertyReader.cc
+++ b/liberty/LibertyReader.cc
@@ -2344,16 +2344,13 @@ LibertyReader::readReceiverCapacitance(const LibertyGroup *timing_group,
std::string cap_group_name1 = sta::format("{}_{}", cap_group_name, rf->to_string());
const LibertyGroup *cap_group = timing_group->findSubgroup(cap_group_name1);
if (cap_group) {
- const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment");
- if (segment_attr) {
- // For receiver_capacitance groups with mulitiple segments this
- // overrides the index passed in beginReceiverCapacitance1Rise/Fall.
- int segment;
- bool exists;
- getAttrInt(segment_attr, segment, exists);
- if (exists)
- index = segment;
- }
+ // For receiver_capacitance groups with mulitiple segments this
+ // overrides the index passed in beginReceiverCapacitance1Rise/Fall.
+ int segment;
+ bool exists;
+ cap_group->findAttrInt("segment", segment, exists);
+ if (exists)
+ index = segment;
TableModel *model = readTableModel(cap_group, rf, TableTemplateType::delay,
cap_scale_, ScaleFactorType::pin_cap);
if (ReceiverModel::checkAxes(model)) {
@@ -3224,24 +3221,6 @@ LibertyReader::makeFloatTable(const LibertyComplexAttr *values_attr,
////////////////////////////////////////////////////////////////
-void
-LibertyReader::getAttrInt(const LibertySimpleAttr *attr,
- // Return values.
- int &value,
- bool &exists)
-{
- value = 0;
- exists = false;
- const LibertyAttrValue &attr_value = attr->value();
- if (attr_value.isFloat()) {
- auto [float_val, valid] = attr_value.floatValue();
- value = static_cast(float_val);
- exists = true;
- }
- else
- warn(1268, attr, "{} attribute is not an integer.", attr->name());
-}
-
// Get two floats in a complex attribute.
// attr(float1, float2);
void
diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh
index cd4a1627..eabdc2cc 100644
--- a/liberty/LibertyReaderPvt.hh
+++ b/liberty/LibertyReaderPvt.hh
@@ -418,10 +418,6 @@ protected:
StateInternalValues parseStateInternalValues(StringSeq &states,
const LibertySimpleAttr *attr);
- void getAttrInt(const LibertySimpleAttr *attr,
- // Return values.
- int &value,
- bool &exists);
void getAttrFloat2(const LibertyComplexAttr *attr,
// Return values.
float &value1,
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/Levelize.hh b/search/Levelize.hh
index a1b680e8..094e3d47 100644
--- a/search/Levelize.hh
+++ b/search/Levelize.hh
@@ -30,11 +30,11 @@
#include "Graph.hh"
#include "StaState.hh"
+#include "sta/LevelizeObserver.hh"
namespace sta {
class SearchPred;
-class LevelizeObserver;
class GraphLoop;
using VertexEdgeIterPair = std::pair;
@@ -133,12 +133,4 @@ private:
EdgeSeq *edges_;
};
-class LevelizeObserver
-{
-public:
- virtual ~LevelizeObserver() = default;
- virtual void levelsChangedBefore() = 0;
- virtual void levelChangedBefore(Vertex *vertex) = 0;
-};
-
} // namespace sta
diff --git a/search/ReportPath.cc b/search/ReportPath.cc
index 01027f35..1bfcdfc6 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,75 +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, 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_orig_name_;
- 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_orig_name_ = makeField("orig_name", "Orig Name", 36,
- true, nullptr, false);
+ 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;
@@ -216,34 +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,
- bool report_orig_name)
+ReportPath::setReportFields(const StringSeq &fields)
{
- report_input_pin_ = report_input_pin;
- report_hier_pins_ = report_hier_pins;
- report_net_ = report_net;
-
- 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);
- field_orig_name_->setEnabled(report_orig_name);
- // for debug
- field_case_->setEnabled(false);
+ 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;
+
+ 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
@@ -2456,16 +2469,11 @@ ReportPath::reportPathLine(const Path *path,
std::string src_attr;
if (inst)
src_attr = network_->getAttribute(inst, "src");
- std::string orig_name;
- if (inst && field_orig_name_->enabled()) {
- std::string port_name = network_->portName(pin);
- orig_name = network_->getAttribute(inst, "orig_name_" + port_name);
- }
// 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_,
- time, false, early_late, rf, src_attr, orig_name, line_case);
+ reportLine(what, path, cap, slew, field_blank_, incr, field_blank_,
+ time, false, early_late, rf, src_attr, line_case);
}
void
@@ -2743,11 +2751,6 @@ ReportPath::reportPath6(const Path *path,
std::string src_attr;
if (inst)
src_attr = network_->getAttribute(inst, "src");
- std::string orig_name;
- if (inst && field_orig_name_->enabled()) {
- std::string port_name = network_->portName(pin);
- orig_name = network_->getAttribute(inst, "orig_name_" + port_name);
- }
// Always show the search start point (register clk pin).
// Skip reporting the clk tree unless it is requested.
if (is_clk_start
@@ -2838,15 +2841,15 @@ 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,
- orig_name, line_case);
+ 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, "", "");
+ nullptr, src_attr, "");
}
prev_time = time;
}
@@ -2857,9 +2860,9 @@ 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,
- orig_name, line_case);
+ line_case);
prev_time = time;
}
}
@@ -2882,29 +2885,29 @@ 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, "", "", "");
+ 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, "", "", "");
+ 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, "", "", "");
+ 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, "", "", "");
+ 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, "", "", "");
+ nullptr, "", "");
break;
}
default:
@@ -2930,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, "", "");
}
}
}
@@ -3124,8 +3127,8 @@ ReportPath::reportLine(std::string_view what,
Delay total,
const EarlyLate *early_late) const
{
- reportLine(what, field_blank_, field_blank_, field_blank_, field_blank_,
- field_blank_, total, false, early_late, nullptr, "", "", "");
+ reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_,
+ field_blank_, total, false, early_late, nullptr, "", "");
}
// Report negative total.
@@ -3134,9 +3137,9 @@ 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, "", "", "");
+ early_late, nullptr, "", "");
}
// Report total, and transition suffix.
@@ -3146,8 +3149,8 @@ ReportPath::reportLine(std::string_view what,
const EarlyLate *early_late,
const RiseFall *rf) const
{
- reportLine(what, field_blank_, field_blank_, field_blank_,
- field_blank_, field_blank_, total, false, early_late, rf, "", "", "");
+ reportLine(what, nullptr, field_blank_, field_blank_, field_blank_,
+ field_blank_, field_blank_, total, false, early_late, rf, "", "");
}
// Report increment, and total.
@@ -3157,8 +3160,8 @@ ReportPath::reportLine(std::string_view what,
const Delay &total,
const EarlyLate *early_late) const
{
- reportLine(what, field_blank_, field_blank_, field_blank_,
- incr, field_blank_, total, false, early_late, nullptr, "", "", "");
+ reportLine(what, nullptr, field_blank_, field_blank_, field_blank_,
+ incr, field_blank_, total, false, early_late, nullptr, "", "");
}
// Report increment, total, and transition suffix.
@@ -3169,8 +3172,8 @@ ReportPath::reportLine(std::string_view what,
const EarlyLate *early_late,
const RiseFall *rf) const
{
- reportLine(what, field_blank_, field_blank_, field_blank_,
- incr, field_blank_, total, false, early_late, rf, "", "", "");
+ reportLine(what, nullptr, field_blank_, field_blank_, field_blank_,
+ incr, field_blank_, total, false, early_late, rf, "", "");
}
// Report slew, increment, and total.
@@ -3181,12 +3184,13 @@ ReportPath::reportLine(std::string_view what,
const Delay &total,
const EarlyLate *early_late) const
{
- reportLine(what, field_blank_, slew, field_blank_,
- incr, field_blank_, total, false, early_late, nullptr, "", "", "");
+ 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,
@@ -3197,7 +3201,6 @@ ReportPath::reportLine(std::string_view what,
const EarlyLate *early_late,
const RiseFall *rf,
std::string_view src_attr,
- std::string_view orig_name,
std::string_view line_case) const
{
std::string line;
@@ -3205,7 +3208,7 @@ ReportPath::reportLine(std::string_view what,
bool first_field = true;
for (const ReportField *field : fields_) {
bool last_field = field_index == (fields_.size() - 1);
-
+
if (field->enabled()) {
if (!first_field)
line += ' ';
@@ -3248,14 +3251,10 @@ ReportPath::reportLine(std::string_view what,
else
reportFieldBlank(field, line);
}
- else if (field == field_orig_name_) {
- if (orig_name != "")
- reportField(orig_name, field, line);
- else
- reportFieldBlank(field, line);
- }
else if (field == field_case_)
- line += line_case;
+ reportField(line_case, field, line);
+ else if (field->getValue())
+ reportField(field->value(path, this), field, line);
first_field = false;
}
diff --git a/search/ReportPath.hh b/search/ReportPath.hh
index c223a50c..c096e4eb 100644
--- a/search/ReportPath.hh
+++ b/search/ReportPath.hh
@@ -25,6 +25,7 @@
#pragma once
#include
+#include