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,
|
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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -420,15 +420,10 @@ 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" \
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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" *)
|
(* 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)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue