blob: f59586f630ae7c9b1cc57f33aa5e6baff3fabdbd [file] [log] [blame]
#!/usr/bin/tclsh
# SPDX-FileCopyrightText: 2020 Efabless Corporation
# Copyright 2020 Efabless Corporation
# Copyright 2020 Sylvain Munaut
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# SPDX-License-Identifier: Apache-2.0
package require openlane;
proc run_placement_step {args} {
# set pdndef_dirname [file dirname $::env(pdn_tmp_file_tag).def]
# set pdndef [lindex [glob $pdndef_dirname/*pdn*] 0]
# set_def $pdndef
if { ! [ info exists ::env(PLACEMENT_CURRENT_DEF) ] } {
set ::env(PLACEMENT_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(PLACEMENT_CURRENT_DEF)
}
run_placement
}
proc run_cts_step {args} {
# set_def $::env(opendp_result_file_tag).def
if { ! [ info exists ::env(CTS_CURRENT_DEF) ] } {
set ::env(CTS_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(CTS_CURRENT_DEF)
}
run_cts
run_resizer_timing
}
proc run_routing_step {args} {
# set resizerdef_dirname [file dirname $::env(resizer_tmp_file_tag)_timing.def]
# set resizerdef [lindex [glob $resizerdef_dirname/*resizer*] 0]
# set_def $resizerdef
if { ! [ info exists ::env(ROUTING_CURRENT_DEF) ] } {
set ::env(ROUTING_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(ROUTING_CURRENT_DEF)
}
run_routing
}
proc run_diode_insertion_2_5_step {args} {
# set_def $::env(tritonRoute_result_file_tag).def
if { ! [ info exists ::env(DIODE_INSERTION_CURRENT_DEF) ] } {
set ::env(DIODE_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(DIODE_INSERTION_CURRENT_DEF)
}
if { ($::env(DIODE_INSERTION_STRATEGY) == 2) || ($::env(DIODE_INSERTION_STRATEGY) == 5) } {
run_antenna_check
heal_antenna_violators; # modifies the routed DEF
}
}
proc run_power_pins_insertion_step {args} {
# set_def $::env(tritonRoute_result_file_tag).def
if { ! [ info exists ::env(POWER_PINS_INSERTION_CURRENT_DEF) ] } {
set ::env(POWER_PINS_INSERTION_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(POWER_PINS_INSERTION_CURRENT_DEF)
}
if { $::env(LVS_INSERT_POWER_PINS) } {
write_powered_verilog
set_netlist $::env(lvs_result_file_tag).powered.v
}
}
proc run_lvs_step {{ lvs_enabled 1 }} {
# set_def $::env(tritonRoute_result_file_tag).def
if { ! [ info exists ::env(LVS_CURRENT_DEF) ] } {
set ::env(LVS_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(LVS_CURRENT_DEF)
}
if { $lvs_enabled } {
run_magic_spice_export
run_lvs; # requires run_magic_spice_export
}
}
proc run_drc_step {{ drc_enabled 1 }} {
if { ! [ info exists ::env(DRC_CURRENT_DEF) ] } {
set ::env(DRC_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(DRC_CURRENT_DEF)
}
if { $drc_enabled } {
run_magic_drc
run_klayout_drc
}
}
proc run_antenna_check_step {{ antenna_check_enabled 1 }} {
if { ! [ info exists ::env(ANTENNA_CHECK_CURRENT_DEF) ] } {
set ::env(ANTENNA_CHECK_CURRENT_DEF) $::env(CURRENT_DEF)
} else {
set ::env(CURRENT_DEF) $::env(ANTENNA_CHECK_CURRENT_DEF)
}
if { $antenna_check_enabled } {
run_antenna_check
}
}
proc run_flow {args} {
set script_dir [file dirname [file normalize [info script]]]
set options {
{-design required}
{-save_path optional}
{-no_lvs optional}
{-no_drc optional}
{-no_antennacheck optional}
}
set flags {-save}
parse_key_args "run_flow" args arg_values $options flags_map $flags -no_consume
prep {*}$args
set LVS_ENABLED 1
set DRC_ENABLED 1
set ANTENNACHECK_ENABLED 1
set steps [dict create "synthesis" {run_synthesis "" } \
"floorplan" {run_floorplan ""} \
"placement" {run_placement_step ""} \
"cts" {run_cts_step ""} \
"routing" {run_routing_step ""}\
"diode_insertion" {run_diode_insertion_2_5_step ""} \
"power_pins_insertion" {run_power_pins_insertion_step ""} \
"gds_magic" {run_magic ""} \
"gds_drc_klayout" {run_klayout ""} \
"gds_xor_klayout" {run_klayout_gds_xor ""} \
"lvs" "run_lvs_step $LVS_ENABLED" \
"drc" "run_drc_step $DRC_ENABLED" \
"antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED" \
"cvc" {run_lef_cvc}
]
set_if_unset arg_values(-to) "cvc";
if { [info exists ::env(CURRENT_STEP) ] } {
puts "\[INFO\]:Picking up where last execution left off"
puts [format "\[INFO\]:Current stage is %s " $::env(CURRENT_STEP)]
} else {
set ::env(CURRENT_STEP) "synthesis";
}
set_if_unset arg_values(-from) $::env(CURRENT_STEP);
set exe 0;
dict for {step_name step_exe} $steps {
if { [ string equal $arg_values(-from) $step_name ] } {
set exe 1;
}
if { $exe } {
# For when it fails
set ::env(CURRENT_STEP) $step_name
[lindex $step_exe 0] [lindex $step_exe 1] ;
}
if { [ string equal $arg_values(-to) $step_name ] } {
set exe 0:
break;
}
}
# for when it resumes
set steps_as_list [dict keys $steps]
set next_idx [expr [lsearch $steps_as_list $::env(CURRENT_STEP)] + 1]
set ::env(CURRENT_STEP) [lindex $steps_as_list $next_idx]
if { [info exists flags_map(-save) ] } {
if { ! [info exists arg_values(-save_path)] } {
set arg_values(-save_path) ""
}
save_views -lef_path $::env(magic_result_file_tag).lef \
-def_path $::env(CURRENT_DEF) \
-gds_path $::env(magic_result_file_tag).gds \
-mag_path $::env(magic_result_file_tag).mag \
-maglef_path $::env(magic_result_file_tag).lef.mag \
-spice_path $::env(magic_result_file_tag).spice \
-spef_path $::env(CURRENT_SPEF) \
-verilog_path $::env(CURRENT_NETLIST) \
-save_path $arg_values(-save_path) \
-tag $::env(RUN_TAG)
}
calc_total_runtime
save_state
generate_final_summary_report
check_timing_violations
puts_success "Flow Completed Without Fatal Errors."
}
run_flow {*}$argv