report_checks -format json
commit d4337917f790d90d7e16d068a19d9d9f8f44b760
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Sep 16 16:42:19 2024 -0700
report json
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit a2707db7210437e4afc7b6af2c0b1e5cbdc0fa2a
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Sep 16 15:45:08 2024 -0700
report json
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit f9d511250046a5d3c5105299e42cdc4d75ccdfef
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Sep 15 18:42:39 2024 -0700
report json
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 82d4d5002e9d134396d199e56d47ea3fdee08a16
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Sep 14 20:44:45 2024 -0700
report json
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
d2ffbffe2e
commit
bae1afcb11
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -40,7 +40,7 @@ public:
|
||||||
size_t size() const { return paths_.size(); }
|
size_t size() const { return paths_.size(); }
|
||||||
// path(0) is the startpoint.
|
// path(0) is the startpoint.
|
||||||
// path(size()-1) is the endpoint.
|
// path(size()-1) is the endpoint.
|
||||||
PathRef *path(size_t index);
|
const PathRef *path(size_t index) const;
|
||||||
TimingArc *prevArc(size_t index);
|
TimingArc *prevArc(size_t index);
|
||||||
// Returns the path start point.
|
// Returns the path start point.
|
||||||
// Register/Latch Q pin
|
// Register/Latch Q pin
|
||||||
|
|
|
||||||
|
|
@ -905,9 +905,9 @@ public:
|
||||||
// Previous path end is used to detect path group changes
|
// Previous path end is used to detect path group changes
|
||||||
// so headers are reported by group.
|
// so headers are reported by group.
|
||||||
void reportPathEnd(PathEnd *end,
|
void reportPathEnd(PathEnd *end,
|
||||||
PathEnd *prev_end);
|
PathEnd *prev_end,
|
||||||
|
bool last);
|
||||||
void reportPathEnd(PathEnd *end);
|
void reportPathEnd(PathEnd *end);
|
||||||
void reportPathEnds(PathEndSeq *ends);
|
|
||||||
ReportPath *reportPath() { return report_path_; }
|
ReportPath *reportPath() { return report_path_; }
|
||||||
void reportPath(Path *path);
|
void reportPath(Path *path);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,11 @@ void
|
||||||
stringPrint(string &str,
|
stringPrint(string &str,
|
||||||
const char *fmt,
|
const char *fmt,
|
||||||
...) __attribute__((format (printf, 2, 3)));
|
...) __attribute__((format (printf, 2, 3)));
|
||||||
|
// Formated append to std::string.
|
||||||
|
void
|
||||||
|
stringAppend(string &str,
|
||||||
|
const char *fmt,
|
||||||
|
...) __attribute__((format (printf, 2, 3)));
|
||||||
|
|
||||||
// Print to a temporary string.
|
// Print to a temporary string.
|
||||||
char *
|
char *
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,8 @@ PathExpanded::startIndex() const
|
||||||
return pathsIndex(start_index_);
|
return pathsIndex(start_index_);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathRef *
|
const PathRef *
|
||||||
PathExpanded::path(size_t index)
|
PathExpanded::path(size_t index) const
|
||||||
{
|
{
|
||||||
if (index < paths_.size())
|
if (index < paths_.size())
|
||||||
return &paths_[pathsIndex(index)];
|
return &paths_[pathsIndex(index)];
|
||||||
|
|
|
||||||
|
|
@ -1260,7 +1260,7 @@ getProperty(PathEnd *end,
|
||||||
PathExpanded expanded(end->path(), sta);
|
PathExpanded expanded(end->path(), sta);
|
||||||
PathRefSeq paths;
|
PathRefSeq paths;
|
||||||
for (auto i = expanded.startIndex(); i < expanded.size(); i++) {
|
for (auto i = expanded.startIndex(); i < expanded.size(); i++) {
|
||||||
PathRef *path = expanded.path(i);
|
const PathRef *path = expanded.path(i);
|
||||||
paths.push_back(*path);
|
paths.push_back(*path);
|
||||||
}
|
}
|
||||||
return PropertyValue(&paths);
|
return PropertyValue(&paths);
|
||||||
|
|
|
||||||
|
|
@ -269,58 +269,16 @@ ReportPath::setReportSigmas(bool report)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
|
||||||
ReportPath::reportPathEndHeader()
|
|
||||||
{
|
|
||||||
switch (format_) {
|
|
||||||
case ReportPathFormat::full:
|
|
||||||
case ReportPathFormat::full_clock:
|
|
||||||
case ReportPathFormat::full_clock_expanded:
|
|
||||||
case ReportPathFormat::shorter:
|
|
||||||
case ReportPathFormat::endpoint:
|
|
||||||
break;
|
|
||||||
case ReportPathFormat::summary:
|
|
||||||
reportSummaryHeader();
|
|
||||||
break;
|
|
||||||
case ReportPathFormat::slack_only:
|
|
||||||
reportSlackOnlyHeader();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
report_->critical(1470, "unsupported path type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ReportPath::reportPathEndFooter()
|
|
||||||
{
|
|
||||||
string header;
|
|
||||||
switch (format_) {
|
|
||||||
case ReportPathFormat::full:
|
|
||||||
case ReportPathFormat::full_clock:
|
|
||||||
case ReportPathFormat::full_clock_expanded:
|
|
||||||
case ReportPathFormat::shorter:
|
|
||||||
break;
|
|
||||||
case ReportPathFormat::endpoint:
|
|
||||||
case ReportPathFormat::summary:
|
|
||||||
case ReportPathFormat::slack_only:
|
|
||||||
reportBlankLine();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
report_->critical(1471, "unsupported path type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ReportPath::reportPathEnd(PathEnd *end)
|
ReportPath::reportPathEnd(PathEnd *end)
|
||||||
{
|
{
|
||||||
reportPathEnd(end, nullptr);
|
reportPathEnd(end, nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ReportPath::reportPathEnd(PathEnd *end,
|
ReportPath::reportPathEnd(PathEnd *end,
|
||||||
PathEnd *prev_end)
|
PathEnd *prev_end,
|
||||||
|
bool last)
|
||||||
{
|
{
|
||||||
switch (format_) {
|
switch (format_) {
|
||||||
case ReportPathFormat::full:
|
case ReportPathFormat::full:
|
||||||
|
|
@ -345,8 +303,8 @@ ReportPath::reportPathEnd(PathEnd *end,
|
||||||
case ReportPathFormat::slack_only:
|
case ReportPathFormat::slack_only:
|
||||||
reportSlackOnly(end);
|
reportSlackOnly(end);
|
||||||
break;
|
break;
|
||||||
default:
|
case ReportPathFormat::json:
|
||||||
report_->critical(1473, "unsupported path type");
|
reportJson(end, last);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -367,6 +325,49 @@ ReportPath::reportPathEnds(PathEndSeq *ends)
|
||||||
reportPathEndFooter();
|
reportPathEndFooter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportPathEndHeader()
|
||||||
|
{
|
||||||
|
switch (format_) {
|
||||||
|
case ReportPathFormat::full:
|
||||||
|
case ReportPathFormat::full_clock:
|
||||||
|
case ReportPathFormat::full_clock_expanded:
|
||||||
|
case ReportPathFormat::shorter:
|
||||||
|
case ReportPathFormat::endpoint:
|
||||||
|
break;
|
||||||
|
case ReportPathFormat::summary:
|
||||||
|
reportSummaryHeader();
|
||||||
|
break;
|
||||||
|
case ReportPathFormat::slack_only:
|
||||||
|
reportSlackOnlyHeader();
|
||||||
|
break;
|
||||||
|
case ReportPathFormat::json:
|
||||||
|
reportJsonHeader();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportPathEndFooter()
|
||||||
|
{
|
||||||
|
string header;
|
||||||
|
switch (format_) {
|
||||||
|
case ReportPathFormat::full:
|
||||||
|
case ReportPathFormat::full_clock:
|
||||||
|
case ReportPathFormat::full_clock_expanded:
|
||||||
|
case ReportPathFormat::shorter:
|
||||||
|
break;
|
||||||
|
case ReportPathFormat::endpoint:
|
||||||
|
case ReportPathFormat::summary:
|
||||||
|
case ReportPathFormat::slack_only:
|
||||||
|
reportBlankLine();
|
||||||
|
break;
|
||||||
|
case ReportPathFormat::json:
|
||||||
|
reportJsonFooter();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ReportPath::reportEndpointHeader(PathEnd *end,
|
ReportPath::reportEndpointHeader(PathEnd *end,
|
||||||
PathEnd *prev_end)
|
PathEnd *prev_end)
|
||||||
|
|
@ -1043,6 +1044,146 @@ ReportPath::pathEndpoint(PathEnd *end)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportJsonHeader()
|
||||||
|
{
|
||||||
|
report_->reportLine("{\"checks\": [");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportJsonFooter()
|
||||||
|
{
|
||||||
|
report_->reportLine("]");
|
||||||
|
report_->reportLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportJson(const PathEnd *end,
|
||||||
|
bool last)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
result += "{\n";
|
||||||
|
stringAppend(result, " \"type\": \"%s\",\n", end->typeName());
|
||||||
|
stringAppend(result, " \"path_group\": \"%s\",\n",
|
||||||
|
search_->pathGroup(end)->name());
|
||||||
|
stringAppend(result, " \"path_type\": \"%s\",\n",
|
||||||
|
end->minMax(this)->asString());
|
||||||
|
|
||||||
|
PathExpanded expanded(end->path(), this);
|
||||||
|
const Pin *startpoint = expanded.startPath()->vertex(this)->pin();
|
||||||
|
const Pin *endpoint = expanded.endPath()->vertex(this)->pin();
|
||||||
|
stringAppend(result, " \"startpoint\": \"%s\",\n",
|
||||||
|
network_->pathName(startpoint));
|
||||||
|
stringAppend(result, " \"endpoint\": \"%s\",\n",
|
||||||
|
network_->pathName(endpoint));
|
||||||
|
|
||||||
|
const ClockEdge *src_clk_edge = end->sourceClkEdge(this);
|
||||||
|
const PathVertex *tgt_clk_path = end->targetClkPath();
|
||||||
|
if (src_clk_edge) {
|
||||||
|
stringAppend(result, " \"source_clock\": \"%s\",\n",
|
||||||
|
src_clk_edge->clock()->name());
|
||||||
|
stringAppend(result, " \"source_clock_edge\": \"%s\",\n",
|
||||||
|
src_clk_edge->transition()->name());
|
||||||
|
}
|
||||||
|
reportJson(expanded, "source_path", 2, !end->isUnconstrained(), result);
|
||||||
|
|
||||||
|
const ClockEdge *tgt_clk_edge = end->targetClkEdge(this);
|
||||||
|
if (tgt_clk_edge) {
|
||||||
|
stringAppend(result, " \"target_clock\": \"%s\",\n",
|
||||||
|
tgt_clk_edge->clock()->name());
|
||||||
|
stringAppend(result, " \"target_clock_edge\": \"%s\",\n",
|
||||||
|
tgt_clk_edge->transition()->name());
|
||||||
|
}
|
||||||
|
if (tgt_clk_path)
|
||||||
|
reportJson(end->targetClkPath(), "target_clock_path", 2, true, result);
|
||||||
|
|
||||||
|
if (end->checkRole(this)) {
|
||||||
|
stringAppend(result, " \"data_arrival_time\": %.3e,\n",
|
||||||
|
end->dataArrivalTimeOffset(this));
|
||||||
|
|
||||||
|
const MultiCyclePath *mcp = end->multiCyclePath();
|
||||||
|
if (mcp)
|
||||||
|
stringAppend(result, " \"multi_cycle_path\": %d,\n",
|
||||||
|
mcp->pathMultiplier());
|
||||||
|
|
||||||
|
PathDelay *path_delay = end->pathDelay();
|
||||||
|
if (path_delay)
|
||||||
|
stringAppend(result, " \"path_delay\": %.3e,\n",
|
||||||
|
path_delay->delay());
|
||||||
|
|
||||||
|
stringAppend(result, " \"crpr\": %.3e,\n", end->checkCrpr(this));
|
||||||
|
stringAppend(result, " \"margin\": %.3e,\n", end->margin(this));
|
||||||
|
stringAppend(result, " \"required_time\": %.3e,\n",
|
||||||
|
end->requiredTimeOffset(this));
|
||||||
|
stringAppend(result, " \"slack\": %.3e\n", end->slack(this));
|
||||||
|
}
|
||||||
|
result += "}";
|
||||||
|
if (!last)
|
||||||
|
result += ",";
|
||||||
|
report_->reportLineString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportJson(const Path *path)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
result += "{\n";
|
||||||
|
reportJson(path, "path", 0, false, result);
|
||||||
|
result += "}\n";
|
||||||
|
report_->reportLineString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportJson(const Path *path,
|
||||||
|
const char *path_name,
|
||||||
|
int indent,
|
||||||
|
bool trailing_comma,
|
||||||
|
string &result)
|
||||||
|
{
|
||||||
|
PathExpanded expanded(path, this);
|
||||||
|
reportJson(expanded, path_name, indent, trailing_comma, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReportPath::reportJson(const PathExpanded &expanded,
|
||||||
|
const char *path_name,
|
||||||
|
int indent,
|
||||||
|
bool trailing_comma,
|
||||||
|
string &result)
|
||||||
|
{
|
||||||
|
stringAppend(result, "%*s\"%s\": [\n", indent, "", path_name);
|
||||||
|
for (size_t i = 0; i < expanded.size(); i++) {
|
||||||
|
const PathRef *path = expanded.path(i);
|
||||||
|
const Pin *pin = path->vertex(this)->pin();
|
||||||
|
stringAppend(result, "%*s {\n", indent, "");
|
||||||
|
stringAppend(result, "%*s \"pin\": \"%s\",\n",
|
||||||
|
indent, "",
|
||||||
|
network_->pathName(pin));
|
||||||
|
double x, y;
|
||||||
|
bool exists;
|
||||||
|
network_->location(pin, x, y, exists);
|
||||||
|
if (exists) {
|
||||||
|
stringAppend(result, "%*s \"x\": %.9f,\n", indent, "", x);
|
||||||
|
stringAppend(result, "%*s \"y\": %.9f,\n", indent, "", y);
|
||||||
|
}
|
||||||
|
|
||||||
|
stringAppend(result, "%*s \"arrival\": %.3e,\n",
|
||||||
|
indent, "",
|
||||||
|
delayAsFloat(path->arrival(this)));
|
||||||
|
stringAppend(result, "%*s \"slew\": %.3e\n",
|
||||||
|
indent, "",
|
||||||
|
delayAsFloat(path->slew(this)));
|
||||||
|
stringAppend(result, "%*s }%s\n",
|
||||||
|
indent, "",
|
||||||
|
(i < expanded.size() - 1) ? "," : "");
|
||||||
|
}
|
||||||
|
stringAppend(result, "%*s]%s\n",
|
||||||
|
indent, "",
|
||||||
|
trailing_comma ? "," : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
ReportPath::reportSlackOnlyHeader()
|
ReportPath::reportSlackOnlyHeader()
|
||||||
{
|
{
|
||||||
|
|
@ -2365,12 +2506,13 @@ ReportPath::reportPath(const Path *path)
|
||||||
reportPathFull(path);
|
reportPathFull(path);
|
||||||
break;
|
break;
|
||||||
case ReportPathFormat::json:
|
case ReportPathFormat::json:
|
||||||
reportPathJson(path);
|
reportJson(path);
|
||||||
break;
|
break;
|
||||||
|
case ReportPathFormat::shorter:
|
||||||
|
case ReportPathFormat::endpoint:
|
||||||
case ReportPathFormat::summary:
|
case ReportPathFormat::summary:
|
||||||
case ReportPathFormat::slack_only:
|
case ReportPathFormat::slack_only:
|
||||||
default:
|
report_->reportLine("Format not supported.");
|
||||||
report_->critical(1474, "unsupported path type");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2383,54 +2525,7 @@ ReportPath::reportPathFull(const Path *path)
|
||||||
reportSrcClkAndPath(path, expanded, 0.0, delay_zero, delay_zero, false);
|
reportSrcClkAndPath(path, expanded, 0.0, delay_zero, delay_zero, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
////////////////////////////////////////////////////////////////
|
||||||
ReportPath::reportPathJson(const Path *path)
|
|
||||||
{
|
|
||||||
report_->reportLine("{ \"path\": [");
|
|
||||||
PathExpanded expanded(path, this);
|
|
||||||
for (auto i = expanded.startIndex(); i < expanded.size(); i++) {
|
|
||||||
string line;
|
|
||||||
PathRef *path = expanded.path(i);
|
|
||||||
const Pin *pin = path->vertex(this)->pin();
|
|
||||||
report_->reportLine(" {");
|
|
||||||
line = " \"pin\": \"";
|
|
||||||
line += network_->pathName(pin);
|
|
||||||
line += "\",";
|
|
||||||
report_->reportLineString(line);
|
|
||||||
|
|
||||||
double x, y;
|
|
||||||
bool exists;
|
|
||||||
string tmp;
|
|
||||||
network_->location(pin, x, y, exists);
|
|
||||||
if (exists) {
|
|
||||||
line = " \"x\": ";
|
|
||||||
stringPrint(tmp, "%.9f", x);
|
|
||||||
line += tmp + ",\n";
|
|
||||||
line += " \"y\": ";
|
|
||||||
stringPrint(tmp, "%.9f", y);
|
|
||||||
line += tmp + ",";
|
|
||||||
report_->reportLineString(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
line = " \"arrival\": ";
|
|
||||||
stringPrint(tmp, "%.3e", delayAsFloat(path->arrival(this)));
|
|
||||||
line += tmp;
|
|
||||||
line += ",";
|
|
||||||
report_->reportLineString(line);
|
|
||||||
|
|
||||||
line = " \"slew\": ";
|
|
||||||
stringPrint(tmp, "%.3e", delayAsFloat(path->slew(this)));
|
|
||||||
line += tmp;
|
|
||||||
report_->reportLineString(line);
|
|
||||||
|
|
||||||
line = " }";
|
|
||||||
if (i < expanded.size() - 1)
|
|
||||||
line += ",";
|
|
||||||
report_->reportLineString(line);
|
|
||||||
}
|
|
||||||
report_->reportLine(" ]");
|
|
||||||
report_->reportLine("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ReportPath::reportPath1(const Path *path,
|
ReportPath::reportPath1(const Path *path,
|
||||||
|
|
@ -2517,7 +2612,7 @@ ReportPath::reportPath4(const Path *path,
|
||||||
Arrival prev_time(0.0);
|
Arrival prev_time(0.0);
|
||||||
if (skip_first_path) {
|
if (skip_first_path) {
|
||||||
path_first_index = 1;
|
path_first_index = 1;
|
||||||
PathRef *start = expanded.path(0);
|
const PathRef *start = expanded.path(0);
|
||||||
prev_time = start->arrival(this) + time_offset;
|
prev_time = start->arrival(this) + time_offset;
|
||||||
}
|
}
|
||||||
size_t path_last_index = expanded.size() - 1;
|
size_t path_last_index = expanded.size() - 1;
|
||||||
|
|
@ -2551,7 +2646,7 @@ ReportPath::reportPath5(const Path *path,
|
||||||
expanded.clkPath(clk_path);
|
expanded.clkPath(clk_path);
|
||||||
Vertex *clk_start = clk_path.vertex(this);
|
Vertex *clk_start = clk_path.vertex(this);
|
||||||
for (size_t i = path_first_index; i <= path_last_index; i++) {
|
for (size_t i = path_first_index; i <= path_last_index; i++) {
|
||||||
PathRef *path1 = expanded.path(i);
|
const PathRef *path1 = expanded.path(i);
|
||||||
TimingArc *prev_arc = expanded.prevArc(i);
|
TimingArc *prev_arc = expanded.prevArc(i);
|
||||||
Vertex *vertex = path1->vertex(this);
|
Vertex *vertex = path1->vertex(this);
|
||||||
Pin *pin = vertex->pin();
|
Pin *pin = vertex->pin();
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,8 @@ public:
|
||||||
// Previous path end is used to detect path group changes
|
// Previous path end is used to detect path group changes
|
||||||
// so headers are reported by group.
|
// so headers are reported by group.
|
||||||
void reportPathEnd(PathEnd *end,
|
void reportPathEnd(PathEnd *end,
|
||||||
PathEnd *prev_end);
|
PathEnd *prev_end,
|
||||||
|
bool last);
|
||||||
void reportPathEnds(PathEndSeq *ends);
|
void reportPathEnds(PathEndSeq *ends);
|
||||||
void reportPath(const Path *path);
|
void reportPath(const Path *path);
|
||||||
|
|
||||||
|
|
@ -81,6 +82,22 @@ public:
|
||||||
void reportFull(const PathEndGatedClock *end);
|
void reportFull(const PathEndGatedClock *end);
|
||||||
void reportFull(const PathEndDataCheck *end);
|
void reportFull(const PathEndDataCheck *end);
|
||||||
|
|
||||||
|
void reportJsonHeader();
|
||||||
|
void reportJsonFooter();
|
||||||
|
void reportJson(const PathEnd *end,
|
||||||
|
bool last);
|
||||||
|
void reportJson(const Path *path);
|
||||||
|
void reportJson(const Path *path,
|
||||||
|
const char *path_name,
|
||||||
|
int indent,
|
||||||
|
bool trailing_comma,
|
||||||
|
string &result);
|
||||||
|
void reportJson(const PathExpanded &expanded,
|
||||||
|
const char *path_name,
|
||||||
|
int indent,
|
||||||
|
bool trailing_comma,
|
||||||
|
string &result);
|
||||||
|
|
||||||
void reportEndHeader();
|
void reportEndHeader();
|
||||||
void reportEndLine(PathEnd *end);
|
void reportEndLine(PathEnd *end);
|
||||||
|
|
||||||
|
|
@ -264,7 +281,6 @@ protected:
|
||||||
void reportPath(const PathEnd *end,
|
void reportPath(const PathEnd *end,
|
||||||
PathExpanded &expanded);
|
PathExpanded &expanded);
|
||||||
void reportPathFull(const Path *path);
|
void reportPathFull(const Path *path);
|
||||||
void reportPathJson(const Path *path);
|
|
||||||
void reportPathHeader();
|
void reportPathHeader();
|
||||||
void reportPath1(const Path *path,
|
void reportPath1(const Path *path,
|
||||||
PathExpanded &expanded,
|
PathExpanded &expanded,
|
||||||
|
|
|
||||||
|
|
@ -480,9 +480,10 @@ report_path_end(PathEnd *end)
|
||||||
|
|
||||||
void
|
void
|
||||||
report_path_end2(PathEnd *end,
|
report_path_end2(PathEnd *end,
|
||||||
PathEnd *prev_end)
|
PathEnd *prev_end,
|
||||||
|
bool last)
|
||||||
{
|
{
|
||||||
Sta::sta()->reportPathEnd(end, prev_end);
|
Sta::sta()->reportPathEnd(end, prev_end, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -1069,9 +1069,12 @@ proc parse_path_group_arg { group_names } {
|
||||||
proc report_path_ends { path_ends } {
|
proc report_path_ends { path_ends } {
|
||||||
report_path_end_header
|
report_path_end_header
|
||||||
set prev_end "NULL"
|
set prev_end "NULL"
|
||||||
|
set end_count [llength $path_ends]
|
||||||
|
set i 0
|
||||||
foreach path_end $path_ends {
|
foreach path_end $path_ends {
|
||||||
report_path_end2 $path_end $prev_end
|
report_path_end2 $path_end $prev_end [expr $i == ($end_count - 1)]
|
||||||
set prev_end $path_end
|
set prev_end $path_end
|
||||||
|
incr i
|
||||||
}
|
}
|
||||||
report_path_end_footer
|
report_path_end_footer
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2518,12 +2518,6 @@ Sta::setReportPathSigmas(bool report_sigmas)
|
||||||
report_path_->setReportSigmas(report_sigmas);
|
report_path_->setReportSigmas(report_sigmas);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Sta::reportPathEnds(PathEndSeq *ends)
|
|
||||||
{
|
|
||||||
report_path_->reportPathEnds(ends);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Sta::reportPathEndHeader()
|
Sta::reportPathEndHeader()
|
||||||
{
|
{
|
||||||
|
|
@ -2544,9 +2538,10 @@ Sta::reportPathEnd(PathEnd *end)
|
||||||
|
|
||||||
void
|
void
|
||||||
Sta::reportPathEnd(PathEnd *end,
|
Sta::reportPathEnd(PathEnd *end,
|
||||||
PathEnd *prev_end)
|
PathEnd *prev_end,
|
||||||
|
bool last)
|
||||||
{
|
{
|
||||||
report_path_->reportPathEnd(end, prev_end);
|
report_path_->reportPathEnd(end, prev_end, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,10 @@ private:
|
||||||
float maxTime();
|
float maxTime();
|
||||||
float pathMaxTime();
|
float pathMaxTime();
|
||||||
void writeMeasureDelayStmt(Stage stage,
|
void writeMeasureDelayStmt(Stage stage,
|
||||||
Path *from_path,
|
const Path *from_path,
|
||||||
Path *to_path);
|
const Path *to_path);
|
||||||
void writeMeasureSlewStmt(Stage stage,
|
void writeMeasureSlewStmt(Stage stage,
|
||||||
Path *path);
|
const Path *path);
|
||||||
void writeInputWaveform();
|
void writeInputWaveform();
|
||||||
void writeClkWaveform();
|
void writeClkWaveform();
|
||||||
|
|
||||||
|
|
@ -110,9 +110,9 @@ private:
|
||||||
int stageGateInputPathIndex(Stage stage);
|
int stageGateInputPathIndex(Stage stage);
|
||||||
int stageDrvrPathIndex(Stage stage);
|
int stageDrvrPathIndex(Stage stage);
|
||||||
int stageLoadPathIndex(Stage stage);
|
int stageLoadPathIndex(Stage stage);
|
||||||
PathRef *stageGateInputPath(Stage stage);
|
const PathRef *stageGateInputPath(Stage stage);
|
||||||
PathRef *stageDrvrPath(Stage stage);
|
const PathRef *stageDrvrPath(Stage stage);
|
||||||
PathRef *stageLoadPath(Stage stage);
|
const PathRef *stageLoadPath(Stage stage);
|
||||||
TimingArc *stageGateArc(Stage stage);
|
TimingArc *stageGateArc(Stage stage);
|
||||||
TimingArc *stageWireArc(Stage stage);
|
TimingArc *stageWireArc(Stage stage);
|
||||||
Edge *stageGateEdge(Stage stage);
|
Edge *stageGateEdge(Stage stage);
|
||||||
|
|
@ -128,8 +128,8 @@ private:
|
||||||
LibertyCell *stageLibertyCell(Stage stage);
|
LibertyCell *stageLibertyCell(Stage stage);
|
||||||
Instance *stageInstance(Stage stage);
|
Instance *stageInstance(Stage stage);
|
||||||
|
|
||||||
float findSlew(Path *path);
|
float findSlew(const Path *path);
|
||||||
float findSlew(Path *path,
|
float findSlew(const Path *path,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
TimingArc *next_arc);
|
TimingArc *next_arc);
|
||||||
Path *path_;
|
Path *path_;
|
||||||
|
|
@ -240,7 +240,7 @@ float
|
||||||
WritePathSpice::maxTime()
|
WritePathSpice::maxTime()
|
||||||
{
|
{
|
||||||
Stage input_stage = stageFirst();
|
Stage input_stage = stageFirst();
|
||||||
PathRef *input_path = stageDrvrPath(input_stage);
|
const PathRef *input_path = stageDrvrPath(input_stage);
|
||||||
if (input_path->isClock(this)) {
|
if (input_path->isClock(this)) {
|
||||||
const Clock *clk = input_path->clock(this);
|
const Clock *clk = input_path->clock(this);
|
||||||
float period = clk->period();
|
float period = clk->period();
|
||||||
|
|
@ -258,7 +258,7 @@ WritePathSpice::pathMaxTime()
|
||||||
{
|
{
|
||||||
float max_time = 0.0;
|
float max_time = 0.0;
|
||||||
for (size_t i = 0; i < path_expanded_.size(); i++) {
|
for (size_t i = 0; i < path_expanded_.size(); i++) {
|
||||||
PathRef *path = path_expanded_.path(i);
|
const PathRef *path = path_expanded_.path(i);
|
||||||
const RiseFall *rf = path->transition(this);
|
const RiseFall *rf = path->transition(this);
|
||||||
Vertex *vertex = path->vertex(this);
|
Vertex *vertex = path->vertex(this);
|
||||||
float path_max_slew = railToRailSlew(findSlew(vertex,rf,nullptr), rf);
|
float path_max_slew = railToRailSlew(findSlew(vertex,rf,nullptr), rf);
|
||||||
|
|
@ -315,7 +315,7 @@ WritePathSpice::writeInputSource()
|
||||||
streamPrint(spice_stream_, "**************\n\n");
|
streamPrint(spice_stream_, "**************\n\n");
|
||||||
|
|
||||||
Stage input_stage = stageFirst();
|
Stage input_stage = stageFirst();
|
||||||
PathRef *input_path = stageDrvrPath(input_stage);
|
const PathRef *input_path = stageDrvrPath(input_stage);
|
||||||
if (input_path->isClock(this))
|
if (input_path->isClock(this))
|
||||||
writeClkWaveform();
|
writeClkWaveform();
|
||||||
else
|
else
|
||||||
|
|
@ -327,7 +327,7 @@ void
|
||||||
WritePathSpice::writeInputWaveform()
|
WritePathSpice::writeInputWaveform()
|
||||||
{
|
{
|
||||||
Stage input_stage = stageFirst();
|
Stage input_stage = stageFirst();
|
||||||
PathRef *input_path = stageDrvrPath(input_stage);
|
const PathRef *input_path = stageDrvrPath(input_stage);
|
||||||
const RiseFall *rf = input_path->transition(this);
|
const RiseFall *rf = input_path->transition(this);
|
||||||
TimingArc *next_arc = stageGateArc(input_stage + 1);
|
TimingArc *next_arc = stageGateArc(input_stage + 1);
|
||||||
float slew0 = findSlew(input_path, rf, next_arc);
|
float slew0 = findSlew(input_path, rf, next_arc);
|
||||||
|
|
@ -352,7 +352,7 @@ void
|
||||||
WritePathSpice::writeClkWaveform()
|
WritePathSpice::writeClkWaveform()
|
||||||
{
|
{
|
||||||
Stage input_stage = stageFirst();
|
Stage input_stage = stageFirst();
|
||||||
PathRef *input_path = stageDrvrPath(input_stage);
|
const PathRef *input_path = stageDrvrPath(input_stage);
|
||||||
TimingArc *next_arc = stageGateArc(input_stage + 1);
|
TimingArc *next_arc = stageGateArc(input_stage + 1);
|
||||||
const ClockEdge *clk_edge = input_path->clkEdge(this);
|
const ClockEdge *clk_edge = input_path->clkEdge(this);
|
||||||
|
|
||||||
|
|
@ -387,7 +387,7 @@ WritePathSpice::writeClkWaveform()
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
WritePathSpice::findSlew(Path *path)
|
WritePathSpice::findSlew(const Path *path)
|
||||||
{
|
{
|
||||||
Vertex *vertex = path->vertex(this);
|
Vertex *vertex = path->vertex(this);
|
||||||
const RiseFall *rf = path->transition(this);
|
const RiseFall *rf = path->transition(this);
|
||||||
|
|
@ -395,9 +395,9 @@ WritePathSpice::findSlew(Path *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
WritePathSpice::findSlew(Path *path,
|
WritePathSpice::findSlew(const Path *path,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
TimingArc *next_arc)
|
TimingArc *next_arc)
|
||||||
{
|
{
|
||||||
Vertex *vertex = path->vertex(this);
|
Vertex *vertex = path->vertex(this);
|
||||||
return findSlew(vertex, rf, next_arc);
|
return findSlew(vertex, rf, next_arc);
|
||||||
|
|
@ -413,9 +413,9 @@ WritePathSpice::writeMeasureStmts()
|
||||||
streamPrint(spice_stream_, "********************\n\n");
|
streamPrint(spice_stream_, "********************\n\n");
|
||||||
|
|
||||||
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
|
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
|
||||||
PathRef *gate_input_path = stageGateInputPath(stage);
|
const PathRef *gate_input_path = stageGateInputPath(stage);
|
||||||
PathRef *drvr_path = stageDrvrPath(stage);
|
const PathRef *drvr_path = stageDrvrPath(stage);
|
||||||
PathRef *load_path = stageLoadPath(stage);
|
const PathRef *load_path = stageLoadPath(stage);
|
||||||
if (gate_input_path) {
|
if (gate_input_path) {
|
||||||
// gate input -> gate output
|
// gate input -> gate output
|
||||||
writeMeasureSlewStmt(stage, gate_input_path);
|
writeMeasureSlewStmt(stage, gate_input_path);
|
||||||
|
|
@ -432,8 +432,8 @@ WritePathSpice::writeMeasureStmts()
|
||||||
|
|
||||||
void
|
void
|
||||||
WritePathSpice::writeMeasureDelayStmt(Stage stage,
|
WritePathSpice::writeMeasureDelayStmt(Stage stage,
|
||||||
Path *from_path,
|
const Path *from_path,
|
||||||
Path *to_path)
|
const Path *to_path)
|
||||||
{
|
{
|
||||||
writeMeasureDelayStmt(from_path->pin(this), from_path->transition(this),
|
writeMeasureDelayStmt(from_path->pin(this), from_path->transition(this),
|
||||||
to_path->pin(this), to_path->transition(this),
|
to_path->pin(this), to_path->transition(this),
|
||||||
|
|
@ -442,7 +442,7 @@ WritePathSpice::writeMeasureDelayStmt(Stage stage,
|
||||||
|
|
||||||
void
|
void
|
||||||
WritePathSpice::writeMeasureSlewStmt(Stage stage,
|
WritePathSpice::writeMeasureSlewStmt(Stage stage,
|
||||||
Path *path)
|
const Path *path)
|
||||||
{
|
{
|
||||||
const Pin *pin = path->pin(this);
|
const Pin *pin = path->pin(this);
|
||||||
const RiseFall *rf = path->transition(this);
|
const RiseFall *rf = path->transition(this);
|
||||||
|
|
@ -514,7 +514,7 @@ WritePathSpice::writeGateStage(Stage stage)
|
||||||
drvr_port->name());
|
drvr_port->name());
|
||||||
writeSubcktInst(inst);
|
writeSubcktInst(inst);
|
||||||
|
|
||||||
PathRef *drvr_path = stageDrvrPath(stage);
|
const PathRef *drvr_path = stageDrvrPath(stage);
|
||||||
const RiseFall *drvr_rf = drvr_path->transition(this);
|
const RiseFall *drvr_rf = drvr_path->transition(this);
|
||||||
Edge *gate_edge = stageGateEdge(stage);
|
Edge *gate_edge = stageGateEdge(stage);
|
||||||
|
|
||||||
|
|
@ -544,7 +544,7 @@ WritePathSpice::writeGateStage(Stage stage)
|
||||||
void
|
void
|
||||||
WritePathSpice::writeStageParasitics(Stage stage)
|
WritePathSpice::writeStageParasitics(Stage stage)
|
||||||
{
|
{
|
||||||
PathRef *drvr_path = stageDrvrPath(stage);
|
const PathRef *drvr_path = stageDrvrPath(stage);
|
||||||
DcalcAnalysisPt *dcalc_ap = drvr_path->dcalcAnalysisPt(this);
|
DcalcAnalysisPt *dcalc_ap = drvr_path->dcalcAnalysisPt(this);
|
||||||
ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||||
const Pin *drvr_pin = stageDrvrPin(stage);
|
const Pin *drvr_pin = stageDrvrPin(stage);
|
||||||
|
|
@ -637,21 +637,21 @@ WritePathSpice::stageLoadPathIndex(Stage stage)
|
||||||
return stage * 2 - 1;
|
return stage * 2 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathRef *
|
const PathRef *
|
||||||
WritePathSpice::stageGateInputPath(Stage stage)
|
WritePathSpice::stageGateInputPath(Stage stage)
|
||||||
{
|
{
|
||||||
int path_index = stageGateInputPathIndex(stage);
|
int path_index = stageGateInputPathIndex(stage);
|
||||||
return path_expanded_.path(path_index);
|
return path_expanded_.path(path_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathRef *
|
const PathRef *
|
||||||
WritePathSpice::stageDrvrPath(Stage stage)
|
WritePathSpice::stageDrvrPath(Stage stage)
|
||||||
{
|
{
|
||||||
int path_index = stageDrvrPathIndex(stage);
|
int path_index = stageDrvrPathIndex(stage);
|
||||||
return path_expanded_.path(path_index);
|
return path_expanded_.path(path_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathRef *
|
const PathRef *
|
||||||
WritePathSpice::stageLoadPath(Stage stage)
|
WritePathSpice::stageLoadPath(Stage stage)
|
||||||
{
|
{
|
||||||
int path_index = stageLoadPathIndex(stage);
|
int path_index = stageLoadPathIndex(stage);
|
||||||
|
|
@ -678,7 +678,7 @@ WritePathSpice::stageWireArc(Stage stage)
|
||||||
Edge *
|
Edge *
|
||||||
WritePathSpice::stageGateEdge(Stage stage)
|
WritePathSpice::stageGateEdge(Stage stage)
|
||||||
{
|
{
|
||||||
PathRef *path = stageDrvrPath(stage);
|
const PathRef *path = stageDrvrPath(stage);
|
||||||
TimingArc *arc = stageGateArc(stage);
|
TimingArc *arc = stageGateArc(stage);
|
||||||
return path->prevEdge(arc, this);
|
return path->prevEdge(arc, this);
|
||||||
}
|
}
|
||||||
|
|
@ -686,7 +686,7 @@ WritePathSpice::stageGateEdge(Stage stage)
|
||||||
Edge *
|
Edge *
|
||||||
WritePathSpice::stageWireEdge(Stage stage)
|
WritePathSpice::stageWireEdge(Stage stage)
|
||||||
{
|
{
|
||||||
PathRef *path = stageLoadPath(stage);
|
const PathRef *path = stageLoadPath(stage);
|
||||||
TimingArc *arc = stageWireArc(stage);
|
TimingArc *arc = stageWireArc(stage);
|
||||||
return path->prevEdge(arc, this);
|
return path->prevEdge(arc, this);
|
||||||
}
|
}
|
||||||
|
|
@ -694,7 +694,7 @@ WritePathSpice::stageWireEdge(Stage stage)
|
||||||
Pin *
|
Pin *
|
||||||
WritePathSpice::stageGateInputPin(Stage stage)
|
WritePathSpice::stageGateInputPin(Stage stage)
|
||||||
{
|
{
|
||||||
PathRef *path = stageGateInputPath(stage);
|
const PathRef *path = stageGateInputPath(stage);
|
||||||
return path->pin(this);
|
return path->pin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -708,7 +708,7 @@ WritePathSpice::stageGateInputPort(Stage stage)
|
||||||
Pin *
|
Pin *
|
||||||
WritePathSpice::stageDrvrPin(Stage stage)
|
WritePathSpice::stageDrvrPin(Stage stage)
|
||||||
{
|
{
|
||||||
PathRef *path = stageDrvrPath(stage);
|
const PathRef *path = stageDrvrPath(stage);
|
||||||
return path->pin(this);
|
return path->pin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -722,7 +722,7 @@ WritePathSpice::stageDrvrPort(Stage stage)
|
||||||
Pin *
|
Pin *
|
||||||
WritePathSpice::stageLoadPin(Stage stage)
|
WritePathSpice::stageLoadPin(Stage stage)
|
||||||
{
|
{
|
||||||
PathRef *path = stageLoadPath(stage);
|
const PathRef *path = stageLoadPath(stage);
|
||||||
return path->pin(this);
|
return path->pin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -341,21 +341,20 @@ proc sta_unknown { args } {
|
||||||
}
|
}
|
||||||
if { $ret != 0 } {
|
if { $ret != 0 } {
|
||||||
return -code $ret -errorcode $errorCode \
|
return -code $ret -errorcode $errorCode \
|
||||||
"error in unknown while checking if \"$name\" is a unique command abbreviation: $msg"
|
"Error in unknown while checking if \"$name\" is a unique command abbreviation: $msg."
|
||||||
}
|
}
|
||||||
if { [llength $cmds] == 1 } {
|
if { [llength $cmds] == 1 } {
|
||||||
return [uplevel 1 [lreplace $args 0 0 $cmds]]
|
return [uplevel 1 [lreplace $args 0 0 $cmds]]
|
||||||
}
|
}
|
||||||
if { [llength $cmds] > 1 } {
|
if { [llength $cmds] > 1 } {
|
||||||
if {[string equal $name ""]} {
|
if {[string equal $name ""]} {
|
||||||
return -code error "empty command name \"\""
|
return -code error "Empty command name \"\""
|
||||||
} else {
|
} else {
|
||||||
return -code error \
|
return -code error \
|
||||||
"ambiguous command name \"$name\": [lsort $cmds]"
|
"Ambiguous command name \"$name\": [lsort $cmds]."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return [uplevel 1 [::unknown {*}$args]]
|
||||||
::unknown {*}$args
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc is_bus_subscript { subscript } {
|
proc is_bus_subscript { subscript } {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,20 @@ stringPrint(string &str,
|
||||||
str = tmp;
|
str = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stringAppend(string &str,
|
||||||
|
const char *fmt,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
char *tmp;
|
||||||
|
size_t tmp_length;
|
||||||
|
stringPrintTmp(fmt, args, tmp, tmp_length);
|
||||||
|
va_end(args);
|
||||||
|
str += tmp;
|
||||||
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
stdstrPrint(const char *fmt,
|
stdstrPrint(const char *fmt,
|
||||||
...)
|
...)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue