| proc write_timing_info {filename} { | 
 |     # Writes timing data in JSON5 format to filename. | 
 |     # | 
 |     # Timing data is array of net objects, containing: | 
 |     #  - Node layout for each net | 
 |     #  - Route taking for each net | 
 |     #  - Interconnect delays from opin to each ipin | 
 |     #  - Slack and hold timing information for each ipin that has a timing | 
 |     #    path. | 
 |     set fp [open $filename w] | 
 |     puts $fp "\[" | 
 |  | 
 |     set nets [get_nets] | 
 |     foreach net $nets { | 
 |         if { $net == "<const0>" || $net == "<const1>" } { | 
 |             continue | 
 |         } | 
 |  | 
 |         if { [get_property ROUTE_STATUS [get_nets $net]] == "INTRASITE" } { | 
 |             continue | 
 |         } | 
 |         if { [get_property ROUTE_STATUS [get_nets $net]] == "NOLOADS" } { | 
 |             continue | 
 |         } | 
 |  | 
 |         puts $fp "{" | 
 |             puts $fp "\"net\":\"$net\"," | 
 |  | 
 |             set route [get_property ROUTE $net] | 
 |             puts $fp "\"route\":\"$route\"," | 
 |  | 
 |             puts $fp "\"nodes\":\[" | 
 |             set nodes [get_nodes -of_objects $net] | 
 |             foreach node $nodes { | 
 |                 puts $fp "{" | 
 |                     puts $fp "\"name\":\"$node\"," | 
 |                     puts $fp "\"wires\":\[" | 
 |                     set wires [get_wires -of_objects $node] | 
 |                     foreach wire $wires { | 
 |                         puts $fp "{" | 
 |                             puts $fp "\"name\":\"$wire\"," | 
 |                         puts $fp "}," | 
 |                     } | 
 |                     puts $fp "\]," | 
 |                 puts $fp "}," | 
 |             } | 
 |             puts $fp "\]," | 
 |  | 
 |             set opin [get_pins -leaf -of_objects [get_nets $net] -filter {DIRECTION == OUT}] | 
 |             puts $fp "\"opin\": {" | 
 |                 puts $fp "\"name\":\"$opin\"," | 
 |                 set opin_site_pin [get_site_pins -of_objects $opin] | 
 |                 puts $fp "\"site_pin\":\"$opin_site_pin\"," | 
 |                 puts $fp "\"node\":\"[get_nodes -of_objects $opin_site_pin]\"," | 
 |                 puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $opin_site_pin]]\"," | 
 |             puts $fp "}," | 
 |             set ipins [get_pins -of_objects [get_nets $net] -filter {DIRECTION == IN} -leaf] | 
 |             puts $fp "\"ipins\":\[" | 
 |             foreach ipin $ipins { | 
 |                 puts $fp "{" | 
 |                     set delay [get_net_delays -interconnect_only -of_objects $net -to $ipin] | 
 |                     puts $fp "\"name\":\"$ipin\"," | 
 |                     puts $fp "\"ic_delays\":{" | 
 |                         foreach prop {"FAST_MAX" "FAST_MIN" "SLOW_MAX" "SLOW_MIN"} { | 
 |                             puts $fp "\"$prop\":\"[get_property $prop $delay]\"," | 
 |                         } | 
 |                     puts $fp "}," | 
 |  | 
 |                     set setup_timing_path [get_timing_paths -to $ipin -setup] | 
 |                     set num_setup [llength $setup_timing_path] | 
 |                     if { $num_setup > 0 } { | 
 |                         if { $num_setup > 1 } { | 
 |                             error "Too many setup timing paths, found $num_setup" | 
 |                         } | 
 |                         puts $fp "\"setup_timing_path\":{" | 
 |                             foreach prop [list_property $setup_timing_path] { | 
 |                                 puts $fp "\"$prop\":\"[get_property $prop $setup_timing_path]\"," | 
 |                             } | 
 |                         puts $fp "}," | 
 |                     } | 
 |  | 
 |                     set hold_timing_path [get_timing_paths -to $ipin -hold] | 
 |                     set num_hold [llength $hold_timing_path] | 
 |                     if { $num_hold > 0 } { | 
 |                         if { $num_hold > 1 } { | 
 |                             error "Too many hold timing paths, found $num_hold" | 
 |                         } | 
 |                         puts $fp "\"hold_timing_path\":{" | 
 |                             foreach prop [list_property $hold_timing_path] { | 
 |                                 puts $fp "\"$prop\":\"[get_property $prop $hold_timing_path]\"," | 
 |                             } | 
 |                         puts $fp "}," | 
 |                     } | 
 |  | 
 |                     set ipin_site_pin [get_site_pin -of_objects $ipin] | 
 |                     puts $fp "\"site_pin\":\"$ipin_site_pin\"," | 
 |                     puts $fp "\"node\":\"[get_nodes -of_objects $ipin_site_pin]\"," | 
 |                     puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $ipin_site_pin]]\"," | 
 |                 puts $fp "}," | 
 |             } | 
 |             puts $fp "\]," | 
 |  | 
 |         puts $fp "}," | 
 |     } | 
 |  | 
 |     puts $fp "\]" | 
 |     close $fp | 
 |  | 
 | } | 
 |  | 
 | proc output_timing {timing_json} { | 
 |     write_timing_info $timing_json | 
 |     report_timing_summary | 
 | } |