Merge branch 'master' of https://github.com/parallaxsw/OpenSTA into update_sta

Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
This commit is contained in:
Eder Monteiro 2025-01-01 12:32:41 -03:00
commit 33b7b5b8b8
20 changed files with 331 additions and 161 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

@ -413,8 +413,8 @@ latch_d_to_q_en()
{
if (self->role() == TimingRole::latchDtoQ()) {
Sta *sta = Sta::sta();
const Network *network = sta->ensureLinked();
const Graph *graph = sta->graph();
const Network *network = sta->network();
const Graph *graph = sta->ensureGraph();
Pin *from_pin = self->from(graph)->pin();
Instance *inst = network->instance(from_pin);
LibertyCell *lib_cell = network->libertyCell(inst);

View File

@ -112,6 +112,7 @@ public:
bool infer_latches);
bool setMinLibrary(const char *min_filename,
const char *max_filename);
bool readVerilog(const char *filename);
// Network readers call this to notify the Sta to delete any previously
// linked network.
void readNetlistBefore();
@ -889,6 +890,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,
@ -1230,8 +1232,10 @@ public:
void setTclInterp(Tcl_Interp *interp);
Tcl_Interp *tclInterp();
// Ensure a network has been read, linked and liberty libraries exist.
// Ensure a network has been read, and linked.
Network *ensureLinked();
// Ensure a network has been read, linked and liberty libraries exist.
Network *ensureLibLinked();
void ensureLevelized();
// Ensure that the timing graph has been built.
Graph *ensureGraph();

View File

@ -618,13 +618,16 @@ void finish() { delete self; }
} // LibraryIterator methods
%extend Cell {
const char *name() { return Sta::sta()->ensureLinked()->name(self); }
Library *library() { return Sta::sta()->ensureLinked()->library(self); }
LibertyCell *liberty_cell() { return Sta::sta()->ensureLinked()->libertyCell(self); }
bool is_leaf() { return Sta::sta()->ensureLinked()->isLeaf(self); }
const char *name() { return Sta::sta()->cmdNetwork()->name(self); }
Library *library() { return Sta::sta()->cmdNetwork()->library(self); }
LibertyCell *liberty_cell() { return Sta::sta()->cmdNetwork()->libertyCell(self); }
bool is_leaf() { return Sta::sta()->cmdNetwork()->isLeaf(self); }
CellPortIterator *
port_iterator() { return Sta::sta()->ensureLinked()->portIterator(self); }
string get_attribute(const char *key) { return Sta::sta()->ensureLinked()->getAttribute(self, key); }
port_iterator() { return Sta::sta()->cmdNetwork()->portIterator(self); }
string get_attribute(const char *key)
{
return Sta::sta()->cmdNetwork()->getAttribute(self, key);
}
Port *
find_port(const char *name)
@ -654,7 +657,7 @@ void finish() { delete self; }
%extend Port {
const char *bus_name() { return Sta::sta()->ensureLinked()->busName(self); }
Cell *cell() { return Sta::sta()->ensureLinked()->cell(self); }
LibertyPort *liberty_port() { return Sta::sta()->ensureLinked()->libertyPort(self); }
LibertyPort *liberty_port() { return Sta::sta()->ensureLibLinked()->libertyPort(self); }
bool is_bus() { return Sta::sta()->ensureLinked()->isBus(self); }
PortMemberIterator *
member_iterator() { return Sta::sta()->ensureLinked()->memberIterator(self); }
@ -670,7 +673,7 @@ void finish() { delete self; }
%extend Instance {
Instance *parent() { return Sta::sta()->ensureLinked()->parent(self); }
Cell *cell() { return Sta::sta()->ensureLinked()->cell(self); }
LibertyCell *liberty_cell() { return Sta::sta()->ensureLinked()->libertyCell(self); }
LibertyCell *liberty_cell() { return Sta::sta()->ensureLibLinked()->libertyCell(self); }
bool is_leaf() { return Sta::sta()->ensureLinked()->isLeaf(self); }
InstanceChildIterator *
child_iterator() { return Sta::sta()->ensureLinked()->childIterator(self); }
@ -683,7 +686,10 @@ find_pin(const char *name)
{
return Sta::sta()->ensureLinked()->findPin(self, name);
}
string get_attribute(const char *key) { return Sta::sta()->ensureLinked()->getAttribute(self, key); }
string get_attribute(const char *key) {
return Sta::sta()->ensureLinked()->getAttribute(self, key);
}
} // Instance methods
%extend InstanceChildIterator {
@ -716,7 +722,7 @@ Instance *instance() { return Sta::sta()->ensureLinked()->instance(self); }
Net *net() { return Sta::sta()->ensureLinked()->net(self); }
Port *port() { return Sta::sta()->ensureLinked()->port(self); }
Term *term() { return Sta::sta()->ensureLinked()->term(self); }
LibertyPort *liberty_port() { return Sta::sta()->ensureLinked()->libertyPort(self); }
LibertyPort *liberty_port() { return Sta::sta()->ensureLibLinked()->libertyPort(self); }
bool is_driver() { return Sta::sta()->ensureLinked()->isDriver(self); }
bool is_load() { return Sta::sta()->ensureLinked()->isLoad(self); }
bool is_leaf() { return Sta::sta()->ensureLinked()->isLeaf(self); }
@ -768,7 +774,7 @@ capacitance(Corner *corner,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
float pin_cap, wire_cap;
sta->connectedCap(self, corner, min_max, pin_cap, wire_cap);
return pin_cap + wire_cap;
@ -779,7 +785,7 @@ pin_capacitance(Corner *corner,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
float pin_cap, wire_cap;
sta->connectedCap(self, corner, min_max, pin_cap, wire_cap);
return pin_cap;
@ -790,7 +796,7 @@ wire_capacitance(Corner *corner,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
float pin_cap, wire_cap;
sta->connectedCap(self, corner, min_max, pin_cap, wire_cap);
return wire_cap;

View File

@ -600,13 +600,16 @@ Power::evalBddActivity(DdNode *bdd,
Cudd_RecursiveDeref(bdd_.cuddMgr(), diff);
float var_act = var_activity.activity() * diff_duty;
activity += var_act;
const Clock *clk = findClk(pin);
float clk_period = clk ? clk->period() : 1.0;
debugPrint(debug_, "power_activity", 3, "var %s %.3e * %.3f = %.3e",
port->name(),
var_activity.activity() / clk_period,
diff_duty,
var_act / clk_period);
if (debug_->check("power_activity", 3)) {
const Clock *clk = findClk(pin);
float clk_period = clk ? clk->period() : 1.0;
debugPrint(debug_, "power_activity", 3, "var %s%s %.3e * %.3f = %.3e",
port->name(),
clk ? "" : " (unclocked)",
var_activity.activity() / clk_period,
diff_duty,
var_act / clk_period);
}
}
}
return activity;

View File

@ -109,7 +109,7 @@ read_vcd_file(const char *filename,
const char *scope)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
readVcdActivities(filename, scope, sta);
}
@ -136,7 +136,7 @@ read_saif_file(const char *filename,
const char *scope)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
return readSaif(filename, scope, sta);
}

View File

@ -271,6 +271,7 @@ proc set_power_activity { args } {
################################################################
# Deprecated 9/2024
define_cmd_args "read_power_activities" { [-scope scope] -vcd filename }
proc read_power_activities { args } {

View File

@ -89,6 +89,7 @@ SaifReader::read()
// yyparse returns 0 on success.
bool success = (::SaifParse_parse() == 0);
gzclose(stream_);
report_->reportLine("Annotated %zu pin activities.", annotated_pins_.size());
return success;
}
else

View File

@ -51,7 +51,7 @@ read_sdf_file(const char *filename,
MinMaxAllNull *cond_use)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
sta->ensureGraph();
if (stringEq(path, ""))
path = NULL;
@ -72,7 +72,7 @@ report_annotated_delay_cmd(bool report_cells,
bool report_constant_arcs)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
sta->ensureGraph();
reportAnnotatedDelay(report_cells, report_nets,
report_in_ports, report_out_ports,
@ -95,7 +95,7 @@ report_annotated_check_cmd(bool report_setup,
bool report_constant_arcs)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
sta->ensureGraph();
reportAnnotatedCheck(report_setup, report_hold,
report_recovery, report_removal,
@ -116,7 +116,7 @@ write_sdf_cmd(char *filename,
bool no_version)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
sta->writeSdf(filename, corner, divider, include_typ, digits, gzip,
no_timestamp, no_version);
}

View File

@ -680,7 +680,7 @@ getProperty(const Library *lib,
const char *property,
Sta *sta)
{
Network *network = sta->ensureLinked();
Network *network = sta->cmdNetwork();
if (stringEqual(property, "name")
|| stringEqual(property, "full_name"))
return PropertyValue(network->name(lib));
@ -711,8 +711,8 @@ getProperty(const LibertyCell *cell,
|| stringEqual(property, "base_name"))
return PropertyValue(cell->name());
else if (stringEqual(property, "full_name")) {
Network *network = sta->ensureLinked();
auto lib = cell->libertyLibrary();
Network *network = sta->cmdNetwork();
LibertyLibrary *lib = cell->libertyLibrary();
string lib_name = lib->name();
string cell_name = cell->name();
string full_name = lib_name + network->pathDivider() + cell_name;
@ -741,7 +741,7 @@ getProperty(const Cell *cell,
const char *property,
Sta *sta)
{
Network *network = sta->ensureLinked();
Network *network = sta->cmdNetwork();
if (stringEqual(property, "name")
|| stringEqual(property, "base_name"))
return PropertyValue(network->name(cell));
@ -767,7 +767,7 @@ getProperty(const Port *port,
const char *property,
Sta *sta)
{
Network *network = sta->ensureLinked();
Network *network = sta->cmdNetwork();
if (stringEqual(property, "name")
|| stringEqual(property, "full_name"))
return PropertyValue(network->name(port));
@ -819,7 +819,7 @@ portSlewProperty(const Port *port,
const MinMax *min_max,
Sta *sta)
{
Network *network = sta->ensureLinked();
Network *network = sta->ensureLibLinked();
Instance *top_inst = network->topInstance();
Pin *pin = network->findPin(top_inst, port);
return pinSlewProperty(pin, min_max, sta);
@ -831,7 +831,7 @@ portSlewProperty(const Port *port,
const MinMax *min_max,
Sta *sta)
{
Network *network = sta->ensureLinked();
Network *network = sta->ensureLibLinked();
Instance *top_inst = network->topInstance();
Pin *pin = network->findPin(top_inst, port);
return pinSlewProperty(pin, rf, min_max, sta);
@ -842,7 +842,7 @@ portSlackProperty(const Port *port,
const MinMax *min_max,
Sta *sta)
{
Network *network = sta->ensureLinked();
Network *network = sta->ensureLibLinked();
Instance *top_inst = network->topInstance();
Pin *pin = network->findPin(top_inst, port);
return pinSlackProperty(pin, min_max, sta);
@ -854,7 +854,7 @@ portSlackProperty(const Port *port,
const MinMax *min_max,
Sta *sta)
{
Network *network = sta->ensureLinked();
Network *network = sta->ensureLibLinked();
Instance *top_inst = network->topInstance();
Pin *pin = network->findPin(top_inst, port);
return pinSlackProperty(pin, rf, min_max, sta);
@ -1075,7 +1075,7 @@ pinSlewProperty(const Pin *pin,
const MinMax *min_max,
Sta *sta)
{
auto graph = sta->ensureGraph();
Graph *graph = sta->ensureGraph();
Vertex *vertex, *bidirect_drvr_vertex;
graph->pinVertices(pin, vertex, bidirect_drvr_vertex);
Slew slew = min_max->initValue();
@ -1098,7 +1098,7 @@ pinSlewProperty(const Pin *pin,
const MinMax *min_max,
Sta *sta)
{
auto graph = sta->ensureGraph();
Graph *graph = sta->ensureGraph();
Vertex *vertex, *bidirect_drvr_vertex;
graph->pinVertices(pin, vertex, bidirect_drvr_vertex);
Slew slew = min_max->initValue();
@ -1139,7 +1139,7 @@ getProperty(Edge *edge,
Sta *sta)
{
if (stringEqual(property, "full_name")) {
Network *network = sta->ensureLinked();
Network *network = sta->cmdNetwork();
Graph *graph = sta->ensureGraph();
const char *from = edge->from(graph)->name(network);
const char *to = edge->to(graph)->name(network);
@ -1177,7 +1177,7 @@ edgeDelayProperty(Edge *edge,
for (TimingArc *arc : arc_set->arcs()) {
RiseFall *to_rf = arc->toEdge()->asRiseFall();
if (to_rf == rf) {
for (auto corner : *sta->corners()) {
for (const Corner *corner : *sta->corners()) {
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
ArcDelay arc_delay = sta->arcDelay(edge, arc, dcalc_ap);
if (!delay_exists
@ -1204,9 +1204,9 @@ getProperty(TimingArcSet *arc_set,
if (arc_set->isWire())
return PropertyValue("wire");
else {
auto from = arc_set->from()->name();
auto to = arc_set->to()->name();
auto cell_name = arc_set->libertyCell()->name();
const char *from = arc_set->from()->name();
const char *to = arc_set->to()->name();
const char *cell_name = arc_set->libertyCell()->name();
string name;
stringPrint(name, "%s %s -> %s", cell_name, from, to);
return PropertyValue(name);
@ -1264,7 +1264,7 @@ getProperty(PathEnd *end,
else if (stringEqual(property, "points")) {
PathExpanded expanded(end->path(), sta);
PathRefSeq paths;
for (auto i = expanded.startIndex(); i < expanded.size(); i++) {
for (size_t i = expanded.startIndex(); i < expanded.size(); i++) {
const PathRef *path = expanded.path(i);
paths.push_back(*path);
}

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

@ -218,7 +218,7 @@ vertex_worst_arrival_path(Vertex *vertex,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
PathRef path = sta->vertexWorstArrivalPath(vertex, min_max);
if (!path.isNull())
return new PathRef(path);
@ -232,7 +232,7 @@ vertex_worst_arrival_path_rf(Vertex *vertex,
MinMax *min_max)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
PathRef path = sta->vertexWorstArrivalPath(vertex, rf, min_max);
if (!path.isNull())
return new PathRef(path);
@ -245,7 +245,7 @@ vertex_worst_slack_path(Vertex *vertex,
const MinMax *min_max)
{
Sta *sta = Sta::sta();
sta->ensureLinked();
sta->ensureLibLinked();
PathRef path = sta->vertexWorstSlackPath(vertex, min_max);
if (!path.isNull())
return new PathRef(path);
@ -335,7 +335,7 @@ void
report_loops()
{
Sta *sta = Sta::sta();
Network *network = sta->ensureLinked();
Network *network = sta->network();
Graph *graph = sta->ensureGraph();
Report *report = sta->report();
for (GraphLoop *loop : *sta->graphLoops()) {
@ -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,
@ -462,7 +464,7 @@ set_report_path_field_properties(const char *field_name,
if (field)
field->setProperties(title, width, left_justify);
else
sta->report()->error(1575, "unknown report path field %s", field_name);
sta->report()->warn(1575, "unknown report path field %s", field_name);
}
void
@ -474,7 +476,7 @@ set_report_path_field_width(const char *field_name,
if (field)
field->setWidth(width);
else
sta->report()->error(1576, "unknown report path field %s", field_name);
sta->report()->warn(1576, "unknown report path field %s", field_name);
}
void

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

@ -723,6 +723,18 @@ Sta::setMinLibrary(const char *min_filename,
return false;
}
bool
Sta::readVerilog(const char *filename)
{
NetworkReader *network = networkReader();
if (network) {
readNetlistBefore();
return readVerilogFile(filename, network);
}
else
return false;
}
void
Sta::readNetlistBefore()
{
@ -2109,7 +2121,7 @@ Sta::writeSdc(const char *filename,
bool gzip,
bool no_timestamp)
{
ensureLinked();
ensureLibLinked();
sta::writeSdc(network_->topInstance(), filename, "write_sdc",
leaf, native, digits, gzip, no_timestamp, sdc_);
}
@ -2481,14 +2493,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 *
@ -3310,7 +3324,7 @@ Sta::findDelays(Level level)
void
Sta::delayCalcPreamble()
{
ensureLinked();
ensureLibLinked();
ensureClkNetwork();
}
@ -3408,6 +3422,15 @@ Sta::vertexSlew(Vertex *vertex,
// Throwing an error means the caller doesn't have to check the result.
Network *
Sta::ensureLinked()
{
if (network_ == nullptr || !network_->isLinked())
report_->error(1570, "No network has been linked.");
// Return cmd/sdc network.
return cmd_network_;
}
Network *
Sta::ensureLibLinked()
{
if (network_ == nullptr || !network_->isLinked())
report_->error(1570, "No network has been linked.");
@ -3422,7 +3445,7 @@ Sta::ensureLinked()
Graph *
Sta::ensureGraph()
{
ensureLinked();
ensureLibLinked();
if (graph_ == nullptr && network_) {
makeGraph();
// Update pointers to graph.
@ -3886,7 +3909,7 @@ Sta::readSpef(const char *filename,
float coupling_cap_factor,
bool reduce)
{
ensureLinked();
ensureLibLinked();
setParasiticAnalysisPts(corner != nullptr);
const MinMax *ap_min_max = (min_max == MinMaxAll::all())
? MinMax::max()
@ -3921,7 +3944,7 @@ void
Sta::reportParasiticAnnotation(bool report_unannotated,
const Corner *corner)
{
ensureLinked();
ensureLibLinked();
ensureGraph();
sta::reportParasiticAnnotation(report_unannotated, corner, this);
}
@ -4768,7 +4791,7 @@ Sta::findRegisterOutputPins(ClockSet *clks,
void
Sta::findRegisterPreamble()
{
ensureLinked();
ensureLibLinked();
ensureGraph();
ensureGraphSdcAnnotated();
sim_->ensureConstantsPropagated();
@ -5625,7 +5648,7 @@ Sta::writeTimingModel(const char *lib_name,
const char *filename,
const Corner *corner)
{
ensureLinked();
ensureLibLinked();
ensureGraph();
LibertyLibrary *library = makeTimingModel(lib_name, cell_name, filename,
corner, this);
@ -5637,7 +5660,7 @@ Sta::writeTimingModel(const char *lib_name,
void
Sta::powerPreamble()
{
ensureLinked();
ensureLibLinked();
// Use arrivals to find clocking info.
searchPreamble();
search_->findAllArrivals();
@ -5685,7 +5708,7 @@ Sta::writePathSpice(PathRef *path,
const char *gnd_name,
CircuitSim ckt_sim)
{
ensureLinked();
ensureLibLinked();
sta::writePathSpice(path, spice_filename, subckt_filename,
lib_subckt_filename, model_filename,
power_name, gnd_name, ckt_sim, this);

View File

@ -32,14 +32,7 @@ using sta::readVerilogFile;
bool
read_verilog_cmd(const char *filename)
{
Sta *sta = Sta::sta();
NetworkReader *network = sta->networkReader();
if (network) {
sta->readNetlistBefore();
return readVerilogFile(filename, network);
}
else
return false;
return Sta::sta()->readVerilog(filename);
}
void
@ -54,9 +47,9 @@ write_verilog_cmd(const char *filename,
bool include_pwr_gnd,
CellSeq *remove_cells)
{
Sta *sta = Sta::sta();
// This does NOT want the SDC (cmd) network because it wants
// to see the sta internal names.
Sta *sta = Sta::sta();
Network *network = sta->network();
writeVerilog(filename, sort, include_pwr_gnd, remove_cells, network);
delete remove_cells;

View File

@ -35,7 +35,7 @@ VerilogParse_parse();
namespace sta {
VerilogReader *verilog_reader;
static const char *unconnected_net_name = reinterpret_cast<const char*>(1);
const char *VerilogReader::unconnected_net_name_ = reinterpret_cast<const char*>(1);
static string
verilogBusBitName(const char *bus_name,
@ -156,12 +156,8 @@ VerilogReader::~VerilogReader()
void
VerilogReader::deleteModules()
{
StringSet filenames;
for (const auto [name, module] : module_map_) {
filenames.insert(module->filename());
for (const auto [name, module] : module_map_)
delete module;
}
deleteContents(&filenames);
module_map_.clear();
}
@ -187,7 +183,8 @@ void
VerilogReader::init(const char *filename)
{
// Statements point to verilog_filename, so copy it.
filename_ = stringCopy(filename);
filename_ = filename;
filenames_.push_back(filename);
line_ = 1;
library_ = network_->findLibrary("verilog");
@ -267,12 +264,11 @@ VerilogReader::makeModule(const char *module_vname,
VerilogModule *module = new VerilogModule(module_name.c_str(), ports, stmts,
attribute_stmts, filename_, line, this);
cell = network_->makeCell(library_, module_name.c_str(), false, filename_);
cell = network_->makeCell(library_, module_name.c_str(), false, filename_.c_str());
for (VerilogAttributeStmt *stmt : *attribute_stmts) {
for (VerilogAttributeEntry *entry : *stmt->attribute_sequence()) {
for (VerilogAttributeEntry *entry : *stmt->attribute_sequence())
network_->setAttribute(cell, entry->key(), entry->value());
}
}
module_map_[cell] = module;
@ -582,10 +578,10 @@ VerilogReader::makeModuleInst(const char *module_vname,
int pin_index = lport->pinIndex();
const char *prev_net_name = net_names[pin_index];
if (prev_net_name
&& prev_net_name !=unconnected_net_name)
&& prev_net_name != unconnected_net_name_)
// Repeated port reference.
stringDelete(prev_net_name);
net_names[pin_index]=(net_name == nullptr) ? unconnected_net_name : net_name;
net_names[pin_index]=(net_name == nullptr) ? unconnected_net_name_ : net_name;
delete vpin;
net_port_ref_scalar_net_count_--;
}
@ -841,7 +837,7 @@ VerilogModule::VerilogModule(const char *name,
VerilogNetSeq *ports,
VerilogStmtSeq *stmts,
VerilogAttributeStmtSeq *attribute_stmts,
const char *filename,
string &filename,
int line,
VerilogReader *reader) :
VerilogStmt(line),
@ -908,7 +904,7 @@ VerilogModule::parseDcl(VerilogDcl *dcl,
dcl_map_[net_name] = dcl;
else if (!dcl->direction()->isInternal()) {
string net_vname = reader->netVerilogName(net_name);
reader->warn(1395, filename_, dcl->line(),
reader->warn(1395, filename_.c_str(), dcl->line(),
"signal %s previously declared on line %d.",
net_vname.c_str(),
existing_dcl->line());
@ -937,7 +933,7 @@ VerilogModule::checkInstanceName(VerilogInst *inst,
replacement_name = stringPrint("%s_%d", inst_name, i++);
} while (inst_names.findKey(replacement_name));
string inst_vname = reader->instanceVerilogName(inst_name);
reader->warn(1396, filename_, inst->line(),
reader->warn(1396, filename_.c_str(), inst->line(),
"instance name %s duplicated - renamed to %s.",
inst_vname.c_str(),
replacement_name);
@ -1035,8 +1031,7 @@ VerilogLibertyInst::~VerilogLibertyInst()
int port_count = cell_->portBitCount();
for (int i = 0; i < port_count; i++) {
const char *net_name = net_names_[i];
if (net_name
&& net_name != unconnected_net_name)
if (net_name != VerilogReader::unconnected_net_name_)
stringDelete(net_name);
}
delete [] net_names_;
@ -1937,7 +1932,7 @@ VerilogReader::makeModuleInstNetwork(VerilogModuleInst *mod_inst,
cell = network_->cell(lib_cell);
Instance *inst = network_->makeInstance(cell, mod_inst->instanceName(),
parent);
VerilogAttributeStmtSeq *attribute_stmts = mod_inst->attribute_stmts();
VerilogAttributeStmtSeq *attribute_stmts = mod_inst->attributeStmts();
for (VerilogAttributeStmt *stmt : *attribute_stmts) {
for (VerilogAttributeEntry *entry : *stmt->attribute_sequence()) {
network_->setAttribute(inst, entry->key(), entry->value());
@ -2129,7 +2124,7 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
Cell *cell = reinterpret_cast<Cell*>(lib_cell);
Instance *inst = network_->makeInstance(cell, lib_inst->instanceName(),
parent);
VerilogAttributeStmtSeq *attribute_stmts = lib_inst->attribute_stmts();
VerilogAttributeStmtSeq *attribute_stmts = lib_inst->attributeStmts();
for (VerilogAttributeStmt *stmt : *attribute_stmts) {
for (VerilogAttributeEntry *entry : *stmt->attribute_sequence()) {
network_->setAttribute(inst, entry->key(), entry->value());
@ -2144,7 +2139,7 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
if (net_name) {
Net *net = nullptr;
// If the pin is unconnected (ie, .A()) make the pin but not the net.
if (net_name != unconnected_net_name) {
if (net_name != unconnected_net_name_) {
VerilogDcl *dcl = parent_module->declaration(net_name);
// Check for single bit bus reference .A(BUS) -> .A(BUS[LSB]).
if (dcl && dcl->isBus()) {

View File

@ -33,6 +33,7 @@ VerilogParse_error(const char *msg);
namespace sta {
using std::string;
using std::vector;
using std::set;
class Debug;
@ -158,7 +159,7 @@ public:
bool make_black_boxes,
Report *report);
int line() const { return line_; }
const char *filename() const { return filename_; }
const char *filename() const { return filename_.c_str(); }
void incrLine();
Report *report() const { return report_; }
void error(int id,
@ -181,6 +182,7 @@ public:
instanceVerilogName(const char *inst_name);
string
netVerilogName(const char *net_name);
static const char *unconnected_net_name_;
protected:
void init(const char *filename);
@ -279,7 +281,8 @@ protected:
Debug *debug_;
NetworkReader *network_;
const char *filename_;
string filename_;
vector<string> filenames_;
int line_;
gzFile stream_;
@ -340,13 +343,13 @@ public:
VerilogNetSeq *ports,
VerilogStmtSeq *stmts,
VerilogAttributeStmtSeq *attribute_stmts,
const char *filename,
string &filename,
int line,
VerilogReader *reader);
virtual ~VerilogModule();
const char *name() { return name_; }
const char *filename() { return filename_; }
VerilogAttributeStmtSeq *attribute_stmts() { return attribute_stmts_; }
const char *filename() { return filename_.c_str(); }
VerilogAttributeStmtSeq *attributeStmts() { return attribute_stmts_; }
VerilogNetSeq *ports() { return ports_; }
VerilogDcl *declaration(const char *net_name);
VerilogStmtSeq *stmts() { return stmts_; }
@ -361,7 +364,7 @@ private:
VerilogReader *reader);
const char *name_;
const char *filename_;
string &filename_;
VerilogNetSeq *ports_;
VerilogStmtSeq *stmts_;
VerilogDclMap dcl_map_;
@ -461,7 +464,7 @@ public:
virtual ~VerilogInst();
virtual bool isInstance() const { return true; }
const char *instanceName() const { return inst_name_; }
VerilogAttributeStmtSeq *attribute_stmts() const { return attribute_stmts_; }
VerilogAttributeStmtSeq *attributeStmts() const { return attribute_stmts_; }
void setInstanceName(const char *inst_name);
private: