Merge remote-tracking branch 'parallax/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
5a46b3ceb2
|
|
@ -30,3 +30,5 @@ doc/._Sta.docx
|
||||||
test/results
|
test/results
|
||||||
# ngspice turd
|
# ngspice turd
|
||||||
test/b3v3_1check.log
|
test/b3v3_1check.log
|
||||||
|
|
||||||
|
doc/messages.txt
|
||||||
|
|
|
||||||
|
|
@ -189,9 +189,10 @@ set(STA_SOURCE
|
||||||
search/PathEnumed.cc
|
search/PathEnumed.cc
|
||||||
search/PathExpanded.cc
|
search/PathExpanded.cc
|
||||||
search/PathGroup.cc
|
search/PathGroup.cc
|
||||||
|
search/PathPrev.cc
|
||||||
search/PathRef.cc
|
search/PathRef.cc
|
||||||
search/PathVertex.cc
|
search/PathVertex.cc
|
||||||
search/PathVertexRep.cc
|
search/PathVertexPtr.cc
|
||||||
search/Property.cc
|
search/Property.cc
|
||||||
search/ReportPath.cc
|
search/ReportPath.cc
|
||||||
search/Search.cc
|
search/Search.cc
|
||||||
|
|
@ -596,3 +597,10 @@ add_custom_target(sta_tags etags -o TAGS
|
||||||
${SWIG_TCL_FILES}
|
${SWIG_TCL_FILES}
|
||||||
WORKING_DIRECTORY ${STA_HOME}
|
WORKING_DIRECTORY ${STA_HOME}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET OpenSTA
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${CMAKE_SOURCE_DIR}/etc/FindMessages.tcl > ${CMAKE_SOURCE_DIR}/doc/messages.txt || true
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -214,11 +214,13 @@ Use Homebrew to install them.
|
||||||
|
|
||||||
Set these variables before using cmake to cirumvent the Xcode versions.
|
Set these variables before using cmake to cirumvent the Xcode versions.
|
||||||
|
|
||||||
|
```
|
||||||
# flex/bison override apple version
|
# flex/bison override apple version
|
||||||
export PATH="$(brew --prefix bison)/bin:${PATH}"
|
export PATH="$(brew --prefix bison)/bin:${PATH}"
|
||||||
export PATH="$(brew --prefix flex)/bin:${PATH}"
|
export PATH="$(brew --prefix flex)/bin:${PATH}"
|
||||||
export CMAKE_INCLUDE_PATH="$(brew --prefix flex)/include"
|
export CMAKE_INCLUDE_PATH="$(brew --prefix flex)/include"
|
||||||
export CMAKE_LIBRARY_PATH="$(brew --prefix flex)/lib;$(brew --prefix bison)/lib"
|
export CMAKE_LIBRARY_PATH="$(brew --prefix flex)/lib;$(brew --prefix bison)/lib"
|
||||||
|
```
|
||||||
|
|
||||||
Homebrew does not support tclreadline, but the macports system does
|
Homebrew does not support tclreadline, but the macports system does
|
||||||
(see https://www.macports.org).
|
(see https://www.macports.org).
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ proc set_delay_calculator { alg } {
|
||||||
if { [is_delay_calc_name $alg] } {
|
if { [is_delay_calc_name $alg] } {
|
||||||
set_delay_calculator_cmd $alg
|
set_delay_calculator_cmd $alg
|
||||||
} else {
|
} else {
|
||||||
sta_error 180 "delay calculator $alg not found."
|
sta_error 195 "delay calculator $alg not found."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,7 +156,7 @@ proc set_assigned_delay { args } {
|
||||||
if [info exists keys(-from)] {
|
if [info exists keys(-from)] {
|
||||||
set from_pins [get_port_pins_error "from_pins" $keys(-from)]
|
set from_pins [get_port_pins_error "from_pins" $keys(-from)]
|
||||||
} else {
|
} else {
|
||||||
sta_error 181 "set_assigned_delay missing -from argument."
|
sta_error 196 "set_assigned_delay missing -from argument."
|
||||||
}
|
}
|
||||||
if [info exists keys(-to)] {
|
if [info exists keys(-to)] {
|
||||||
set to_pins [get_port_pins_error "to_pins" $keys(-to)]
|
set to_pins [get_port_pins_error "to_pins" $keys(-to)]
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
581
doc/messages.txt
581
doc/messages.txt
|
|
@ -1,581 +0,0 @@
|
||||||
0100 CmdArgs.tcl:108 unsupported object type $object_type.
|
|
||||||
0101 CmdArgs.tcl:165 object '$obj' not found.
|
|
||||||
0102 CmdArgs.tcl:413 $corner_arg is not the name of process corner.
|
|
||||||
0103 CmdArgs.tcl:419 -corner keyword required with multi-corner analysis.
|
|
||||||
0104 CmdArgs.tcl:433 $corner_name is not the name of process corner.
|
|
||||||
0105 CmdArgs.tcl:438 missing -corner arg.
|
|
||||||
0106 CmdArgs.tcl:449 $corner_name is not the name of process corner.
|
|
||||||
0107 CmdArgs.tcl:466 $corner_name is not the name of process corner.
|
|
||||||
0108 CmdArgs.tcl:501 both -min and -max specified.
|
|
||||||
0109 CmdArgs.tcl:515 both -min and -max specified.
|
|
||||||
0110 CmdArgs.tcl:542 only one of -early and -late can be specified.
|
|
||||||
0111 CmdArgs.tcl:548 -early or -late must be specified.
|
|
||||||
0112 CmdArgs.tcl:555 both -early and -late specified.
|
|
||||||
0113 CmdArgs.tcl:570 $arg_name must be a single library.
|
|
||||||
0114 CmdArgs.tcl:576 $arg_name type '$object_type' is not a library.
|
|
||||||
0115 CmdArgs.tcl:581 library '$arg' not found.
|
|
||||||
0116 CmdArgs.tcl:598 $arg_name must be a single lib cell.
|
|
||||||
0123 CmdArgs.tcl:685 $arg_name must be a single instance.
|
|
||||||
0124 CmdArgs.tcl:691 $arg_name type '$object_type' is not an instance.
|
|
||||||
0125 CmdArgs.tcl:696 instance '$arg' not found.
|
|
||||||
0126 CmdArgs.tcl:715 $arg_name type '$object_type' is not an instance.
|
|
||||||
0127 CmdArgs.tcl:722 instance '$arg' not found.
|
|
||||||
0128 CmdArgs.tcl:742 $arg_name type '$object_type' is not a liberty cell.
|
|
||||||
0129 CmdArgs.tcl:749 liberty cell '$arg' not found.
|
|
||||||
0131 CmdArgs.tcl:810 $arg_name type '$object_type' is not a pin or port.
|
|
||||||
0132 CmdArgs.tcl:817 pin '$arg' not found.
|
|
||||||
0133 CmdArgs.tcl:837 $arg_name type '$object_type' is not a port.
|
|
||||||
0139 CmdArgs.tcl:918 unsupported object type $object_type.
|
|
||||||
0141 CmdArgs.tcl:939 $arg_name '$object_type' is not a net.
|
|
||||||
0142 CmdArgs.tcl:963 unsupported object type $object_type.
|
|
||||||
0143 CmdArgs.tcl:944 $arg_name '$arg' not found.
|
|
||||||
0144 CmdArgs.tcl:408 corner object type '$object_type' is not a corner.
|
|
||||||
0160 CmdUtil.tcl:44 no commands match '$pattern'.
|
|
||||||
0161 CmdUtil.tcl:89 Usage: $cmd $cmd_args($cmd)
|
|
||||||
0162 CmdUtil.tcl:91 Usage: $cmd argument error
|
|
||||||
0164 CmdUtil.tcl:220 unsupported object type $list_type.
|
|
||||||
0165 CmdUtil.tcl:237 unknown namespace $namespc.
|
|
||||||
0166 CmdUtil.tcl:170 unknown unit $unit prefix '${arg_prefix}'.
|
|
||||||
0167 CmdUtil.tcl:173 incorrect unit suffix '$arg_suffix'.
|
|
||||||
0180 DelayCalc.tcl:126 delay calculator $alg not found.
|
|
||||||
0181 DelayCalc.tcl:151 set_assigned_delay missing -from argument.
|
|
||||||
0182 DelayCalc.tcl:156 set_assigned_delay missing -to argument.
|
|
||||||
0183 DelayCalc.tcl:161 set_assigned_delay delay is not a float.
|
|
||||||
0184 DelayCalc.tcl:166 set_annotated_delay -cell and -net options are mutually excluive.
|
|
||||||
0185 DelayCalc.tcl:172 set_assigned_delay pin [get_full_name $pin] is not attached to instance [get_full_name $inst].
|
|
||||||
0186 DelayCalc.tcl:177 set_assigned_delay pin [get_full_name $pin] is not attached to instance [get_full_name $inst]
|
|
||||||
0187 DelayCalc.tcl:182 set_assigned_delay -cell or -net required.
|
|
||||||
0188 DelayCalc.tcl:247 set_assigned_check missing -from argument.
|
|
||||||
0189 DelayCalc.tcl:256 set_assigned_check -clock must be rise or fall.
|
|
||||||
0190 DelayCalc.tcl:263 set_assigned_check missing -to argument.
|
|
||||||
0191 DelayCalc.tcl:278 set_assigned_check missing -setup|-hold|-recovery|-removal check type..
|
|
||||||
0192 DelayCalc.tcl:286 set_assigned_check check_value is not a float.
|
|
||||||
0193 DelayCalc.tcl:226 set_assigned_delay no timing arcs found between from/to pins.
|
|
||||||
0194 DelayCalc.tcl:338 set_assigned_check no check arcs found between from/to pins.
|
|
||||||
0204 ArnoldiDelayCalc.cc:607 arnoldi delay calc failed.
|
|
||||||
0210 DelayCalc.tcl:359 set_assigned_transition transition is not a float.
|
|
||||||
0220 Link.tcl:36 missing top_cell_name argument and no current_design.
|
|
||||||
0225 InternalPower.cc:192 unsupported table order
|
|
||||||
0226 InternalPower.cc:207 unsupported table axes
|
|
||||||
0230 Network.tcl:41 instance $instance_path not found.
|
|
||||||
0231 Network.tcl:217 net $net_path not found.
|
|
||||||
0232 Network.tcl:220 net $net_path not found.
|
|
||||||
0233 Network.tcl:30 report_instance -connections is deprecated.
|
|
||||||
0234 Network.tcl:34 report_instance -verbose is deprecated.
|
|
||||||
0235 Network.tcl:189 report_net -connections is deprecated.
|
|
||||||
0236 Network.tcl:193 report_net -verbose is deprecated.
|
|
||||||
0237 Network.tcl:197 report_net -hier_pins is deprecated.
|
|
||||||
0239 TableModel.cc:265 unsupported table order
|
|
||||||
0240 TableModel.cc:328 unsupported table axes
|
|
||||||
0241 TableModel.cc:545 unsupported table order
|
|
||||||
0242 TableModel.cc:563 unsupported table axes
|
|
||||||
0243 TimingArc.cc:242 timing arc max index exceeded
|
|
||||||
|
|
||||||
0244 Clock.cc:474 generated clock edges size is not three.
|
|
||||||
0245 CheckTiming.cc:428 unknown print flag
|
|
||||||
0246 Corner.cc:377 unknown parasitic analysis point count
|
|
||||||
0247 Corner.cc:421 unknown analysis point count
|
|
||||||
0249 GatedClk.cc:247 illegal gated clock active value
|
|
||||||
0250 NetworkEdit.tcl:107 unsupported object type $object_type.
|
|
||||||
0252 NetworkEdit.tcl:174 unsupported object type $object_type.
|
|
||||||
0253 NetworkEdit.tcl:192 unsupported object type $object_type.
|
|
||||||
0266 VertexVisitor.cc:32 VertexPinCollector::copy not supported.
|
|
||||||
0267 WriteSpice.cc:1217 out of memory
|
|
||||||
0268 VerilogWriter.cc:258 unknown port direction
|
|
||||||
0272 Parasitics.tcl:41 read_spef -quiet is deprecated.
|
|
||||||
0273 Parasitics.tcl:45 read_spef -reduce_to is deprecated. Use -reduce instead.
|
|
||||||
0274 Parasitics.tcl:50 read_spef -delete_after_reduce is deprecated.
|
|
||||||
0275 Parasitics.tcl:54 read_spef -save is deprecated.
|
|
||||||
0276 Parasitics.tcl:62 path instance '$path' not found.
|
|
||||||
0280 PathEnum.cc:574 diversion path not found
|
|
||||||
0301 Power.tcl:234 activity should be 0.0 to 1.0 or 2.0
|
|
||||||
0302 Power.tcl:242 duty should be 0.0 to 1.0
|
|
||||||
0303 Power.tcl:257 activity cannot be set on clock ports.
|
|
||||||
0304 Power.tcl:40 No liberty libraries have been read.
|
|
||||||
0305 Power.tcl:286 read_power_activities is deprecated. Use read_vcd.
|
|
||||||
0320 Property.tcl:32 $cmd object is null.
|
|
||||||
0321 Property.tcl:37 $cmd $type_key must be specified with object name argument.
|
|
||||||
0322 Property.tcl:77 get_property unsupported object type $object_type.
|
|
||||||
0323 Property.tcl:80 get_property $object is not an object.
|
|
||||||
0324 Property.tcl:107 $object_type not supported.
|
|
||||||
0325 Property.tcl:110 $object_type '$object_name' not found.
|
|
||||||
0326 Sdc.tcl:494 object '$pattern' is not an instance.
|
|
||||||
0327 Sdc.tcl:542 object '$pattern' is not an clock.
|
|
||||||
0328 Sdc.tcl:606 object '$pattern' is not a liberty cell.
|
|
||||||
0329 Sdc.tcl:689 object '$pattern' is not a liberty pin.
|
|
||||||
0330 Sdc.tcl:769 object '$pattern' is not a liberty library.
|
|
||||||
0331 Sdc.tcl:868 object '$pattern' is not a net.
|
|
||||||
0332 Sdc.tcl:948 object '$pattern' is not a pin.
|
|
||||||
0333 Sdc.tcl:1005 object '$pattern' is not a port.
|
|
||||||
0334 Sdc.tcl:2860 object '$cell_name' is not a liberty cell.
|
|
||||||
0335 Sdc.tcl:679 positional arguments not supported with -of_objects.
|
|
||||||
0340 Sdc.tcl:73 cannot open '$filename'.
|
|
||||||
0341 Sdc.tcl:128 incomplete command at end of file.
|
|
||||||
0342 Sdc.tcl:212 hierarchy separator must be one of '$sdc_dividers'.
|
|
||||||
0343 Sdc.tcl:256 unknown unit $unit prefix '${arg_prefix}'.
|
|
||||||
0344 Sdc.tcl:275 unknown $unit prefix '$prefix'.
|
|
||||||
0345 Sdc.tcl:281 $unit scale [format %.0e $scale] does not match library scale [format %.0e $unit_scale].
|
|
||||||
0346 Sdc.tcl:358 only one of -cells, -data_pins, -clock_pins, -async_pins, -output_pins are suppported.
|
|
||||||
0347 Sdc.tcl:401 current_design for other than top cell not supported.
|
|
||||||
0348 Sdc.tcl:468 patterns argument not supported with -of_objects.
|
|
||||||
0349 Sdc.tcl:507 instance '$pattern' not found.
|
|
||||||
0350 Sdc.tcl:429 unsupported $object_type -filter expression.
|
|
||||||
0351 Sdc.tcl:551 clock '$pattern' not found.
|
|
||||||
0352 Sdc.tcl:581 positional arguments not supported with -of_objects.
|
|
||||||
0353 Sdc.tcl:618 library '$lib_name' not found.
|
|
||||||
0354 Sdc.tcl:630 cell '$cell_pattern' not found.
|
|
||||||
0355 Sdc.tcl:702 library/cell/port '$pattern' not found.
|
|
||||||
0356 Sdc.tcl:722 port '$port_pattern' not found.
|
|
||||||
0357 Sdc.tcl:727 library '$lib_name' not found.
|
|
||||||
0358 Sdc.tcl:742 -nocase ignored without -regexp.
|
|
||||||
0359 Sdc.tcl:778 library '$pattern' not found.
|
|
||||||
0360 Sdc.tcl:849 patterns argument not supported with -of_objects.
|
|
||||||
0361 Sdc.tcl:879 net '$pattern' not found.
|
|
||||||
0362 Sdc.tcl:912 patterns argument not supported with -of_objects.
|
|
||||||
0363 Sdc.tcl:959 pin '$pattern' not found.
|
|
||||||
0365 Sdc.tcl:994 patterns argument not supported with -of_objects.
|
|
||||||
0366 Sdc.tcl:1014 port '$pattern' not found.
|
|
||||||
0368 Sdc.tcl:1054 -add requires -name.
|
|
||||||
0369 Sdc.tcl:1059 -name or port_pin_list must be specified.
|
|
||||||
0370 Sdc.tcl:1067 missing -period argument.
|
|
||||||
0371 Sdc.tcl:1073 -waveform edge_list must have an even number of edge times.
|
|
||||||
0372 Sdc.tcl:1082 non-increasing clock -waveform edge times.
|
|
||||||
0373 Sdc.tcl:1085 -waveform time greater than two periods.
|
|
||||||
0374 Sdc.tcl:1143 empty ports/pins/nets argument.
|
|
||||||
0375 Sdc.tcl:1151 -add requires -name.
|
|
||||||
0376 Sdc.tcl:1156 name or port_pin_list must be specified.
|
|
||||||
0377 Sdc.tcl:1163 missing -source argument.
|
|
||||||
0378 Sdc.tcl:1178 -master_clock argument empty.
|
|
||||||
0379 Sdc.tcl:1181 -add requireds -master_clock.
|
|
||||||
0380 Sdc.tcl:1185 -multiply_by and -divide_by options are exclusive.
|
|
||||||
0381 Sdc.tcl:1189 -divide_by is not an integer greater than one.
|
|
||||||
0382 Sdc.tcl:1192 -combinational implies -divide_by 1.
|
|
||||||
0383 Sdc.tcl:1197 -multiply_by is not an integer greater than one.
|
|
||||||
0384 Sdc.tcl:1203 -duty_cycle is not a float between 0 and 100.
|
|
||||||
0385 Sdc.tcl:1209 -edges only supported for three edges.
|
|
||||||
0386 Sdc.tcl:1215 edges times are not monotonically increasing.
|
|
||||||
0387 Sdc.tcl:1224 -edge_shift length does not match -edges length.
|
|
||||||
0388 Sdc.tcl:1230 missing -multiply_by, -divide_by, -combinational or -edges argument.
|
|
||||||
0389 Sdc.tcl:1238 cannot specify -invert without -multiply_by, -divide_by or -combinational.
|
|
||||||
0390 Sdc.tcl:1244 -duty_cycle requires -multiply_by value.
|
|
||||||
0391 Sdc.tcl:1304 group_path command failed.
|
|
||||||
0392 Sdc.tcl:1311 positional arguments not supported.
|
|
||||||
0393 Sdc.tcl:1315 -from, -through or -to required.
|
|
||||||
0394 Sdc.tcl:1321 -name and -default are mutually exclusive.
|
|
||||||
0395 Sdc.tcl:1323 -name or -default option is required.
|
|
||||||
0396 Sdc.tcl:1364 cannot specify both -high and -low.
|
|
||||||
0397 Sdc.tcl:1372 missing -setup or -hold argument.
|
|
||||||
0398 Sdc.tcl:1386 -high and -low only permitted for pins and instances.
|
|
||||||
0399 Sdc.tcl:1393 -high and -low only permitted for pins and instances.
|
|
||||||
0400 Sdc.tcl:1436 one of -logically_exclusive, -physically_exclusive or -asynchronous is required.
|
|
||||||
0401 Sdc.tcl:1439 the keywords -logically_exclusive, -physically_exclusive and -asynchronous are mutually exclusive.
|
|
||||||
0402 Sdc.tcl:1458 unknown keyword argument $arg.
|
|
||||||
0403 Sdc.tcl:1460 extra positional argument $arg.
|
|
||||||
0404 Sdc.tcl:1489 the -all and -name options are mutually exclusive.
|
|
||||||
0405 Sdc.tcl:1492 either -all or -name options must be specified.
|
|
||||||
0406 Sdc.tcl:1500 one of -logically_exclusive, -physically_exclusive or -asynchronous is required.
|
|
||||||
0407 Sdc.tcl:1503 the keywords -logically_exclusive, -physically_exclusive and -asynchronous are mutually exclusive.
|
|
||||||
0408 Sdc.tcl:1553 -clock ignored for clock objects.
|
|
||||||
0409 Sdc.tcl:1567 -source '[get_full_name $pin]' is not a clock pin.
|
|
||||||
0410 Sdc.tcl:1574 -early/-late is only allowed with -source.
|
|
||||||
0411 Sdc.tcl:1603 -clock ignored for clock objects.
|
|
||||||
0412 Sdc.tcl:1615 -source '[$pin path_name]' is not a clock pin.
|
|
||||||
0413 Sdc.tcl:1643 set_sense -type data not supported.
|
|
||||||
0414 Sdc.tcl:1647 set_sense -type clock|data
|
|
||||||
0415 Sdc.tcl:1658 set_clock_sense is deprecated as of SDC 2.1. Use set_sense -type clock.
|
|
||||||
0416 Sdc.tcl:1670 -pulse argument not supported.
|
|
||||||
0417 Sdc.tcl:1679 -positive, -negative, -stop_propagation and -pulse are mutually exclusive.
|
|
||||||
0418 Sdc.tcl:1692 hierarchical pin '[get_full_name $pin]' not supported.
|
|
||||||
0419 Sdc.tcl:1716 transition time can not be specified for virtual clocks.
|
|
||||||
0420 Sdc.tcl:1749 missing uncertainty value.
|
|
||||||
0421 Sdc.tcl:1797 -from/-to must be used together.
|
|
||||||
0422 Sdc.tcl:1817 -rise, -fall options not allowed for single clock uncertainty.
|
|
||||||
0423 Sdc.tcl:1883 -from/-to must be used together.
|
|
||||||
0424 Sdc.tcl:1903 -rise, -fall options not allowed for single clock uncertainty.
|
|
||||||
0425 Sdc.tcl:1944 missing -from, -rise_from or -fall_from argument.
|
|
||||||
0426 Sdc.tcl:1956 missing -to, -rise_to or -fall_to argument.
|
|
||||||
0427 Sdc.tcl:2004 missing -from, -rise_from or -fall_from argument.
|
|
||||||
0428 Sdc.tcl:2016 missing -to, -rise_to or -fall_to argument.
|
|
||||||
0429 Sdc.tcl:2058 -from/-to keywords ignored for lib_pin, port and pin arguments.
|
|
||||||
0430 Sdc.tcl:2088 -from/-to hierarchical instance not supported.
|
|
||||||
0431 Sdc.tcl:2120 pin '[get_full_name $inst]${hierarchy_separator}${port_name}' not found.
|
|
||||||
0432 Sdc.tcl:2177 pin '[get_name $cell]${hierarchy_separator}${port_name}' not found.
|
|
||||||
0434 Sdc.tcl:2211 -from/-to keywords ignored for lib_pin, port and pin arguments.
|
|
||||||
0435 Sdc.tcl:2263 -from/-to hierarchical instance not supported.
|
|
||||||
0436 Sdc.tcl:2317 '$args' ignored.
|
|
||||||
0437 Sdc.tcl:2321 -from, -through or -to required.
|
|
||||||
0438 Sdc.tcl:2400 -source_latency_included ignored with -reference_pin.
|
|
||||||
0439 Sdc.tcl:2403 -network_latency_included ignored with -reference_pin.
|
|
||||||
0440 Sdc.tcl:2422 $cmd not allowed on [pin_direction $pin] port '[get_full_name $pin]'.
|
|
||||||
0441 Sdc.tcl:2424 $cmd relative to a clock defined on the same port/pin not allowed.
|
|
||||||
0442 Sdc.tcl:2472 missing delay argument.
|
|
||||||
0443 Sdc.tcl:2478 '$args' ignored.
|
|
||||||
0444 Sdc.tcl:2603 missing path multiplier argument.
|
|
||||||
0445 Sdc.tcl:2608 '$args' ignored.
|
|
||||||
0446 Sdc.tcl:2615 cannot use -start with -end.
|
|
||||||
0447 Sdc.tcl:2665 $cmd command failed.
|
|
||||||
0448 Sdc.tcl:2672 positional arguments not supported.
|
|
||||||
0449 Sdc.tcl:2676 -from, -through or -to required.
|
|
||||||
0450 Sdc.tcl:2743 virtual clock [get_name $clk] can not be propagated.
|
|
||||||
0451 Sdc.tcl:2785 value must be 0, zero, 1, one, rise, rising, fall, or falling.
|
|
||||||
0452 Sdc.tcl:2854 cell '$lib_name:$cell_name' not found.
|
|
||||||
0453 Sdc.tcl:2867 '$cell_name' not found.
|
|
||||||
0454 Sdc.tcl:2871 missing -lib_cell argument.
|
|
||||||
0455 Sdc.tcl:2879 port '$to_port_name' not found.
|
|
||||||
0456 Sdc.tcl:2891 -pin argument required for cells with multiple outputs.
|
|
||||||
0457 Sdc.tcl:2906 port '$from_port_name' not found.
|
|
||||||
0458 Sdc.tcl:2924 -multiply_by ignored.
|
|
||||||
0459 Sdc.tcl:2927 -dont_scale ignored.
|
|
||||||
0460 Sdc.tcl:2930 -no_design_rule ignored.
|
|
||||||
0461 Sdc.tcl:2953 set_fanout_load not supported.
|
|
||||||
0462 Sdc.tcl:2977 -clock not supported.
|
|
||||||
0463 Sdc.tcl:2980 -clock_fall not supported.
|
|
||||||
0464 Sdc.tcl:3030 -pin_load not allowed for net objects.
|
|
||||||
0465 Sdc.tcl:3033 -wire_load not allowed for net objects.
|
|
||||||
0466 Sdc.tcl:3036 -rise/-fall not allowed for net objects.
|
|
||||||
0467 Sdc.tcl:3123 port '[get_name $port]' is not an input.
|
|
||||||
0468 Sdc.tcl:3169 -data_path, -clock_path, -rise, -fall ignored for ports and designs.
|
|
||||||
0469 Sdc.tcl:3240 derating factor greater than 2.0.
|
|
||||||
0470 Sdc.tcl:3277 -cell_delay and -cell_check flags ignored for net objects.
|
|
||||||
0471 Sdc.tcl:3347 no valid objects specified for $key.
|
|
||||||
0472 Sdc.tcl:3380 no valid objects specified for $key
|
|
||||||
0473 Sdc.tcl:3429 no valid objects specified for $key.
|
|
||||||
0474 Sdc.tcl:3497 operating condition '$op_cond_name' not found.
|
|
||||||
0475 Sdc.tcl:3515 operating condition '$op_cond_name' not found.
|
|
||||||
0476 Sdc.tcl:3529 -analysis_type must be single, bc_wc or on_chip_variation.
|
|
||||||
0477 Sdc.tcl:3541 set_wire_load_min_block_size not supported.
|
|
||||||
0478 Sdc.tcl:3554 mode must be top, enclosed or segmented.
|
|
||||||
0479 Sdc.tcl:3569 no wire load model specified.
|
|
||||||
0480 Sdc.tcl:3591 wire load model '$model_name' not found.
|
|
||||||
0481 Sdc.tcl:3630 wire load selection group '$selection_name' not found.
|
|
||||||
0482 Sdc.tcl:3718 define_corners must be called before read_liberty.
|
|
||||||
0500 Sdc.tcl:3791 no default operating conditions found.
|
|
||||||
0501 Sdc.tcl:259 incorrect unit suffix '$arg_suffix'.
|
|
||||||
0502 Search.tcl:165 $cmd -endpoint_count is deprecated. Use -endpoint_path_count instead.
|
|
||||||
0503 Search.tcl:178 $cmd -group_count is deprecated. Use -group_path_count instead.
|
|
||||||
0510 Search.tcl:137 $cmd -path_delay must be min, min_rise, min_fall, max, max_rise, max_fall or min_max.
|
|
||||||
0511 Search.tcl:147 $cmd command failed.
|
|
||||||
0512 Search.tcl:172 -endpoint_path_count must be a positive integer.
|
|
||||||
0513 Search.tcl:186 -group_path_count must be >= 1.
|
|
||||||
0514 Search.tcl:216 '$arg' is not a known keyword or flag.
|
|
||||||
0515 Search.tcl:218 positional arguments not supported.
|
|
||||||
0516 Search.tcl:339 report_clock_skew -setup and -hold are mutually exclusive options.
|
|
||||||
0520 Search.tcl:543 analysis type single is not consistent with doing both setup/max and hold/min checks.
|
|
||||||
0521 Search.tcl:548 positional arguments not supported.
|
|
||||||
0522 Search.tcl:802 -min and -max cannot both be specified.
|
|
||||||
0523 Search.tcl:822 pin '$pin_arg' is hierarchical.
|
|
||||||
0524 Search.tcl:878 -format $format not recognized.
|
|
||||||
0526 Search.tcl:1026 specify one of -setup and -hold.
|
|
||||||
0527 Search.tcl:1076 unknown path group '$name'.
|
|
||||||
0540 Sta.tcl:158 -from/-to arguments not supported with -of_objects.
|
|
||||||
0560 Util.tcl:44 $cmd $key missing value.
|
|
||||||
0561 Util.tcl:61 $cmd $key missing value.
|
|
||||||
0562 Util.tcl:71 $cmd $arg is not a known keyword or flag.
|
|
||||||
0563 Util.tcl:93 $cmd $arg is not a known keyword or flag.
|
|
||||||
0564 Util.tcl:241 $cmd positional arguments not supported.
|
|
||||||
0565 Util.tcl:247 $cmd requires one positional argument.
|
|
||||||
0566 Util.tcl:254 $cmd requires zero or one positional arguments.
|
|
||||||
0567 Util.tcl:260 $cmd requires two positional arguments.
|
|
||||||
0568 Util.tcl:267 $cmd requires one or two positional arguments.
|
|
||||||
0569 Util.tcl:273 $cmd requires three positional arguments.
|
|
||||||
0570 Util.tcl:279 $cmd requires four positional arguments.
|
|
||||||
0571 Util.tcl:287 $cmd_arg '$arg' is not a float.
|
|
||||||
0572 Util.tcl:293 $cmd_arg '$arg' is not a positive float.
|
|
||||||
0573 Util.tcl:299 $cmd_arg '$arg' is not an integer.
|
|
||||||
0574 Util.tcl:305 $cmd_arg '$arg' is not a positive integer.
|
|
||||||
0575 Util.tcl:311 $cmd_arg '$arg' is not an integer greater than or equal to one.
|
|
||||||
0576 Util.tcl:317 $cmd_arg '$arg' is not between 0 and 100.
|
|
||||||
0577 Sdc.tcl:3721 define_corners must define at least one corner.
|
|
||||||
0590 Variables.tcl:37 sta_report_default_digits must be a positive integer.
|
|
||||||
0591 Variables.tcl:62 sta_crpr_mode must be pin or transition.
|
|
||||||
0592 Variables.tcl:179 $var_name value must be 0 or 1.
|
|
||||||
0616 Levelize.cc:220 maximum logic level exceeded
|
|
||||||
0620 Sdf.tcl:41 -cond_use must be min, max or min_max.
|
|
||||||
0621 Sdf.tcl:46 -cond_use min_max cannot be used with analysis type single.
|
|
||||||
0623 Sdf.tcl:154 SDF -divider must be / or .
|
|
||||||
0800 VcdReader.cc:112 unhandled vcd command.
|
|
||||||
0801 VcdReader.cc:151 timescale syntax error.
|
|
||||||
0802 VcdReader.cc:165 Unknown timescale unit.
|
|
||||||
0804 VcdReader.cc:222 Variable syntax error.
|
|
||||||
1000 ConcreteNetwork.cc:1973 cell type %s can not be linked.
|
|
||||||
1010 CycleAccting.cc:87 No common period was found between clocks %s and %s.
|
|
||||||
1040 DmpCeff.cc:1510 parasitic Pi model has NaNs.
|
|
||||||
1041 DmpCeff.cc:1536 cell %s delay model not supported on SPF parasitics by DMP delay calculator
|
|
||||||
1060 Genclks.cc:275 no master clock found for generated clock %s.
|
|
||||||
1062 Genclks.cc:939 generated clock %s source pin %s missing paths from master clock %s.
|
|
||||||
1100 Power.cc:559 unknown cudd constant
|
|
||||||
1110 Liberty.cc:763 cell %s/%s port %s not found in cell %s/%s.
|
|
||||||
1111 Liberty.cc:789 cell %s/%s %s -> %s timing group %s not found in cell %s/%s.
|
|
||||||
1112 Liberty.cc:808 Liberty cell %s/%s for corner %s/%s not found.
|
|
||||||
1113 Liberty.cc:1824 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check.
|
|
||||||
1114 Liberty.cc:1765 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.
|
|
||||||
1115 Liberty.cc:1773 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.
|
|
||||||
1116 Liberty.cc:362 unsupported slew degradation table axes
|
|
||||||
1117 Liberty.cc:378 unsupported slew degradation table axes
|
|
||||||
1118 Liberty.cc:383 unsupported slew degradation table order
|
|
||||||
1119 Liberty.cc:413 unsupported slew degradation table axes
|
|
||||||
1120 Liberty.cc:1979 library missing vdd
|
|
||||||
1121 Liberty.cc:1391 timing arc count mismatch
|
|
||||||
1125 LibertyParser.cc:310 valueIterator called for LibertySimpleAttribute
|
|
||||||
1126 LibertyParser.cc:390 LibertyStringAttrValue called for float value
|
|
||||||
1127 LibertyParser.cc:420 LibertyStringAttrValue called for float value
|
|
||||||
1130 LibertyExpr.cc:82 %s references unknown port %s.
|
|
||||||
1131 LibertyExpr.cc:175 %s %s.
|
|
||||||
1140 LibertyReader.cc:632 library %s already exists.
|
|
||||||
1141 LibertyReader.cc:665 library missing name.
|
|
||||||
1142 LibertyReader.cc:691 default_wire_load %s not found.
|
|
||||||
1143 LibertyReader.cc:702 default_wire_selection %s not found.
|
|
||||||
1144 LibertyReader.cc:714 default_operating_condition %s not found.
|
|
||||||
1145 LibertyReader.cc:724 input_threshold_pct_%s not found.
|
|
||||||
1146 LibertyReader.cc:728 output_threshold_pct_%s not found.
|
|
||||||
1147 LibertyReader.cc:732 slew_lower_threshold_pct_%s not found.
|
|
||||||
1148 LibertyReader.cc:736 slew_upper_threshold_pct_%s not found.
|
|
||||||
1149 LibertyReader.cc:741 Library %s is missing one or more thresholds.
|
|
||||||
1150 LibertyReader.cc:820 unknown unit multiplier %s.
|
|
||||||
1151 LibertyReader.cc:843 unknown unit scale %c.
|
|
||||||
1152 LibertyReader.cc:846 unknown unit suffix %s.
|
|
||||||
1153 LibertyReader.cc:849 unknown unit suffix %s.
|
|
||||||
1154 LibertyReader.cc:874 capacitive_load_units are not ff or pf.
|
|
||||||
1155 LibertyReader.cc:877 capacitive_load_units are not a string.
|
|
||||||
1156 LibertyReader.cc:880 capacitive_load_units missing suffix.
|
|
||||||
1157 LibertyReader.cc:883 capacitive_load_units scale is not a float.
|
|
||||||
1158 LibertyReader.cc:886 capacitive_load_units missing scale and suffix.
|
|
||||||
1159 LibertyReader.cc:889 capacitive_load_unit missing values suffix.
|
|
||||||
1160 LibertyReader.cc:907 delay_model %s not supported.
|
|
||||||
1161 LibertyReader.cc:911 delay_model %s not supported.
|
|
||||||
1162 LibertyReader.cc:915 delay_model %s not supported.
|
|
||||||
1163 LibertyReader.cc:920 delay_model %s not supported..
|
|
||||||
1164 LibertyReader.cc:923 unknown delay_model %s.
|
|
||||||
1165 LibertyReader.cc:942 unknown bus_naming_style format.
|
|
||||||
1166 LibertyReader.cc:963 voltage_map voltage is not a float.
|
|
||||||
1167 LibertyReader.cc:966 voltage_map missing voltage.
|
|
||||||
1168 LibertyReader.cc:969 voltage_map supply name is not a string.
|
|
||||||
1169 LibertyReader.cc:972 voltage_map missing supply name and voltage.
|
|
||||||
1170 LibertyReader.cc:975 voltage_map missing values suffix.
|
|
||||||
1171 LibertyReader.cc:1060 default_max_transition is 0.0.
|
|
||||||
1172 LibertyReader.cc:1075 default_max_fanout is 0.0.
|
|
||||||
1173 LibertyReader.cc:1165 default_fanout_load is 0.0.
|
|
||||||
1174 LibertyReader.cc:1193 default_wire_load_mode %s not found.
|
|
||||||
1175 LibertyReader.cc:1379 table template missing name.
|
|
||||||
1176 LibertyReader.cc:1424 missing variable_%d attribute.
|
|
||||||
1177 LibertyReader.cc:1500 missing table index values.
|
|
||||||
1178 LibertyReader.cc:1506 non-increasing table index values.
|
|
||||||
1179 LibertyReader.cc:1538 bus type %s missing bit_from.
|
|
||||||
1180 LibertyReader.cc:1540 bus type %s missing bit_to.
|
|
||||||
1181 LibertyReader.cc:1544 type missing name.
|
|
||||||
1182 LibertyReader.cc:1571 scaling_factors do not have a name.
|
|
||||||
1183 LibertyReader.cc:1740 operating_conditions missing name.
|
|
||||||
1184 LibertyReader.cc:1811 wire_load missing name.
|
|
||||||
1185 LibertyReader.cc:1854 fanout_length is missing length and fanout.
|
|
||||||
1186 LibertyReader.cc:1869 wire_load_selection missing name.
|
|
||||||
1187 LibertyReader.cc:1900 wireload %s not found.
|
|
||||||
1189 LibertyReader.cc:1907 wire_load_from_area min not a float.
|
|
||||||
1190 LibertyReader.cc:1910 wire_load_from_area max not a float.
|
|
||||||
1191 LibertyReader.cc:1913 wire_load_from_area missing parameters.
|
|
||||||
1192 LibertyReader.cc:1916 wire_load_from_area missing parameters.
|
|
||||||
1193 LibertyReader.cc:1935 cell missing name.
|
|
||||||
1194 LibertyReader.cc:1959 cell %s ocv_derate_group %s not found.
|
|
||||||
1195 LibertyReader.cc:1992 port %s function size does not match port size.
|
|
||||||
1196 LibertyReader.cc:2089 %s %s bus width mismatch.
|
|
||||||
1197 LibertyReader.cc:2100 %s %s bus width mismatch.
|
|
||||||
1198 LibertyReader.cc:2110 clear
|
|
||||||
1199 LibertyReader.cc:2120 preset
|
|
||||||
1200 LibertyReader.cc:2156 latch enable function is non-unate for port %s.
|
|
||||||
1201 LibertyReader.cc:2161 latch enable function is unknown for port %s.
|
|
||||||
1202 LibertyReader.cc:2263 operating conditions %s not found.
|
|
||||||
1203 LibertyReader.cc:2266 scaled_cell missing operating condition.
|
|
||||||
1204 LibertyReader.cc:2269 scaled_cell cell %s has not been defined.
|
|
||||||
1205 LibertyReader.cc:2272 scaled_cell missing name.
|
|
||||||
1206 LibertyReader.cc:2298 scaled_cell %s, %s port functions do not match cell port functions.
|
|
||||||
1207 LibertyReader.cc:2303 scaled_cell ports do not match cell ports.
|
|
||||||
1208 LibertyReader.cc:2305 scaled_cell %s, %s timing does not match cell timing.
|
|
||||||
1209 LibertyReader.cc:2324 combinational timing to an input port.
|
|
||||||
1210 LibertyReader.cc:2419 missing %s_transition.
|
|
||||||
1211 LibertyReader.cc:2421 missing cell_%s.
|
|
||||||
1212 LibertyReader.cc:2442 timing group from output port.
|
|
||||||
1213 LibertyReader.cc:2452 timing group from output port.
|
|
||||||
1214 LibertyReader.cc:2462 timing group from output port.
|
|
||||||
1215 LibertyReader.cc:2497 timing group from output port.
|
|
||||||
1217 LibertyReader.cc:2507 timing group from output port.
|
|
||||||
1218 LibertyReader.cc:2608 receiver_capacitance group not in timing or pin group.
|
|
||||||
1219 LibertyReader.cc:2626 unsupported model axis.
|
|
||||||
1220 LibertyReader.cc:2654 output_current_%s group not in timing group.
|
|
||||||
1221 LibertyReader.cc:2696 output current waveform %.2e %.2e not found.
|
|
||||||
1222 LibertyReader.cc:2717 unsupported model axis.
|
|
||||||
1223 LibertyReader.cc:2759 vector index_1 and index_2 must have exactly one value.
|
|
||||||
1224 LibertyReader.cc:2761 vector reference_time not found.
|
|
||||||
1225 LibertyReader.cc:2794 normalized_driver_waveform variable_2 must be normalized_voltage
|
|
||||||
1226 LibertyReader.cc:2797 normalized_driver_waveform variable_1 must be input_net_transition
|
|
||||||
1228 LibertyReader.cc:3019 level_shifter_type must be HL, LH, or HL_LH
|
|
||||||
1229 LibertyReader.cc:3055 switch_cell_type must be coarse_grain or fine_grain
|
|
||||||
1230 LibertyReader.cc:3079 scaling_factors %s not found.
|
|
||||||
1231 LibertyReader.cc:3140 pin name is not a string.
|
|
||||||
1232 LibertyReader.cc:3157 pin name is not a string.
|
|
||||||
1233 LibertyReader.cc:3171 pin name is not a string.
|
|
||||||
1234 LibertyReader.cc:3243 bus %s bus_type not found.
|
|
||||||
1235 LibertyReader.cc:3295 bus_type %s not found.
|
|
||||||
1236 LibertyReader.cc:3298 bus_type is not a string.
|
|
||||||
1237 LibertyReader.cc:3316 bundle %s member not found.
|
|
||||||
1238 LibertyReader.cc:3339 member is not a string.
|
|
||||||
1239 LibertyReader.cc:3346 members attribute is missing values.
|
|
||||||
1240 LibertyReader.cc:3397 unknown port direction.
|
|
||||||
1241 LibertyReader.cc:3644 max_transition is 0.0.
|
|
||||||
1242 LibertyReader.cc:3750 pulse_latch unknown pulse type.
|
|
||||||
1243 LibertyReader.cc:4202 timing group missing related_pin/related_bus_pin.
|
|
||||||
1244 LibertyReader.cc:4301 unknown timing_type %s.
|
|
||||||
1245 LibertyReader.cc:4321 unknown timing_sense %s.
|
|
||||||
1246 LibertyReader.cc:4361 mode value is not a string.
|
|
||||||
1247 LibertyReader.cc:4364 missing mode value.
|
|
||||||
1248 LibertyReader.cc:4367 mode name is not a string.
|
|
||||||
1249 LibertyReader.cc:4370 mode missing values.
|
|
||||||
1250 LibertyReader.cc:4373 mode missing mode name and value.
|
|
||||||
1251 LibertyReader.cc:4449 unsupported model axis.
|
|
||||||
1252 LibertyReader.cc:4476 unsupported model axis.
|
|
||||||
1253 LibertyReader.cc:4505 unsupported model axis.
|
|
||||||
1254 LibertyReader.cc:4540 unsupported model axis.
|
|
||||||
1255 LibertyReader.cc:4556 %s group not in timing group.
|
|
||||||
1256 LibertyReader.cc:4595 table template %s not found.
|
|
||||||
1257 LibertyReader.cc:4679 %s is missing values.
|
|
||||||
1258 LibertyReader.cc:4702 %s is not a list of floats.
|
|
||||||
1259 LibertyReader.cc:4704 table row has %u columns but axis has %d.
|
|
||||||
1260 LibertyReader.cc:4714 table has %u rows but axis has %d.
|
|
||||||
1261 LibertyReader.cc:4765 lut output is not a string.
|
|
||||||
1262 LibertyReader.cc:4781 cell %s test_cell redefinition.
|
|
||||||
1263 LibertyReader.cc:4829 mode definition missing name.
|
|
||||||
1264 LibertyReader.cc:4846 mode value missing name.
|
|
||||||
1265 LibertyReader.cc:4860 when attribute inside table model.
|
|
||||||
1266 LibertyReader.cc:4909 %s attribute is not a string.
|
|
||||||
1267 LibertyReader.cc:4912 %s is not a simple attribute.
|
|
||||||
1268 LibertyReader.cc:4932 %s attribute is not an integer.
|
|
||||||
1269 LibertyReader.cc:4935 %s is not a simple attribute.
|
|
||||||
1270 LibertyReader.cc:4948 %s is not a simple attribute.
|
|
||||||
1271 LibertyReader.cc:4974 %s value %s is not a float.
|
|
||||||
1272 LibertyReader.cc:5003 %s missing values.
|
|
||||||
1273 LibertyReader.cc:5007 %s missing values.
|
|
||||||
1274 LibertyReader.cc:5010 %s is not a complex attribute.
|
|
||||||
1275 LibertyReader.cc:5036 %s is not a float.
|
|
||||||
1276 LibertyReader.cc:5059 %s is missing values.
|
|
||||||
1277 LibertyReader.cc:5062 %s has more than one string.
|
|
||||||
1278 LibertyReader.cc:5071 %s is missing values.
|
|
||||||
1279 LibertyReader.cc:5096 %s attribute is not boolean.
|
|
||||||
1280 LibertyReader.cc:5099 %s attribute is not boolean.
|
|
||||||
1281 LibertyReader.cc:5102 %s is not a simple attribute.
|
|
||||||
1282 LibertyReader.cc:5118 attribute %s value %s not recognized.
|
|
||||||
1283 LibertyReader.cc:5149 unknown early/late value.
|
|
||||||
1284 LibertyReader.cc:5369 OCV derate group named %s not found.
|
|
||||||
1285 LibertyReader.cc:5385 ocv_derate missing name.
|
|
||||||
1286 LibertyReader.cc:5438 unknown rise/fall.
|
|
||||||
1287 LibertyReader.cc:5458 unknown derate type.
|
|
||||||
1288 LibertyReader.cc:5490 unsupported model axis.
|
|
||||||
1289 LibertyReader.cc:5522 unsupported model axis.
|
|
||||||
1290 LibertyReader.cc:5554 unsupported model axis.
|
|
||||||
1291 LibertyReader.cc:5625 unknown pg_type.
|
|
||||||
1292 LibertyReader.cc:6039 port %s subscript out of range.
|
|
||||||
1293 LibertyReader.cc:6043 port range %s of non-bus port %s.
|
|
||||||
1294 LibertyReader.cc:6057 port %s not found.
|
|
||||||
1295 LibertyReader.cc:6127 port %s not found.
|
|
||||||
1297 LibertyReader.cc:1466 axis type %s not supported.
|
|
||||||
1298 LibertyReader.cc:2180 statetable input port %s not found.
|
|
||||||
1299 LibertyReader.cc:3809 unknown signal_type %s.
|
|
||||||
1300 LibertyReader.cc:4076 table row must have 3 groups separated by ':'.
|
|
||||||
1301 LibertyReader.cc:4081 table row has %zu input values but %zu are required.
|
|
||||||
1302 LibertyReader.cc:4088 table row has %zu current values but %zu are required.
|
|
||||||
1303 LibertyReader.cc:4095 table row has %zu next values but %zu are required.
|
|
||||||
1304 LibertyReader.cc:4141 table input value '%s' not recognized.
|
|
||||||
1305 LibertyReader.cc:4160 table internal value '%s' not recognized.
|
|
||||||
1340 LibertyWriter.cc:308 %s/%s bundled ports not supported.
|
|
||||||
1341 LibertyWriter.cc:456 %s/%s/%s timing model not supported.
|
|
||||||
1342 LibertyWriter.cc:476 3 axis table models not supported.
|
|
||||||
1343 LibertyWriter.cc:625 %s/%s/%s timing arc type %s not supported.
|
|
||||||
1350 LumpedCapDelayCalc.cc:138 gate delay input variable is NaN
|
|
||||||
1355 MakeTimingModel.cc:227 clock %s pin %s is inside model block.
|
|
||||||
1360 Vcd.cc:172 Unknown variable %s ID %s
|
|
||||||
1370 PathEnum.cc:478 path diversion missing edge.
|
|
||||||
1398 VerilogReader.cc:1860 %s is not a verilog module.
|
|
||||||
1399 VerilogReader.cc:1865 %s is not a verilog module.
|
|
||||||
1400 PathVertex.cc:236 missing arrivals.
|
|
||||||
1401 PathVertex.cc:250 missing arrivals.
|
|
||||||
1402 PathVertex.cc:279 missing requireds.
|
|
||||||
1422 PathVertexRep.cc:153 missing arrivals.
|
|
||||||
1450 ReadVcdActivities.cc:107 VCD max time is zero.
|
|
||||||
1451 ReadVcdActivities.cc:174 problem parsing bus %s.
|
|
||||||
1452 ReadVcdActivities.cc:250 clock %s vcd period %s differs from SDC clock period %s
|
|
||||||
1521 Sim.cc:511 propagated logic value %c differs from constraint value of %c on pin %s.
|
|
||||||
1525 SpefParse.yy:805 %d is not positive.
|
|
||||||
1526 SpefParse.yy:814 %.4f is not positive.
|
|
||||||
1527 SpefParse.yy:820 %.4f is not positive.
|
|
||||||
1550 Sta.cc:2000 '%s' is not a valid start point.
|
|
||||||
1551 Sta.cc:2073 '%s' is not a valid endpoint.
|
|
||||||
1552 Sta.cc:2076 '%s' is not a valid endpoint.
|
|
||||||
1553 Sta.cc:2393 maximum corner count exceeded
|
|
||||||
1554 Sta.cc:1997 '%s' is not a valid start point.
|
|
||||||
1570 Sta.cc:3413 No network has been linked.
|
|
||||||
1574 Search.i:1026 POCV support requires compilation with SSTA=1.
|
|
||||||
1575 Search.i:465 unknown report path field %s
|
|
||||||
1576 Search.i:477 unknown report path field %s
|
|
||||||
1602 WriteSpice.cc:458 Liberty pg_port %s/%s missing voltage_name attribute,
|
|
||||||
1603 WriteSpice.cc:428 %s pg_port %s not found,
|
|
||||||
1604 WriteSpice.cc:1019 no register/latch found for path from %s to %s,
|
|
||||||
1605 WriteSpice.cc:241 The subkct file %s is missing definitions for %s
|
|
||||||
1606 WriteSpice.cc:270 subckt %s port %s has no corresponding liberty port, pg_port and is not power or ground.
|
|
||||||
1640 SpefReader.cc:157 illegal bus delimiters.
|
|
||||||
1641 SpefReader.cc:241 unknown units %s.
|
|
||||||
1642 SpefReader.cc:254 unknown units %s.
|
|
||||||
1643 SpefReader.cc:267 unknown units %s.
|
|
||||||
1644 SpefReader.cc:282 unknown units %s.
|
|
||||||
1645 SpefReader.cc:303 no name map entry for %d.
|
|
||||||
1646 SpefReader.cc:322 unknown port direction %s.
|
|
||||||
1647 SpefReader.cc:349 pin %s not found.
|
|
||||||
1648 SpefReader.cc:352 instance %s not found.
|
|
||||||
1650 SpefReader.cc:372 net %s not found.
|
|
||||||
1651 SpefReader.cc:486 %s not connected to net %s.
|
|
||||||
1652 SpefReader.cc:492 pin %s not found.
|
|
||||||
1653 SpefReader.cc:506 %s not connected to net %s.
|
|
||||||
1654 SpefReader.cc:512 node %s not a pin or net:number
|
|
||||||
1655 SpefReader.cc:524 %s not connected to net %s.
|
|
||||||
1656 SpefReader.cc:528 pin %s not found.
|
|
||||||
1657 SpefReader.cc:645 %s.
|
|
||||||
1658 SpefReader.cc:61 Delay calculator %s does not support reduction.
|
|
||||||
1700 CcsCeffDelayCalc.cc:102 VDD not defined in library %s
|
|
||||||
1701 CcsCeffDelayCalc.cc:273 unsupported ccs region count.
|
|
||||||
1720 PrimaDelayCalc.cc:229 VDD not defined in library %s
|
|
||||||
1751 ArcDcalcWaveforms.cc:56 VDD not defined in library %s
|
|
||||||
1752 PrimaDelayCalc.cc:765 G matrix is singular.
|
|
||||||
1903 WriteSpice.tcl:145 Cannot write $spice_dir.
|
|
||||||
1904 WriteSpice.tcl:148 No -spice_filename specified.
|
|
||||||
1905 WriteSpice.tcl:154 -lib_subckt_file $lib_subckt_file is not readable.
|
|
||||||
1906 WriteSpice.tcl:157 No -lib_subckt_file specified.
|
|
||||||
1907 WriteSpice.tcl:163 -model_file $model_file is not readable.
|
|
||||||
1908 WriteSpice.tcl:166 No -model_file specified.
|
|
||||||
1909 WriteSpice.tcl:172 No -power specified.
|
|
||||||
1910 WriteSpice.tcl:111 Unknown circuit simulator
|
|
||||||
1913 WriteSpice.tcl:244 Cannot write $plot_dir.
|
|
||||||
1914 WriteSpice.tcl:247 No -plot_basename specified.
|
|
||||||
1915 WriteSpice.tcl:178 No -ground specified.
|
|
||||||
1920 WriteSpice.tcl:36 Directory $spice_dir not found.
|
|
||||||
1921 WriteSpice.tcl:39 $spice_dir is not a directory.
|
|
||||||
1922 WriteSpice.tcl:42 Cannot write in $spice_dir.
|
|
||||||
1923 WriteSpice.tcl:45 No -spice_directory specified.
|
|
||||||
1924 WriteSpice.tcl:51 -lib_subckt_file $lib_subckt_file is not readable.
|
|
||||||
1925 WriteSpice.tcl:54 No -lib_subckt_file specified.
|
|
||||||
1926 WriteSpice.tcl:60 -model_file $model_file is not readable.
|
|
||||||
1927 WriteSpice.tcl:63 No -model_file specified.
|
|
||||||
1928 WriteSpice.tcl:69 No -power specified.
|
|
||||||
1929 WriteSpice.tcl:75 No -ground specified.
|
|
||||||
1930 WriteSpice.tcl:81 No -path_args specified.
|
|
||||||
1931 WriteSpice.tcl:86 No paths found for -path_args $path_args.
|
|
||||||
1932 WriteSpice.tcl:139 Missing -gates argument.
|
|
||||||
1933 WriteSpice.tcl:212 Missing -gates argument.
|
|
||||||
2100 ArcDelayCalc.cc:86 no timing arc for %s input/driver pins.
|
|
||||||
2101 ArcDelayCalc.cc:91 %s not a valid rise/fall.
|
|
||||||
2102 ArcDelayCalc.cc:94 Pin %s/%s not found.
|
|
||||||
2103 ArcDelayCalc.cc:97 %s not a valid rise/fall.
|
|
||||||
2104 ArcDelayCalc.cc:100 Pin %s/%s not found.
|
|
||||||
2105 ArcDelayCalc.cc:103 Instance %s not found.
|
|
||||||
2120 Network.i:255 unknown namespace
|
|
||||||
2121 Sdc.i:104 unknown analysis type
|
|
||||||
2122 Sdc.i:227 unknown wire load mode
|
|
||||||
2140 StaTclTypes.i:424 Delay calc arg requires 5 or 6 args.
|
|
||||||
2141 Sta.cc:3417 No liberty libraries found.
|
|
||||||
2200 Crpr.cc:62 missing prev paths
|
|
||||||
2201 Crpr.cc:73 missing prev paths
|
|
||||||
|
|
@ -29,8 +29,11 @@ exec tclsh $0 ${1+"$@"}
|
||||||
# Find warning/error message IDs and detect collisions.
|
# Find warning/error message IDs and detect collisions.
|
||||||
# Usage: FindMessages.tcl > doc/messages.txt
|
# Usage: FindMessages.tcl > doc/messages.txt
|
||||||
|
|
||||||
|
set has_error 0
|
||||||
|
|
||||||
proc scan_file { file warn_regexp } {
|
proc scan_file { file warn_regexp } {
|
||||||
global msgs
|
global msgs
|
||||||
|
global has_error
|
||||||
|
|
||||||
if { [file exists $file] } {
|
if { [file exists $file] } {
|
||||||
set in_stream [open $file r]
|
set in_stream [open $file r]
|
||||||
|
|
@ -38,7 +41,7 @@ proc scan_file { file warn_regexp } {
|
||||||
set file_line 1
|
set file_line 1
|
||||||
|
|
||||||
while { ![eof $in_stream] } {
|
while { ![eof $in_stream] } {
|
||||||
if { [regexp -- $warn_regexp $line ignore1 ignore2 msg_id msg] } {
|
if { [regexp -- $warn_regexp $line ignore msg_id msg] } {
|
||||||
lappend msgs "$msg_id $file $file_line $msg"
|
lappend msgs "$msg_id $file $file_line $msg"
|
||||||
}
|
}
|
||||||
gets $in_stream line
|
gets $in_stream line
|
||||||
|
|
@ -46,7 +49,8 @@ proc scan_file { file warn_regexp } {
|
||||||
}
|
}
|
||||||
close $in_stream
|
close $in_stream
|
||||||
} else {
|
} else {
|
||||||
puts "Warning: file $file not found."
|
puts stderr "Warning: Source file $file not found during message scanning"
|
||||||
|
set has_error 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,13 +61,13 @@ foreach subdir $subdirs {
|
||||||
set files [glob -nocomplain [file join $subdir "*.{cc,hh,yy,ll,i}"]]
|
set files [glob -nocomplain [file join $subdir "*.{cc,hh,yy,ll,i}"]]
|
||||||
set files_c [concat $files_c $files]
|
set files_c [concat $files_c $files]
|
||||||
}
|
}
|
||||||
set warn_regexp_c {(criticalError|->warn|->fileWarn|->error|->fileError|libWarn|libError| warn)\(([0-9]+),.*(".+")}
|
set warn_regexp_c {(?:(?:criticalError|->warn|->fileWarn|->error|->fileError|libWarn|libError| warn)\(|tclArgError\(interp,\s*)([0-9]+),.*(".+")}
|
||||||
|
|
||||||
set files_tcl {}
|
set files_tcl {}
|
||||||
foreach subdir $subdirs {
|
foreach subdir $subdirs {
|
||||||
set files_tcl [concat $files_tcl [glob -nocomplain [file join $subdir "*.tcl"]]]
|
set files_tcl [concat $files_tcl [glob -nocomplain [file join $subdir "*.tcl"]]]
|
||||||
}
|
}
|
||||||
set warn_regexp_tcl {(sta_warn|sta_error|sta_warn_error) ([0-9]+) (".+")}
|
set warn_regexp_tcl {(?:sta_warn|sta_error|sta_warn_error) ([0-9]+) (".+")}
|
||||||
|
|
||||||
proc scan_files {files warn_regexp } {
|
proc scan_files {files warn_regexp } {
|
||||||
foreach file $files {
|
foreach file $files {
|
||||||
|
|
@ -73,13 +77,15 @@ proc scan_files {files warn_regexp } {
|
||||||
|
|
||||||
proc check_msgs { } {
|
proc check_msgs { } {
|
||||||
global msgs
|
global msgs
|
||||||
|
global has_error
|
||||||
|
|
||||||
set msgs [lsort -index 0 -integer $msgs]
|
set msgs [lsort -index 0 -integer $msgs]
|
||||||
set prev_id -1
|
set prev_id -1
|
||||||
foreach msg $msgs {
|
foreach msg $msgs {
|
||||||
set msg_id [lindex $msg 0]
|
set msg_id [lindex $msg 0]
|
||||||
if { $msg_id == $prev_id } {
|
if { $msg_id == $prev_id } {
|
||||||
puts "Warning: $msg_id duplicated"
|
puts stderr "Warning: Message id $msg_id duplicated"
|
||||||
|
set has_error 1
|
||||||
}
|
}
|
||||||
set prev_id $msg_id
|
set prev_id $msg_id
|
||||||
}
|
}
|
||||||
|
|
@ -99,3 +105,7 @@ scan_files $files_c $warn_regexp_c
|
||||||
scan_files $files_tcl $warn_regexp_tcl
|
scan_files $files_tcl $warn_regexp_tcl
|
||||||
check_msgs
|
check_msgs
|
||||||
report_msgs
|
report_msgs
|
||||||
|
|
||||||
|
if {$has_error} {
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -613,17 +613,17 @@ Graph::deleteRequireds(Vertex *vertex)
|
||||||
vertex->setRequireds(nullptr);
|
vertex->setRequireds(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertexRep *
|
PathPrev *
|
||||||
Graph::prevPaths(const Vertex *vertex) const
|
Graph::prevPaths(const Vertex *vertex) const
|
||||||
{
|
{
|
||||||
return vertex->prevPaths();
|
return vertex->prevPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertexRep *
|
PathPrev *
|
||||||
Graph::makePrevPaths(Vertex *vertex,
|
Graph::makePrevPaths(Vertex *vertex,
|
||||||
uint32_t count)
|
uint32_t count)
|
||||||
{
|
{
|
||||||
PathVertexRep *prev_paths = new PathVertexRep[count];
|
PathPrev *prev_paths = new PathPrev[count];
|
||||||
vertex->setPrevPaths(prev_paths);
|
vertex->setPrevPaths(prev_paths);
|
||||||
return prev_paths;
|
return prev_paths;
|
||||||
}
|
}
|
||||||
|
|
@ -1023,7 +1023,6 @@ Vertex::init(Pin *pin,
|
||||||
level_ = 0;
|
level_ = 0;
|
||||||
bfs_in_queue_ = 0;
|
bfs_in_queue_ = 0;
|
||||||
crpr_path_pruning_disabled_ = false;
|
crpr_path_pruning_disabled_ = false;
|
||||||
requireds_pruned_ = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex::~Vertex()
|
Vertex::~Vertex()
|
||||||
|
|
@ -1141,12 +1140,6 @@ Vertex::setCrprPathPruningDisabled(bool disabled)
|
||||||
crpr_path_pruning_disabled_ = disabled;
|
crpr_path_pruning_disabled_ = disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Vertex::setRequiredsPruned(bool pruned)
|
|
||||||
{
|
|
||||||
requireds_pruned_ = pruned;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagGroupIndex
|
TagGroupIndex
|
||||||
Vertex::tagGroupIndex() const
|
Vertex::tagGroupIndex() const
|
||||||
{
|
{
|
||||||
|
|
@ -1174,7 +1167,7 @@ Vertex::setRequireds(Required *requireds)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Vertex::setPrevPaths(PathVertexRep *prev_paths)
|
Vertex::setPrevPaths(PathPrev *prev_paths)
|
||||||
{
|
{
|
||||||
delete [] prev_paths_;
|
delete [] prev_paths_;
|
||||||
prev_paths_ = prev_paths;
|
prev_paths_ = prev_paths;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
#include "Delay.hh"
|
#include "Delay.hh"
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
#include "VertexId.hh"
|
#include "VertexId.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -55,7 +55,7 @@ typedef ObjectId EdgeId;
|
||||||
|
|
||||||
static constexpr EdgeId edge_id_null = object_id_null;
|
static constexpr EdgeId edge_id_null = object_id_null;
|
||||||
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
||||||
static constexpr ObjectIdx vertex_idx_null = object_id_null;
|
static constexpr ObjectIdx vertex_idx_null = object_idx_null;
|
||||||
|
|
||||||
// The graph acts as a BUILDER for the graph vertices and edges.
|
// The graph acts as a BUILDER for the graph vertices and edges.
|
||||||
class Graph : public StaState
|
class Graph : public StaState
|
||||||
|
|
@ -104,9 +104,9 @@ public:
|
||||||
uint32_t count);
|
uint32_t count);
|
||||||
Required *requireds(const Vertex *vertex) const;
|
Required *requireds(const Vertex *vertex) const;
|
||||||
void deleteRequireds(Vertex *vertex);
|
void deleteRequireds(Vertex *vertex);
|
||||||
PathVertexRep *makePrevPaths(Vertex *vertex,
|
PathPrev *makePrevPaths(Vertex *vertex,
|
||||||
uint32_t count);
|
uint32_t count);
|
||||||
PathVertexRep *prevPaths(const Vertex *vertex) const;
|
PathPrev *prevPaths(const Vertex *vertex) const;
|
||||||
void deletePrevPaths(Vertex *vertex);
|
void deletePrevPaths(Vertex *vertex);
|
||||||
// Private to Search::deletePaths(Vertex).
|
// Private to Search::deletePaths(Vertex).
|
||||||
void deletePaths(Vertex *vertex);
|
void deletePaths(Vertex *vertex);
|
||||||
|
|
@ -271,8 +271,8 @@ public:
|
||||||
const Slew *slews() const { return slews_; }
|
const Slew *slews() const { return slews_; }
|
||||||
Arrival *arrivals() const { return arrivals_; }
|
Arrival *arrivals() const { return arrivals_; }
|
||||||
Arrival *requireds() const { return requireds_; }
|
Arrival *requireds() const { return requireds_; }
|
||||||
PathVertexRep *prevPaths() const { return prev_paths_; }
|
PathPrev *prevPaths() const { return prev_paths_; }
|
||||||
void setPrevPaths(PathVertexRep *prev_paths);
|
void setPrevPaths(PathPrev *prev_paths);
|
||||||
TagGroupIndex tagGroupIndex() const;
|
TagGroupIndex tagGroupIndex() const;
|
||||||
void setTagGroupIndex(TagGroupIndex tag_index);
|
void setTagGroupIndex(TagGroupIndex tag_index);
|
||||||
// Slew is annotated by sdc set_annotated_transition cmd.
|
// Slew is annotated by sdc set_annotated_transition cmd.
|
||||||
|
|
@ -312,8 +312,6 @@ public:
|
||||||
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
|
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
|
||||||
void setCrprPathPruningDisabled(bool disabled);
|
void setCrprPathPruningDisabled(bool disabled);
|
||||||
bool hasRequireds() const { return requireds_ != nullptr; }
|
bool hasRequireds() const { return requireds_ != nullptr; }
|
||||||
bool requiredsPruned() const { return requireds_pruned_; }
|
|
||||||
void setRequiredsPruned(bool pruned);
|
|
||||||
|
|
||||||
// ObjectTable interface.
|
// ObjectTable interface.
|
||||||
ObjectIdx objectIdx() const { return object_idx_; }
|
ObjectIdx objectIdx() const { return object_idx_; }
|
||||||
|
|
@ -339,13 +337,13 @@ protected:
|
||||||
// Search
|
// Search
|
||||||
Arrival *arrivals_;
|
Arrival *arrivals_;
|
||||||
Arrival *requireds_;
|
Arrival *requireds_;
|
||||||
PathVertexRep *prev_paths_;
|
PathPrev *prev_paths_;
|
||||||
|
|
||||||
// These fields are written by multiple threads, so they
|
// These fields are written by multiple threads, so they
|
||||||
// cannot share the same word as the following bit fields.
|
// cannot share the same word as the following bit fields.
|
||||||
uint32_t tag_group_index_;
|
uint32_t tag_group_index_;
|
||||||
// Each bit corresponds to a different BFS queue.
|
// Each bit corresponds to a different BFS queue.
|
||||||
std::atomic<uint8_t> bfs_in_queue_; // 4
|
std::atomic<uint8_t> bfs_in_queue_; // 8
|
||||||
|
|
||||||
unsigned int level_:Graph::vertex_level_bits; // 24
|
unsigned int level_:Graph::vertex_level_bits; // 24
|
||||||
unsigned int slew_annotated_:slew_annotated_bits; // 4
|
unsigned int slew_annotated_:slew_annotated_bits; // 4
|
||||||
|
|
@ -367,7 +365,6 @@ protected:
|
||||||
bool is_constrained_:1;
|
bool is_constrained_:1;
|
||||||
bool has_downstream_clk_pin_:1;
|
bool has_downstream_clk_pin_:1;
|
||||||
bool crpr_path_pruning_disabled_:1;
|
bool crpr_path_pruning_disabled_:1;
|
||||||
bool requireds_pruned_:1;
|
|
||||||
unsigned object_idx_:VertexTable::idx_bits; // 7
|
unsigned object_idx_:VertexTable::idx_bits; // 7
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -385,7 +382,9 @@ public:
|
||||||
Edge();
|
Edge();
|
||||||
~Edge();
|
~Edge();
|
||||||
Vertex *to(const Graph *graph) const { return graph->vertex(to_); }
|
Vertex *to(const Graph *graph) const { return graph->vertex(to_); }
|
||||||
|
VertexId to() const { return to_; }
|
||||||
Vertex *from(const Graph *graph) const { return graph->vertex(from_); }
|
Vertex *from(const Graph *graph) const { return graph->vertex(from_); }
|
||||||
|
VertexId from() const { return from_; }
|
||||||
TimingRole *role() const;
|
TimingRole *role() const;
|
||||||
bool isWire() const;
|
bool isWire() const;
|
||||||
TimingSense sense() const;
|
TimingSense sense() const;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SdcClass.hh"
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc.
|
||||||
|
class PathPrev
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathPrev();
|
||||||
|
PathPrev(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
|
const StaState *sta);
|
||||||
|
void init();
|
||||||
|
void init(const PathPrev *path);
|
||||||
|
void init(const PathPrev &path);
|
||||||
|
void init(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
|
const StaState *sta);
|
||||||
|
bool isNull() const;
|
||||||
|
const char *name(const StaState *sta) const;
|
||||||
|
Vertex *vertex(const StaState *sta) const;
|
||||||
|
VertexId vertexId(const StaState *sta) const;
|
||||||
|
Edge *prevEdge(const StaState *sta) const;
|
||||||
|
TimingArc *prevArc(const StaState *sta) const;
|
||||||
|
Tag *tag(const StaState *sta) const;
|
||||||
|
TagIndex tagIndex() const { return prev_tag_index_; }
|
||||||
|
Arrival arrival(const StaState *sta) const;
|
||||||
|
void prevPath(const StaState *sta,
|
||||||
|
// Return values.
|
||||||
|
PathRef &prev_path,
|
||||||
|
TimingArc *&prev_arc) const;
|
||||||
|
|
||||||
|
static bool equal(const PathPrev *path1,
|
||||||
|
const PathPrev *path2);
|
||||||
|
static bool equal(const PathPrev &path1,
|
||||||
|
const PathPrev &path2);
|
||||||
|
static int cmp(const PathPrev &path1,
|
||||||
|
const PathPrev &path2);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EdgeId prev_edge_id_;
|
||||||
|
TagIndex prev_tag_index_:tag_index_bit_count;
|
||||||
|
unsigned prev_arc_idx_:2;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -49,6 +49,8 @@ public:
|
||||||
void init(const PathRef *path);
|
void init(const PathRef *path);
|
||||||
void init(const PathVertex &path);
|
void init(const PathVertex &path);
|
||||||
void init(const PathVertex *path);
|
void init(const PathVertex *path);
|
||||||
|
void init(const PathPrev &path,
|
||||||
|
const StaState *sta);
|
||||||
void init(Vertex *vertex,
|
void init(Vertex *vertex,
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
int arrival_index);
|
int arrival_index);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
class PathVertexRep;
|
class PathPrev;
|
||||||
|
class PathVertexPtr;
|
||||||
|
|
||||||
// Implements Path API for a vertex.
|
// Implements Path API for a vertex.
|
||||||
class PathVertex : public Path
|
class PathVertex : public Path
|
||||||
|
|
@ -38,9 +39,11 @@ public:
|
||||||
PathVertex();
|
PathVertex();
|
||||||
PathVertex(const PathVertex &path);
|
PathVertex(const PathVertex &path);
|
||||||
PathVertex(const PathVertex *path);
|
PathVertex(const PathVertex *path);
|
||||||
PathVertex(const PathVertexRep *path,
|
PathVertex(const PathPrev *path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
PathVertex(const PathVertexRep &path,
|
PathVertex(const PathPrev &path,
|
||||||
|
const StaState *sta);
|
||||||
|
PathVertex(const PathVertexPtr &path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
// If tag is not in the vertex tag group isNull() is true.
|
// If tag is not in the vertex tag group isNull() is true.
|
||||||
PathVertex(Vertex *vertex,
|
PathVertex(Vertex *vertex,
|
||||||
|
|
@ -50,9 +53,11 @@ public:
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
int arrival_index);
|
int arrival_index);
|
||||||
void init();
|
void init();
|
||||||
void init(const PathVertexRep *path,
|
void init(const PathPrev *path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
void init(const PathVertexRep &path,
|
void init(const PathPrev &path,
|
||||||
|
const StaState *sta);
|
||||||
|
void init(const PathVertexPtr &path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
void init(Vertex *vertex,
|
void init(Vertex *vertex,
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
// "Pointer" to a vertex path because there is no real path object to point to.
|
||||||
|
class PathVertexPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathVertexPtr();
|
||||||
|
PathVertexPtr(const PathVertex *path,
|
||||||
|
const StaState *sta);
|
||||||
|
void init();
|
||||||
|
void init(const PathVertexPtr *path);
|
||||||
|
void init(const PathVertexPtr &path);
|
||||||
|
void init(const PathVertex *path,
|
||||||
|
const StaState *sta);
|
||||||
|
bool isNull() const;
|
||||||
|
const char *name(const StaState *sta) const;
|
||||||
|
Vertex *vertex(const StaState *sta) const;
|
||||||
|
VertexId vertexId() const { return vertex_id_; }
|
||||||
|
Tag *tag(const StaState *sta) const;
|
||||||
|
TagIndex tagIndex() const { return tag_index_; }
|
||||||
|
Arrival arrival(const StaState *sta) const;
|
||||||
|
|
||||||
|
static bool equal(const PathVertexPtr *path1,
|
||||||
|
const PathVertexPtr *path2);
|
||||||
|
static bool equal(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2);
|
||||||
|
static int cmp(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
VertexId vertex_id_;
|
||||||
|
TagIndex tag_index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -29,34 +29,30 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
// Path representation that references a vertex arrival via a tag.
|
// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc.
|
||||||
// This does not implement the Path API which uses virtual functions
|
|
||||||
// that would make it larger.
|
|
||||||
class PathVertexRep
|
class PathVertexRep
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PathVertexRep();
|
PathVertexRep();
|
||||||
explicit PathVertexRep(const PathVertexRep *path);
|
PathVertexRep(const PathVertex *path,
|
||||||
PathVertexRep(const PathVertexRep &path);
|
const Edge *prev_edge,
|
||||||
explicit PathVertexRep(const PathVertex *path,
|
const TimingArc *prev_arc,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
explicit PathVertexRep(const PathVertex &path,
|
|
||||||
const StaState *sta);
|
|
||||||
explicit PathVertexRep(VertexId vertex_id,
|
|
||||||
TagIndex tag_index,
|
|
||||||
bool is_enum);
|
|
||||||
void init();
|
void init();
|
||||||
void init(const PathVertexRep *path);
|
void init(const PathVertexRep *path);
|
||||||
void init(const PathVertexRep &path);
|
void init(const PathVertexRep &path);
|
||||||
void init(const PathVertex *path,
|
void init(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
void init(const PathVertex &path,
|
bool isNull() const;
|
||||||
const StaState *sta);
|
const char *name(const StaState *sta) const;
|
||||||
bool isNull() const { return vertex_id_ == 0; }
|
Vertex *vertex(const StaState *sta) const;
|
||||||
Vertex *vertex(const StaState *) const;
|
VertexId vertexId(const StaState *sta) const;
|
||||||
VertexId vertexId() const { return vertex_id_; }
|
Edge *prevEdge(const StaState *sta) const;
|
||||||
|
TimingArc *prevArc(const StaState *sta) const;
|
||||||
Tag *tag(const StaState *sta) const;
|
Tag *tag(const StaState *sta) const;
|
||||||
TagIndex tagIndex() const { return tag_index_; }
|
TagIndex tagIndex() const { return prev_tag_index_; }
|
||||||
Arrival arrival(const StaState *sta) const;
|
Arrival arrival(const StaState *sta) const;
|
||||||
void prevPath(const StaState *sta,
|
void prevPath(const StaState *sta,
|
||||||
// Return values.
|
// Return values.
|
||||||
|
|
@ -67,15 +63,13 @@ public:
|
||||||
const PathVertexRep *path2);
|
const PathVertexRep *path2);
|
||||||
static bool equal(const PathVertexRep &path1,
|
static bool equal(const PathVertexRep &path1,
|
||||||
const PathVertexRep &path2);
|
const PathVertexRep &path2);
|
||||||
static int cmp(const PathVertexRep *path1,
|
|
||||||
const PathVertexRep *path2);
|
|
||||||
static int cmp(const PathVertexRep &path1,
|
static int cmp(const PathVertexRep &path1,
|
||||||
const PathVertexRep &path2);
|
const PathVertexRep &path2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VertexId vertex_id_;
|
EdgeId prev_edge_id_;
|
||||||
TagIndex tag_index_;
|
TagIndex prev_tag_index_:tag_index_bit_count;
|
||||||
bool is_enum_:1;
|
unsigned prev_arc_idx_:2;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ findLeafDriverPins(const Pin *pin,
|
||||||
class Sdc : public StaState
|
class Sdc : public StaState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Sdc(StaState *sta);
|
Sdc(StaState *sta);
|
||||||
~Sdc();
|
~Sdc();
|
||||||
// Note that Search may reference a Filter exception removed by clear().
|
// Note that Search may reference a Filter exception removed by clear().
|
||||||
void clear();
|
void clear();
|
||||||
|
|
@ -377,31 +377,29 @@ public:
|
||||||
float fanout);
|
float fanout);
|
||||||
void setMaxArea(float area);
|
void setMaxArea(float area);
|
||||||
float maxArea() const;
|
float maxArea() const;
|
||||||
virtual Clock *makeClock(const char *name,
|
Clock *makeClock(const char *name,
|
||||||
PinSet *pins,
|
PinSet *pins,
|
||||||
bool add_to_pins,
|
bool add_to_pins,
|
||||||
float period,
|
float period,
|
||||||
FloatSeq *waveform,
|
FloatSeq *waveform,
|
||||||
const char *comment);
|
const char *comment);
|
||||||
// edges size must be 3.
|
// edges size must be 3.
|
||||||
virtual Clock *makeGeneratedClock(const char *name,
|
Clock *makeGeneratedClock(const char *name,
|
||||||
PinSet *pins,
|
PinSet *pins,
|
||||||
bool add_to_pins,
|
bool add_to_pins,
|
||||||
Pin *src_pin,
|
Pin *src_pin,
|
||||||
Clock *master_clk,
|
Clock *master_clk,
|
||||||
int divide_by,
|
int divide_by,
|
||||||
int multiply_by,
|
int multiply_by,
|
||||||
float duty_cycle,
|
float duty_cycle,
|
||||||
bool invert,
|
bool invert,
|
||||||
bool combinational,
|
bool combinational,
|
||||||
IntSeq *edges,
|
IntSeq *edges,
|
||||||
FloatSeq *edge_shifts,
|
FloatSeq *edge_shifts,
|
||||||
const char *comment);
|
const char *comment);
|
||||||
// Invalidate all generated clock waveforms.
|
// Invalidate all generated clock waveforms.
|
||||||
void invalidateGeneratedClks() const;
|
void invalidateGeneratedClks() const;
|
||||||
virtual void removeClock(Clock *clk);
|
void removeClock(Clock *clk);
|
||||||
virtual void clockDeletePin(Clock *clk,
|
|
||||||
Pin *pin);
|
|
||||||
// Clock used for inputs without defined arrivals.
|
// Clock used for inputs without defined arrivals.
|
||||||
ClockEdge *defaultArrivalClockEdge() const;
|
ClockEdge *defaultArrivalClockEdge() const;
|
||||||
Clock *defaultArrivalClock() const { return default_arrival_clk_; }
|
Clock *defaultArrivalClock() const { return default_arrival_clk_; }
|
||||||
|
|
@ -485,22 +483,22 @@ public:
|
||||||
bool &exists) const;
|
bool &exists) const;
|
||||||
const ClockInsertions &clockInsertions() const { return clk_insertions_; }
|
const ClockInsertions &clockInsertions() const { return clk_insertions_; }
|
||||||
// Clock uncertainty.
|
// Clock uncertainty.
|
||||||
virtual void setClockUncertainty(Pin *pin,
|
void setClockUncertainty(Pin *pin,
|
||||||
const SetupHoldAll *setup_hold,
|
const SetupHoldAll *setup_hold,
|
||||||
float uncertainty);
|
float uncertainty);
|
||||||
virtual void removeClockUncertainty(Pin *pin,
|
void removeClockUncertainty(Pin *pin,
|
||||||
const SetupHoldAll *setup_hold);
|
const SetupHoldAll *setup_hold);
|
||||||
virtual void setClockUncertainty(Clock *from_clk,
|
void setClockUncertainty(Clock *from_clk,
|
||||||
const RiseFallBoth *from_rf,
|
const RiseFallBoth *from_rf,
|
||||||
Clock *to_clk,
|
Clock *to_clk,
|
||||||
const RiseFallBoth *to_rf,
|
const RiseFallBoth *to_rf,
|
||||||
const SetupHoldAll *setup_hold,
|
const SetupHoldAll *setup_hold,
|
||||||
float uncertainty);
|
float uncertainty);
|
||||||
virtual void removeClockUncertainty(Clock *from_clk,
|
void removeClockUncertainty(Clock *from_clk,
|
||||||
const RiseFallBoth *from_rf,
|
const RiseFallBoth *from_rf,
|
||||||
Clock *to_clk,
|
Clock *to_clk,
|
||||||
const RiseFallBoth *to_rf,
|
const RiseFallBoth *to_rf,
|
||||||
const SetupHoldAll *setup_hold);
|
const SetupHoldAll *setup_hold);
|
||||||
ClockGroups *makeClockGroups(const char *name,
|
ClockGroups *makeClockGroups(const char *name,
|
||||||
bool logically_exclusive,
|
bool logically_exclusive,
|
||||||
bool physically_exclusive,
|
bool physically_exclusive,
|
||||||
|
|
@ -873,7 +871,7 @@ public:
|
||||||
float voltage);
|
float voltage);
|
||||||
InputDrive *findInputDrive(Port *port);
|
InputDrive *findInputDrive(Port *port);
|
||||||
Clock *findClock(const char *name) const;
|
Clock *findClock(const char *name) const;
|
||||||
virtual ClockSeq findClocksMatching(PatternMatch *pattern) const;
|
ClockSeq findClocksMatching(PatternMatch *pattern) const;
|
||||||
// True if pin is defined as a clock source (pin may be hierarchical).
|
// True if pin is defined as a clock source (pin may be hierarchical).
|
||||||
bool isClock(const Pin *pin) const;
|
bool isClock(const Pin *pin) const;
|
||||||
// True if pin is a clock source vertex.
|
// True if pin is a clock source vertex.
|
||||||
|
|
@ -1036,13 +1034,13 @@ public:
|
||||||
// Return values.
|
// Return values.
|
||||||
ExceptionPath *&hi_priority_exception,
|
ExceptionPath *&hi_priority_exception,
|
||||||
int &hi_priority) const;
|
int &hi_priority) const;
|
||||||
virtual bool exceptionMatchesTo(ExceptionPath *exception,
|
bool exceptionMatchesTo(ExceptionPath *exception,
|
||||||
const Pin *pin,
|
const Pin *pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const ClockEdge *clk_edge,
|
const ClockEdge *clk_edge,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
bool match_min_max_exactly,
|
bool match_min_max_exactly,
|
||||||
bool require_to_pin) const;
|
bool require_to_pin) const;
|
||||||
bool isCompleteTo(ExceptionState *state,
|
bool isCompleteTo(ExceptionState *state,
|
||||||
const Pin *pin,
|
const Pin *pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
|
|
@ -1085,8 +1083,8 @@ protected:
|
||||||
void deleteClkPinMappings(Clock *clk);
|
void deleteClkPinMappings(Clock *clk);
|
||||||
void deleteExceptionPtHashMapSets(ExceptionPathPtHash &map);
|
void deleteExceptionPtHashMapSets(ExceptionPathPtHash &map);
|
||||||
void makeClkPinMappings(Clock *clk);
|
void makeClkPinMappings(Clock *clk);
|
||||||
virtual void deletePinClocks(Clock *defining_clk,
|
void deletePinClocks(Clock *defining_clk,
|
||||||
PinSet *pins);
|
PinSet *pins);
|
||||||
void makeDefaultArrivalClock();
|
void makeDefaultArrivalClock();
|
||||||
InputDrive *ensureInputDrive(const Port *port);
|
InputDrive *ensureInputDrive(const Port *port);
|
||||||
PortExtCap *ensurePortExtPinCap(const Port *port,
|
PortExtCap *ensurePortExtPinCap(const Port *port,
|
||||||
|
|
@ -1097,8 +1095,8 @@ protected:
|
||||||
void recordPathDelayInternalStartpoints(ExceptionPath *exception);
|
void recordPathDelayInternalStartpoints(ExceptionPath *exception);
|
||||||
void unrecordPathDelayInternalStartpoints(ExceptionFrom *from);
|
void unrecordPathDelayInternalStartpoints(ExceptionFrom *from);
|
||||||
bool pathDelayFrom(const Pin *pin);
|
bool pathDelayFrom(const Pin *pin);
|
||||||
virtual void recordPathDelayInternalEndpoints(ExceptionPath *exception);
|
void recordPathDelayInternalEndpoints(ExceptionPath *exception);
|
||||||
virtual void unrecordPathDelayInternalEndpoints(ExceptionPath *exception);
|
void unrecordPathDelayInternalEndpoints(ExceptionPath *exception);
|
||||||
bool pathDelayTo(const Pin *pin);
|
bool pathDelayTo(const Pin *pin);
|
||||||
bool hasLibertyCheckTo(const Pin *pin);
|
bool hasLibertyCheckTo(const Pin *pin);
|
||||||
void deleteMatchingExceptions(ExceptionPath *exception);
|
void deleteMatchingExceptions(ExceptionPath *exception);
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,6 @@ public:
|
||||||
void arrivalsInvalid();
|
void arrivalsInvalid();
|
||||||
// Invalidate vertex arrival time.
|
// Invalidate vertex arrival time.
|
||||||
void arrivalInvalid(Vertex *vertex);
|
void arrivalInvalid(Vertex *vertex);
|
||||||
void arrivalInvalidDelete(Vertex *vertex);
|
|
||||||
void arrivalInvalid(const Pin *pin);
|
void arrivalInvalid(const Pin *pin);
|
||||||
// Invalidate all required times.
|
// Invalidate all required times.
|
||||||
void requiredsInvalid();
|
void requiredsInvalid();
|
||||||
|
|
@ -373,6 +372,7 @@ public:
|
||||||
bool unconstrained,
|
bool unconstrained,
|
||||||
bool thru_latches);
|
bool thru_latches);
|
||||||
VertexSeq filteredEndpoints();
|
VertexSeq filteredEndpoints();
|
||||||
|
bool alwaysSavePrevPaths() const { return always_save_prev_paths_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void init(StaState *sta);
|
void init(StaState *sta);
|
||||||
|
|
@ -613,6 +613,7 @@ protected:
|
||||||
std::mutex pending_latch_outputs_lock_;
|
std::mutex pending_latch_outputs_lock_;
|
||||||
VertexSet *endpoints_;
|
VertexSet *endpoints_;
|
||||||
VertexSet *invalid_endpoints_;
|
VertexSet *invalid_endpoints_;
|
||||||
|
bool always_save_prev_paths_;
|
||||||
// Filter exception to tag arrivals for
|
// Filter exception to tag arrivals for
|
||||||
// report_timing -from pin|inst -through.
|
// report_timing -from pin|inst -through.
|
||||||
// -to is always nullptr.
|
// -to is always nullptr.
|
||||||
|
|
@ -760,6 +761,7 @@ protected:
|
||||||
void constrainedRequiredsInvalid(Vertex *vertex,
|
void constrainedRequiredsInvalid(Vertex *vertex,
|
||||||
bool is_clk);
|
bool is_clk);
|
||||||
bool always_to_endpoints_;
|
bool always_to_endpoints_;
|
||||||
|
bool always_save_prev_paths_;
|
||||||
TagGroupBldr *tag_bldr_;
|
TagGroupBldr *tag_bldr_;
|
||||||
TagGroupBldr *tag_bldr_no_crpr_;
|
TagGroupBldr *tag_bldr_no_crpr_;
|
||||||
SearchPred *adj_pred_;
|
SearchPred *adj_pred_;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ class Corner;
|
||||||
class Path;
|
class Path;
|
||||||
class PathRep;
|
class PathRep;
|
||||||
class PathVertex;
|
class PathVertex;
|
||||||
class PathVertexRep;
|
class PathPrev;
|
||||||
|
class PathVertexPtr;
|
||||||
class PathRef;
|
class PathRef;
|
||||||
class PathEnumed;
|
class PathEnumed;
|
||||||
class PathEnd;
|
class PathEnd;
|
||||||
|
|
@ -136,7 +137,8 @@ enum class ReportPathFormat { full,
|
||||||
json
|
json
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TagIndex tag_index_max = std::numeric_limits<uint32_t>::max();
|
static const TagIndex tag_index_bit_count = 28;
|
||||||
|
static const TagIndex tag_index_max = (1 << tag_index_bit_count) - 1;
|
||||||
static const TagIndex tag_index_null = tag_index_max;
|
static const TagIndex tag_index_null = tag_index_max;
|
||||||
static const int path_ap_index_bit_count = 8;
|
static const int path_ap_index_bit_count = 8;
|
||||||
// One path analysis point per corner min/max.
|
// One path analysis point per corner min/max.
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ tclListSetStdString(Tcl_Obj *const source,
|
||||||
|
|
||||||
void
|
void
|
||||||
tclArgError(Tcl_Interp *interp,
|
tclArgError(Tcl_Interp *interp,
|
||||||
|
int id,
|
||||||
const char *msg,
|
const char *msg,
|
||||||
const char *arg);
|
const char *arg);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -502,7 +502,7 @@ SpefReader::findParasiticNode(char *name,
|
||||||
warn(1656, "pin %s not found.", name1);
|
warn(1656, "pin %s not found.", name1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
warn(1656, "pin %s not found.", name);
|
warn(1657, "pin %s not found.", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -624,7 +624,7 @@ SpefScanner::SpefScanner(std::istream *stream,
|
||||||
void
|
void
|
||||||
SpefScanner::error(const char *msg)
|
SpefScanner::error(const char *msg)
|
||||||
{
|
{
|
||||||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
report_->fileError(1867, filename_.c_str(), lineno(), "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -664,7 +664,9 @@ Power::ensureActivities()
|
||||||
// unless it has been set by command.
|
// unless it has been set by command.
|
||||||
if (input_activity_.density() == 0.0) {
|
if (input_activity_.density() == 0.0) {
|
||||||
float min_period = clockMinPeriod();
|
float min_period = clockMinPeriod();
|
||||||
float density = 0.1 / (min_period != 0.0 ? min_period : 0.0);
|
float density = 0.1 / (min_period != 0.0
|
||||||
|
? min_period
|
||||||
|
: units_->timeUnit()->scale());
|
||||||
input_activity_.set(density, 0.5, PwrActivityOrigin::input);
|
input_activity_.set(density, 0.5, PwrActivityOrigin::input);
|
||||||
}
|
}
|
||||||
ActivitySrchPred activity_srch_pred(this);
|
ActivitySrchPred activity_srch_pred(this);
|
||||||
|
|
|
||||||
|
|
@ -266,7 +266,7 @@ proc set_power_activity { args } {
|
||||||
check_positive_float "density" $density
|
check_positive_float "density" $density
|
||||||
set density [expr $density / [time_ui_sta 1.0]]
|
set density [expr $density / [time_ui_sta 1.0]]
|
||||||
if { [info exists keys(-clock)] } {
|
if { [info exists keys(-clock)] } {
|
||||||
sta_warn 302 "-clock ignored for -density"
|
sta_warn 308 "-clock ignored for -density"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set duty 0.5
|
set duty 0.5
|
||||||
|
|
@ -274,7 +274,7 @@ proc set_power_activity { args } {
|
||||||
set duty $keys(-duty)
|
set duty $keys(-duty)
|
||||||
check_float "duty" $duty
|
check_float "duty" $duty
|
||||||
if { $duty < 0.0 || $duty > 1.0 } {i
|
if { $duty < 0.0 || $duty > 1.0 } {i
|
||||||
sta_error 302 "duty should be 0.0 to 1.0"
|
sta_error 309 "duty should be 0.0 to 1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ void
|
||||||
sta::SaifParse::error(const location_type &loc,
|
sta::SaifParse::error(const location_type &loc,
|
||||||
const string &msg)
|
const string &msg)
|
||||||
{
|
{
|
||||||
reader->report()->fileError(164,reader->filename(),loc.begin.line,"%s",msg.c_str());
|
reader->report()->fileError(169,reader->filename(),loc.begin.line,"%s",msg.c_str());
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ SaifScanner::SaifScanner(std::istream *stream,
|
||||||
void
|
void
|
||||||
SaifScanner::error(const char *msg)
|
SaifScanner::error(const char *msg)
|
||||||
{
|
{
|
||||||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
report_->fileError(1868, filename_.c_str(), lineno(), "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
13
sdc/Sdc.cc
13
sdc/Sdc.cc
|
|
@ -1176,19 +1176,6 @@ Sdc::deleteMasterClkRefs(Clock *clk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Sdc::clockDeletePin(Clock *clk,
|
|
||||||
Pin *pin)
|
|
||||||
{
|
|
||||||
ClockSet *pin_clks = clock_pin_map_.findKey(pin);
|
|
||||||
pin_clks->erase(clk);
|
|
||||||
if (pin_clks->empty())
|
|
||||||
clock_pin_map_.erase(pin);
|
|
||||||
clk->deletePin(pin);
|
|
||||||
clk->makeLeafPins(network_);
|
|
||||||
makeClkPinMappings(clk);
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock *
|
Clock *
|
||||||
Sdc::findClock(const char *name) const
|
Sdc::findClock(const char *name) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
11
sdc/Sdc.i
11
sdc/Sdc.i
|
|
@ -1323,6 +1323,17 @@ filter_timing_arcs(const char *property,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
StringSeq
|
||||||
|
path_group_names()
|
||||||
|
{
|
||||||
|
StringSeq pg_names;
|
||||||
|
for (auto const& [name, group] : Sta::sta()->sdc()->groupPaths())
|
||||||
|
pg_names.push_back(name);
|
||||||
|
return pg_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
set_voltage_global(const MinMax *min_max,
|
set_voltage_global(const MinMax *min_max,
|
||||||
float voltage)
|
float voltage)
|
||||||
|
|
|
||||||
|
|
@ -1100,7 +1100,7 @@ SdfScanner::SdfScanner(std::istream *stream,
|
||||||
void
|
void
|
||||||
SdfScanner::error(const char *msg)
|
SdfScanner::error(const char *msg)
|
||||||
{
|
{
|
||||||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
report_->fileError(1869, filename_.c_str(), lineno(), "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
|
||||||
float latency,
|
float latency,
|
||||||
ClockUncertainties *uncertainties,
|
ClockUncertainties *uncertainties,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
PathVertexRep &crpr_clk_path,
|
PathVertexPtr &crpr_clk_path,
|
||||||
const StaState *sta) :
|
const StaState *sta) :
|
||||||
clk_edge_(clk_edge),
|
clk_edge_(clk_edge),
|
||||||
clk_src_(clk_src),
|
clk_src_(clk_src),
|
||||||
|
|
@ -128,6 +128,7 @@ ClkInfo::asString(const StaState *sta) const
|
||||||
result += "/";
|
result += "/";
|
||||||
result += std::to_string(path_ap_index_);
|
result += std::to_string(path_ap_index_);
|
||||||
|
|
||||||
|
result += " ";
|
||||||
if (clk_edge_)
|
if (clk_edge_)
|
||||||
result += clk_edge_->name();
|
result += clk_edge_->name();
|
||||||
else
|
else
|
||||||
|
|
@ -212,7 +213,7 @@ clkInfoEqual(const ClkInfo *clk_info1,
|
||||||
&& clk_info1->clkSrc() == clk_info2->clkSrc()
|
&& clk_info1->clkSrc() == clk_info2->clkSrc()
|
||||||
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
|
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
|
||||||
&& (!crpr_on
|
&& (!crpr_on
|
||||||
|| (PathVertexRep::equal(clk_info1->crprClkPath(),
|
|| (PathVertexPtr::equal(clk_info1->crprClkPath(),
|
||||||
clk_info2->crprClkPath())))
|
clk_info2->crprClkPath())))
|
||||||
&& ((uncertainties1 == nullptr
|
&& ((uncertainties1 == nullptr
|
||||||
&& uncertainties2 == nullptr)
|
&& uncertainties2 == nullptr)
|
||||||
|
|
@ -278,9 +279,9 @@ clkInfoCmp(const ClkInfo *clk_info1,
|
||||||
|
|
||||||
bool crpr_on = sta->sdc()->crprActive();
|
bool crpr_on = sta->sdc()->crprActive();
|
||||||
if (crpr_on) {
|
if (crpr_on) {
|
||||||
const PathVertexRep &crpr_path1 = clk_info1->crprClkPath();
|
const PathVertexPtr &crpr_path1 = clk_info1->crprClkPath();
|
||||||
const PathVertexRep &crpr_path2 = clk_info2->crprClkPath();
|
const PathVertexPtr &crpr_path2 = clk_info2->crprClkPath();
|
||||||
int path_cmp = PathVertexRep::cmp(crpr_path1, crpr_path2);
|
int path_cmp = PathVertexPtr::cmp(crpr_path1, crpr_path2);
|
||||||
if (path_cmp != 0)
|
if (path_cmp != 0)
|
||||||
return path_cmp;
|
return path_cmp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
#include "Transition.hh"
|
#include "Transition.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathVertexPtr.hh"
|
||||||
|
#include "Sdc.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -45,7 +46,7 @@ public:
|
||||||
float latency,
|
float latency,
|
||||||
ClockUncertainties *uncertainties,
|
ClockUncertainties *uncertainties,
|
||||||
PathAPIndex path_ap_index,
|
PathAPIndex path_ap_index,
|
||||||
PathVertexRep &crpr_clk_path,
|
PathVertexPtr &crpr_clk_path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
~ClkInfo();
|
~ClkInfo();
|
||||||
const char *asString(const StaState *sta) const;
|
const char *asString(const StaState *sta) const;
|
||||||
|
|
@ -64,8 +65,8 @@ public:
|
||||||
PathAPIndex pathAPIndex() const { return path_ap_index_; }
|
PathAPIndex pathAPIndex() const { return path_ap_index_; }
|
||||||
// Clock path used for crpr resolution.
|
// Clock path used for crpr resolution.
|
||||||
// Null for clocks because the path cannot point to itself.
|
// Null for clocks because the path cannot point to itself.
|
||||||
PathVertexRep &crprClkPath() { return crpr_clk_path_; }
|
PathVertexPtr &crprClkPath() { return crpr_clk_path_; }
|
||||||
const PathVertexRep &crprClkPath() const { return crpr_clk_path_; }
|
const PathVertexPtr &crprClkPath() const { return crpr_clk_path_; }
|
||||||
VertexId crprClkVertexId() const;
|
VertexId crprClkVertexId() const;
|
||||||
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
|
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
|
||||||
bool refsFilter(const StaState *sta) const;
|
bool refsFilter(const StaState *sta) const;
|
||||||
|
|
@ -80,7 +81,7 @@ private:
|
||||||
const ClockEdge *clk_edge_;
|
const ClockEdge *clk_edge_;
|
||||||
const Pin *clk_src_;
|
const Pin *clk_src_;
|
||||||
const Pin *gen_clk_src_;
|
const Pin *gen_clk_src_;
|
||||||
PathVertexRep crpr_clk_path_;
|
PathVertexPtr crpr_clk_path_;
|
||||||
ClockUncertainties *uncertainties_;
|
ClockUncertainties *uncertainties_;
|
||||||
Arrival insertion_;
|
Arrival insertion_;
|
||||||
float latency_;
|
float latency_;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "PathVertex.hh"
|
#include "PathVertex.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
#include "Path.hh"
|
#include "Path.hh"
|
||||||
#include "PathAnalysisPt.hh"
|
#include "PathAnalysisPt.hh"
|
||||||
#include "ClkInfo.hh"
|
#include "ClkInfo.hh"
|
||||||
|
|
@ -63,7 +63,7 @@ CheckCrpr::clkPathPrev(const PathVertex *path,
|
||||||
int arrival_index;
|
int arrival_index;
|
||||||
bool exists;
|
bool exists;
|
||||||
path->arrivalIndex(arrival_index, exists);
|
path->arrivalIndex(arrival_index, exists);
|
||||||
PathVertexRep *prevs = graph_->prevPaths(vertex);
|
PathPrev *prevs = graph_->prevPaths(vertex);
|
||||||
if (prevs)
|
if (prevs)
|
||||||
prev.init(prevs[arrival_index], this);
|
prev.init(prevs[arrival_index], this);
|
||||||
else
|
else
|
||||||
|
|
@ -74,7 +74,7 @@ PathVertex
|
||||||
CheckCrpr::clkPathPrev(Vertex *vertex,
|
CheckCrpr::clkPathPrev(Vertex *vertex,
|
||||||
int arrival_index)
|
int arrival_index)
|
||||||
{
|
{
|
||||||
PathVertexRep *prevs = graph_->prevPaths(vertex);
|
PathPrev *prevs = graph_->prevPaths(vertex);
|
||||||
if (prevs)
|
if (prevs)
|
||||||
return PathVertex(prevs[arrival_index], this);
|
return PathVertex(prevs[arrival_index], this);
|
||||||
else {
|
else {
|
||||||
|
|
@ -90,7 +90,7 @@ CheckCrpr::clkPathPrev(Vertex *vertex,
|
||||||
Arrival
|
Arrival
|
||||||
CheckCrpr::maxCrpr(ClkInfo *clk_info)
|
CheckCrpr::maxCrpr(ClkInfo *clk_info)
|
||||||
{
|
{
|
||||||
const PathVertexRep &crpr_clk_path = clk_info->crprClkPath();
|
const PathVertexPtr &crpr_clk_path = clk_info->crprClkPath();
|
||||||
if (!crpr_clk_path.isNull()) {
|
if (!crpr_clk_path.isNull()) {
|
||||||
PathVertex crpr_clk_vpath(crpr_clk_path, this);
|
PathVertex crpr_clk_vpath(crpr_clk_path, this);
|
||||||
if (!crpr_clk_vpath.isNull()) {
|
if (!crpr_clk_vpath.isNull()) {
|
||||||
|
|
@ -166,7 +166,7 @@ CheckCrpr::checkCrpr1(const Path *src_path,
|
||||||
const Clock *src_clk = src_clk_info->clock();
|
const Clock *src_clk = src_clk_info->clock();
|
||||||
const Clock *tgt_clk = tgt_clk_info->clock();
|
const Clock *tgt_clk = tgt_clk_info->clock();
|
||||||
PathVertex src_clk_path1;
|
PathVertex src_clk_path1;
|
||||||
PathVertexRep &src_crpr_clk_path = src_clk_info->crprClkPath();
|
const PathVertexPtr &src_crpr_clk_path = src_clk_info->crprClkPath();
|
||||||
const PathVertex *src_clk_path = nullptr;
|
const PathVertex *src_clk_path = nullptr;
|
||||||
if (src_tag->isClock()) {
|
if (src_tag->isClock()) {
|
||||||
src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this);
|
src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this);
|
||||||
|
|
@ -302,8 +302,8 @@ CheckCrpr::genClkSrcPaths(const PathVertex *path,
|
||||||
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
||||||
gclk_paths.push_back(path);
|
gclk_paths.push_back(path);
|
||||||
while (clk_edge->clock()->isGenerated()) {
|
while (clk_edge->clock()->isGenerated()) {
|
||||||
PathVertex genclk_path;
|
PathVertex genclk_path =
|
||||||
search_->genclks()->srcPath(clk_edge, clk_src, path_ap, genclk_path);
|
search_->genclks()->srcPath(clk_edge, clk_src, path_ap);
|
||||||
if (genclk_path.isNull())
|
if (genclk_path.isNull())
|
||||||
break;
|
break;
|
||||||
clk_info = genclk_path.clkInfo(this);
|
clk_info = genclk_path.clkInfo(this);
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
#include "PathAnalysisPt.hh"
|
#include "PathAnalysisPt.hh"
|
||||||
#include "Levelize.hh"
|
#include "Levelize.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathVertexPtr.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -856,7 +856,7 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex,
|
||||||
{
|
{
|
||||||
Arrival *arrivals = graph_->arrivals(vertex);
|
Arrival *arrivals = graph_->arrivals(vertex);
|
||||||
if (arrivals) {
|
if (arrivals) {
|
||||||
PathVertexRep *prev_paths = graph_->prevPaths(vertex);
|
PathPrev *prev_paths = graph_->prevPaths(vertex);
|
||||||
TagGroup *tag_group = search_->tagGroup(vertex);
|
TagGroup *tag_group = search_->tagGroup(vertex);
|
||||||
if (tag_group) {
|
if (tag_group) {
|
||||||
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
||||||
|
|
@ -866,7 +866,7 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex,
|
||||||
arrival_iter.next(tag, arrival_index);
|
arrival_iter.next(tag, arrival_index);
|
||||||
if (tag->isGenClkSrcPath()) {
|
if (tag->isGenClkSrcPath()) {
|
||||||
Arrival arrival = arrivals[arrival_index];
|
Arrival arrival = arrivals[arrival_index];
|
||||||
PathVertexRep *prev_path = prev_paths
|
PathPrev *prev_path = prev_paths
|
||||||
? &prev_paths[arrival_index]
|
? &prev_paths[arrival_index]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
tag_bldr->setArrival(tag, arrival, prev_path);
|
tag_bldr->setArrival(tag, arrival, prev_path);
|
||||||
|
|
@ -903,7 +903,7 @@ Genclks::recordSrcPaths(Clock *gclk)
|
||||||
bool has_edges = gclk->edges() != nullptr;
|
bool has_edges = gclk->edges() != nullptr;
|
||||||
|
|
||||||
for (const Pin *gclk_pin : gclk->leafPins()) {
|
for (const Pin *gclk_pin : gclk->leafPins()) {
|
||||||
PathVertexRep *src_paths = new PathVertexRep[path_count];
|
PathVertexPtr *src_paths = new PathVertexPtr[path_count];
|
||||||
genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths);
|
genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths);
|
||||||
|
|
||||||
Vertex *gclk_vertex = srcPathVertex(gclk_pin);
|
Vertex *gclk_vertex = srcPathVertex(gclk_pin);
|
||||||
|
|
@ -920,7 +920,7 @@ Genclks::recordSrcPaths(Clock *gclk)
|
||||||
bool inverting_path = (rf != src_clk_rf);
|
bool inverting_path = (rf != src_clk_rf);
|
||||||
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
||||||
int path_index = srcPathIndex(rf, path_ap);
|
int path_index = srcPathIndex(rf, path_ap);
|
||||||
PathVertexRep &src_path = src_paths[path_index];
|
PathVertexPtr &src_path = src_paths[path_index];
|
||||||
if ((!divide_by_1
|
if ((!divide_by_1
|
||||||
|| (inverting_path == invert))
|
|| (inverting_path == invert))
|
||||||
&& (!has_edges
|
&& (!has_edges
|
||||||
|
|
@ -973,47 +973,40 @@ Genclks::matchesSrcFilter(Path *path,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
PathVertex
|
||||||
Genclks::srcPath(Path *clk_path,
|
Genclks::srcPath(Path *clk_path) const
|
||||||
// Return value.
|
|
||||||
PathVertex &src_path) const
|
|
||||||
{
|
{
|
||||||
const Pin *src_pin = clk_path->pin(this);
|
const Pin *src_pin = clk_path->pin(this);
|
||||||
const ClockEdge *clk_edge = clk_path->clkEdge(this);
|
const ClockEdge *clk_edge = clk_path->clkEdge(this);
|
||||||
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this);
|
const PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this);
|
||||||
const EarlyLate *early_late = clk_path->minMax(this);
|
const EarlyLate *early_late = clk_path->minMax(this);
|
||||||
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
|
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
|
||||||
srcPath(clk_edge->clock(), src_pin, clk_edge->transition(),
|
return srcPath(clk_edge->clock(), src_pin, clk_edge->transition(),
|
||||||
insert_ap, src_path);
|
insert_ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
PathVertex
|
||||||
Genclks::srcPath(const ClockEdge *clk_edge,
|
Genclks::srcPath(const ClockEdge *clk_edge,
|
||||||
const Pin *src_pin,
|
const Pin *src_pin,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap) const
|
||||||
// Return value.
|
|
||||||
PathVertex &src_path) const
|
|
||||||
{
|
{
|
||||||
srcPath(clk_edge->clock(), src_pin, clk_edge->transition(),
|
return srcPath(clk_edge->clock(), src_pin, clk_edge->transition(), path_ap);
|
||||||
path_ap, src_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
PathVertex
|
||||||
Genclks::srcPath(const Clock *gclk,
|
Genclks::srcPath(const Clock *gclk,
|
||||||
const Pin *src_pin,
|
const Pin *src_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap) const
|
||||||
// Return value.
|
|
||||||
PathVertex &src_path) const
|
|
||||||
{
|
{
|
||||||
PathVertexRep *src_paths =
|
PathVertexPtr *src_paths =
|
||||||
genclk_src_paths_.findKey(ClockPinPair(gclk, src_pin));
|
genclk_src_paths_.findKey(ClockPinPair(gclk, src_pin));
|
||||||
if (src_paths) {
|
if (src_paths) {
|
||||||
int path_index = srcPathIndex(rf, path_ap);
|
int path_index = srcPathIndex(rf, path_ap);
|
||||||
src_path.init(src_paths[path_index], this);
|
return PathVertex(src_paths[path_index], this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
src_path.init();
|
return PathVertex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Arrival
|
Arrival
|
||||||
|
|
@ -1023,9 +1016,8 @@ Genclks::insertionDelay(const Clock *clk,
|
||||||
const EarlyLate *early_late,
|
const EarlyLate *early_late,
|
||||||
const PathAnalysisPt *path_ap) const
|
const PathAnalysisPt *path_ap) const
|
||||||
{
|
{
|
||||||
PathVertex src_path;
|
|
||||||
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
|
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
|
||||||
srcPath(clk, pin, rf, insert_ap, src_path);
|
PathVertex src_path = srcPath(clk, pin, rf, insert_ap);
|
||||||
if (!src_path.isNull())
|
if (!src_path.isNull())
|
||||||
return src_path.arrival(this);
|
return src_path.arrival(this);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Map<Clock*, GenclkInfo*> GenclkInfoMap;
|
typedef Map<Clock*, GenclkInfo*> GenclkInfoMap;
|
||||||
typedef Map<ClockPinPair, PathVertexRep*, ClockPinPairLess> GenclkSrcPathMap;
|
typedef Map<ClockPinPair, PathVertexPtr*, ClockPinPairLess> GenclkSrcPathMap;
|
||||||
|
|
||||||
class Genclks : public StaState
|
class Genclks : public StaState
|
||||||
{
|
{
|
||||||
|
|
@ -71,21 +71,15 @@ public:
|
||||||
const EarlyLate *early_late,
|
const EarlyLate *early_late,
|
||||||
const PathAnalysisPt *path_ap) const;
|
const PathAnalysisPt *path_ap) const;
|
||||||
// Generated clock source path for a clock path root.
|
// Generated clock source path for a clock path root.
|
||||||
void srcPath(Path *clk_path,
|
PathVertex srcPath(Path *clk_path) const;
|
||||||
// Return value.
|
|
||||||
PathVertex &src_path) const;
|
|
||||||
// Generated clock source path.
|
// Generated clock source path.
|
||||||
void srcPath(const ClockEdge *clk_edge,
|
PathVertex srcPath(const ClockEdge *clk_edge,
|
||||||
const Pin *src_pin,
|
const Pin *src_pin,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap) const;
|
||||||
// Return value.
|
PathVertex srcPath(const Clock *clk,
|
||||||
PathVertex &src_path) const;
|
const Pin *src_pin,
|
||||||
void srcPath(const Clock *clk,
|
const RiseFall *rf,
|
||||||
const Pin *src_pin,
|
const PathAnalysisPt *path_ap) const;
|
||||||
const RiseFall *rf,
|
|
||||||
const PathAnalysisPt *path_ap,
|
|
||||||
// Return value.
|
|
||||||
PathVertex &src_path) const;
|
|
||||||
Vertex *srcPathVertex(const Pin *pin) const;
|
Vertex *srcPathVertex(const Pin *pin) const;
|
||||||
Level clkPinMaxLevel(const Clock *clk) const;
|
Level clkPinMaxLevel(const Clock *clk) const;
|
||||||
void copyGenClkSrcPaths(Vertex *vertex,
|
void copyGenClkSrcPaths(Vertex *vertex,
|
||||||
|
|
|
||||||
|
|
@ -354,13 +354,15 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
|
||||||
PathEnumed *after_div_copy;
|
PathEnumed *after_div_copy;
|
||||||
// Make the diverted path end to check slack with from_path crpr.
|
// Make the diverted path end to check slack with from_path crpr.
|
||||||
makeDivertedPathEnd(from_path, arc, div_end, after_div_copy);
|
makeDivertedPathEnd(from_path, arc, div_end, after_div_copy);
|
||||||
// Only enumerate paths with greater slack.
|
if (div_end) {
|
||||||
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
|
// Only enumerate paths with greater slack.
|
||||||
reportDiversion(arc, from_path);
|
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
|
||||||
path_enum_->makeDiversion(div_end, after_div_copy);
|
reportDiversion(arc, from_path);
|
||||||
|
path_enum_->makeDiversion(div_end, after_div_copy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete div_end;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
delete div_end;
|
|
||||||
}
|
}
|
||||||
// Only enumerate slower/faster paths.
|
// Only enumerate slower/faster paths.
|
||||||
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) {
|
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) {
|
||||||
|
|
@ -384,8 +386,12 @@ PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
|
||||||
PathEnumed *div_path;
|
PathEnumed *div_path;
|
||||||
path_enum_->makeDivertedPath(path_end_->path(), &before_div_, after_div,
|
path_enum_->makeDivertedPath(path_end_->path(), &before_div_, after_div,
|
||||||
div_arc, div_path, after_div_copy);
|
div_arc, div_path, after_div_copy);
|
||||||
div_end = path_end_->copy();
|
if (after_div_copy) {
|
||||||
div_end->setPath(div_path);
|
div_end = path_end_->copy();
|
||||||
|
div_end->setPath(div_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
div_end = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -539,17 +545,15 @@ PathEnum::makeDivertedPath(Path *path,
|
||||||
PathEnumed *&div_path,
|
PathEnumed *&div_path,
|
||||||
PathEnumed *&after_div_copy)
|
PathEnumed *&after_div_copy)
|
||||||
{
|
{
|
||||||
|
div_path = nullptr;
|
||||||
|
after_div_copy = nullptr;
|
||||||
// Copy the diversion path.
|
// Copy the diversion path.
|
||||||
bool found_div = false;
|
bool found_div = false;
|
||||||
PathEnumedSeq copies;
|
PathEnumedSeq copies;
|
||||||
PathRef p(path);
|
PathRef p(path);
|
||||||
bool first = true;
|
bool first = true;
|
||||||
PathEnumed *prev_copy = nullptr;
|
PathEnumed *prev_copy = nullptr;
|
||||||
VertexSet visited(graph_);
|
while (!p.isNull()) {
|
||||||
while (!p.isNull()
|
|
||||||
// Break latch loops.
|
|
||||||
&& !visited.hasKey(p.vertex(this))) {
|
|
||||||
visited.insert(p.vertex(this));
|
|
||||||
PathRef prev;
|
PathRef prev;
|
||||||
TimingArc *prev_arc;
|
TimingArc *prev_arc;
|
||||||
p.prevPath(this, prev, prev_arc);
|
p.prevPath(this, prev, prev_arc);
|
||||||
|
|
@ -562,10 +566,12 @@ PathEnum::makeDivertedPath(Path *path,
|
||||||
prev_copy->setPrevPath(copy);
|
prev_copy->setPrevPath(copy);
|
||||||
copies.push_back(copy);
|
copies.push_back(copy);
|
||||||
|
|
||||||
if (first)
|
|
||||||
div_path = copy;
|
|
||||||
if (Path::equal(&p, after_div, this))
|
if (Path::equal(&p, after_div, this))
|
||||||
after_div_copy = copy;
|
after_div_copy = copy;
|
||||||
|
if (first)
|
||||||
|
div_path = copy;
|
||||||
|
else if (network_->isLatchData(p.pin(this)))
|
||||||
|
break;
|
||||||
if (Path::equal(&p, before_div, this)) {
|
if (Path::equal(&p, before_div, this)) {
|
||||||
copy->setPrevArc(div_arc);
|
copy->setPrevArc(div_arc);
|
||||||
// Update the delays forward from before_div to the end of the path.
|
// Update the delays forward from before_div to the end of the path.
|
||||||
|
|
@ -598,7 +604,7 @@ PathEnum::updatePathHeadDelays(PathEnumedSeq &paths,
|
||||||
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_),
|
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_),
|
||||||
arc, edge, false, path_ap);
|
arc, edge, false, path_ap);
|
||||||
Arrival arrival = prev_arrival + arc_delay;
|
Arrival arrival = prev_arrival + arc_delay;
|
||||||
debugPrint(debug_, "path_enum", 3, "update arrival %s %s %s -> %s",
|
debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s",
|
||||||
path->vertex(this)->name(network_),
|
path->vertex(this)->name(network_),
|
||||||
path->tag(this)->asString(this),
|
path->tag(this)->asString(this),
|
||||||
delayAsString(path->arrival(this), this),
|
delayAsString(path->arrival(this), this),
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,7 @@ PathExpanded::expandGenclk(PathRef *clk_path)
|
||||||
if (!clk_path->isNull()) {
|
if (!clk_path->isNull()) {
|
||||||
const Clock *src_clk = clk_path->clock(sta_);
|
const Clock *src_clk = clk_path->clock(sta_);
|
||||||
if (src_clk && src_clk->isGenerated()) {
|
if (src_clk && src_clk->isGenerated()) {
|
||||||
PathVertex src_path;
|
PathVertex src_path = sta_->search()->genclks()->srcPath(clk_path);
|
||||||
sta_->search()->genclks()->srcPath(clk_path, src_path);
|
|
||||||
if (!src_path.isNull()) {
|
if (!src_path.isNull()) {
|
||||||
// The head of the genclk src path is already in paths_,
|
// The head of the genclk src path is already in paths_,
|
||||||
// so skip past it.
|
// so skip past it.
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ PathGroup::saveable(PathEnd *path_end)
|
||||||
|
|
||||||
// endpoint_path_count > 1 with slack_min requires
|
// endpoint_path_count > 1 with slack_min requires
|
||||||
// saving endpoints with slack > slack_min so that
|
// saving endpoints with slack > slack_min so that
|
||||||
// path enumeration can find them. Use the patg end
|
// path enumeration can find them. Use the path end
|
||||||
// with the min(max) delay to prune ends that cannot
|
// with the min(max) delay to prune ends that cannot
|
||||||
// onion peel down to slack_min.
|
// onion peel down to slack_min.
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#include "PathPrev.hh"
|
||||||
|
|
||||||
|
#include "Graph.hh"
|
||||||
|
#include "TimingArc.hh"
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
#include "Tag.hh"
|
||||||
|
#include "TagGroup.hh"
|
||||||
|
#include "Search.hh"
|
||||||
|
#include "PathAnalysisPt.hh"
|
||||||
|
#include "PathVertex.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
PathPrev::PathPrev()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init()
|
||||||
|
{
|
||||||
|
prev_edge_id_ = edge_id_null;
|
||||||
|
prev_arc_idx_ = 0;
|
||||||
|
prev_tag_index_ = tag_index_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init(const PathPrev *path)
|
||||||
|
{
|
||||||
|
if (path) {
|
||||||
|
prev_edge_id_ = path->prev_edge_id_;
|
||||||
|
prev_arc_idx_ = path->prev_arc_idx_;
|
||||||
|
prev_tag_index_ = path->prev_tag_index_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init(const PathPrev &path)
|
||||||
|
{
|
||||||
|
prev_edge_id_ = path.prev_edge_id_;
|
||||||
|
prev_arc_idx_ = path.prev_arc_idx_;
|
||||||
|
prev_tag_index_ = path.prev_tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::init(const PathVertex *path,
|
||||||
|
const Edge *prev_edge,
|
||||||
|
const TimingArc *prev_arc,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (path == nullptr || path->isNull())
|
||||||
|
init();
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
prev_edge_id_ = graph->id(prev_edge);
|
||||||
|
prev_arc_idx_ = prev_arc->index();
|
||||||
|
prev_tag_index_ = path->tag(sta)->index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
PathPrev::name(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Network *network = sta->network();
|
||||||
|
const Search *search = sta->search();
|
||||||
|
Vertex *vertex = this->vertex(sta);
|
||||||
|
if (vertex) {
|
||||||
|
const char *vertex_name = vertex->name(network);
|
||||||
|
const Tag *tag = this->tag(search);
|
||||||
|
const RiseFall *rf = tag->transition();
|
||||||
|
const char *rf_str = rf->asString();
|
||||||
|
const PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta);
|
||||||
|
int ap_index = path_ap->index();
|
||||||
|
const char *min_max = path_ap->pathMinMax()->asString();
|
||||||
|
TagIndex tag_index = tag->index();
|
||||||
|
return stringPrintTmp("%s %s %s/%d %d",
|
||||||
|
vertex_name, rf_str, min_max,
|
||||||
|
ap_index, tag_index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathPrev::isNull() const
|
||||||
|
{
|
||||||
|
return prev_edge_id_ == edge_id_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexId
|
||||||
|
PathPrev::vertexId(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return vertex_id_null;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
const Edge *edge = graph->edge(prev_edge_id_);
|
||||||
|
return edge->from();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex *
|
||||||
|
PathPrev::vertex(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
const Edge *edge = graph->edge(prev_edge_id_);
|
||||||
|
return edge->from(graph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Edge *
|
||||||
|
PathPrev::prevEdge(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
return graph->edge(prev_edge_id_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TimingArc *
|
||||||
|
PathPrev::prevArc(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (prev_edge_id_ == edge_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
const Edge *edge = graph->edge(prev_edge_id_);
|
||||||
|
TimingArcSet *arc_set = edge->timingArcSet();
|
||||||
|
return arc_set->findTimingArc(prev_arc_idx_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag *
|
||||||
|
PathPrev::tag(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Search *search = sta->search();
|
||||||
|
return search->tag(prev_tag_index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrival
|
||||||
|
PathPrev::arrival(const StaState *sta) const
|
||||||
|
{
|
||||||
|
Graph *graph = sta->graph();
|
||||||
|
const Search *search = sta->search();
|
||||||
|
Tag *tag = search->tag(prev_tag_index_);
|
||||||
|
Vertex *vertex = this->vertex(sta);
|
||||||
|
TagGroup *tag_group = search->tagGroup(vertex);
|
||||||
|
if (tag_group) {
|
||||||
|
int arrival_index;
|
||||||
|
bool arrival_exists;
|
||||||
|
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
||||||
|
if (!arrival_exists)
|
||||||
|
sta->report()->critical(1420, "tag group missing tag");
|
||||||
|
Arrival *arrivals = graph->arrivals(vertex);
|
||||||
|
if (arrivals)
|
||||||
|
return arrivals[arrival_index];
|
||||||
|
else
|
||||||
|
sta->report()->critical(1421, "missing arrivals");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sta->report()->error(1422, "missing arrivals.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathPrev::prevPath(const StaState *sta,
|
||||||
|
// Return values.
|
||||||
|
PathRef &prev_path,
|
||||||
|
TimingArc *&prev_arc) const
|
||||||
|
{
|
||||||
|
PathVertex path_vertex(this, sta);
|
||||||
|
path_vertex.prevPath(sta, prev_path, prev_arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathPrev::equal(const PathPrev *path1,
|
||||||
|
const PathPrev *path2)
|
||||||
|
{
|
||||||
|
return path1->prev_edge_id_ == path2->prev_edge_id_
|
||||||
|
&& path1->prev_tag_index_ == path2->prev_tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathPrev::equal(const PathPrev &path1,
|
||||||
|
const PathPrev &path2)
|
||||||
|
{
|
||||||
|
return path1.prev_edge_id_ == path2.prev_edge_id_
|
||||||
|
&& path1.prev_tag_index_ == path2.prev_tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PathPrev::cmp(const PathPrev &path1,
|
||||||
|
const PathPrev &path2)
|
||||||
|
{
|
||||||
|
EdgeId edge_id1 = path1.prev_edge_id_;
|
||||||
|
EdgeId edge_id2 = path2.prev_edge_id_;
|
||||||
|
if (edge_id1 == edge_id2) {
|
||||||
|
TagIndex tag_index1 = path1.prev_tag_index_;
|
||||||
|
TagIndex tag_index2 = path2.prev_tag_index_;
|
||||||
|
if (tag_index1 == tag_index2)
|
||||||
|
return 0;
|
||||||
|
else if (tag_index1 < tag_index2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (edge_id1 < edge_id2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -96,6 +96,26 @@ PathRef::init(const PathVertex &path)
|
||||||
path_vertex_ = path;
|
path_vertex_ = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathRef::init(const PathPrev &path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
int arrival_index = 0;
|
||||||
|
TagIndex tag_index = path.tagIndex();
|
||||||
|
Tag *tag = nullptr;
|
||||||
|
if (tag_index != tag_index_null) {
|
||||||
|
const Search *search = sta->search();
|
||||||
|
tag = search->tag(tag_index);
|
||||||
|
Vertex *vertex = path.vertex(sta);
|
||||||
|
TagGroup *tag_group = search->tagGroup(vertex);
|
||||||
|
if (tag_group) {
|
||||||
|
bool arrival_exists;
|
||||||
|
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path_vertex_.init(path.vertex(sta), tag, arrival_index);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathRef::init(Vertex *vertex,
|
PathRef::init(Vertex *vertex,
|
||||||
Tag *tag,
|
Tag *tag,
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@
|
||||||
#include "TagGroup.hh"
|
#include "TagGroup.hh"
|
||||||
#include "PathAnalysisPt.hh"
|
#include "PathAnalysisPt.hh"
|
||||||
#include "PathRef.hh"
|
#include "PathRef.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
|
#include "PathVertexPtr.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -83,7 +84,7 @@ PathVertex::PathVertex(Vertex *vertex,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertex::PathVertex(const PathVertexRep *path,
|
PathVertex::PathVertex(const PathPrev *path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (path)
|
if (path)
|
||||||
|
|
@ -92,7 +93,16 @@ PathVertex::PathVertex(const PathVertexRep *path,
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
PathVertex::PathVertex(const PathVertexRep &path,
|
PathVertex::PathVertex(const PathPrev &path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (path.isNull())
|
||||||
|
init();
|
||||||
|
else
|
||||||
|
init(path.vertex(sta), path.tag(sta), sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
PathVertex::PathVertex(const PathVertexPtr &path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (path.isNull())
|
if (path.isNull())
|
||||||
|
|
@ -140,7 +150,7 @@ PathVertex::init(Vertex *vertex,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathVertex::init(const PathVertexRep *path,
|
PathVertex::init(const PathPrev *path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (path)
|
if (path)
|
||||||
|
|
@ -150,7 +160,17 @@ PathVertex::init(const PathVertexRep *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PathVertex::init(const PathVertexRep &path,
|
PathVertex::init(const PathPrev &path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (!path.isNull())
|
||||||
|
init(path.vertex(sta), path.tag(sta), sta);
|
||||||
|
else
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertex::init(const PathVertexPtr &path,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
if (!path.isNull())
|
if (!path.isNull())
|
||||||
|
|
@ -481,9 +501,19 @@ PathVertex::prevPath(const StaState *sta,
|
||||||
PathRef &prev_path,
|
PathRef &prev_path,
|
||||||
TimingArc *&prev_arc) const
|
TimingArc *&prev_arc) const
|
||||||
{
|
{
|
||||||
PathVertex prev;
|
const Graph *graph = sta->graph();
|
||||||
prevPath(sta, prev, prev_arc);
|
Vertex *vertex = this->vertex(graph);
|
||||||
prev.setRef(prev_path);
|
PathPrev *prev_paths = vertex->prevPaths();
|
||||||
|
if (prev_paths) {
|
||||||
|
PathPrev &prev = prev_paths[arrival_index_];
|
||||||
|
prev_path.init(prev, sta);
|
||||||
|
prev_arc = prev.isNull() ? nullptr : prev.prevArc(sta);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PathVertex prev;
|
||||||
|
prevPath(sta, prev, prev_arc);
|
||||||
|
prev.setRef(prev_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2025, Parallax Software, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software.
|
||||||
|
//
|
||||||
|
// Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#include "PathVertexPtr.hh"
|
||||||
|
|
||||||
|
#include "Graph.hh"
|
||||||
|
#include "TimingArc.hh"
|
||||||
|
#include "SearchClass.hh"
|
||||||
|
#include "Tag.hh"
|
||||||
|
#include "TagGroup.hh"
|
||||||
|
#include "Search.hh"
|
||||||
|
#include "PathAnalysisPt.hh"
|
||||||
|
#include "PathVertex.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
PathVertexPtr::PathVertexPtr() :
|
||||||
|
vertex_id_(vertex_id_null),
|
||||||
|
tag_index_(tag_index_null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PathVertexPtr::PathVertexPtr(const PathVertex *path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
init(path, sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init()
|
||||||
|
{
|
||||||
|
vertex_id_ = vertex_id_null;
|
||||||
|
tag_index_ = tag_index_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init(const PathVertexPtr *path)
|
||||||
|
{
|
||||||
|
if (path) {
|
||||||
|
vertex_id_ = path->vertex_id_;
|
||||||
|
tag_index_ = path->tag_index_;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertex_id_ = vertex_id_null;
|
||||||
|
tag_index_ = tag_index_null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init(const PathVertexPtr &path)
|
||||||
|
{
|
||||||
|
vertex_id_ = path.vertex_id_;
|
||||||
|
tag_index_ = path.tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PathVertexPtr::init(const PathVertex *path,
|
||||||
|
const StaState *sta)
|
||||||
|
{
|
||||||
|
if (path == nullptr || path->isNull())
|
||||||
|
init();
|
||||||
|
else {
|
||||||
|
vertex_id_ = path->vertexId(sta);
|
||||||
|
tag_index_ = path->tagIndex(sta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
PathVertexPtr::name(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Network *network = sta->network();
|
||||||
|
const Search *search = sta->search();
|
||||||
|
Vertex *vertex = this->vertex(sta);
|
||||||
|
if (vertex) {
|
||||||
|
const char *vertex_name = vertex->name(network);
|
||||||
|
const Tag *tag = this->tag(search);
|
||||||
|
const RiseFall *rf = tag->transition();
|
||||||
|
const char *rf_str = rf->asString();
|
||||||
|
const PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta);
|
||||||
|
int ap_index = path_ap->index();
|
||||||
|
const char *min_max = path_ap->pathMinMax()->asString();
|
||||||
|
TagIndex tag_index = tag->index();
|
||||||
|
return stringPrintTmp("%s %s %s/%d %d",
|
||||||
|
vertex_name, rf_str, min_max,
|
||||||
|
ap_index, tag_index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathVertexPtr::isNull() const
|
||||||
|
{
|
||||||
|
return vertex_id_ == vertex_id_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex *
|
||||||
|
PathVertexPtr::vertex(const StaState *sta) const
|
||||||
|
{
|
||||||
|
if (vertex_id_ == vertex_id_null)
|
||||||
|
return nullptr;
|
||||||
|
else {
|
||||||
|
const Graph *graph = sta->graph();
|
||||||
|
return graph->vertex(vertex_id_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag *
|
||||||
|
PathVertexPtr::tag(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Search *search = sta->search();
|
||||||
|
return search->tag(tag_index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrival
|
||||||
|
PathVertexPtr::arrival(const StaState *sta) const
|
||||||
|
{
|
||||||
|
const Vertex *vertex = this->vertex(sta);
|
||||||
|
Arrival *arrivals = sta->graph()->arrivals(vertex);
|
||||||
|
if (arrivals) {
|
||||||
|
const Search *search = sta->search();
|
||||||
|
TagGroup *tag_group = search->tagGroup(vertex);
|
||||||
|
Tag *tag = this->tag(sta);
|
||||||
|
int arrival_index;
|
||||||
|
bool arrival_exists;
|
||||||
|
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
||||||
|
if (arrival_exists)
|
||||||
|
return arrivals[arrival_index];
|
||||||
|
else {
|
||||||
|
sta->report()->error(1403, "missing arrival.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sta->report()->error(1404, "missing arrivals.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathVertexPtr::equal(const PathVertexPtr *path1,
|
||||||
|
const PathVertexPtr *path2)
|
||||||
|
{
|
||||||
|
return path1->vertex_id_ == path2->vertex_id_
|
||||||
|
&& path1->tag_index_ == path2->tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathVertexPtr::equal(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2)
|
||||||
|
{
|
||||||
|
return path1.vertex_id_ == path2.vertex_id_
|
||||||
|
&& path1.tag_index_ == path2.tag_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PathVertexPtr::cmp(const PathVertexPtr &path1,
|
||||||
|
const PathVertexPtr &path2)
|
||||||
|
{
|
||||||
|
VertexId vertex_id1 = path1.vertex_id_;
|
||||||
|
VertexId vertex_id2 = path2.vertex_id_;
|
||||||
|
if (vertex_id1 == vertex_id2) {
|
||||||
|
TagIndex tag_index1 = path1.tagIndex();
|
||||||
|
TagIndex tag_index2 = path2.tagIndex();
|
||||||
|
if (tag_index1 == tag_index2)
|
||||||
|
return 0;
|
||||||
|
else if (tag_index1 < tag_index2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (vertex_id1 < vertex_id2)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -1,246 +0,0 @@
|
||||||
// OpenSTA, Static Timing Analyzer
|
|
||||||
// Copyright (c) 2025, Parallax Software, Inc.
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
//
|
|
||||||
// The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software.
|
|
||||||
//
|
|
||||||
// Altered source versions must be plainly marked as such, and must not be
|
|
||||||
// misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
#include "PathVertexRep.hh"
|
|
||||||
|
|
||||||
#include "Graph.hh"
|
|
||||||
#include "SearchClass.hh"
|
|
||||||
#include "Tag.hh"
|
|
||||||
#include "TagGroup.hh"
|
|
||||||
#include "Search.hh"
|
|
||||||
#include "PathVertex.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep()
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertexRep *path)
|
|
||||||
{
|
|
||||||
init(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertexRep &path)
|
|
||||||
{
|
|
||||||
init(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertex *path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
init(path, sta);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(const PathVertex &path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
init(path, sta);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathVertexRep::PathVertexRep(VertexId vertex_id,
|
|
||||||
TagIndex tag_index,
|
|
||||||
bool is_enum) :
|
|
||||||
vertex_id_(vertex_id),
|
|
||||||
tag_index_(tag_index),
|
|
||||||
is_enum_(is_enum)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init()
|
|
||||||
{
|
|
||||||
vertex_id_ = 0;
|
|
||||||
tag_index_ = tag_index_null;
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertexRep *path)
|
|
||||||
{
|
|
||||||
if (path) {
|
|
||||||
vertex_id_ = path->vertex_id_;
|
|
||||||
tag_index_ = path->tag_index_;
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertexRep &path)
|
|
||||||
{
|
|
||||||
vertex_id_ = path.vertex_id_;
|
|
||||||
tag_index_ = path.tag_index_;
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertex *path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
if (path == nullptr || path->isNull())
|
|
||||||
init();
|
|
||||||
else {
|
|
||||||
vertex_id_ = sta->graph()->id(path->vertex(sta));
|
|
||||||
tag_index_ = path->tag(sta)->index();
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::init(const PathVertex &path,
|
|
||||||
const StaState *sta)
|
|
||||||
{
|
|
||||||
if (path.isNull())
|
|
||||||
init();
|
|
||||||
else {
|
|
||||||
vertex_id_ = sta->graph()->id(path.vertex(sta));
|
|
||||||
tag_index_ = path.tag(sta)->index();
|
|
||||||
is_enum_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vertex *
|
|
||||||
PathVertexRep::vertex(const StaState *sta) const
|
|
||||||
{
|
|
||||||
const Graph *graph = sta->graph();
|
|
||||||
return graph->vertex(vertex_id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Tag *
|
|
||||||
PathVertexRep::tag(const StaState *sta) const
|
|
||||||
{
|
|
||||||
const Search *search = sta->search();
|
|
||||||
return search->tag(tag_index_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Arrival
|
|
||||||
PathVertexRep::arrival(const StaState *sta) const
|
|
||||||
{
|
|
||||||
Graph *graph = sta->graph();
|
|
||||||
const Search *search = sta->search();
|
|
||||||
Tag *tag = search->tag(tag_index_);
|
|
||||||
Vertex *vertex = graph->vertex(vertex_id_);
|
|
||||||
TagGroup *tag_group = search->tagGroup(vertex);
|
|
||||||
if (tag_group) {
|
|
||||||
int arrival_index;
|
|
||||||
bool arrival_exists;
|
|
||||||
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
|
||||||
if (!arrival_exists)
|
|
||||||
sta->report()->critical(1420, "tag group missing tag");
|
|
||||||
Arrival *arrivals = graph->arrivals(vertex);
|
|
||||||
if (arrivals)
|
|
||||||
return arrivals[arrival_index];
|
|
||||||
else
|
|
||||||
sta->report()->critical(1421, "missing arrivals");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sta->report()->error(1422, "missing arrivals.");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PathVertexRep::prevPath(const StaState *sta,
|
|
||||||
// Return values.
|
|
||||||
PathRef &prev_path,
|
|
||||||
TimingArc *&prev_arc) const
|
|
||||||
{
|
|
||||||
PathVertex path_vertex(this, sta);
|
|
||||||
path_vertex.prevPath(sta, prev_path, prev_arc);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
bool
|
|
||||||
PathVertexRep::equal(const PathVertexRep *path1,
|
|
||||||
const PathVertexRep *path2)
|
|
||||||
{
|
|
||||||
return path1->vertex_id_ == path2->vertex_id_
|
|
||||||
&& path1->tag_index_ == path2->tag_index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PathVertexRep::equal(const PathVertexRep &path1,
|
|
||||||
const PathVertexRep &path2)
|
|
||||||
{
|
|
||||||
return path1.vertex_id_ == path2.vertex_id_
|
|
||||||
&& path1.tag_index_ == path2.tag_index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PathVertexRep::cmp(const PathVertexRep *path1,
|
|
||||||
const PathVertexRep *path2)
|
|
||||||
{
|
|
||||||
if (path1 && path2) {
|
|
||||||
VertexId vertex_id1 = path1->vertexId();
|
|
||||||
VertexId vertex_id2 = path2->vertexId();
|
|
||||||
if (vertex_id1 == vertex_id2) {
|
|
||||||
TagIndex tag_index1 = path1->tagIndex();
|
|
||||||
TagIndex tag_index2 = path2->tagIndex();
|
|
||||||
if (tag_index1 == tag_index2)
|
|
||||||
return 0;
|
|
||||||
else if (tag_index1 < tag_index2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (vertex_id1 < vertex_id2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (path1 == nullptr
|
|
||||||
&& path2 == nullptr)
|
|
||||||
return 0;
|
|
||||||
else if (path1 == nullptr)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PathVertexRep::cmp(const PathVertexRep &path1,
|
|
||||||
const PathVertexRep &path2)
|
|
||||||
{
|
|
||||||
VertexId vertex_id1 = path1.vertexId();
|
|
||||||
VertexId vertex_id2 = path2.vertexId();
|
|
||||||
if (vertex_id1 == vertex_id2) {
|
|
||||||
TagIndex tag_index1 = path1.tagIndex();
|
|
||||||
TagIndex tag_index2 = path2.tagIndex();
|
|
||||||
if (tag_index1 == tag_index2)
|
|
||||||
return 0;
|
|
||||||
else if (tag_index1 < tag_index2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (vertex_id1 < vertex_id2)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
@ -2394,9 +2394,9 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
|
||||||
bool clk_used_as_data) const
|
bool clk_used_as_data) const
|
||||||
{
|
{
|
||||||
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
|
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
|
||||||
PathVertex src_path;
|
|
||||||
const MinMax *min_max = path_ap->pathMinMax();
|
const MinMax *min_max = path_ap->pathMinMax();
|
||||||
search_->genclks()->srcPath(clk, clk_pin, clk_rf, insert_ap, src_path);
|
PathVertex src_path =
|
||||||
|
search_->genclks()->srcPath(clk, clk_pin, clk_rf, insert_ap);
|
||||||
if (!src_path.isNull()) {
|
if (!src_path.isNull()) {
|
||||||
ClkInfo *src_clk_info = src_path.clkInfo(search_);
|
ClkInfo *src_clk_info = src_path.clkInfo(search_);
|
||||||
const ClockEdge *src_clk_edge = src_clk_info->clkEdge();
|
const ClockEdge *src_clk_edge = src_clk_info->clkEdge();
|
||||||
|
|
|
||||||
101
search/Search.cc
101
search/Search.cc
|
|
@ -55,7 +55,7 @@
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
#include "Sim.hh"
|
#include "Sim.hh"
|
||||||
#include "PathVertex.hh"
|
#include "PathVertex.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
#include "PathRef.hh"
|
#include "PathRef.hh"
|
||||||
#include "ClkInfo.hh"
|
#include "ClkInfo.hh"
|
||||||
#include "Tag.hh"
|
#include "Tag.hh"
|
||||||
|
|
@ -255,6 +255,7 @@ Search::init(StaState *sta)
|
||||||
path_groups_ = nullptr;
|
path_groups_ = nullptr;
|
||||||
endpoints_ = nullptr;
|
endpoints_ = nullptr;
|
||||||
invalid_endpoints_ = nullptr;
|
invalid_endpoints_ = nullptr;
|
||||||
|
always_save_prev_paths_ = true;
|
||||||
filter_ = nullptr;
|
filter_ = nullptr;
|
||||||
filter_from_ = nullptr;
|
filter_from_ = nullptr;
|
||||||
filter_to_ = nullptr;
|
filter_to_ = nullptr;
|
||||||
|
|
@ -786,13 +787,6 @@ Search::arrivalInvalid(Vertex *vertex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Search::arrivalInvalidDelete(Vertex *vertex)
|
|
||||||
{
|
|
||||||
arrivalInvalid(vertex);
|
|
||||||
deletePaths(vertex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Search::levelChangedBefore(Vertex *vertex)
|
Search::levelChangedBefore(Vertex *vertex)
|
||||||
{
|
{
|
||||||
|
|
@ -1072,7 +1066,8 @@ Search::findArrivalsSeed()
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
|
ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
|
||||||
PathVisitor(nullptr, sta)
|
PathVisitor(nullptr, sta),
|
||||||
|
always_save_prev_paths_(true)
|
||||||
{
|
{
|
||||||
init0();
|
init0();
|
||||||
init(true);
|
init(true);
|
||||||
|
|
@ -1109,6 +1104,8 @@ ArrivalVisitor::init(bool always_to_endpoints,
|
||||||
always_to_endpoints_ = always_to_endpoints;
|
always_to_endpoints_ = always_to_endpoints;
|
||||||
pred_ = pred;
|
pred_ = pred;
|
||||||
crpr_active_ = sdc_->crprActive();
|
crpr_active_ = sdc_->crprActive();
|
||||||
|
if (search_)
|
||||||
|
always_save_prev_paths_ = search_->alwaysSavePrevPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1241,6 +1238,7 @@ Search::arrivalsChanged(Vertex *vertex,
|
||||||
TagGroupBldr *tag_bldr)
|
TagGroupBldr *tag_bldr)
|
||||||
{
|
{
|
||||||
Arrival *arrivals1 = graph_->arrivals(vertex);
|
Arrival *arrivals1 = graph_->arrivals(vertex);
|
||||||
|
PathPrev *prev_paths1 = graph_->prevPaths(vertex);
|
||||||
if (arrivals1) {
|
if (arrivals1) {
|
||||||
TagGroup *tag_group = tagGroup(vertex);
|
TagGroup *tag_group = tagGroup(vertex);
|
||||||
if (tag_group == nullptr
|
if (tag_group == nullptr
|
||||||
|
|
@ -1257,7 +1255,10 @@ Search::arrivalsChanged(Vertex *vertex,
|
||||||
int arrival_index2;
|
int arrival_index2;
|
||||||
tag_bldr->tagMatchArrival(tag1, tag2, arrival2, arrival_index2);
|
tag_bldr->tagMatchArrival(tag1, tag2, arrival2, arrival_index2);
|
||||||
if (tag2 != tag1
|
if (tag2 != tag1
|
||||||
|| !delayEqual(arrival1, arrival2))
|
|| !delayEqual(arrival1, arrival2)
|
||||||
|
|| (prev_paths1
|
||||||
|
&& !PathPrev::equal(prev_paths1[arrival_index1],
|
||||||
|
tag_bldr->prevPath(arrival_index2))))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1273,10 +1274,10 @@ ArrivalVisitor::visitFromToPath(const Pin *,
|
||||||
Tag *from_tag,
|
Tag *from_tag,
|
||||||
PathVertex *from_path,
|
PathVertex *from_path,
|
||||||
const Arrival &from_arrival,
|
const Arrival &from_arrival,
|
||||||
Edge *,
|
Edge *edge,
|
||||||
TimingArc *,
|
TimingArc *arc,
|
||||||
ArcDelay arc_delay,
|
ArcDelay arc_delay,
|
||||||
Vertex *,
|
Vertex * /* to_vertex */,
|
||||||
const RiseFall *to_rf,
|
const RiseFall *to_rf,
|
||||||
Tag *to_tag,
|
Tag *to_tag,
|
||||||
Arrival &to_arrival,
|
Arrival &to_arrival,
|
||||||
|
|
@ -1307,9 +1308,13 @@ ArrivalVisitor::visitFromToPath(const Pin *,
|
||||||
delayAsString(to_arrival, this),
|
delayAsString(to_arrival, this),
|
||||||
min_max == MinMax::max() ? ">" : "<",
|
min_max == MinMax::max() ? ">" : "<",
|
||||||
tag_match ? delayAsString(arrival, this) : "MIA");
|
tag_match ? delayAsString(arrival, this) : "MIA");
|
||||||
PathVertexRep prev_path;
|
PathPrev prev_path;
|
||||||
if (to_tag->isClock() || to_tag->isGenClkSrcPath())
|
bool always_save_prev_paths = true;
|
||||||
prev_path.init(from_path, this);
|
bool save_prev = always_save_prev_paths
|
||||||
|
|| to_tag->isClock()
|
||||||
|
|| to_tag->isGenClkSrcPath();
|
||||||
|
if (save_prev)
|
||||||
|
prev_path.init(from_path, edge, arc, this);
|
||||||
tag_bldr_->setMatchArrival(to_tag, tag_match,
|
tag_bldr_->setMatchArrival(to_tag, tag_match,
|
||||||
to_arrival, arrival_index,
|
to_arrival, arrival_index,
|
||||||
&prev_path);
|
&prev_path);
|
||||||
|
|
@ -1333,13 +1338,13 @@ ArrivalVisitor::visitFromToPath(const Pin *,
|
||||||
void
|
void
|
||||||
ArrivalVisitor::pruneCrprArrivals()
|
ArrivalVisitor::pruneCrprArrivals()
|
||||||
{
|
{
|
||||||
ArrivalMap::Iterator arrival_iter(tag_bldr_->arrivalMap());
|
|
||||||
CheckCrpr *crpr = search_->checkCrpr();
|
CheckCrpr *crpr = search_->checkCrpr();
|
||||||
while (arrival_iter.hasNext()) {
|
ArrivalMap *arrival_map = tag_bldr_->arrivalMap();
|
||||||
Tag *tag;
|
for (auto arrival_itr = arrival_map->cbegin(); arrival_itr != arrival_map->cend(); ) {
|
||||||
int arrival_index;
|
Tag *tag = arrival_itr->first;
|
||||||
arrival_iter.next(tag, arrival_index);
|
int arrival_index = arrival_itr->second;
|
||||||
ClkInfo *clk_info = tag->clkInfo();
|
ClkInfo *clk_info = tag->clkInfo();
|
||||||
|
bool deleted_tag = false;
|
||||||
if (!tag->isClock()
|
if (!tag->isClock()
|
||||||
&& clk_info->hasCrprClkPin()) {
|
&& clk_info->hasCrprClkPin()) {
|
||||||
PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
|
PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
|
||||||
|
|
@ -1364,10 +1369,13 @@ ArrivalVisitor::pruneCrprArrivals()
|
||||||
if (delayGreater(max_arrival_max_crpr, arrival, min_max, this)) {
|
if (delayGreater(max_arrival_max_crpr, arrival, min_max, this)) {
|
||||||
debugPrint(debug_, "search", 3, " pruned %s",
|
debugPrint(debug_, "search", 3, " pruned %s",
|
||||||
tag->asString(this));
|
tag->asString(this));
|
||||||
tag_bldr_->deleteArrival(tag);
|
arrival_itr = arrival_map->erase(arrival_itr);
|
||||||
|
deleted_tag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!deleted_tag)
|
||||||
|
arrival_itr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2710,7 +2718,10 @@ Search::setVertexArrivals(Vertex *vertex,
|
||||||
else {
|
else {
|
||||||
TagGroup *prev_tag_group = tagGroup(vertex);
|
TagGroup *prev_tag_group = tagGroup(vertex);
|
||||||
Arrival *prev_arrivals = graph_->arrivals(vertex);
|
Arrival *prev_arrivals = graph_->arrivals(vertex);
|
||||||
PathVertexRep *prev_paths = graph_->prevPaths(vertex);
|
PathPrev *prev_paths = graph_->prevPaths(vertex);
|
||||||
|
bool save_prev = always_save_prev_paths_
|
||||||
|
|| tag_bldr->hasClkTag()
|
||||||
|
|| tag_bldr->hasGenClkSrcTag();
|
||||||
|
|
||||||
TagGroup *tag_group = findTagGroup(tag_bldr);
|
TagGroup *tag_group = findTagGroup(tag_bldr);
|
||||||
int arrival_count = tag_group->arrivalCount();
|
int arrival_count = tag_group->arrivalCount();
|
||||||
|
|
@ -2718,7 +2729,7 @@ Search::setVertexArrivals(Vertex *vertex,
|
||||||
// Reuse arrival array if it is the same size.
|
// Reuse arrival array if it is the same size.
|
||||||
if (prev_tag_group
|
if (prev_tag_group
|
||||||
&& arrival_count == prev_tag_group->arrivalCount()) {
|
&& arrival_count == prev_tag_group->arrivalCount()) {
|
||||||
if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag()) {
|
if (save_prev) {
|
||||||
if (prev_paths == nullptr)
|
if (prev_paths == nullptr)
|
||||||
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
||||||
}
|
}
|
||||||
|
|
@ -2751,7 +2762,7 @@ Search::setVertexArrivals(Vertex *vertex,
|
||||||
}
|
}
|
||||||
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
|
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
|
||||||
prev_paths = nullptr;
|
prev_paths = nullptr;
|
||||||
if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag())
|
if (save_prev)
|
||||||
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
||||||
tag_bldr->copyArrivals(tag_group, arrivals, prev_paths);
|
tag_bldr->copyArrivals(tag_group, arrivals, prev_paths);
|
||||||
|
|
||||||
|
|
@ -2771,6 +2782,7 @@ Search::reportArrivals(Vertex *vertex) const
|
||||||
TagGroup *tag_group = tagGroup(vertex);
|
TagGroup *tag_group = tagGroup(vertex);
|
||||||
Arrival *arrivals = graph_->arrivals(vertex);
|
Arrival *arrivals = graph_->arrivals(vertex);
|
||||||
Required *requireds = graph_->requireds(vertex);
|
Required *requireds = graph_->requireds(vertex);
|
||||||
|
PathPrev *prev_paths = graph_->prevPaths(vertex);
|
||||||
if (tag_group) {
|
if (tag_group) {
|
||||||
report_->reportLine("Group %u", tag_group->index());
|
report_->reportLine("Group %u", tag_group->index());
|
||||||
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
||||||
|
|
@ -2791,14 +2803,34 @@ Search::reportArrivals(Vertex *vertex) const
|
||||||
if (!prev.isNull())
|
if (!prev.isNull())
|
||||||
clk_prev = prev.name(this);
|
clk_prev = prev.name(this);
|
||||||
}
|
}
|
||||||
report_->reportLine(" %d %s %s %s / %s %s %s",
|
string prev_str;
|
||||||
|
if (prev_paths) {
|
||||||
|
PathPrev &prev = prev_paths[arrival_index];
|
||||||
|
if (!prev.isNull()) {
|
||||||
|
prev_str += prev.name(this);
|
||||||
|
prev_str += " ";
|
||||||
|
const Edge *prev_edge = prev.prevEdge(this);
|
||||||
|
TimingArc *arc = prev.prevArc(this);
|
||||||
|
prev_str += prev_edge->from(graph_)->name(network_);
|
||||||
|
prev_str += " ";
|
||||||
|
prev_str += arc->fromEdge()->asString();
|
||||||
|
prev_str += " -> ";
|
||||||
|
prev_str += prev_edge->to(graph_)->name(network_);
|
||||||
|
prev_str += " ";
|
||||||
|
prev_str += arc->toEdge()->asString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prev_str = "NULL";
|
||||||
|
}
|
||||||
|
report_->reportLine(" %d %s %s %s / %s %s %s prev %s",
|
||||||
arrival_index,
|
arrival_index,
|
||||||
rf->asString(),
|
rf->asString(),
|
||||||
path_ap->pathMinMax()->asString(),
|
path_ap->pathMinMax()->asString(),
|
||||||
delayAsString(arrivals[arrival_index], this),
|
delayAsString(arrivals[arrival_index], this),
|
||||||
req,
|
req,
|
||||||
tag->asString(true, false, this),
|
tag->asString(true, false, this),
|
||||||
clk_prev);
|
clk_prev,
|
||||||
|
prev_str.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2966,7 +2998,7 @@ Search::reportClkInfos() const
|
||||||
clk_infos.push_back(clk_info);
|
clk_infos.push_back(clk_info);
|
||||||
sort(clk_infos, ClkInfoLess(this));
|
sort(clk_infos, ClkInfoLess(this));
|
||||||
for (ClkInfo *clk_info : clk_infos)
|
for (ClkInfo *clk_info : clk_infos)
|
||||||
report_->reportLine("ClkInfo %s", clk_info->asString(this));
|
report_->reportLine("%s", clk_info->asString(this));
|
||||||
report_->reportLine("%zu clk infos", clk_info_set_->size());
|
report_->reportLine("%zu clk infos", clk_info_set_->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2983,17 +3015,17 @@ Search::findClkInfo(const ClockEdge *clk_edge,
|
||||||
const PathAnalysisPt *path_ap,
|
const PathAnalysisPt *path_ap,
|
||||||
PathVertex *crpr_clk_path)
|
PathVertex *crpr_clk_path)
|
||||||
{
|
{
|
||||||
PathVertexRep crpr_clk_path_rep(crpr_clk_path, this);
|
PathVertexPtr crpr_clk_path_ptr(crpr_clk_path, this);
|
||||||
ClkInfo probe(clk_edge, clk_src, is_propagated, gen_clk_src, gen_clk_src_path,
|
ClkInfo probe(clk_edge, clk_src, is_propagated, gen_clk_src, gen_clk_src_path,
|
||||||
pulse_clk_sense, insertion, latency, uncertainties,
|
pulse_clk_sense, insertion, latency, uncertainties,
|
||||||
path_ap->index(), crpr_clk_path_rep, this);
|
path_ap->index(), crpr_clk_path_ptr, this);
|
||||||
LockGuard lock(clk_info_lock_);
|
LockGuard lock(clk_info_lock_);
|
||||||
ClkInfo *clk_info = clk_info_set_->findKey(&probe);
|
ClkInfo *clk_info = clk_info_set_->findKey(&probe);
|
||||||
if (clk_info == nullptr) {
|
if (clk_info == nullptr) {
|
||||||
clk_info = new ClkInfo(clk_edge, clk_src,
|
clk_info = new ClkInfo(clk_edge, clk_src,
|
||||||
is_propagated, gen_clk_src, gen_clk_src_path,
|
is_propagated, gen_clk_src, gen_clk_src_path,
|
||||||
pulse_clk_sense, insertion, latency, uncertainties,
|
pulse_clk_sense, insertion, latency, uncertainties,
|
||||||
path_ap->index(), crpr_clk_path_rep, this);
|
path_ap->index(), crpr_clk_path_ptr, this);
|
||||||
clk_info_set_->insert(clk_info);
|
clk_info_set_->insert(clk_info);
|
||||||
}
|
}
|
||||||
return clk_info;
|
return clk_info;
|
||||||
|
|
@ -3497,7 +3529,6 @@ RequiredVisitor::visit(Vertex *vertex)
|
||||||
debugPrint(debug_, "search", 2, "find required %s",
|
debugPrint(debug_, "search", 2, "find required %s",
|
||||||
vertex->name(network_));
|
vertex->name(network_));
|
||||||
required_cmp_->requiredsInit(vertex, this);
|
required_cmp_->requiredsInit(vertex, this);
|
||||||
vertex->setRequiredsPruned(false);
|
|
||||||
// Back propagate requireds from fanout.
|
// Back propagate requireds from fanout.
|
||||||
visitFanoutPaths(vertex);
|
visitFanoutPaths(vertex);
|
||||||
// Check for constraints at endpoints that set required times.
|
// Check for constraints at endpoints that set required times.
|
||||||
|
|
@ -3514,7 +3545,7 @@ RequiredVisitor::visit(Vertex *vertex)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RequiredVisitor::visitFromToPath(const Pin *,
|
RequiredVisitor::visitFromToPath(const Pin *,
|
||||||
Vertex *from_vertex,
|
Vertex *,
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
Tag *from_tag,
|
Tag *from_tag,
|
||||||
PathVertex *from_path,
|
PathVertex *from_path,
|
||||||
|
|
@ -3586,11 +3617,7 @@ RequiredVisitor::visitFromToPath(const Pin *,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
from_vertex->setRequiredsPruned(true);
|
|
||||||
}
|
}
|
||||||
// Propagate requireds pruned flag backwards.
|
|
||||||
if (to_vertex->requiredsPruned())
|
|
||||||
from_vertex->setRequiredsPruned(true);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -934,7 +934,7 @@ proc parse_report_path_options { cmd args_var default_format
|
||||||
} elseif { [string match "src*" $field] } {
|
} elseif { [string match "src*" $field] } {
|
||||||
set report_src_attr 1
|
set report_src_attr 1
|
||||||
} else {
|
} else {
|
||||||
sta_warn 166 "unknown field $field."
|
sta_warn 168 "unknown field $field."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3210,11 +3210,10 @@ Sta::findRequired(Vertex *vertex)
|
||||||
if (sdc_->crprEnabled()
|
if (sdc_->crprEnabled()
|
||||||
&& search_->crprPathPruningEnabled()
|
&& search_->crprPathPruningEnabled()
|
||||||
&& !search_->crprApproxMissingRequireds()
|
&& !search_->crprApproxMissingRequireds()
|
||||||
// Clocks invariably have requireds that are pruned but isn't
|
// Clocks invariably have requireds that are pruned but it isn't
|
||||||
// worth finding arrivals and requireds all over again for
|
// worth finding arrivals and requireds all over again for
|
||||||
// the entire fanout of the clock.
|
// the entire fanout of the clock.
|
||||||
&& !search_->isClock(vertex)
|
&& !search_->isClock(vertex)) {
|
||||||
&& vertex->requiredsPruned()) {
|
|
||||||
// Invalidate arrivals and requireds and disable
|
// Invalidate arrivals and requireds and disable
|
||||||
// path pruning on fanout vertices with DFS.
|
// path pruning on fanout vertices with DFS.
|
||||||
int fanout = 0;
|
int fanout = 0;
|
||||||
|
|
@ -3451,7 +3450,7 @@ Network *
|
||||||
Sta::ensureLibLinked()
|
Sta::ensureLibLinked()
|
||||||
{
|
{
|
||||||
if (network_ == nullptr || !network_->isLinked())
|
if (network_ == nullptr || !network_->isLinked())
|
||||||
report_->error(1570, "No network has been linked.");
|
report_->error(1571, "No network has been linked.");
|
||||||
// OpenROAD db is inherently linked but may not have associated
|
// OpenROAD db is inherently linked but may not have associated
|
||||||
// liberty files so check for them here.
|
// liberty files so check for them here.
|
||||||
if (network_->defaultLibertyLibrary() == nullptr)
|
if (network_->defaultLibertyLibrary() == nullptr)
|
||||||
|
|
@ -4610,8 +4609,7 @@ Sta::deletePinBefore(const Pin *pin)
|
||||||
if (edge->role()->isWire()) {
|
if (edge->role()->isWire()) {
|
||||||
// Only notify to vertex (from will be deleted).
|
// Only notify to vertex (from will be deleted).
|
||||||
Vertex *to = edge->to(graph_);
|
Vertex *to = edge->to(graph_);
|
||||||
// to->prev_paths point to vertex, so delete them.
|
search_->arrivalInvalid(to);
|
||||||
search_->arrivalInvalidDelete(to);
|
|
||||||
graph_delay_calc_->delayInvalid(to);
|
graph_delay_calc_->delayInvalid(to);
|
||||||
levelize_->relevelizeFrom(to);
|
levelize_->relevelizeFrom(to);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
#include "Tag.hh"
|
#include "Tag.hh"
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
#include "PathVertexRep.hh"
|
#include "PathPrev.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -200,7 +200,7 @@ TagGroupBldr::arrival(int arrival_index) const
|
||||||
void
|
void
|
||||||
TagGroupBldr::setArrival(Tag *tag,
|
TagGroupBldr::setArrival(Tag *tag,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
PathVertexRep *prev_path)
|
PathPrev *prev_path)
|
||||||
{
|
{
|
||||||
Tag *tag_match;
|
Tag *tag_match;
|
||||||
Arrival ignore;
|
Arrival ignore;
|
||||||
|
|
@ -215,7 +215,7 @@ TagGroupBldr::setMatchArrival(Tag *tag,
|
||||||
Tag *tag_match,
|
Tag *tag_match,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
int arrival_index,
|
int arrival_index,
|
||||||
PathVertexRep *prev_path)
|
PathPrev *prev_path)
|
||||||
{
|
{
|
||||||
if (tag_match) {
|
if (tag_match) {
|
||||||
// If the group_tag exists there has to be an arrival map entry for it.
|
// If the group_tag exists there has to be an arrival map entry for it.
|
||||||
|
|
@ -234,7 +234,7 @@ TagGroupBldr::setMatchArrival(Tag *tag,
|
||||||
if (prev_path)
|
if (prev_path)
|
||||||
prev_paths_.push_back(*prev_path);
|
prev_paths_.push_back(*prev_path);
|
||||||
else
|
else
|
||||||
prev_paths_.push_back(PathVertexRep());
|
prev_paths_.push_back(PathPrev());
|
||||||
|
|
||||||
if (tag->isClock())
|
if (tag->isClock())
|
||||||
has_clk_tag_ = true;
|
has_clk_tag_ = true;
|
||||||
|
|
@ -248,12 +248,6 @@ TagGroupBldr::setMatchArrival(Tag *tag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
TagGroupBldr::deleteArrival(Tag *tag)
|
|
||||||
{
|
|
||||||
arrival_map_.erase(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
TagGroup *
|
TagGroup *
|
||||||
TagGroupBldr::makeTagGroup(TagGroupIndex index,
|
TagGroupBldr::makeTagGroup(TagGroupIndex index,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
|
|
@ -285,7 +279,7 @@ TagGroupBldr::makeArrivalMap(const StaState *sta)
|
||||||
void
|
void
|
||||||
TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
||||||
Arrival *arrivals,
|
Arrival *arrivals,
|
||||||
PathVertexRep *prev_paths)
|
PathPrev *prev_paths)
|
||||||
{
|
{
|
||||||
ArrivalMap::Iterator arrival_iter1(arrival_map_);
|
ArrivalMap::Iterator arrival_iter1(arrival_map_);
|
||||||
while (arrival_iter1.hasNext()) {
|
while (arrival_iter1.hasNext()) {
|
||||||
|
|
@ -297,7 +291,7 @@ TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
||||||
if (exists2) {
|
if (exists2) {
|
||||||
arrivals[arrival_index2] = arrivals_[arrival_index1];
|
arrivals[arrival_index2] = arrivals_[arrival_index1];
|
||||||
if (prev_paths) {
|
if (prev_paths) {
|
||||||
PathVertexRep *prev_path = &prev_paths_[arrival_index1];
|
PathPrev *prev_path = &prev_paths_[arrival_index1];
|
||||||
prev_paths[arrival_index2].init(prev_path);
|
prev_paths[arrival_index2].init(prev_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -306,6 +300,12 @@ TagGroupBldr::copyArrivals(TagGroup *tag_group,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PathPrev &
|
||||||
|
TagGroupBldr::prevPath(int arrival_index)
|
||||||
|
{
|
||||||
|
return prev_paths_[arrival_index];
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ namespace sta {
|
||||||
|
|
||||||
class TagGroupBldr;
|
class TagGroupBldr;
|
||||||
|
|
||||||
typedef Vector<PathVertexRep> PathVertexRepSeq;
|
typedef Vector<PathPrev> PathPrevSeq;
|
||||||
|
|
||||||
class TagGroup
|
class TagGroup
|
||||||
{
|
{
|
||||||
|
|
@ -110,7 +110,6 @@ public:
|
||||||
bool hasGenClkSrcTag() const { return has_genclk_src_tag_; }
|
bool hasGenClkSrcTag() const { return has_genclk_src_tag_; }
|
||||||
bool hasFilterTag() const { return has_filter_tag_; }
|
bool hasFilterTag() const { return has_filter_tag_; }
|
||||||
bool hasLoopTag() const { return has_loop_tag_; }
|
bool hasLoopTag() const { return has_loop_tag_; }
|
||||||
void deleteArrival(Tag *tag);
|
|
||||||
void tagMatchArrival(Tag *tag,
|
void tagMatchArrival(Tag *tag,
|
||||||
// Return values.
|
// Return values.
|
||||||
Tag *&tag_match,
|
Tag *&tag_match,
|
||||||
|
|
@ -119,16 +118,17 @@ public:
|
||||||
Arrival arrival(int arrival_index) const;
|
Arrival arrival(int arrival_index) const;
|
||||||
void setArrival(Tag *tag,
|
void setArrival(Tag *tag,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
PathVertexRep *prev_path);
|
PathPrev *prev_path);
|
||||||
void setMatchArrival(Tag *tag,
|
void setMatchArrival(Tag *tag,
|
||||||
Tag *tag_match,
|
Tag *tag_match,
|
||||||
const Arrival &arrival,
|
const Arrival &arrival,
|
||||||
int arrival_index,
|
int arrival_index,
|
||||||
PathVertexRep *prev_path);
|
PathPrev *prev_path);
|
||||||
ArrivalMap *arrivalMap() { return &arrival_map_; }
|
ArrivalMap *arrivalMap() { return &arrival_map_; }
|
||||||
|
PathPrev &prevPath(int arrival_index);
|
||||||
void copyArrivals(TagGroup *tag_group,
|
void copyArrivals(TagGroup *tag_group,
|
||||||
Arrival *arrivals,
|
Arrival *arrivals,
|
||||||
PathVertexRep *prev_paths);
|
PathPrev *prev_paths);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int tagMatchIndex();
|
int tagMatchIndex();
|
||||||
|
|
@ -138,7 +138,7 @@ protected:
|
||||||
int default_arrival_count_;
|
int default_arrival_count_;
|
||||||
ArrivalMap arrival_map_;
|
ArrivalMap arrival_map_;
|
||||||
ArrivalSeq arrivals_;
|
ArrivalSeq arrivals_;
|
||||||
PathVertexRepSeq prev_paths_;
|
PathPrevSeq prev_paths_;
|
||||||
bool has_clk_tag_;
|
bool has_clk_tag_;
|
||||||
bool has_genclk_src_tag_:1;
|
bool has_genclk_src_tag_:1;
|
||||||
bool has_filter_tag_;
|
bool has_filter_tag_;
|
||||||
|
|
|
||||||
|
|
@ -441,8 +441,7 @@ using namespace sta;
|
||||||
const char *arg = Tcl_GetStringFromObj($input, &length);
|
const char *arg = Tcl_GetStringFromObj($input, &length);
|
||||||
Transition *tr = Transition::find(arg);
|
Transition *tr = Transition::find(arg);
|
||||||
if (tr == nullptr) {
|
if (tr == nullptr) {
|
||||||
Tcl_SetResult(interp,const_cast<char*>("Error: transition not found."),
|
tclArgError(interp, 2150, "Unknown transition '%s'.", arg);
|
||||||
TCL_STATIC);
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -462,8 +461,7 @@ using namespace sta;
|
||||||
const char *arg = Tcl_GetStringFromObj($input, &length);
|
const char *arg = Tcl_GetStringFromObj($input, &length);
|
||||||
RiseFall *rf = RiseFall::find(arg);
|
RiseFall *rf = RiseFall::find(arg);
|
||||||
if (rf == nullptr) {
|
if (rf == nullptr) {
|
||||||
Tcl_SetResult(interp,const_cast<char*>("Error: unknown rise/fall edge."),
|
tclArgError(interp, 2151, "Unknown rise/fall edge '%s'.", arg);
|
||||||
TCL_STATIC);
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
$1 = rf;
|
$1 = rf;
|
||||||
|
|
@ -482,8 +480,7 @@ using namespace sta;
|
||||||
const char *arg = Tcl_GetStringFromObj($input, &length);
|
const char *arg = Tcl_GetStringFromObj($input, &length);
|
||||||
RiseFallBoth *tr = RiseFallBoth::find(arg);
|
RiseFallBoth *tr = RiseFallBoth::find(arg);
|
||||||
if (tr == nullptr) {
|
if (tr == nullptr) {
|
||||||
Tcl_SetResult(interp,const_cast<char*>("Error: unknown transition name."),
|
tclArgError(interp, 2152, "Unknown transition name '%s'.", arg);
|
||||||
TCL_STATIC);
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
$1 = tr;
|
$1 = tr;
|
||||||
|
|
@ -502,8 +499,7 @@ using namespace sta;
|
||||||
const char *arg = Tcl_GetStringFromObj($input, &length);
|
const char *arg = Tcl_GetStringFromObj($input, &length);
|
||||||
PortDirection *dir = PortDirection::find(arg);
|
PortDirection *dir = PortDirection::find(arg);
|
||||||
if (dir == nullptr) {
|
if (dir == nullptr) {
|
||||||
Tcl_SetResult(interp,const_cast<char*>("Error: port direction not found."),
|
tclArgError(interp, 2153, "Unknown port direction '%s'.", arg);
|
||||||
TCL_STATIC);
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -517,8 +513,7 @@ using namespace sta;
|
||||||
if (role)
|
if (role)
|
||||||
$1 = TimingRole::find(arg);
|
$1 = TimingRole::find(arg);
|
||||||
else {
|
else {
|
||||||
Tcl_SetResult(interp,const_cast<char*>("Error: unknown timing role."),
|
tclArgError(interp, 2154, "Unknown timing role '%s'.", arg);
|
||||||
TCL_STATIC);
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -541,8 +536,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "fall") || stringEq(arg, "falling"))
|
else if (stringEq(arg, "fall") || stringEq(arg, "falling"))
|
||||||
$1 = LogicValue::fall;
|
$1 = LogicValue::fall;
|
||||||
else {
|
else {
|
||||||
Tcl_SetResult(interp,const_cast<char*>("Error: unknown logic value."),
|
tclArgError(interp, 2155, "Unknown logic value '%s'.", arg);
|
||||||
TCL_STATIC);
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -557,9 +551,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "on_chip_variation"))
|
else if (stringEq(arg, "on_chip_variation"))
|
||||||
$1 = AnalysisType::ocv;
|
$1 = AnalysisType::ocv;
|
||||||
else {
|
else {
|
||||||
Tcl_SetResult(interp,const_cast<char*>("Error: unknown analysis type."),
|
tclArgError(interp, 2156, "Unknown analysis type '%s'.", arg);
|
||||||
TCL_STATIC);
|
|
||||||
|
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -757,11 +749,11 @@ using namespace sta;
|
||||||
char *arg = Tcl_GetString(argv[i]);
|
char *arg = Tcl_GetString(argv[i]);
|
||||||
double value;
|
double value;
|
||||||
if (Tcl_GetDouble(interp, arg, &value) == TCL_OK)
|
if (Tcl_GetDouble(interp, arg, &value) == TCL_OK)
|
||||||
floats->push_back(static_cast<float>(value));
|
floats->push_back(static_cast<float>(value));
|
||||||
else {
|
else {
|
||||||
delete floats;
|
delete floats;
|
||||||
tclArgError(interp, "%s is not a floating point number.", arg);
|
tclArgError(interp, 2157, "%s is not a floating point number.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -802,11 +794,11 @@ using namespace sta;
|
||||||
char *arg = Tcl_GetString(argv[i]);
|
char *arg = Tcl_GetString(argv[i]);
|
||||||
int value;
|
int value;
|
||||||
if (Tcl_GetInt(interp, arg, &value) == TCL_OK)
|
if (Tcl_GetInt(interp, arg, &value) == TCL_OK)
|
||||||
ints->push_back(value);
|
ints->push_back(value);
|
||||||
else {
|
else {
|
||||||
delete ints;
|
delete ints;
|
||||||
tclArgError(interp, "%s is not an integer.", arg);
|
tclArgError(interp, 2158, "%s is not an integer.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -860,7 +852,7 @@ using namespace sta;
|
||||||
if (min_max)
|
if (min_max)
|
||||||
$1 = min_max;
|
$1 = min_max;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not min or max.", arg);
|
tclArgError(interp, 2159, "%s not min or max.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -880,7 +872,7 @@ using namespace sta;
|
||||||
if (min_max)
|
if (min_max)
|
||||||
$1 = min_max;
|
$1 = min_max;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not min, max or min_max.", arg);
|
tclArgError(interp, 2160, "%s not min, max or min_max.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -895,7 +887,7 @@ using namespace sta;
|
||||||
if (min_max)
|
if (min_max)
|
||||||
$1 = min_max;
|
$1 = min_max;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not min, max or min_max.", arg);
|
tclArgError(interp, 2161, "%s not min, max or min_max.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -916,7 +908,7 @@ using namespace sta;
|
||||||
|| stringEqual(arg, "max"))
|
|| stringEqual(arg, "max"))
|
||||||
$1 = MinMax::max();
|
$1 = MinMax::max();
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not setup, hold, min or max.", arg);
|
tclArgError(interp, 2162, "%s not setup, hold, min or max.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -935,7 +927,7 @@ using namespace sta;
|
||||||
|| stringEqual(arg, "min_max"))
|
|| stringEqual(arg, "min_max"))
|
||||||
$1 = SetupHoldAll::all();
|
$1 = SetupHoldAll::all();
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not setup, hold, setup_hold, min, max or min_max.", arg);
|
tclArgError(interp, 2163, "%s not setup, hold, setup_hold, min, max or min_max.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -948,7 +940,7 @@ using namespace sta;
|
||||||
if (early_late)
|
if (early_late)
|
||||||
$1 = early_late;
|
$1 = early_late;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
|
tclArgError(interp, 2164, "%s not early/min, late/max or early_late/min_max.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -961,7 +953,7 @@ using namespace sta;
|
||||||
if (early_late)
|
if (early_late)
|
||||||
$1 = early_late;
|
$1 = early_late;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
|
tclArgError(interp, 2165, "%s not early/min, late/max or early_late/min_max.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -976,7 +968,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "cell_check"))
|
else if (stringEq(arg, "cell_check"))
|
||||||
$1 = TimingDerateType::cell_check;
|
$1 = TimingDerateType::cell_check;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not net_delay, cell_delay or cell_check.", arg);
|
tclArgError(interp, 2166, "%s not net_delay, cell_delay or cell_check.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -989,7 +981,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "cell_check"))
|
else if (stringEq(arg, "cell_check"))
|
||||||
$1 = TimingDerateCellType::cell_check;
|
$1 = TimingDerateCellType::cell_check;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not cell_delay or cell_check.", arg);
|
tclArgError(interp, 2167, "%s not cell_delay or cell_check.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1002,7 +994,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "data"))
|
else if (stringEq(arg, "data"))
|
||||||
$1 = PathClkOrData::data;
|
$1 = PathClkOrData::data;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not clk or data.", arg);
|
tclArgError(interp, 2168, "%s not clk or data.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1015,7 +1007,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "slack"))
|
else if (stringEq(arg, "slack"))
|
||||||
$1 = sort_by_slack;
|
$1 = sort_by_slack;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "%s not group or slack.", arg);
|
tclArgError(interp, 2169, "%s not group or slack.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1040,7 +1032,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "json"))
|
else if (stringEq(arg, "json"))
|
||||||
$1 = ReportPathFormat::json;
|
$1 = ReportPathFormat::json;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "unknown path type %s.", arg);
|
tclArgError(interp, 2170, "unknown path type %s.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1406,7 +1398,7 @@ using namespace sta;
|
||||||
else if (stringEq(arg, "xyce"))
|
else if (stringEq(arg, "xyce"))
|
||||||
$1 = CircuitSim::xyce;
|
$1 = CircuitSim::xyce;
|
||||||
else {
|
else {
|
||||||
tclArgError(interp, "unknown circuit simulator %s.", arg);
|
tclArgError(interp, 2171, "unknown circuit simulator %s.", arg);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,15 +93,16 @@ tclListSetStdString(Tcl_Obj *const source,
|
||||||
|
|
||||||
void
|
void
|
||||||
tclArgError(Tcl_Interp *interp,
|
tclArgError(Tcl_Interp *interp,
|
||||||
|
int id,
|
||||||
const char *msg,
|
const char *msg,
|
||||||
const char *arg)
|
const char *arg)
|
||||||
{
|
{
|
||||||
// Swig does not add try/catch around arg parsing so this cannot use Report::error.
|
// Swig does not add try/catch around arg parsing so this cannot use Report::error.
|
||||||
string error_msg = "Error: ";
|
try {
|
||||||
error_msg += msg;
|
Sta::sta()->report()->error(id, msg, arg);
|
||||||
char *error = stringPrint(error_msg.c_str(), arg);
|
} catch (const std::exception &e) {
|
||||||
Tcl_SetResult(interp, error, TCL_VOLATILE);
|
Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_STATIC);
|
||||||
stringDelete(error);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Initial path groups:
|
||||||
|
Final path groups: In2Out In2Reg Reg2Out Reg2Reg
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
# path_group_names
|
||||||
|
|
||||||
|
read_liberty asap7_small.lib.gz
|
||||||
|
read_verilog reg1_asap7.v
|
||||||
|
link_design top
|
||||||
|
create_clock -name clk -period 500 {clk1 clk2 clk3}
|
||||||
|
set_input_delay -clock clk 0 [all_inputs -no_clocks]
|
||||||
|
set_output_delay -clock clk 0 [all_outputs]
|
||||||
|
puts "Initial path groups: [sta::path_group_names]"
|
||||||
|
group_path -name In2Reg -from [all_inputs] -to [all_registers -data_pins]
|
||||||
|
group_path -name In2Out -from [all_inputs] -to [all_outputs]
|
||||||
|
group_path -name Reg2Out -from [all_registers -clock_pins] -to [all_outputs]
|
||||||
|
group_path -name Reg2Reg -from [all_registers -clock_pins] -to [all_registers -data_pins]
|
||||||
|
puts "Final path groups: [sta::path_group_names]"
|
||||||
|
|
@ -147,6 +147,7 @@ record_sta_tests {
|
||||||
liberty_arcs_one2one_2
|
liberty_arcs_one2one_2
|
||||||
liberty_ccsn
|
liberty_ccsn
|
||||||
liberty_latch3
|
liberty_latch3
|
||||||
|
path_group_names
|
||||||
prima3
|
prima3
|
||||||
report_checks_src_attr
|
report_checks_src_attr
|
||||||
report_json1
|
report_json1
|
||||||
|
|
|
||||||
|
|
@ -2263,7 +2263,7 @@ VerilogScanner::VerilogScanner(std::istream *stream,
|
||||||
void
|
void
|
||||||
VerilogScanner::error(const char *msg)
|
VerilogScanner::error(const char *msg)
|
||||||
{
|
{
|
||||||
report_->fileError(1866, filename_, lineno(), "%s", msg);
|
report_->fileError(1870, filename_, lineno(), "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -508,19 +508,15 @@ VerilogWriter::findPortNCcount(const Instance *inst,
|
||||||
const Port *port)
|
const Port *port)
|
||||||
{
|
{
|
||||||
int nc_count = 0;
|
int nc_count = 0;
|
||||||
LibertyPort *lib_port = network_->libertyPort(port);
|
PortMemberIterator *member_iter = network_->memberIterator(port);
|
||||||
if (lib_port) {
|
while (member_iter->hasNext()) {
|
||||||
Cell *cell = network_->cell(inst);
|
Port *member = member_iter->next();
|
||||||
LibertyPortMemberIterator member_iter(lib_port);
|
Pin *pin = network_->findPin(inst, member);
|
||||||
while (member_iter.hasNext()) {
|
if (pin == nullptr
|
||||||
LibertyPort *lib_member = member_iter.next();
|
|| network_->net(pin) == nullptr)
|
||||||
Port *member = network_->findPort(cell, lib_member->name());
|
nc_count++;
|
||||||
Pin *pin = network_->findPin(inst, member);
|
|
||||||
if (pin == nullptr
|
|
||||||
|| network_->net(pin) == nullptr)
|
|
||||||
nc_count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
delete member_iter;
|
||||||
return nc_count;
|
return nc_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue