report_checks -fileds hierarchical_pins resolves #136
commit bbcb5e6d69a7f01af186e1adf7aaff8bccada638
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Dec 25 11:07:15 2024 -0700
report hier pins factor
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 2b00bde920deb4f6f997f30f6f4d8ee41d2a686f
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Dec 24 18:35:24 2024 -0700
report_checks hier pins
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit dd1a1b99d51f0adbedc6ef43b6b5e60fae075025
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Dec 24 11:22:17 2024 -0700
report_checks error check fields
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit dc500534bddee9d514b4ed7ffb9d83289f0aaad5
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Dec 24 11:22:01 2024 -0700
report_checks hierarchical_pins field
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit c6a4a12d9449773e677d2b12f1a41444a011b526
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Dec 24 09:56:33 2024 -0700
report_checks hierarchical_pins field
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
3cf999c344
commit
26fccd8e7f
|
|
@ -33,6 +33,9 @@ is now supported by the the read_saif command.
|
|||
The report_checks -group_count option has been renamed to -group_path_count.
|
||||
The report_checks -endpoing_count option has been renamed to -endpoint_path_count.
|
||||
|
||||
The report_checks -field hierarchical_pins field reports hierarical pins between
|
||||
a driver and a load in the path report.
|
||||
|
||||
Release 2.5.0 2024/01/17
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -889,6 +889,7 @@ public:
|
|||
void setReportPathFormat(ReportPathFormat format);
|
||||
void setReportPathFieldOrder(StringSeq *field_names);
|
||||
void setReportPathFields(bool report_input_pin,
|
||||
bool report_hier_pins,
|
||||
bool report_net,
|
||||
bool report_cap,
|
||||
bool report_slew,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <algorithm> // reverse
|
||||
|
||||
#include "ReportPath.hh"
|
||||
|
||||
#include "Report.hh"
|
||||
|
|
@ -53,6 +55,11 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
static PinSeq
|
||||
hierPinsThruEdge(const Edge *edge,
|
||||
const Network *network,
|
||||
const Graph *graph);
|
||||
|
||||
ReportField::ReportField(const char *name,
|
||||
const char *title,
|
||||
int width,
|
||||
|
|
@ -122,7 +129,7 @@ ReportPath::ReportPath(StaState *sta) :
|
|||
{
|
||||
setDigits(2);
|
||||
makeFields();
|
||||
setReportFields(false, false, false, false, false, false);
|
||||
setReportFields(false, false, false, false, false, false, false);
|
||||
}
|
||||
|
||||
ReportPath::~ReportPath()
|
||||
|
|
@ -225,6 +232,7 @@ ReportPath::setReportFieldOrder(StringSeq *field_names)
|
|||
|
||||
void
|
||||
ReportPath::setReportFields(bool report_input_pin,
|
||||
bool report_hier_pins,
|
||||
bool report_net,
|
||||
bool report_cap,
|
||||
bool report_slew,
|
||||
|
|
@ -232,6 +240,7 @@ ReportPath::setReportFields(bool report_input_pin,
|
|||
bool report_src_attr)
|
||||
{
|
||||
report_input_pin_ = report_input_pin;
|
||||
report_hier_pins_ = report_hier_pins;
|
||||
report_net_ = report_net;
|
||||
|
||||
field_capacitance_->setEnabled(report_cap);
|
||||
|
|
@ -2402,7 +2411,7 @@ ReportPath::reportPathLine(const Path *path,
|
|||
{
|
||||
Vertex *vertex = path->vertex(this);
|
||||
Pin *pin = vertex->pin();
|
||||
auto what = descriptionField(vertex);
|
||||
const string what = descriptionField(vertex);
|
||||
const RiseFall *rf = path->transition(this);
|
||||
bool is_driver = network_->isDriver(pin);
|
||||
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
||||
|
|
@ -2761,52 +2770,39 @@ ReportPath::reportPath5(const Path *path,
|
|||
incr = delayIncr(time, prev_time, min_max);
|
||||
line_case = "normal";
|
||||
}
|
||||
if (report_input_pin_
|
||||
|| (i == path_last_index)
|
||||
|| is_clk_start
|
||||
|| (prev_arc == nullptr)
|
||||
// Filter wire edges from report unless reporting
|
||||
// input pins.
|
||||
|| (prev_arc
|
||||
&& !prev_arc->role()->isWire())) {
|
||||
bool is_driver = network_->isDriver(pin);
|
||||
float cap = field_blank_;
|
||||
|
||||
if (vertex->isDriver(network_)) {
|
||||
float cap = field_blank_;
|
||||
float fanout = field_blank_;
|
||||
// Don't show capacitance field for input pins.
|
||||
if (is_driver && field_capacitance_->enabled())
|
||||
if (field_capacitance_->enabled())
|
||||
cap = graph_delay_calc_->loadCap(pin, rf, dcalc_ap);
|
||||
// Don't show fanout field for input pins.
|
||||
if (is_driver && field_fanout_->enabled())
|
||||
fanout = drvrFanout(vertex, dcalc_ap->corner(), min_max);
|
||||
auto what = descriptionField(vertex);
|
||||
if (report_net_ && is_driver) {
|
||||
reportLine(what.c_str(), cap, slew, fanout,
|
||||
incr, time, false, min_max, rf,
|
||||
src_attr, line_case);
|
||||
string what2;
|
||||
if (network_->isTopLevelPort(pin)) {
|
||||
const char *pin_name = cmd_network_->pathName(pin);
|
||||
what2 = stdstrPrint("%s (net)", pin_name);
|
||||
}
|
||||
else {
|
||||
Net *net = network_->net(pin);
|
||||
if (net) {
|
||||
Net *highest_net = network_->highestNetAbove(net);
|
||||
const char *net_name = cmd_network_->pathName(highest_net);
|
||||
what2 = stdstrPrint("%s (net)", net_name);
|
||||
}
|
||||
else
|
||||
what2 = "(unconnected)";
|
||||
}
|
||||
reportLine(what2.c_str(), field_blank_, field_blank_, field_blank_,
|
||||
field_blank_, field_blank_, false, min_max,
|
||||
nullptr, src_attr, line_case);
|
||||
}
|
||||
else
|
||||
reportLine(what.c_str(), cap, slew, fanout,
|
||||
incr, time, false, min_max, rf, src_attr,
|
||||
line_case);
|
||||
prev_time = time;
|
||||
if (field_fanout_->enabled())
|
||||
fanout = drvrFanout(vertex, dcalc_ap->corner(), min_max);
|
||||
const string what = descriptionField(vertex);
|
||||
reportLine(what.c_str(), cap, slew, fanout,
|
||||
incr, time, false, min_max, rf, src_attr,
|
||||
line_case);
|
||||
|
||||
if (report_net_) {
|
||||
const string what2 = descriptionNet(pin);
|
||||
reportLine(what2.c_str(), field_blank_, field_blank_, field_blank_,
|
||||
field_blank_, field_blank_, false, min_max,
|
||||
nullptr, src_attr, "");
|
||||
}
|
||||
prev_time = time;
|
||||
}
|
||||
else {
|
||||
reportHierPinsThru(path1, prev_arc);
|
||||
if (report_input_pin_
|
||||
|| (i == 0)
|
||||
|| (i == path_last_index)
|
||||
|| is_clk_start) {
|
||||
const string what = descriptionField(vertex);
|
||||
reportLine(what.c_str(), field_blank_, slew, field_blank_,
|
||||
incr, time, false, min_max, rf, src_attr,
|
||||
line_case);
|
||||
prev_time = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -2814,6 +2810,23 @@ ReportPath::reportPath5(const Path *path,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReportPath::reportHierPinsThru(const Path *path,
|
||||
const TimingArc *prev_arc)
|
||||
{
|
||||
if (report_hier_pins_) {
|
||||
const Edge *prev_edge = path->prevEdge(prev_arc, this);
|
||||
if (prev_edge && prev_edge->isWire()) {
|
||||
for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) {
|
||||
const string what = descriptionField(hpin);
|
||||
reportLine(what.c_str(), field_blank_, field_blank_, field_blank_,
|
||||
field_blank_, field_blank_, false, path->minMax(this),
|
||||
nullptr, "", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Delay
|
||||
ReportPath::delayIncr(Delay time,
|
||||
Delay prev,
|
||||
|
|
@ -2839,7 +2852,12 @@ ReportPath::nextArcAnnotated(const PathRef *next_path,
|
|||
string
|
||||
ReportPath::descriptionField(Vertex *vertex)
|
||||
{
|
||||
Pin *pin = vertex->pin();
|
||||
return descriptionField(vertex->pin());
|
||||
}
|
||||
|
||||
string
|
||||
ReportPath::descriptionField(const Pin *pin)
|
||||
{
|
||||
const char *pin_name = cmd_network_->pathName(pin);
|
||||
const char *name2;
|
||||
if (network_->isTopLevelPort(pin)) {
|
||||
|
|
@ -2863,6 +2881,25 @@ ReportPath::descriptionField(Vertex *vertex)
|
|||
return stdstrPrint("%s (%s)", pin_name, name2);
|
||||
}
|
||||
|
||||
string
|
||||
ReportPath::descriptionNet(const Pin *pin)
|
||||
{
|
||||
if (network_->isTopLevelPort(pin)) {
|
||||
const char *pin_name = cmd_network_->pathName(pin);
|
||||
return stdstrPrint("%s (net)", pin_name);
|
||||
}
|
||||
else {
|
||||
Net *net = network_->net(pin);
|
||||
if (net) {
|
||||
Net *highest_net = network_->highestNetAbove(net);
|
||||
const char *net_name = cmd_network_->pathName(highest_net);
|
||||
return stdstrPrint("%s (net)", net_name);
|
||||
}
|
||||
else
|
||||
return "(unconnected)";
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
ReportPath::drvrFanout(Vertex *drvr,
|
||||
const Corner *corner,
|
||||
|
|
@ -3442,4 +3479,85 @@ ReportPath::latchDesc(const RiseFall *clk_rf) const
|
|||
: "negative level-sensitive latch";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
hierPinsAbove(const Net *net,
|
||||
const Network *network,
|
||||
PinSeq &pins_above);
|
||||
static void
|
||||
hierPinsAbove(const Pin *pin,
|
||||
const Network *network,
|
||||
PinSeq &pins_above);
|
||||
|
||||
static PinSeq
|
||||
hierPinsThruEdge(const Edge *edge,
|
||||
const Network *network,
|
||||
const Graph *graph)
|
||||
{
|
||||
const Pin *drvr_pin = edge->from(graph)->pin();
|
||||
const Pin *load_pin = edge->to(graph)->pin();
|
||||
PinSeq drvr_hpins;
|
||||
PinSeq load_hpins;
|
||||
hierPinsAbove(drvr_pin, network, drvr_hpins);
|
||||
hierPinsAbove(load_pin, network, load_hpins);
|
||||
if (drvr_hpins.empty()) {
|
||||
std::reverse(load_hpins.begin(), load_hpins.end());
|
||||
return load_hpins;
|
||||
}
|
||||
if (load_hpins.empty())
|
||||
return drvr_hpins;
|
||||
for (size_t l1 = 0; l1 < load_hpins.size(); l1++) {
|
||||
const Pin *load_hpin = load_hpins[l1];
|
||||
const Net *load_net = network->net(load_hpin);
|
||||
for (size_t d1 = 0; d1 < drvr_hpins.size(); d1++) {
|
||||
const Pin *drvr_hpin = drvr_hpins[d1];
|
||||
const Net *drvr_net = network->net(drvr_hpin);
|
||||
if (load_net == drvr_net) {
|
||||
PinSeq hpins_thru;
|
||||
for (size_t d2 = 0; d2 < d1; d2++) {
|
||||
const Pin *drvr_hpin2 = drvr_hpins[d2];
|
||||
hpins_thru.push_back(drvr_hpin2);
|
||||
}
|
||||
hpins_thru.push_back(drvr_hpin);
|
||||
hpins_thru.push_back(load_hpin);
|
||||
for (size_t l2 = 0; l2 < l1; l2++) {
|
||||
const Pin *load_hpin2 = load_hpins[l2];
|
||||
hpins_thru.push_back(load_hpin2);
|
||||
}
|
||||
return hpins_thru;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PinSeq();
|
||||
}
|
||||
|
||||
static void
|
||||
hierPinsAbove(const Pin *pin,
|
||||
const Network *network,
|
||||
PinSeq &pins_above)
|
||||
{
|
||||
const Net *net = network->net(pin);
|
||||
hierPinsAbove(net, network, pins_above);
|
||||
}
|
||||
|
||||
static void
|
||||
hierPinsAbove(const Net *net,
|
||||
const Network *network,
|
||||
PinSeq &pins_above)
|
||||
{
|
||||
if (net) {
|
||||
NetTermIterator *term_iter = network->termIterator(net);
|
||||
while (term_iter->hasNext()) {
|
||||
const Term *term = term_iter->next();
|
||||
const Pin *net_pin = network->pin(term);
|
||||
if (network->isHierarchical(net_pin))
|
||||
pins_above.push_back(net_pin);
|
||||
const Net *hpin_net = network->net(net_pin);
|
||||
if (hpin_net)
|
||||
hierPinsAbove(hpin_net, network, pins_above);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ public:
|
|||
void setPathFormat(ReportPathFormat format);
|
||||
void setReportFieldOrder(StringSeq *field_names);
|
||||
void setReportFields(bool report_input_pin,
|
||||
bool report_hier_pins,
|
||||
bool report_net,
|
||||
bool report_cap,
|
||||
bool report_slew,
|
||||
|
|
@ -316,6 +317,8 @@ protected:
|
|||
bool report_clk_path,
|
||||
Arrival prev_time,
|
||||
float time_offset);
|
||||
void reportHierPinsThru(const Path *path,
|
||||
const TimingArc *prev_arc);
|
||||
void reportInputExternalDelay(const Path *path,
|
||||
float time_offset);
|
||||
void reportLine(const char *what,
|
||||
|
|
@ -401,6 +404,8 @@ protected:
|
|||
void reportDashLine(int line_width);
|
||||
void reportBlankLine();
|
||||
string descriptionField(Vertex *vertex);
|
||||
string descriptionField(const Pin *pin);
|
||||
string descriptionNet(const Pin *pin);
|
||||
bool reportClkPath() const;
|
||||
string clkName(const Clock *clk,
|
||||
bool inverted);
|
||||
|
|
@ -455,6 +460,7 @@ protected:
|
|||
ReportPathFormat format_;
|
||||
ReportFieldSeq fields_;
|
||||
bool report_input_pin_;
|
||||
bool report_hier_pins_;
|
||||
bool report_net_;
|
||||
bool no_split_;
|
||||
int digits_;
|
||||
|
|
|
|||
|
|
@ -437,6 +437,7 @@ set_report_path_field_order(StringSeq *field_names)
|
|||
|
||||
void
|
||||
set_report_path_fields(bool report_input_pin,
|
||||
bool report_hier_pins,
|
||||
bool report_net,
|
||||
bool report_cap,
|
||||
bool report_slew,
|
||||
|
|
@ -444,6 +445,7 @@ set_report_path_fields(bool report_input_pin,
|
|||
bool report_src_attr)
|
||||
{
|
||||
Sta::sta()->setReportPathFields(report_input_pin,
|
||||
report_hier_pins,
|
||||
report_net,
|
||||
report_cap,
|
||||
report_slew,
|
||||
|
|
|
|||
|
|
@ -907,23 +907,35 @@ proc parse_report_path_options { cmd args_var default_format
|
|||
set_report_path_field_width $field $field_width
|
||||
}
|
||||
|
||||
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_src_attr 0
|
||||
if { [info exists path_options(-fields)] } {
|
||||
set fields $path_options(-fields)
|
||||
set report_input_pin [expr [lsearch $fields "input*"] != -1]
|
||||
set report_cap [expr [lsearch $fields "cap*"] != -1]
|
||||
set report_net [expr [lsearch $fields "net*"] != -1]
|
||||
set report_slew [expr [lsearch $fields "slew*"] != -1]
|
||||
set report_fanout [expr [lsearch $fields "fanout*"] != -1]
|
||||
set report_src_attr [expr [lsearch $fields "src_attr*"] != -1]
|
||||
} else {
|
||||
set report_input_pin 0
|
||||
set report_cap 0
|
||||
set report_net 0
|
||||
set report_slew 0
|
||||
set report_fanout 0
|
||||
set report_src_attr 0
|
||||
foreach field $path_options(-fields) {
|
||||
if { [string match "input*" $field] } {
|
||||
set report_input_pin 1
|
||||
} elseif { [string match "hier*" $field] } {
|
||||
set report_hier_pins 1
|
||||
} elseif { [string match "cap*" $field] } {
|
||||
set report_cap 1
|
||||
} 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 "src*" $field] } {
|
||||
set report_src_attr 1
|
||||
} else {
|
||||
sta_warn 166 "unknown field $field."
|
||||
}
|
||||
}
|
||||
}
|
||||
set_report_path_fields $report_input_pin $report_net \
|
||||
set_report_path_fields $report_input_pin $report_hier_pins $report_net \
|
||||
$report_cap $report_slew $report_fanout $report_src_attr
|
||||
|
||||
set_report_path_no_split [info exists path_options(-no_line_splits)]
|
||||
|
|
|
|||
|
|
@ -2481,14 +2481,16 @@ Sta::setReportPathFieldOrder(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_src_attr)
|
||||
{
|
||||
report_path_->setReportFields(report_input_pin, report_net, report_cap,
|
||||
report_slew, report_fanout, report_src_attr);
|
||||
report_path_->setReportFields(report_input_pin, report_hier_pins, report_net,
|
||||
report_cap, report_slew, report_fanout,
|
||||
report_src_attr);
|
||||
}
|
||||
|
||||
ReportField *
|
||||
|
|
|
|||
Loading…
Reference in New Issue