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:
James Cherry 2024-12-25 17:44:28 -07:00
parent 3cf999c344
commit 26fccd8e7f
9 changed files with 208 additions and 64 deletions

View File

@ -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
-------------------------

Binary file not shown.

Binary file not shown.

View File

@ -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,

View File

@ -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

View File

@ -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_;

View File

@ -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,

View File

@ -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)]

View File

@ -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 *