Add {`instance`, `cell`, `verilog_src`, `pin`, `net`, `hier_pins`, `capacitance`} fields to `report_checks -format json` for paths (#135)

* Add {`inst`, `cell`, `src`, `nets`} to `report_checks -format json`

* Smallfix

* Improved nets

* Race condition fix

* Fixes

* Small whitespace fix

* Add no paths corner case stuff

* Adjustments to naming of fields

* Requested fixes

* Reintroduce escapeBackslashes, use stringCopy to prevent stack memory warning

* Fix escapeBackslashes to use preferred style

* No backslash escaping

* Make requested fixes
This commit is contained in:
Akash Levy 2025-01-13 19:28:04 -08:00 committed by GitHub
parent 560eba7dae
commit 44e7316da1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 207 additions and 52 deletions

View File

@ -911,6 +911,7 @@ public:
PathEnd *prev_end, PathEnd *prev_end,
bool last); 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

@ -55,6 +55,15 @@
namespace sta { namespace sta {
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 static PinSeq
hierPinsThruEdge(const Edge *edge, hierPinsThruEdge(const Edge *edge,
const Network *network, const Network *network,
@ -326,15 +335,15 @@ void
ReportPath::reportPathEnds(PathEndSeq *ends) ReportPath::reportPathEnds(PathEndSeq *ends)
{ {
reportPathEndHeader(); reportPathEndHeader();
if (ends) {
PathEndSeq::Iterator end_iter(ends); PathEndSeq::Iterator end_iter(ends);
PathEnd *prev_end = nullptr; PathEnd *prev_end = nullptr;
while (end_iter.hasNext()) { while (end_iter.hasNext()) {
PathEnd *end = end_iter.next(); PathEnd *end = end_iter.next();
reportEndpointHeader(end, prev_end); reportPathEnd(end, prev_end, !end_iter.hasNext());
end->reportFull(this);
reportBlankLine();
prev_end = end; prev_end = end;
} }
}
reportPathEndFooter(); reportPathEndFooter();
} }
@ -1086,9 +1095,9 @@ ReportPath::reportJson(const PathEnd *end,
const Pin *startpoint = expanded.startPath()->vertex(this)->pin(); const Pin *startpoint = expanded.startPath()->vertex(this)->pin();
const Pin *endpoint = expanded.endPath()->vertex(this)->pin(); const Pin *endpoint = expanded.endPath()->vertex(this)->pin();
stringAppend(result, " \"startpoint\": \"%s\",\n", stringAppend(result, " \"startpoint\": \"%s\",\n",
network_->pathName(startpoint)); sdc_network_->pathName(startpoint));
stringAppend(result, " \"endpoint\": \"%s\",\n", stringAppend(result, " \"endpoint\": \"%s\",\n",
network_->pathName(endpoint)); sdc_network_->pathName(endpoint));
const ClockEdge *src_clk_edge = end->sourceClkEdge(this); const ClockEdge *src_clk_edge = end->sourceClkEdge(this);
const PathVertex *tgt_clk_path = end->targetClkPath(); const PathVertex *tgt_clk_path = end->targetClkPath();
@ -1171,10 +1180,51 @@ ReportPath::reportJson(const PathExpanded &expanded,
for (size_t i = 0; i < expanded.size(); i++) { for (size_t i = 0; i < expanded.size(); i++) {
const PathRef *path = expanded.path(i); const PathRef *path = expanded.path(i);
const Pin *pin = path->vertex(this)->pin(); const Pin *pin = path->vertex(this)->pin();
const Net *net = network_->net(pin);
const Instance *inst = network_->instance(pin);
const RiseFall *rf = path->transition(this);
DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt();
bool is_driver = network_->isDriver(pin);
stringAppend(result, "%*s {\n", indent, ""); stringAppend(result, "%*s {\n", indent, "");
if (inst) {
stringAppend(result, "%*s \"instance\": \"%s\",\n",
indent, "",
sdc_network_->pathName(inst));
Cell *cell = network_->cell(inst);
if (cell)
stringAppend(result, "%*s \"cell\": \"%s\",\n",
indent, "",
sdc_network_->name(cell));
stringAppend(result, "%*s \"verilog_src\": \"%s\",\n",
indent, "",
sdc_network_->getAttribute(inst, "src").c_str());
}
stringAppend(result, "%*s \"pin\": \"%s\",\n", stringAppend(result, "%*s \"pin\": \"%s\",\n",
indent, "", indent, "",
network_->pathName(pin)); sdc_network_->pathName(pin));
if (net) {
stringAppend(result, "%*s \"net\": \"%s\",\n",
indent, "",
sdc_network_->pathName(net));
}
PinSeq pins_above;
hierPinsAbove(pin, network_, pins_above);
if (!pins_above.empty()) {
stringAppend(result, "%*s \"hier_pins\": [\n", indent, "");
for (const Pin *hpin : pins_above) {
stringAppend(result, "%*s \"%s\"%s\n",
indent, "",
sdc_network_->pathName(hpin),
(hpin != pins_above.back()) ? "," : "");
}
stringAppend(result, "%*s ],\n", indent, "");
}
double x, y; double x, y;
bool exists; bool exists;
network_->location(pin, x, y, exists); network_->location(pin, x, y, exists);
@ -1186,6 +1236,10 @@ ReportPath::reportJson(const PathExpanded &expanded,
stringAppend(result, "%*s \"arrival\": %.3e,\n", stringAppend(result, "%*s \"arrival\": %.3e,\n",
indent, "", indent, "",
delayAsFloat(path->arrival(this))); delayAsFloat(path->arrival(this)));
if (is_driver)
stringAppend(result, "%*s \"capacitance\": %.3e,\n",
indent, "",
graph_delay_calc_->loadCap(pin, rf, dcalc_ap));
stringAppend(result, "%*s \"slew\": %.3e\n", stringAppend(result, "%*s \"slew\": %.3e\n",
indent, "", indent, "",
delayAsFloat(path->slew(this))); delayAsFloat(path->slew(this)));
@ -3481,15 +3535,6 @@ ReportPath::latchDesc(const RiseFall *clk_rf) const
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
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 static PinSeq
hierPinsThruEdge(const Edge *edge, hierPinsThruEdge(const Edge *edge,
const Network *network, const Network *network,

View File

@ -38,6 +38,7 @@ class ReportPath : public StaState
public: public:
explicit ReportPath(StaState *sta); explicit ReportPath(StaState *sta);
virtual ~ReportPath(); virtual ~ReportPath();
ReportPathFormat pathFormat() const { return format_; }
void setPathFormat(ReportPathFormat format); void setPathFormat(ReportPathFormat format);
void setReportFieldOrder(StringSeq *field_names); void setReportFieldOrder(StringSeq *field_names);
void setReportFields(bool report_input_pin, void setReportFields(bool report_input_pin,

View File

@ -509,6 +509,18 @@ report_path_cmd(PathRef *path)
Sta::sta()->reportPath(path); Sta::sta()->reportPath(path);
} }
void
report_path_ends(PathEndSeq *ends)
{
Sta *sta = Sta::sta();
Report *report = sta->report();
ReportPathFormat path_format = sta->reportPath()->pathFormat();
if (path_format == ReportPathFormat::json || (ends && ends->size() > 0))
sta->reportPathEnds(ends);
else
report->reportLine("No paths found.");
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void

View File

@ -420,14 +420,9 @@ define_cmd_args "report_checks" \
proc_redirect report_checks { proc_redirect report_checks {
global sta_report_unconstrained_paths global sta_report_unconstrained_paths
parse_report_path_options "report_checks" args "full" 0 parse_report_path_options "report_checks" args "full" 0
set path_ends [find_timing_paths_cmd "report_checks" args] set path_ends [find_timing_paths_cmd "report_checks" args]
if { $path_ends == {} } {
report_line "No paths found."
} else {
report_path_ends $path_ends report_path_ends $path_ends
}
} }
################################################################ ################################################################
@ -1091,19 +1086,6 @@ proc parse_path_group_arg { group_names } {
return $names return $names
} }
proc report_path_ends { path_ends } {
report_path_end_header
set prev_end "NULL"
set end_count [llength $path_ends]
set i 0
foreach path_end $path_ends {
report_path_end2 $path_end $prev_end [expr $i == ($end_count - 1)]
set prev_end $path_end
incr i
}
report_path_end_footer
}
################################################################ ################################################################
define_cmd_args "report_clock_min_period" \ define_cmd_args "report_clock_min_period" \

View File

@ -2555,6 +2555,12 @@ Sta::reportPathEnd(PathEnd *end,
report_path_->reportPathEnd(end, prev_end, last); report_path_->reportPathEnd(end, prev_end, last);
} }
void
Sta::reportPathEnds(PathEndSeq *ends)
{
report_path_->reportPathEnds(ends);
}
void void
Sta::reportPath(Path *path) Sta::reportPath(Path *path)
{ {

View File

@ -1286,6 +1286,10 @@ using namespace sta;
Tcl_SetObjResult(interp, obj); Tcl_SetObjResult(interp, obj);
} }
%typemap(in) PathEndSeq* {
$1 = tclListSeqPtr<PathEnd*>($input, SWIGTYPE_p_PathEnd, interp);
}
%typemap(out) PathEndSeq* { %typemap(out) PathEndSeq* {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr); Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
const PathEndSeq *path_ends = $1; const PathEndSeq *path_ends = $1;

View File

@ -132,6 +132,8 @@ record_sta_tests {
get_objrefs get_objrefs
get_lib_pins_of_objects get_lib_pins_of_objects
report_checks_src_attr report_checks_src_attr
report_json1
report_json2
liberty_latch3 liberty_latch3
} }

View File

@ -1,5 +1,5 @@
Startpoint: in (input port clocked by clk) Startpoint: _1415_ (rising edge-triggered flip-flop clocked by clk)
Endpoint: _1415_ (rising edge-triggered flip-flop clocked by clk) Endpoint: _1416_[0] (rising edge-triggered flip-flop clocked by clk)
Path Group: clk Path Group: clk
Path Type: max Path Type: max
@ -7,22 +7,22 @@ Path Type: max
--------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------
0.00 0.00 0.00 clock clk (rise edge) 0.00 0.00 0.00 clock clk (rise edge)
0.00 0.00 clock network delay (ideal) 0.00 0.00 clock network delay (ideal)
0.00 0.00 v input external delay 0.00 0.00 0.00 ^ _1415_/CLK (sky130_fd_sc_hd__dfrtp_1) synthesis/tests/counter.v:22.3-28.6
0.00 0.00 0.00 0.00 v in (in) 0.00 0.04 0.33 0.33 v _1415_/Q (sky130_fd_sc_hd__dfrtp_1) synthesis/tests/counter.v:22.3-28.6
in (net) mid (net) synthesis/tests/counter.v:22.3-28.6
0.00 0.00 0.00 v _1415_/D (sky130_fd_sc_hd__dfrtp_1) synthesis/tests/counter.v:22.3-28.6 0.04 0.00 0.33 v _1416_[0]/D (sky130_fd_sc_hd__dfrtp_1) synthesis/tests/counter.v:22.3-28.6
0.00 data arrival time 0.33 data arrival time
0.00 10.00 10.00 clock clk (rise edge) 0.00 10.00 10.00 clock clk (rise edge)
0.00 10.00 clock network delay (ideal) 0.00 10.00 clock network delay (ideal)
0.00 10.00 clock reconvergence pessimism 0.00 10.00 clock reconvergence pessimism
10.00 ^ _1415_/CLK (sky130_fd_sc_hd__dfrtp_1) 10.00 ^ _1416_[0]/CLK (sky130_fd_sc_hd__dfrtp_1)
-0.10 9.90 library setup time -0.12 9.88 library setup time
9.90 data required time 9.88 data required time
--------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------
9.90 data required time 9.88 data required time
-0.00 data arrival time -0.33 data arrival time
--------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------
9.90 slack (MET) 9.55 slack (MET)

78
test/report_json1.ok Normal file
View File

@ -0,0 +1,78 @@
{"checks": [
{
"type": "check",
"path_group": "clk",
"path_type": "max",
"startpoint": "_1415_/Q",
"endpoint": "_1416_[0]/D",
"source_clock": "clk",
"source_clock_edge": "rise",
"source_path": [
{
"instance": "",
"cell": "counter",
"verilog_src": "",
"pin": "clk",
"arrival": 0.000e+00,
"capacitance": 3.742e-15,
"slew": 0.000e+00
},
{
"instance": "_1415_",
"cell": "sky130_fd_sc_hd__dfrtp_1",
"verilog_src": "synthesis/tests/counter.v:22.3-28.6",
"pin": "_1415_/CLK",
"net": "clk",
"arrival": 0.000e+00,
"slew": 0.000e+00
},
{
"instance": "_1415_",
"cell": "sky130_fd_sc_hd__dfrtp_1",
"verilog_src": "synthesis/tests/counter.v:22.3-28.6",
"pin": "_1415_/Q",
"net": "mid",
"arrival": 3.296e-10,
"capacitance": 1.949e-15,
"slew": 3.612e-11
},
{
"instance": "_1416_[0]",
"cell": "sky130_fd_sc_hd__dfrtp_1",
"verilog_src": "synthesis/tests/counter.v:22.3-28.6",
"pin": "_1416_[0]/D",
"net": "mid",
"arrival": 3.296e-10,
"slew": 3.612e-11
}
],
"target_clock": "clk",
"target_clock_edge": "rise",
"target_clock_path": [
{
"instance": "",
"cell": "counter",
"verilog_src": "",
"pin": "clk",
"arrival": 0.000e+00,
"capacitance": 3.742e-15,
"slew": 0.000e+00
},
{
"instance": "_1416_[0]",
"cell": "sky130_fd_sc_hd__dfrtp_1",
"verilog_src": "synthesis/tests/counter.v:22.3-28.6",
"pin": "_1416_[0]/CLK",
"net": "clk",
"arrival": 0.000e+00,
"slew": 0.000e+00
}
],
"data_arrival_time": 3.296e-10,
"crpr": 0.000e+00,
"margin": 1.207e-10,
"required_time": 9.879e-09,
"slack": 9.550e-09
}
]
}

7
test/report_json1.tcl Normal file
View File

@ -0,0 +1,7 @@
# report_checks -format json
read_liberty ../examples/sky130hd_tt.lib.gz
read_verilog verilog_attribute.v
link_design counter
create_clock -name clk -period 10 clk
set_input_delay -clock clk 0 [all_inputs -no_clocks]
report_checks -path_group clk -format json >> results/report_json1.log

3
test/report_json2.ok Normal file
View File

@ -0,0 +1,3 @@
{"checks": [
]
}

6
test/report_json2.tcl Normal file
View File

@ -0,0 +1,6 @@
# report_checks -format json with no paths
read_liberty ../examples/sky130hd_tt.lib.gz
read_verilog verilog_attribute.v
link_design counter
create_clock -name clk -period 10
report_checks -path_group clk -format json >> results/report_json2.log

View File

@ -11,11 +11,19 @@ module counter(clk, reset, in, out);
(* src = "synthesis/tests/counter.v:18.14-18.19" *) (* src = "synthesis/tests/counter.v:18.14-18.19" *)
input reset; input reset;
input in; input in;
wire mid;
(* bottom_bound = 1'sh0 *) (* bottom_bound = 1'sh0 *)
(* src = "synthesis/tests/counter.v:22.3-28.6", attr1 = "test_attr1", attr2 = "test_attr2" *) (* src = "synthesis/tests/counter.v:22.3-28.6", attr1 = "test_attr1", attr2 = "test_attr2" *)
sky130_fd_sc_hd__dfrtp_1 _1415_ ( sky130_fd_sc_hd__dfrtp_1 _1415_ (
.CLK(clk), .CLK(clk),
.D(in), .D(in),
.Q(mid),
.RESET_B(reset)
);
(* src = "synthesis/tests/counter.v:22.3-28.6" *)
sky130_fd_sc_hd__dfrtp_1 \_1416_[0] (
.CLK(clk),
.D(mid),
.Q(out), .Q(out),
.RESET_B(reset) .RESET_B(reset)
); );