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:
James Cherry 2024-09-16 17:04:31 -07:00
parent d2ffbffe2e
commit bae1afcb11
15 changed files with 285 additions and 157 deletions

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
} }

View File

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

View File

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