Files
OpenROAD/test/flow.tcl
2026-02-17 05:47:38 +00:00

300 lines
9.4 KiB
Tcl

## SPDX-License-Identifier: BSD-3-Clause
## Copyright (c) 2019-2026, The OpenROAD Authors
# Assumes flow_helpers.tcl has been read.
read_libraries
read_verilog $synth_verilog
link_design $top_module
read_sdc $sdc_file
set_thread_count [cpu_count]
# Temporarily disable sta's threading due to random failures
sta::set_thread_count 1
utl::metric "IFP::ord_version" [ord::openroad_git_describe]
# Note that sta::network_instance_count is not valid after tapcells are added.
utl::metric "IFP::instance_count" [sta::network_instance_count]
initialize_floorplan -site $site \
-die_area $die_area \
-core_area $core_area
source $tracks_file
# remove buffers inserted by synthesis
remove_buffers
if { $pre_placed_macros_file != "" } {
source $pre_placed_macros_file
}
################################################################
# Macro Placement
if { [have_macros] } {
lassign $macro_place_halo halo_x halo_y
set report_dir [make_result_file ${design}_${platform}_rtlmp]
rtl_macro_placer -halo_width $halo_x -halo_height $halo_y \
-report_directory $report_dir
}
################################################################
# Tapcell insertion
eval tapcell $tapcell_args ;# tclint-disable command-args
################################################################
# Power distribution network insertion
source $pdn_cfg
pdngen
################################################################
# Global placement
foreach layer_adjustment $global_routing_layer_adjustments {
lassign $layer_adjustment layer adjustment
set_global_routing_layer_adjustment $layer $adjustment
}
set_routing_layers -signal $global_routing_layers \
-clock $global_routing_clock_layers
set_macro_extension 2
# Global placement skip IOs
global_placement -density $global_place_density \
-pad_left $global_place_pad -pad_right $global_place_pad -skip_io
# IO Placement
place_pins -hor_layers $io_placer_hor_layer -ver_layers $io_placer_ver_layer
# Global placement with placed IOs and routability-driven
global_placement -routability_driven -density $global_place_density \
-pad_left $global_place_pad -pad_right $global_place_pad
# checkpoint
set global_place_db [make_result_file ${design}_${platform}_global_place.db]
write_db $global_place_db
################################################################
# Repair max slew/cap/fanout violations and normalize slews
source $layer_rc_file
set_wire_rc -signal -layer $wire_rc_layer
set_wire_rc -clock -layer $wire_rc_layer_clk
set_dont_use $dont_use
estimate_parasitics -placement
repair_design -slew_margin $slew_margin -cap_margin $cap_margin
repair_tie_fanout -separation $tie_separation $tielo_port
repair_tie_fanout -separation $tie_separation $tiehi_port
set_placement_padding -global -left $detail_place_pad -right $detail_place_pad
detailed_placement
# post resize timing report (ideal clocks)
report_worst_slack -min -digits 3
report_worst_slack -max -digits 3
report_tns -digits 3
# Check slew repair
report_check_types -max_slew -max_capacitance -max_fanout -violators
utl::metric "RSZ::repair_design_buffer_count" [rsz::repair_design_buffer_count]
utl::metric "RSZ::max_slew_slack" [expr [sta::max_slew_check_slack_limit] * 100]
utl::metric "RSZ::max_fanout_slack" [expr [sta::max_fanout_check_slack_limit] * 100]
utl::metric "RSZ::max_capacitance_slack" [expr [sta::max_capacitance_check_slack_limit] * 100]
################################################################
# Clock Tree Synthesis
# Clone clock tree inverters next to register loads
# so cts does not try to buffer the inverted clocks.
repair_clock_inverters
clock_tree_synthesis -root_buf $cts_buffer -buf_list $cts_buffer \
-sink_clustering_enable \
-sink_clustering_max_diameter $cts_cluster_diameter
# CTS leaves a long wire from the pad to the clock tree root.
repair_clock_nets
# place clock buffers
detailed_placement
# checkpoint
set cts_db [make_result_file ${design}_${platform}_cts.db]
write_db $cts_db
################################################################
# Setup/hold timing repair
set_propagated_clock [all_clocks]
# Global routing is fast enough for the flow regressions.
# It is NOT FAST ENOUGH FOR PRODUCTION USE.
set repair_timing_use_grt_parasitics 0
if { $repair_timing_use_grt_parasitics } {
# Global route for parasitics - no guide file requied
global_route -congestion_iterations 100
estimate_parasitics -global_routing
} else {
estimate_parasitics -placement
}
repair_timing -skip_gate_cloning
# Post timing repair.
report_worst_slack -min -digits 3
report_worst_slack -max -digits 3
report_tns -digits 3
report_check_types -max_slew -max_capacitance -max_fanout -violators -digits 3
utl::metric "RSZ::worst_slack_min" [sta::worst_slack -min]
utl::metric "RSZ::worst_slack_max" [sta::worst_slack -max]
utl::metric "RSZ::tns_max" [sta::total_negative_slack -max]
utl::metric "RSZ::hold_buffer_count" [rsz::hold_buffer_count]
################################################################
# Detailed Placement
detailed_placement
# Capture utilization before fillers make it 100%
utl::metric "DPL::utilization" [format %.1f [expr [rsz::utilization] * 100]]
utl::metric "DPL::design_area" [sta::format_area [rsz::design_area] 0]
# checkpoint
set dpl_db [make_result_file ${design}_${platform}_dpl.db]
write_db $dpl_db
set verilog_file [make_result_file ${design}_${platform}.v]
write_verilog $verilog_file
################################################################
# Global routing
pin_access
set route_guide [make_result_file ${design}_${platform}.route_guide]
global_route -guide_file $route_guide \
-congestion_iterations 100 -verbose
set verilog_file [make_result_file ${design}_${platform}.v]
write_verilog -remove_cells $filler_cells $verilog_file
################################################################
# Repair antennas post-GRT
utl::set_metrics_stage "grt__{}"
repair_antennas -iterations 5
check_antennas
utl::clear_metrics_stage
utl::metric "GRT::ANT::errors" [ant::antenna_violation_count]
################################################################
# Detailed routing
# Run pin access again after inserting diodes and moving cells
# pin_access
detailed_route -output_drc [make_result_file "${design}_${platform}_route_drc.rpt"] \
-output_maze [make_result_file "${design}_${platform}_maze.log"] \
-no_pin_access \
-verbose 0
write_guides [make_result_file "${design}_${platform}_output_guide.mod"]
set drv_count [detailed_route_num_drvs]
utl::metric "DRT::drv" $drv_count
set routed_db [make_result_file ${design}_${platform}_route.db]
write_db $routed_db
set routed_def [make_result_file ${design}_${platform}_route.def]
write_def $routed_def
################################################################
# Repair antennas post-DRT
set repair_antennas_iters 0
utl::set_metrics_stage "drt__repair_antennas__pre_repair__{}"
while { [check_antennas] && $repair_antennas_iters < 5 } {
utl::set_metrics_stage "drt__repair_antennas__iter_${repair_antennas_iters}__{}"
repair_antennas
detailed_route -output_drc [make_result_file "${design}_${platform}_ant_fix_drc.rpt"] \
-output_maze [make_result_file "${design}_${platform}_ant_fix_maze.log"] \
-no_pin_access \
-verbose 0
incr repair_antennas_iters
}
utl::set_metrics_stage "drt__{}"
check_antennas
utl::clear_metrics_stage
utl::metric "DRT::ANT::errors" [ant::antenna_violation_count]
if { ![design_is_routed] } {
error "Design has unrouted nets."
}
set repair_antennas_db [make_result_file ${design}_${platform}_repaired_route.odb]
write_db $repair_antennas_db
################################################################
# Filler placement
filler_placement $filler_cells
check_placement -verbose
# checkpoint
set fill_db [make_result_file ${design}_${platform}_fill.db]
write_db $fill_db
################################################################
# Extraction
if { $rcx_rules_file != "" } {
define_process_corner -ext_model_index 0 X
extract_parasitics -ext_model_file $rcx_rules_file
set spef_file [make_result_file ${design}_${platform}.spef]
write_spef $spef_file
read_spef $spef_file
} else {
# Use global routing based parasitics inlieu of rc extraction
estimate_parasitics -global_routing
}
################################################################
# Final Report
report_checks -path_delay min_max -format full_clock_expanded \
-fields {input_pin slew capacitance} -digits 3
report_worst_slack -min -digits 3
report_worst_slack -max -digits 3
report_tns -digits 3
report_check_types -max_slew -max_capacitance -max_fanout -violators -digits 3
report_clock_skew -digits 3
report_power -corner $power_corner
report_floating_nets -verbose
report_design_area
utl::metric "DRT::worst_slack_min" [sta::worst_slack -min]
utl::metric "DRT::worst_slack_max" [sta::worst_slack -max]
utl::metric "DRT::tns_max" [sta::total_negative_slack -max]
utl::metric "DRT::clock_skew" [expr abs([sta::worst_clock_skew -setup])]
# slew/cap/fanout slack/limit
utl::metric "DRT::max_slew_slack" [expr [sta::max_slew_check_slack_limit] * 100]
utl::metric "DRT::max_fanout_slack" [expr [sta::max_fanout_check_slack_limit] * 100]
utl::metric "DRT::max_capacitance_slack" [expr [sta::max_capacitance_check_slack_limit] * 100]
# report clock period as a metric for updating limits
utl::metric "DRT::clock_period" [get_property [lindex [all_clocks] 0] period]
# not really useful without pad locations
#set_pdnsim_net_voltage -net $vdd_net_name -voltage $vdd_voltage
#analyze_power_grid -net $vdd_net_name