From 44e7316da19fe839ee9bb9d99b1b9346bae63387 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Mon, 13 Jan 2025 19:28:04 -0800 Subject: [PATCH] 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 --- include/sta/Sta.hh | 1 + search/ReportPath.cc | 85 ++++++++++++++++++++++++++-------- search/ReportPath.hh | 1 + search/Search.i | 12 +++++ search/Search.tcl | 20 +------- search/Sta.cc | 6 +++ tcl/StaTclTypes.i | 4 ++ test/regression_vars.tcl | 2 + test/report_checks_src_attr.ok | 26 +++++------ test/report_json1.ok | 78 +++++++++++++++++++++++++++++++ test/report_json1.tcl | 7 +++ test/report_json2.ok | 3 ++ test/report_json2.tcl | 6 +++ test/verilog_attribute.v | 8 ++++ 14 files changed, 207 insertions(+), 52 deletions(-) create mode 100644 test/report_json1.ok create mode 100644 test/report_json1.tcl create mode 100644 test/report_json2.ok create mode 100644 test/report_json2.tcl diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 9f0503bb..46c9306b 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -911,6 +911,7 @@ public: PathEnd *prev_end, bool last); void reportPathEnd(PathEnd *end); + void reportPathEnds(PathEndSeq *ends); ReportPath *reportPath() { return report_path_; } void reportPath(Path *path); diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 67f0ca33..6ddf90bc 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -55,6 +55,15 @@ 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 hierPinsThruEdge(const Edge *edge, const Network *network, @@ -326,14 +335,14 @@ void ReportPath::reportPathEnds(PathEndSeq *ends) { reportPathEndHeader(); - PathEndSeq::Iterator end_iter(ends); - PathEnd *prev_end = nullptr; - while (end_iter.hasNext()) { - PathEnd *end = end_iter.next(); - reportEndpointHeader(end, prev_end); - end->reportFull(this); - reportBlankLine(); - prev_end = end; + if (ends) { + PathEndSeq::Iterator end_iter(ends); + PathEnd *prev_end = nullptr; + while (end_iter.hasNext()) { + PathEnd *end = end_iter.next(); + reportPathEnd(end, prev_end, !end_iter.hasNext()); + prev_end = end; + } } reportPathEndFooter(); } @@ -1086,9 +1095,9 @@ ReportPath::reportJson(const PathEnd *end, const Pin *startpoint = expanded.startPath()->vertex(this)->pin(); const Pin *endpoint = expanded.endPath()->vertex(this)->pin(); stringAppend(result, " \"startpoint\": \"%s\",\n", - network_->pathName(startpoint)); + sdc_network_->pathName(startpoint)); stringAppend(result, " \"endpoint\": \"%s\",\n", - network_->pathName(endpoint)); + sdc_network_->pathName(endpoint)); const ClockEdge *src_clk_edge = end->sourceClkEdge(this); 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++) { const PathRef *path = expanded.path(i); 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, ""); + + 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", 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; bool exists; network_->location(pin, x, y, exists); @@ -1186,6 +1236,10 @@ ReportPath::reportJson(const PathExpanded &expanded, stringAppend(result, "%*s \"arrival\": %.3e,\n", indent, "", 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", indent, "", 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 hierPinsThruEdge(const Edge *edge, const Network *network, diff --git a/search/ReportPath.hh b/search/ReportPath.hh index 964a3e30..b709b780 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -38,6 +38,7 @@ class ReportPath : public StaState public: explicit ReportPath(StaState *sta); virtual ~ReportPath(); + ReportPathFormat pathFormat() const { return format_; } void setPathFormat(ReportPathFormat format); void setReportFieldOrder(StringSeq *field_names); void setReportFields(bool report_input_pin, diff --git a/search/Search.i b/search/Search.i index 5a231248..72c5ce52 100644 --- a/search/Search.i +++ b/search/Search.i @@ -509,6 +509,18 @@ report_path_cmd(PathRef *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 diff --git a/search/Search.tcl b/search/Search.tcl index fa1e5138..15fe5a61 100644 --- a/search/Search.tcl +++ b/search/Search.tcl @@ -420,14 +420,9 @@ define_cmd_args "report_checks" \ proc_redirect report_checks { global sta_report_unconstrained_paths - parse_report_path_options "report_checks" args "full" 0 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 } -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" \ diff --git a/search/Sta.cc b/search/Sta.cc index cd56d3bf..1cf5ea84 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2555,6 +2555,12 @@ Sta::reportPathEnd(PathEnd *end, report_path_->reportPathEnd(end, prev_end, last); } +void +Sta::reportPathEnds(PathEndSeq *ends) +{ + report_path_->reportPathEnds(ends); +} + void Sta::reportPath(Path *path) { diff --git a/tcl/StaTclTypes.i b/tcl/StaTclTypes.i index 2526b548..4745f20a 100644 --- a/tcl/StaTclTypes.i +++ b/tcl/StaTclTypes.i @@ -1286,6 +1286,10 @@ using namespace sta; Tcl_SetObjResult(interp, obj); } +%typemap(in) PathEndSeq* { + $1 = tclListSeqPtr($input, SWIGTYPE_p_PathEnd, interp); +} + %typemap(out) PathEndSeq* { Tcl_Obj *list = Tcl_NewListObj(0, nullptr); const PathEndSeq *path_ends = $1; diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index 354a2193..974f57b0 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -132,6 +132,8 @@ record_sta_tests { get_objrefs get_lib_pins_of_objects report_checks_src_attr + report_json1 + report_json2 liberty_latch3 } diff --git a/test/report_checks_src_attr.ok b/test/report_checks_src_attr.ok index f830cbe9..a9b3e609 100644 --- a/test/report_checks_src_attr.ok +++ b/test/report_checks_src_attr.ok @@ -1,5 +1,5 @@ -Startpoint: in (input port clocked by clk) -Endpoint: _1415_ (rising edge-triggered flip-flop clocked by clk) +Startpoint: _1415_ (rising edge-triggered flip-flop clocked by clk) +Endpoint: _1416_[0] (rising edge-triggered flip-flop clocked by clk) Path Group: clk Path Type: max @@ -7,22 +7,22 @@ Path Type: max --------------------------------------------------------------------------------------------------------------- 0.00 0.00 0.00 clock clk (rise edge) 0.00 0.00 clock network delay (ideal) - 0.00 0.00 v input external delay - 0.00 0.00 0.00 0.00 v in (in) - in (net) - 0.00 0.00 0.00 v _1415_/D (sky130_fd_sc_hd__dfrtp_1) synthesis/tests/counter.v:22.3-28.6 - 0.00 data arrival time + 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.04 0.33 0.33 v _1415_/Q (sky130_fd_sc_hd__dfrtp_1) synthesis/tests/counter.v:22.3-28.6 + mid (net) 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.33 data arrival time 0.00 10.00 10.00 clock clk (rise edge) 0.00 10.00 clock network delay (ideal) 0.00 10.00 clock reconvergence pessimism - 10.00 ^ _1415_/CLK (sky130_fd_sc_hd__dfrtp_1) - -0.10 9.90 library setup time - 9.90 data required time + 10.00 ^ _1416_[0]/CLK (sky130_fd_sc_hd__dfrtp_1) + -0.12 9.88 library setup time + 9.88 data required time --------------------------------------------------------------------------------------------------------------- - 9.90 data required time - -0.00 data arrival time + 9.88 data required time + -0.33 data arrival time --------------------------------------------------------------------------------------------------------------- - 9.90 slack (MET) + 9.55 slack (MET) diff --git a/test/report_json1.ok b/test/report_json1.ok new file mode 100644 index 00000000..f5a1e56e --- /dev/null +++ b/test/report_json1.ok @@ -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 +} +] +} diff --git a/test/report_json1.tcl b/test/report_json1.tcl new file mode 100644 index 00000000..742dc14f --- /dev/null +++ b/test/report_json1.tcl @@ -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 diff --git a/test/report_json2.ok b/test/report_json2.ok new file mode 100644 index 00000000..f400fde9 --- /dev/null +++ b/test/report_json2.ok @@ -0,0 +1,3 @@ +{"checks": [ +] +} diff --git a/test/report_json2.tcl b/test/report_json2.tcl new file mode 100644 index 00000000..0d898045 --- /dev/null +++ b/test/report_json2.tcl @@ -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 diff --git a/test/verilog_attribute.v b/test/verilog_attribute.v index f3735059..e1f1c8f2 100644 --- a/test/verilog_attribute.v +++ b/test/verilog_attribute.v @@ -11,11 +11,19 @@ module counter(clk, reset, in, out); (* src = "synthesis/tests/counter.v:18.14-18.19" *) input reset; input in; + wire mid; (* bottom_bound = 1'sh0 *) (* src = "synthesis/tests/counter.v:22.3-28.6", attr1 = "test_attr1", attr2 = "test_attr2" *) sky130_fd_sc_hd__dfrtp_1 _1415_ ( .CLK(clk), .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), .RESET_B(reset) );