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:
parent
560eba7dae
commit
44e7316da1
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1286,6 +1286,10 @@ using namespace sta;
|
|||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
|
||||
%typemap(in) PathEndSeq* {
|
||||
$1 = tclListSeqPtr<PathEnd*>($input, SWIGTYPE_p_PathEnd, interp);
|
||||
}
|
||||
|
||||
%typemap(out) PathEndSeq* {
|
||||
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
|
||||
const PathEndSeq *path_ends = $1;
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ record_sta_tests {
|
|||
get_objrefs
|
||||
get_lib_pins_of_objects
|
||||
report_checks_src_attr
|
||||
report_json1
|
||||
report_json2
|
||||
liberty_latch3
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{"checks": [
|
||||
]
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue