blob: 19dd6a418cceb494c1a80f1f3effff3a83176221 [file] [log] [blame]
###############################################################################
# CADENCE COPYRIGHT NOTICE
# © 2008-2013 Cadence Design Systems, Inc. All rights reserved.
#------------------------------------------------------------------------------
#
# This Foundation Flow is provided as an example of how to perform specialized
# tasks.
#
# This work may not be copied, re-published, uploaded, or distributed in any way,
# in any medium, whether in whole or in part, without prior written permission
# from Cadence. Notwithstanding any restrictions herein, subject to compliance
# with the terms and conditions of the Cadence software license agreement under
# which this material was provided, this material may be copied and internally
# distributed solely for internal purposes for use with Cadence tools.
#
# This work is Cadence intellectual property and may under no circumstances be
# given to third parties, neither in original nor in modified versions, without
# explicit written permission from Cadence. The information contained herein is
# the proprietary and confidential information of Cadence or its licensors, and
# is supplied subject to, and may be used only by Cadence's current customers
# in accordance with, a previously executed license agreement between Cadence
# and its customer.
#
#------------------------------------------------------------------------------
# THIS MATERIAL IS PROVIDED BY CADENCE "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL CADENCE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL
# OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS MATERIAL, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###############################################################################
package provide foundation_flow 1.0
namespace eval FF_NOVUS:: {
###############################################################################
# Procedure to seed certain flow variables to a known default value as well
# as data variables required to seed the generic configuration file
###############################################################################
proc seed_variables {{force 0}} {
global vars
global rda_defaults
global udm
global env
global infos
global warnings
global errors
global fargs
global dargs
if {$force} {
if {[info exists vars(seed)]} {
unset vars(seed)
}
}
if {![info exists vars(seed)]} {
puts "<FF> Seeding variables ..."
if {![info exists vars(warning_count)]} {
set vars(warning_count) 0
}
if {![info exists vars(error_count)]} {
set vars(error_count) 0
}
if {![info exists vars(info_count)]} {
set vars(info_count) 0
}
###############################################################################
# Set vars(version) to "17.1.0" if not defined
###############################################################################
if {![info exists vars(version)]} {
if {[info exists fargs(version)]} {
# puts "<FF> INFO: Variable vars(version) not defined - setting to '$fargs(version)'"
set vars(version) $fargs(version)
} else {
set vars(version) $dargs(version)
}
set vars(flow) mmmc
} else {
if {([lsearch $FF::valid_versions $vars(version)] < 0)} {
set msg "Version '$vars(version)' not supported - setting to '17.1.0'"
puts "<FF> WARNING: $msg"
append commands "# $msg\n"
set warnings($vars(warning_count)) $msg
incr vars(warning_count)
set vars(flow) mmmc
set vars(version) "17.1.0"
} else {
if {[lindex [split $vars(version) "."] 0] > 10} {
set vars(flow) mmmc
}
}
}
if {[regexp "9.1" $vars(version)]} {
set vars(enable_ldb) FALSE
}
# if {[lindex [split $vars(version) "."] 0] > 14} {
# set vars(novus) true
# } else {
# set vars(novus) false
# }
if {[info exists fargs(novus)]} {
set vars(novus) $fargs(novus)
} else {
set vars(novus) $dargs(novus)
}
# Tool should always be innovus for 15.x as encounter is going away
if {![info exists vars(make_tool)]} {
if {[lindex [split $vars(version) "."] 0] > 14} {
set vars(make_tool) innovus
} else {
set vars(make_tool) encounter
}
}
if {[info exists vars(enable_ldb)] && $vars(enable_ldb)} {
if {[info exists vars(ran_compile)]} {
append commands [FF_NOVUS::run_compile]
}
}
###############################################################################
# Set vars(flow) to "mmmc" if not defined
###############################################################################
if {![info exists vars(flow)]} {
puts "<FF> INFO: Variable vars(flow) not defined - setting to 'mmmc'"
set vars(flow) mmmc
} else {
if {([lsearch [list "default" "pr_mmmc" "mmmc"] $vars(flow)] < 0)} {
puts "<FF> WARNING: Flow type '$vars(flow)' not supported - setting to 'mmmc'"
append commands "# WARNING: Flow type '$vars(flow)' not supported - setting to 'mmmc'\n"
set warnings($vars(warning_count)) "Flow type '$vars(flow)' not supported - setting to 'mmmc'"
incr vars(warning_count)
set vars(flow) mmmc
}
}
###############################################################################
# Make sure all scaling factors are either set or are 1.0 ... also
# support backwards compatibility of old names
###############################################################################
set map(pre_route_res_factor) def_res_factor
set map(pre_route_clk_res_factor) def_clk_res_factor
set map(pre_route_cap_factor) def_cap_factor
set map(pre_route_clk_cap_factor) def_clk_cap_factor
set map(post_route_res_factor) det_res_factor
set map(post_route_clk_res_factor) det_clk_res_factor
set map(post_route_cap_factor) det_cap_factor
set map(post_route_clk_cap_factor) det_clk_cap_factor
set map(post_route_xcap_factor) xcap_factor
if {[info exists vars(view_definition_tcl)] && ![info exists vars(parsed_view_definition_tcl)]} {
if {![file exists $vars(view_definition_tcl)]} {
puts "<FF> ERROR: View definition file $vars(view_definition_tcl) does not exist ... cannot continue"
exit
}
source $vars(script_path)/ETC/INNOVUS/overlay.tcl
puts "<FF> Parsing user view definition file ..."
set rc [catch {source $vars(view_definition_tcl)}]
# puts "-------------------------------------------------"
if {$vars(novus)} {
foreach var "library_sets rc_corners delay_corners timing_conditions setup_analysis_views hold_analysis_views power_domains" {
if {[info exists vars($var)]} {
set infos($vars(info_count)) "Variable vars($var) has been set to \"$vars($var)\""
incr vars(info_count)
}
}
} else {
foreach var "library_sets rc_corners delay_corners setup_analysis_views hold_analysis_views power_domains" {
if {[info exists vars($var)]} {
set infos($vars(info_count)) "Variable vars($var) has been set to \"$vars($var)\""
incr vars(info_count)
}
}
}
# puts $rc
# puts "-------------------------------------------------"
set vars(parsed_view_definition_tcl) true
}
# if {![info exists vars(view_definition_tcl)]} {
foreach rc_corner $vars(rc_corners) {
foreach option "pre_route_res_factor pre_route_clk_res_factor \
post_route_res_factor post_route_clk_res_factor \
pre_route_cap_factor pre_route_clk_cap_factor \
post_route_cap_factor post_route_clk_cap_factor \
post_route_xcap_factor" {
if {![info exists vars($rc_corner,$option)] && [info exists vars($rc_corner,$map($option))]} {
append commands "# INFO: Variable $map($option) has been changed to $option ... please update\n"
set infos($vars(info_count)) "Variable $map($option) has been changed to $option ... please update"
incr vars(info_count)
set vars($rc_corner,$option) $vars($rc_corner,$map($option))
}
}
}
###############################################################################
# The following will be used to seed the config file
###############################################################################
if {![FF::is_lp_flow]} {
set max_libs [list]
set min_libs [list]
set count 0
if {[info exists vars($vars($vars(default_setup_view),delay_corner),library_set)]} {
foreach lib $vars($vars($vars($vars(default_setup_view),delay_corner),library_set),timing) {
if {[lsearch $max_libs $lib] == -1} {
lappend max_libs $lib
incr count
}
}
} else {
if {[info exists vars($vars($vars(default_setup_view),delay_corner),late_library_set)]} {
foreach lib $vars($vars($vars($vars(default_setup_view),delay_corner),late_library_set),timing) {
if {[lsearch $max_libs $lib] == -1} {
lappend max_libs $lib
incr count
}
}
}
}
if {![info exists vars(timelib,max)]} {
set vars(timelib,max) $max_libs
}
if {[info exists vars($vars($vars(default_hold_view),delay_corner),library_set)]} {
foreach lib $vars($vars($vars($vars(default_hold_view),delay_corner),library_set),timing) {
if {[lsearch $min_libs $lib] == -1} {
lappend min_libs $lib
incr count
}
}
} else {
if {[info exists vars($vars($vars(default_hold_view),delay_corner),early_library_set)]} {
foreach lib $vars($vars($vars($vars(default_hold_view),delay_corner),early_library_set),timing) {
if {[lsearch $min_libs $lib] == -1} {
lappend min_libs $lib
incr count
}
}
}
}
if {![info exists vars(timelib,min)]} {
set vars(timelib,min) $min_libs
}
if {![info exists vars(timelib)]} {
set vars(timelib) ""
}
set vars(cdb_file) ""
set vars(cdb_file,min) ""
set vars(cdb_file,max) ""
if {[info exists vars($vars($vars(default_setup_view),delay_corner),library_set)]} {
if {[info exists vars($vars($vars($vars(default_setup_view),delay_corner),library_set),si)]} {
set vars(cdb_file,max) $vars($vars($vars($vars(default_setup_view),delay_corner),library_set),si)
}
} elseif {[info exists vars($vars($vars(default_setup_view),delay_corner),late_library_set)]} {
if {[info exists ars($vars($vars($vars(default_setup_view),delay_corner),late_library_set),si)]} {
set vars(cdb_file,max) $vars($vars($vars($vars(default_setup_view),delay_corner),late_library_set),si)
}
} else {
set vars(cdb_file,max) ""
}
if {[info exists vars($vars($vars(default_hold_view),delay_corner),library_set)]} {
if {[info exists vars($vars($vars($vars(default_hold_view),delay_corner),library_set),si)]} {
set vars(cdb_file,min) $vars($vars($vars($vars(default_hold_view),delay_corner),library_set),si)
}
} elseif {[info exists vars($vars($vars(default_hold_view),delay_corner),early_library_set)]} {
if {[info exists vars($vars($vars($vars(default_hold_view),delay_corner),early_library_set),si)]} {
set vars(cdb_file,min) $vars($vars($vars($vars(default_hold_view),delay_corner),early_library_set),si)
}
} else {
set vars(cdb_file,min) ""
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),pre_cts_sdc)]} {
if {$vars(flow) != "mmmc"} {
set vars(timingcon_file) $vars($vars($vars(default_setup_view),constraint_mode),pre_cts_sdc)
}
set vars(pre_cts_sdc) $vars($vars($vars(default_setup_view),constraint_mode),pre_cts_sdc)
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),pre_cts_ilm_sdc)]} {
if {$vars(flow) != "mmmc"} {
set vars(timingcon_file,full) $vars($vars($vars(default_setup_view),constraint_mode),pre_cts_ilm_sdc)
}
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),incr_cts_sdc)]} {
set vars(incr_cts_sdc) $vars($vars($vars(default_setup_view),constraint_mode),incr_cts_sdc)
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),post_cts_sdc)]} {
set vars(post_cts_sdc) $vars($vars($vars(default_setup_view),constraint_mode),post_cts_sdc)
}
if {[info exists vars($vars($vars($vars(default_hold_view),delay_corner),rc_corner),cap_table)] &&\
[info exists vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)]} {
set vars(captbl_file) [concat \
"-best" $vars($vars($vars($vars(default_hold_view),delay_corner),rc_corner),cap_table) \
"-worst" $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table) \
]
set vars(wc_cap_table) $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)
} else {
if {[info exists vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)]} {
set vars(captbl_file) [concat \
"-best" $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table) \
"-worst" $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table) \
]
set vars(wc_cap_table) $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)
} else {
set vars(captbl_file) ""
}
}
} else {
set vars(timelib) ""
set vars(cdb_file) ""
set vars(timelib,max) ""
set vars(cdb_file,max) ""
set vars(timelib,min) ""
set vars(cdb_file,min) ""
set found_max 0
set found_min 0
if {[info exists vars(setup_analysis_views)] && [info exists vars(hold_analysis_views)]} {
foreach view $vars(setup_analysis_views) {
if {[info exists vars($vars($view,delay_corner),library_set)]} {
if {[info exists vars($vars($vars($view,delay_corner),library_set),timing)]} {
foreach file $vars($vars($vars($view,delay_corner),library_set),timing) {
if {[lsearch $vars(timelib,max) $file] == -1} {
lappend vars(timelib,max) $file
}
set found_max 1
}
} else {
puts "<FF> WARNING: Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
incr vars(warning_count)
}
} else {
if {![info exists vars($vars($view,delay_corner),early_library_set)]} {
puts "<FF> WARNING: Variable vars($vars($view,delay_corner),library_set) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($view,delay_corner),library_set) not defined"
incr vars(warning_count)
}
}
}
foreach view $vars(hold_analysis_views) {
if {[info exists vars($vars($view,delay_corner),library_set)]} {
if {[info exists vars($vars($vars($view,delay_corner),library_set),timing)]} {
foreach file $vars($vars($vars($view,delay_corner),library_set),timing) {
if {[lsearch $vars(timelib,min) $file] == -1} {
lappend vars(timelib,min) $file
}
set found_min 1
}
} else {
puts "<FF> WARNING: vars($vars($vars($view,delay_corner),library_set),timing) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
incr vars(warning_count)
}
} else {
if {![info exists vars($vars($view,delay_corner),early_library_set)]} {
puts "<FF> WARNING: vars($vars($view,delay_corner),early_library_set) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($view,delay_corner),early_library_set) not defined"
incr vars(warning_count)
}
}
}
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set view $vars(power_analysis_view)
if {[info exists vars($vars($view,delay_corner),library_set)]} {
if {![info exists vars($vars($vars($view,delay_corner),library_set),timing)]} {
puts "<FF> WARNING: vars($vars($vars($view,delay_corner),library_set),timing) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
incr vars(warning_count)
}
} else {
if {![info exists vars($vars($view,delay_corner),early_library_set)]} {
puts "<FF> WARNING: vars($vars($view,delay_corner),early_library_set) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($view,delay_corner),early_library_set) not defined"
incr vars(warning_count)
}
}
}
}
if {!$found_min || !$found_max} {
append commands "# WARNING: Either setup or hold analysis views inadequately defined"
set warnings($vars(warning_count)) "Either setup or hold analysis views inadequately defined"
incr vars(warning_count)
set vars(timelib,min) ""
set vars(timelib,max) ""
foreach library_set $vars(library_sets) {
if {[info exists vars($library_set,timing)]} {
set vars(timelib) [concat $vars(timelib) $vars($library_set,timing)]
}
if {[info exists vars($library_set,si)]} {
set vars(cdb_file) [concat $vars(cdb_file) $vars($library_set,si)]
}
}
}
set vars(captbl_file) ""
set vars(timingcon_file) ""
# set vars(pre_route_res_factor) 1.0
# set vars(post_route_res_factor) 1.0
# set vars(pre_route_cap_factor) 1.0
# set vars(post_route_cap_factor) 1.0
# set vars(pre_route_clk_res_factor) 1.0
# set vars(post_route_clk_res_factor) 1.0
# set vars(pre_route_clk_cap_factor) 1.0
# set vars(post_route_clk_cap_factor) 1.0
# set vars(post_route_xcap_factor) 1.0
# set vars(qxtech_file) ""
# set vars(qxconf_file) ""
# set vars(qxlib_file) ""
# set vars(qxlayermap_file) ""
}
set map(qx_tech_file) qxtech_file
set map(qx_conf_file) qxconf_file
set map(qx_lib_file) qxlib_file
foreach option "qx_tech_file qx_conf_file qx_lib_file" {
if {[info exists vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),$option)]} {
set vars($map($option)) $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),$option)
} else {
set vars($map($option)) ""
}
}
if {![info exists vars(qx_layermap_file)]} {
if {[info exists vars(qrc_layer_map)]} {
set vars(qxlayermap_file) $vars(qrc_layer_map)
} else {
set vars(qxlayermap_file) ""
}
} else {
set vars(qxlayermap_file) $vars(qx_layermap_file)
set vars(qrc_layer_map) $vars(qx_layermap_file)
}
# }
###############################################################################
# Backwards compatibility
###############################################################################
if {[info exists vars(leakage_effort)] && ![info exists vars(leakage_power_effort)]} {
set vars(leakage_power_effort) $vars(leakage_effort)
}
if {[info exists vars(enable_cppr)] && (($vars(enable_cppr) == 0) || ($vars(enable_cppr) == false))} {
set vars(enable_cppr) none
}
if {[info exists vars(enable_cppr)] && (($vars(enable_cppr) == 1) || ($vars(enable_cppr) == true))} {
set vars(enable_cppr) both
}
if {[info exists vars(def_file)]} {
append commands "# WARNING: Variable def_file has been changed to def_files ... please update\n"
set warnings($vars(warning_count)) "Variable def_file has been changed to def_files ... please update"
incr vars(warning_count)
set vars(def_files) $vars(def_file)
}
###############################################################################
# Seed the rest of the config variables allowing user overrides ...
# Default values for all variables are in defaults.tcl
###############################################################################
if {![info exists vars(script_path)]} {
if {[info exists vars(script_root)]} {
set vars(script_path) $vars(script_root)
} else {
puts "<FF> ERROR: Variable vars(script_root) not defined"
exit 1
}
} else {
if {![info exists vars(script_root)]} {
set vars(script_root) $vars(script_path)
}
}
if {![info exists vars(setup_path)]} {
set vars(setup_path) "."
}
if {[info command FFF::get_tool] ne "" && [FFF::get_tool] eq "rc"} {
tcl_source $vars(script_path)/ETC/INNOVUS/rda_defaults.tcl
} else {
source $vars(script_path)/ETC/common_defaults.tcl
source $vars(script_path)/ETC/INNOVUS/defaults.tcl
source $vars(script_path)/ETC/INNOVUS/rda_defaults.tcl
}
if {$vars(novus)} {
FF_NOVUS::dump_novus_attributes
}
foreach option [array names rda_defaults] {
if {![info exists vars($option)]} {
set vars($option) $rda_defaults($option)
} else {
if {$vars($option) != $rda_defaults($option)} {
# puts "# <FF> INFO: User override of $option to $vars($option)"
}
}
}
if {![info exists vars(cpus_per_remote_host)] && [info exists vars(cpu_per_remote_host)]} {
puts "<FF> INFO: Setting 'vars(cpus_per_remote_host)' to 'vars(cpu_per_remote_host)'"
puts "<FF> INFO: ^"
puts "<FF> INFO: Please update your setup to cpus_per_remote ..."
set vars(cpus_per_remote_host) $vars(cpu_per_remote_host)
}
if {![info exists vars(flexmodel_art_based)]} {
if {[info exists vars(flexmodel_as_ptn)] && $vars(flexmodel_as_ptn)} {
set flow_defaults(flexmodel_art_based) 1
}
}
if {![info exists vars(high_timing_effort)]} {
set vars(high_timing_effort) $flow_defaults(high_timing_effort)
}
if {[info exists vars(clock_eco)] && ($vars(clock_eco) == "postcts")} {
set vars(clock_eco) "post_cts"
}
if {[info exists vars(clock_eco)] && ($vars(clock_eco) == "postroute")} {
set vars(clock_eco) "post_route"
}
if {[regexp "9.1" $vars(version)]} {
if {$vars(high_timing_effort)} {
if {[info exists vars(critical_range)] && ($vars(critical_range) != 1.0)} {
puts "<FF> High timing effort enabled but critical_range overridden by user settings"
}
if {[info exists vars(clock_eco)] && ($vars(clock_eco) != "post_cts")} {
puts "<FF> High timing effort enabled but clock_eco overridden by user settings"
}
if {[info exists vars(in_place_opt)] && !$vars(in_place_opt)} {
puts "<FF> High timing effort enabled but in_place_opt overridden by user settings"
}
}
}
if {[info exists vars(cts_engine)] && ([string tolower $vars(cts_engine)] == "cts")} {
set flow_defaults(update_io_latency) false
# set vars(cts,update_timing,skip) true
}
foreach option [array names flow_defaults] {
if {![info exists vars($option)]} {
set vars($option) $flow_defaults($option)
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
set vars(in_place_opt) true
set vars(critical_range) 1.0
# set vars(useful_skew) true
set vars(clock_eco) post_cts
}
} else {
set user($option) $vars($option)
}
}
# if {![info exists user(ccopt_effort)] && ($vars(cts_engine) == "ccopt")} {
# set vars(ccopt_effort) low
# }
if {![info exists flow_defaults(time_info_db)]} {
set flow_defaults(time_info_db) $flow_defaults(rpt_dir)/time_info.db
}
if {![info exists flow_defaults(time_info_full_rpt)]} {
set flow_defaults(time_info_full_rpt) $flow_defaults(rpt_dir)/time_info_full.rpt
}
if {![info exists flow_defaults(html_summary)]} {
set flow_defaults(html_summary) $flow_defaults(rpt_dir)/summary.html
}
if {![info exists vars(enable_si_aware)]} {
# if {[regsub "nm" $vars(process) ""] <= 65} {
# set vars(enable_si_aware) true
# } else {
set vars(enable_si_aware) false
# }
}
if {![info exists vars(dbs_format)]} {
if {[string compare -nocase $vars(netlist_type) "verilog"]>=0} {
set vars(dbs_format) fe
} else {
set vars(dbs_format) oa
}
}
if {![info exists vars(partition_dir)]} {
set vars(partition_dir) PARTITION
}
if {![info exists vars(partition_dir_pass2)]} {
if {$vars(enable_flexilm)} {
set vars(partition_dir_pass2) $vars(partition_dir)_PRECTS
} else {
set vars(partition_dir_pass2) $vars(partition_dir)_CTS
}
}
if {$vars(user_mode) == "hier"} {
FF_NOVUS::normalize_files
if {$vars(enable_flexilm)} {
# set vars(cts,starting_dbs) "\[glob *_post_eco.enc\]"
# # DLM is a two pass flow but user doesn't need to specify it
set vars(hier_flow_type) "2pass"
# set vars(place_opt_design) false
} else {
if {$vars(hier_flow_type) == "2pass"} {
set vars(postcts,starting_dbs) .
}
# }
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {![info exists vars(oa_abstract_name)]} { set vars(oa_abstract_name) abstract}
if {![info exists vars(oa_layout_name)]} { set vars(oa_layout_name) layout}
if {![info exists vars(oa_design_cell)]} { set vars(oa_design_cell) $vars(design)}
if {![info exists vars(oa_design_view)]} { set vars(oa_design_view) ""}
if {![info exists vars(oa_partition_lib)]} { set vars(oa_partition_lib) OA_PTN_LIB}
} else {
if {![info exists vars(oa_abstract_name)]} { set vars(oa_abstract_name) ""}
if {![info exists vars(oa_layout_name)]} { set vars(oa_layout_name) ""}
if {![info exists vars(oa_design_cell)]} { set vars(oa_design_cell) ""}
if {![info exists vars(oa_design_view)]} { set vars(oa_design_view) ""}
if {![info exists vars(oa_design_lib)]} { set vars(oa_design_lib) ""}
}
if {([string tolower $vars(fix_hold)] == "true") || ($vars(fix_hold) == 1)} {
set infos($vars(info_count)) "Changing vars(fix_hold) from $vars(fix_hold) to \"$flow_defaults(fix_hold)\""
incr vars(info_count)
set vars(fix_hold) $flow_defaults(fix_hold)
}
if {([string tolower $vars(enable_ocv)] == "true") || ($vars(enable_ocv) == 1)} {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ocv)\" to \"pre_place\""
incr vars(info_count)
set vars(enable_ocv) pre_place
} elseif {($vars(enable_ocv) == "none") || ($vars(enable_ocv) == 0)} {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ocv)\" to \"false\""
incr vars(info_count)
set vars(enable_ocv) false
}
if {[lindex [split $vars(version) "."] 0] > 11} {
if {[string tolower $vars(enable_ocv)] == "false"} {
if {[lindex [split $vars(version) "."] 0] < 15} {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ocv)\" to \"pre_postroute\""
incr vars(info_count)
set vars(enable_ocv) "pre_postroute"
} else {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ocv)\" to \"pre_cts\""
incr vars(info_count)
set vars(enable_ocv) "pre_place"
}
}
}
if {([string tolower $vars(enable_ss)] == "true") || ($vars(enable_ss) == 1)} {
set infos($vars(info_count)) "Changing vars(enable_ss) from $vars(enable_ss) to \"pre_postroute\""
incr vars(info_count)
set vars(enable_ss) pre_postroute
} elseif {($vars(enable_ss) == "none") || ($vars(enable_ss) == 0)} {
set infos($vars(info_count)) "Changing vars(enable_ss) from $vars(enable_ss) to \"false\""
incr vars(info_count)
set vars(enable_ss) false
}
if {([string tolower $vars(metalfill)] == "none") || ([string tolower $vars(metalfill)] == "false" && $vars(metalfill) != "false") || ($vars(metalfill) == 0)} {
set infos($vars(info_count)) "Changing vars(metalfill) from $vars(metalfill) to \"false\""
incr vars(info_count)
set vars(metalfill) false
}
if {[info exists vars(clock_eco)]} {
if {($vars(clock_eco) == "true") || ($vars(clock_eco) == 1)} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"post_cts\""
incr vars(info_count)
set vars(clock_eco) post_cts
} elseif {($vars(clock_eco) == "false") || ($vars(clock_eco) == 0)} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"none\""
incr vars(info_count)
set vars(clock_eco) none
} elseif {($vars(clock_eco) == "preroute") || ($vars(clock_eco) == "pre_route")} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"post_cts\""
incr vars(info_count)
set vars(clock_eco) post_cts
} elseif {$vars(clock_eco) == "postroute"} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"post_route\""
incr vars(info_count)
set vars(clock_eco) post_route
}
}
if {([string tolower $vars(flow_effort)] == "none") || ([string tolower $vars(flow_effort)] == "default")} {
append warnings($vars(warning_count)) "Changing vars(flow_effort) from '$vars(flow_effort)' to 'standard'"
incr vars(warning_count)
set vars(flow_effort) standard
}
if {([string tolower $vars(use_flexmodels)] == "true") || ($vars(use_flexmodels) == 1)} {
set vars(use_flexmodels) 1
} else {
set vars(use_flexmodels) 0
}
# if {$vars(use_flexmodels) && $vars(place_opt_design)} {
# set warnings($vars(warning_count)) "Setting vars(place_opt_design) to 'false' as vars(use_flexmodels) is true"
# incr vars(warning_count)
# set vars(place_opt_design) false
# }
if {([string tolower $vars(flexmodel_as_ptn)] == "true") || ($vars(flexmodel_as_ptn) == 1)} {
set vars(flexmodel_as_ptn) 1
} else {
set vars(flexmodel_as_ptn) 0
}
if {([string tolower $vars(placement_based_ptn)] == "true") || ($vars(placement_based_ptn) == 1)} {
set vars(placement_based_ptn) 1
} else {
set vars(placement_based_ptn) 0
}
if {([string tolower $vars(abutted_design)] == "true") || ($vars(abutted_design) == 1)} {
set vars(abutted_design) 1
} else {
set vars(abutted_design) 0
}
if {([string tolower $vars(insert_feedthrough)] == "true") || ($vars(insert_feedthrough) == 1)} {
set vars(insert_feedthrough) 1
} else {
set vars(insert_feedthrough) 0
}
if {![info exists vars(resize_shifter_and_iso_insts)] || $vars(resize_shifter_and_iso_insts) == ""} {
set vars(resize_shifter_and_iso_insts) true
}
if {![info exists vars(activity_file_format)] || $vars(activity_file_format) == ""} {
set vars(activity_file_format) TCF
}
if {![info exists vars(power_nets)]} {
if {[info exists vars(pwrnet)]} {
append commands "# INFO: Variable pwrnet has been changed to power_nets ... please update\n"
set infos($vars(info_count)) "Variable pwrnet has been changed to power_nets ... please update"
incr vars(info_count)
set vars(power_nets) $vars(pwrnet)
} else {
set vars(power_nets) ""
}
}
if {![info exists vars(ground_nets)]} {
if {[info exists vars(gndnet)]} {
append commands "# INFO: Variable gndnet has been changed to ground_nets ... please update\n"
set infos($vars(info_count)) "Variable gndnet has been changed to ground_nets ... please update"
incr vars(info_count)
set vars(ground_nets) $vars(gndnet)
} else {
set vars(ground_nets) ""
}
}
if {![info exists vars(superhosts)]} {
set vars(superhosts) 0
}
if {![info exists vars(superthreads)]} {
set vars(superthreads) 1
} else {
if {($vars(threads) > 1) && ($vars(superthreads) == 1)} {
set vars(superthreads) $vars(threads)
}
}
if {![info exists vars(makefile)]} {
set vars(makefile) 1
}
if {![info exists vars(flat)]} {
set vars(flat) none
}
if {![info exists vars(abort)]} {
set vars(abort) 0
}
if {![info exists vars(catch_errors)]} {
set vars(catch_errors) 1
}
if {![info exists vars(restore_design)]} {
set vars(restore_design) 1
}
if {$vars(catch_errors)} {
if {![info exists vars(save_on_catch)]} {
set vars(save_on_catch) 1
}
if {![info exists vars(exit_on_error)]} {
set vars(exit_on_error) 1
}
}
if {![info exists env(VPATH)]} {
set env(VPATH) $flow_defaults(vpath)
puts "<FF> INFO: Setting env(VPATH) to $flow_defaults(vpath)"
}
if {[info exists vars(cpf_file)]} {
if {![info exists vars(cpf_timing)]} {
set vars(cpf_timing) true
# set vars(flat) true
}
} else {
set vars(cpf_timing) false
}
if {!$vars(codegen)} {
if {[FF::is_lp_flow]} {
catch {alias ff_modify_power_domains FF_NOVUS::modify_power_domains}
catch {alias ff_add_power_switches FF_NOVUS::add_power_switches}
catch {alias ff_route_secondary_pg_nets FF_NOVUS::route_secondary_pg_nets}
catch {alias ff_get_power_domains FF_NOVUS::get_power_domains}
catch {alias ff_buffer_always_on_nets FF_NOVUS::buffer_always_on_nets}
catch {alias ff_insert_welltaps_endcaps FF_NOVUS::insert_welltaps_endcaps}
}
set flow_defaults(script_dir) "."
}
# Remember these for step based reporting ...
set vars(orig_rpt_dir) $vars(rpt_dir)
set vars(orig_log_dir) $vars(log_dir)
set vars(orig_dbs_dir) $vars(dbs_dir)
# Add these for get metric
if {![info exists vars(html_summary)]} {
set vars(html_summary) $vars(rpt_dir)/summary.html
}
if {![info exists vars(time_info_db)]} {
set vars(time_info_db) $vars(rpt_dir)/time_info.db
}
if {![info exists vars(time_info_rpt)]} {
set vars(time_info_rpt) $vars(rpt_dir)/time_info.rpt
}
if {[info command FFF::get_tool] ne "" && [FFF::get_tool] eq "rc"} {
tcl_source $vars(script_path)/ETC/INNOVUS/udm.tcl
} else {
source $vars(script_path)/ETC/INNOVUS/udm.tcl
}
if {!$vars(rc) || ($vars(rc) && ![info exists vars(rc_steps)])} {
set vars(seed) 1
}
}
# if {![info exists vars(view_definition_tcl)]} {
FF_NOVUS::normalize_constraints
# }
if {$vars(generate_flow_steps)} {
# set vars(skip_signoff_checks) true
FF_NOVUS::normalize_files
}
# if {[info exists vars(view_definition_tcl)]} {
# set vars(skip_signoff_checks) false
# }
# RC Stuff ...
# ------------------------------------------------------------------------------
if {$vars(rc)} {
if {![info exists vars(ovf_dir)]} { set vars(ovf_dir) OVF }
if {![info exists vars(lec_dir)]} { set vars(lec_dir) LEC }
if {![info exists vars(enable_rcp)]} { set vars(enable_rcp) 0 }
if {![info exists vars(enable_pam)]} { set vars(enable_pam) 0 }
set vars(syn_map,set_lib_attributes,skip) true
set vars(syn_map,set_misc_attributes,skip) true
set vars(syn_map,set_hdl_attributes,skip) true
set vars(syn_map,set_icg_attributes,skip) true
set vars(syn_map,set_dft_attributes,skip) true
set vars(syn_incr,set_opt_attributes,skip) true
###############################################################################
# Set netlist and def variables when RC / RCP enabled
###############################################################################
if {$vars(enable_rcp)} {
set vars(netlist) $vars(dbs_dir)/syn_place/syn_place.v.gz
# set vars(def_files) $vars(dbs_dir)/syn_place.def.gz
} else {
set vars(netlist) $vars(dbs_dir)/syn_incr/syn_incr.v.gz
# set vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.def.gz
}
}
if {$vars(novus)} {
#set vars(make_tool_args) "-nowin -64"
set vars(make_syn_tool_args) "-64"
set vars(generate_flow_steps) true
} else {
#set vars(make_tool_args) "-nowin -64"
set vars(make_syn_tool_args) "-64 -legacy_ui"
set vars(generate_flow_steps) true
}
}
###############################################################################
# Procedure to check the flow variables defined in the setup.tcl
###############################################################################
proc check_setup {} {
global vars
global tvars
global errors
global warnings
global infos
global check
if {[info exists vars(check_setup)] && !$vars(check_setup)} {
return
}
if {[info exists vars(warning_count)]} {
set warning_count $vars(warning_count)
} else {
set warning_count 0
}
if {[info exists vars(error_count)]} {
set error_count $vars(error_count)
} else {
set error_count 0
}
if {[info exists vars(info_count)]} {
set info_count $vars(info_count)
} else {
set info_count 0
}
if {$vars(place_opt_design) && $vars(enable_flexilm)} {
set warnings($warning_count) "Feature vars(place_opt_design) not support for top level implementation when vars(enable_flexilm) is true"
incr warning_count
}
if {[info exists vars(power_analysis_view)]} {
if {[lsearch [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] $vars(power_analysis_view)] == -1} {
append commands "# ERROR: Power analysis view $vars(power_analysis_view) is not a defined view\n"
set errors($error_count) "Power analysis view $vars(power_analysis_view) is not a defined view"
incr error_count
}
}
set valid [list trial_ipo giga_opt proto_net_delay_model]
if {[lsearch $valid [string tolower $vars(budget_mode)]] == -1} {
append commands "# ERROR: Variable vars(budget_mode) has illegal value $vars(budget_mode)\n"
set errors($error_count) "Variable vars(budget_mode) has illegal value $vars(budget_mode)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
if {[info exists vars(cts_engine)]} {
if {[string tolower $vars(cts_engine)] == "ccoptdesign"} {
set vars(cts_engine) ccopt
}
if {[string tolower $vars(cts_engine)] == "clockdesign"} {
set vars(cts_engine) cts
}
set valid [list ccopt ccopt_cts]
if {[lsearch $valid [string tolower $vars(cts_engine)]] == -1} {
append commands "# ERROR: Variable vars(cts_engine) has illegal value $vars(cts_engine)\n"
set errors($error_count) "Variable vars(cts_engine) has illegal value $vars(cts_engine)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
if {[info exists vars(ccopt_integration)]} {
set valid {scripted native}
if {[lsearch $valid $vars(ccopt_integration)] == -1} {
append commands "# ERROR: Variable vars(cts_engine) has illegal value $vars(cts_engine)\n"
set errors($error_count) "Variable vars(cts_engine) has illegal value $vars(cts_engine)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
} else {
# Default to native integration
set vars(ccopt_integration) "native"
}
if {[lindex [split $vars(version) "."] 0] > 10} {
foreach var [array names vars] {
set save_vars($var) $vars($var)
if {[info exists tvars($var)]} {
set vars($var) $tvars($var)
}
}
}
set commands ""
set check(files) [list]
set check(integers) [list]
if {![info exists vars(abort)]} {
set vars(abort) 0
}
if {[info exists vars(check_vars)] && $vars(check_vars)} {
source $vars(script_root)/ETC/INNOVUS/check_vars.tcl
}
append commands "# ==============================================\n"
append commands "# Required Variables\n"
append commands "# ==============================================\n"
set count 0
foreach required "fp_tcl_file fp_file def_files" {
# BCL: Note - This code removed as the RC Foundation Flow will set vars(def_files) when it
# isn't defined in the user's setup.tcl
#if {$vars(rc) && ![info exists vars(def_files)]} {
# set vars(def_files) $vars(dbs_dir)/$vars(design).syn_placed.def.gz
#}
if {!$vars(rc)} {
# BCL: Only check for vars(def_files) if not in RC mode
if {[info exists vars($required)] && ($vars($required) != "")} {
if {$required == "def_files"} {
set first 1
# BCL: Added subst around vars(def_files) to resolve vars(rundir)
foreach file [subst $vars(def_files)] {
if {$first == 1} {
append commands "# INFO: $required = $file\n"
set first 0
} else {
append commands "# INFO: $file"
}
if {!$vars(rc)} {
lappend check(files) $file
}
}
} else {
lappend check(files) $vars($required)
append commands "# INFO: $required = $vars($required)\n"
}
incr count
}
}
}
if {[info exists vars(fp_tcl_proc)]} {
append commands "# INFO: fp_tcl_proc = $vars(fp_tcl_proc)\n"
incr count
}
if {[info exists vars(oa_fp)]} {
if {[llength $vars(oa_fp)] == 3} {
append commands "# INFO: oa_fp = $vars(oa_fp)\n"
incr count
} else {
append commands "# ERROR: OA floorplan variable (oa_fp) should be 'lib cell view'"
set errors($error_count) "OA floorplan variable (oa_fp) should be 'lib cell view'"
incr error_count
}
} else {
if {$count == 0} {
append commands "# WARNING: Neither fp_file, def_files, fp_tcl_file, fp_tcl_proc are defined\n"
set warnings($warning_count) "Either fp_file, def_files, fp_tcl_file, fp_tcl_proc should be defined"
incr warning_count
}
}
if {[string compare -nocase $vars(netlist_type) "verilog"]>=0} {
# BCL: Note - This code removed as the RC Foundation Flow will set vars(def_netlist) when it
# isn't defined in the user's setup.tcl
#if {$vars(rc) && ![info exists vars(netlist)]} {
# set vars(netlist) $vars(dbs_dir)/$vars(design).syn_placed.v.gz
#}
if {!$vars(rc)} {
# BCL: Only check for vars(netlist) if not in RC mode
if {[info exists vars(netlist)]} {
# BCL: Added subst around vars(netlist)
foreach file [subst $vars(netlist)] {
if {!$vars(rc)} {
lappend check(files) $file
}
}
append commands "# INFO: netlist = $vars(netlist)\n"
} else {
if {($vars(netlist_type) == "Verilog")} {
append commands "# ERROR: A verilog netlist file must be defined\n"
set errors($error_count) "A verilog netlist file must be defined"
incr error_count
}
}
}
} elseif {[string compare -nocase $vars(netlist_type) "oa"]==0} {
append commands "# INFO: netlist_type = $vars(netlist_type)\n"
foreach required "oa_ref_lib oa_design_lib oa_design_cell oa_design_view" {
if {[info exists vars($required)] && ($vars($required) != "")} {
append commands "# INFO: $required = $vars($required)\n"
} else {
append commands "# ERROR: Variable $required must be defined when netlist_type is open access"
set errors($error_count) "Variable $required must be defined when netlist_type is open access"
incr error_count
}
}
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append commands "# INFO: dbs_format = $vars(dbs_format)\n"
foreach required "oa_ref_lib oa_design_lib oa_abstract_name oa_layout_name" {
if {[info exists vars($required)] && ($vars($required) != "")} {
append commands "# INFO: $required = $vars($required)\n"
} else {
append commands "# ERROR: Variable $required must be defined when dbs_format is open access"
set errors($error_count) "Variable $required must be defined when dbs_format is open access"
incr error_count
}
}
}
if {[info exists vars(enable_lvs)] && $vars(enable_lvs)} {
if {[string compare -nocase $vars(dbs_format) "oa"]!=0} {
append commands "# WARNING: Variable enable_lvs is only allowed when dbs_format is open access"
set warnings($warning_count) "Variable enable_lvs is only allowed when dbs_format is open access"
incr warning_count
set vars(enable_lvs) false
}
}
# if {[info exists vars(netlist)]} {
# foreach file $vars(netlist) {
# lappend check(files) $file
# }
# } else {
# if {$vars(netlist_type) == "Verilog"} {
# append commands "# ERROR: A verilog netlist file must be defined\n"
# set errors($error_count) "A verilog netlist file must be defined"
# incr error_count
#
# }
# }
if {[info exists vars(cts_spec)] && ($vars(cts_engine) == "ccopt")} {
# append commands "# ERROR: Variable cts_spec defined and cts_engine is set to ccopt\n"
# set errors($error_count) "Variable cts_spec defined and cts_engine is set to ccopt"
# incr error_count
append commands "# WARNING: Variable cts_spec defined and cts_engine is set to ccopt\n"
set warnings($warning_count) "Variable cts_spec defined and cts_engine is set to ccopt"
incr warning_count
foreach file $vars(cts_spec) {
lappend check(files) $file
}
}
# if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
# set required_list "flow process library_sets rc_corners delay_corners"
# } else {
set required_list "flow process library_sets rc_corners delay_corners setup_analysis_views \
hold_analysis_views active_setup_views active_hold_views default_setup_view default_hold_view"
# }
foreach required $required_list {
if {[info exists vars($required)] && ($vars($required) != "")} {
append commands "# INFO: $required = $vars($required)\n"
if {$required == "flow"} {
if {([info exists vars(partition_list)] || ($vars(ilm_list) != "")) && ($vars(flow) != "mmmc")} {
append commands "# ERROR: Flow variable vars(flow) must be \"mmmc\" when ILMs are defined\n"
set errors($error_count) "# ERROR: Flow variable vars(flow) must be \"mmmc\" when ILMs are defined"
incr error_count
}
}
}
}
# if {![info exists vars(view_definition_tcl)]} {
append commands "# ==============================================\n"
append commands "# Library Sets\n"
append commands "# ==============================================\n"
foreach library_set $vars(library_sets) {
append commands "# INFO: $library_set:\n"
foreach required "timing" {
if {[info exists vars($library_set,$required)] && ($vars($library_set,$required) != "")} {
append commands "# INFO: $required = \n"
foreach lib $vars($library_set,$required) {
# lappend check(files) $lib
append commands "# INFO: $lib\n"
}
} else {
if {[FF::is_lp_flow]} {
append commands "# WARNING: Variable vars($library_set,$required) not defined\n"
set warnings($warning_count) "Variable vars($library_set,$required) not defined"
incr warning_count
} else {
append commands "# ERROR: Required variable vars($library_set,$required) not defined or empty\n"
set errors($error_count) "Required variable vars($library_set,$required) not defined or empty"
incr error_count
}
}
}
if {[info exists vars($library_set,aocv)]} {
foreach file $vars($library_set,aocv) {
if {![file exists $file]} {
append commands "# WARNING: AOCV table file does not exist ($file)\n"
set warnings($warning_count) "AOCV table file does not exist ($file)"
incr warning_count
}
}
} else {
if {$vars(enable_aocv)} {
append commands "# WARNING: AOCV enabled, but table not provided for $library_set\n"
set warnings($warning_count) "AOCV enabled, but table not provided for $library_set"
incr warning_count
}
}
if {[info exists vars($library_set,socv)]} {
foreach file $vars($library_set,socv) {
if {![file exists $file]} {
append commands "# WARNING: SOCV table file does not exist ($file)\n"
set warnings($warning_count) "SOCV table file does not exist ($file)"
incr warning_count
}
}
} else {
if {$vars(enable_socv)} {
append commands "# WARNING: SOCV enabled, but table not provided for $library_set\n"
set warnings($warning_count) "SOCV enabled, but table not provided for $library_set"
incr warning_count
}
}
if {[info exists vars($library_set,si)]} {
foreach file $vars($library_set,si) {
if {![file exists $file]} {
append commands "# WARNING: CDB file does not exist ($file)\n"
set warnings($warning_count) "CDB file does not exist ($file)"
incr warning_count
}
}
}
}
# }
append commands "# ==============================================\n"
append commands "# LEF Files\n"
append commands "# ==============================================\n"
if {[info exists vars(lef_files)]} {
foreach file $vars(lef_files) {
# lappend check(files) $file
append commands "# INFO: $file\n"
}
} else {
if {([string tolower $vars(netlist_type)] == "verilog") && (![info exists vars(oa_ref_lib)])} {
append commands "# ERROR: Required variable vars(lef_files) not defined\n"
set errors($error_count) "Required variable vars(lef_files) not defined"
incr error_count
}
}
if {[info exists vars(partition_list)]} {
append commands "# ==============================================\n"
append commands "# Hierarchical \n"
append commands "# ==============================================\n"
append commands "# INFO: partitions = $vars(partition_list)\n"
set cts_spec [FF::get_by_suffix vars ",cts_spec"]
if {$cts_spec != ""} {
append commands "# CTS Specs : \n"
foreach partition $cts_spec {
lappend check(files) $vars($partition,cts_spec)
append commands "# $partition -> $vars($partition,cts_spec)\n"
}
}
set latency_sdc [FF::get_by_suffix vars ",latency_sdc"]
if {$latency_sdc != ""} {
append commands "# Latency SDCs :\n"
foreach partition $latency_sdc {
lappend check(files) $vars($partition,latency_sdc)
if {[llength [split $partition ","]] == 1} {
append commands "# $partition -> $vars($partition,latency_sdc)\n"
} else {
append commands "# [lindex [split $partition ","] 0] ([lindex [split $partition ","] 1]) -> $vars($partition,latency_sdc)\n"
}
}
}
}
if {[info exists vars(enable_pac)] && $vars(enable_pac)} {
append commands "# WARNING: PAC is obsolete and will be removed in a future version. Consider using Sign-off ECO."
set warnings($warning_count) "PAC is obsolete and will be removed in a future version. Consider using Sign-off ECO."
incr warning_count
set pac_mode [FF::get_by_suffix vars ",pac_mode"]
if {$pac_mode != ""} {
set pac_list [list "read_only" "interface" "ilm" "all"]
foreach pac $pac_mode {
if {[lsearch $pac_list $vars($pac,pac_mode)] == -1} {
append commands "# ERROR: $pac pac_mode invalid value; must be one of \'$pac_list\'\n"
set errors($error_count) "$pac pac_mode invalid value; must be one of \'$pac_list\'"
incr error_count
}
}
}
}
if {[FF::is_lp_flow]} {
append commands "# ==============================================\n"
append commands "# Low Power \n"
append commands "# ==============================================\n"
if {[info exists vars(ieee1801_file)]} {
set warnings($warning_count) "Using vars(ieee1801_file) requires the following limited access feature : mvsSupportIEEE1801"
incr warning_count
}
set num_power_intent_files 0
foreach v {cpf_file ieee1801_file} {
if {[info exists vars($v)]} {
append commands "# INFO: $v = $vars($v)\n"
lappend check(files) $vars($v)
incr num_power_intent_files
}
}
if {$num_power_intent_files > 1} {
set errors($error_count) "vars(cpf_file) and vars(ieee1801_file) may not both be specified."
append commands "# ERROR: $errors($error_count)\n"
incr error_count
}
if {[info exists vars(power_domains)] && ($vars(power_domains) != "")} {
append commands "# INFO: power_domains = $vars(power_domains)\n"
foreach domain $vars(power_domains) {
set print($domain) 1
foreach optional "filler_cells tie_cells endcaps welltaps" {
if {[info exists vars($domain,$optional)] && ($vars($domain,$optional) != "")} {
if {$print($domain)} {
append commands "# INFO: $domain:\n"
set print($domain) 0
}
append commands "# INFO: $optional = $vars($domain,$optional)\n"
}
# if {$optional == "filler_cells} {
# set process [regsub "nm" $vars(process) ""]
# if {[expr $process <= 28)] && [info exists vars(filler_cells,min_gap)]} {
# append commands "# ERROR: For process node < 28nm, variable vars(filler_cells,min_gap) is required\n"
# set errors($error_count) "For process node < 28nm, variable vars(filler_cells,min_gap) is required"
# incr error_count
# }
# }
}
}
} else {
append commands "# WARNING: Recommended variable vars(power_domains) not defined\n"
set warnings($warning_count) "Recommended variable vars(power_domains) not defined"
incr warning_count
}
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
append commands "# INFO: power_analysis_view = $vars(power_analysis_view)\n"
} else {
append commands "# WARNING: Recommended variable vars(power_analysis_view) not defined\n"
append commands "# Will default to the default setup analysis view\n"
set warnings($warning_count) "Recommended variable vars(power_analysis_view) not defined"
incr warning_count
}
}
# if {![info exists vars(view_definition_tcl)]} {
append commands "# ==============================================\n"
append commands "# RC Corners\n"
append commands "# ==============================================\n"
set check(rc_corners) [list]
foreach rc_corner $vars(rc_corners) {
append commands "# INFO: $rc_corner:\n"
if {[info exists vars($rc_corner,cap_table)] && ($vars($rc_corner,cap_table) != "")} {
append commands "# INFO: cap_table = $vars($rc_corner,cap_table)\n"
lappend check(rc_corners) $vars($rc_corner,cap_table)
} else {
if {![info exists vars($rc_corner,qx_tech_file)]} {
append commands "# ERROR: Variable vars($rc_corner,cap_table) or vars($rc_corner,qx_tech_file) must be defined\n"
set errors($error_count) "Variable vars($rc_corner,cap_table) or vars($rc_corner,qx_tech_file) must be defined"
incr error_count
} else {
if {[lindex [split $vars(version) "."] 0] < 15} {
append commands "# INFO: Variable vars($rc_corner,cap_table) not defined\n"
set infos($info_count) "Variable vars($rc_corner,cap_table) not defined"
incr info_count
}
}
}
# if {$vars(cts_engine) != "cts"} {
# if {[info exists vars($rc_corner,atf_file)] && ($vars($rc_corner,atf_file) != "")} {
# append commands "# INFO: atf_file = $vars($rc_corner,atf_file)\n"
# lappend check(rc_corners) $vars($rc_corner,atf_file)
# } else {
# append commands "# WARNING: Recommended variable vars($rc_corner,atf_file) not defined\n"
# set warnings($warning_count) "Recommended variable vars($rc_corner,atf_file) not defined"
# incr warning_count
# }
# }
if {[info exists vars($rc_corner,T)] && ($vars($rc_corner,T) != "")} {
append commands "# INFO: temperature = $vars($rc_corner,T)\n"
set vars($rc_corner,temperature) $vars($rc_corner,T)
lappend check(integers) "$rc_corner,T"
} else {
append commands "# WARNING: Recommended variable vars($rc_corner,T) not defined\n"
set warnings($warning_count) "Recommended variable vars($rc_corner,T) not defined"
incr warning_count
}
if {[info exists vars($rc_corner,qx_tech_file)] && ($vars($rc_corner,qx_tech_file) != "")} {
append commands "# INFO: qx_tech_file = $vars($rc_corner,qx_tech_file)\n"
set vars($rc_corner,qrc_tech) $vars($rc_corner,qx_tech_file)
lappend check(rc_corners) $vars($rc_corner,qx_tech_file)
} else {
if {[info exists vars(postroute_extraction_effort)] && ($vars(postroute_extraction_effort) != "low")} {
append commands "# ERROR: qx_tech_file not defined for $rc_corner and postroute_extraction_effort is set to $vars(postroute_extraction_effort)\n"
set errors($error_count) "qx_tech_file not defined for $rc_corner and postroute_extraction_effort is set to $vars(postroute_extraction_effort)"
incr error_count
}
if {[info exists vars(signoff_extraction_effort)] && ($vars(signoff_extraction_effort) != "low")} {
append commands "# ERROR: qx_tech_file not defined for $rc_corner and signoff_extraction_effort is set to $vars(signoff_extraction_effort)\n"
set errors($error_count) "qx_tech_file not defined for $rc_corner and signoff_extraction_effort is set to $vars(signoff_extraction_effort)"
# set errors($error_count) "Required variable vars($rc_corner,cap_table) not defined"
incr error_count
}
}
}
if {[info exists vars(opconds)]} {
append commands "# ==============================================\n"
append commands "# Operating Conditions\n"
append commands "# ==============================================\n"
foreach opcond $vars(opconds) {
append commands "# INFO: $opcond:\n"
foreach required "P V T" {
if {[info exists vars($opcond,$required)] && ($vars($opcond,$required) != "")} {
append commands "# INFO: $required = $vars($opcond,$required)\n"
} else {
append commands "# ERROR: Required variable vars($opcond,$required) not defined\n"
set errors($error_count) "Required variable vars($opcond,$required) not defined"
incr error_count
}
}
}
}
append commands "# ==============================================\n"
append commands "# Timing Conditions\n"
append commands "# ==============================================\n"
if {[info exists vars(timing_conditions)]} {
foreach timing_condition $vars(timing_conditions) {
append commands "# INFO: $timing_condition:\n"
if {![FF::is_lp_flow]} {
if {[info exists vars($timing_condition,library_set)] && ($vars($timing_condition,library_set) != "")} {
append commands "# INFO: library_set = $vars($timing_condition,library_set)\n"
} else {
foreach additional "early_library_set late_library_set" {
if {[info exists vars($timing_condition,$additional)] && ($vars($timing_condition,$additional) != "")} {
append commands "# INFO: $additional = $vars($timing_condition,$additional)\n"
} else {
append commands "# ERROR: Required variable vars($timing_condition,library_set) and vars($timing_condition,$additional) not defined\n"
set errors($error_count) "Required variable vars($timing_condition,library_set) and vars($timing_condition,$additional) not defined\n"
incr error_count
}
}
}
}
foreach optional "opcond opcond_library early_opcond_library late_opcond_library" {
if {[info exists vars($timing_condition,$optional)] && ($vars($timing_condition,$optional) != "")} {
append commands "# INFO: $optional = $vars($timing_condition,$optional)\n"
}
}
}
} else {
foreach delay_corner $vars(delay_corners) {
append commands "# INFO: $delay_corner:\n"
if {![FF::is_lp_flow]} {
if {[info exists vars($delay_corner,library_set)] && ($vars($delay_corner,library_set) != "")} {
append commands "# INFO: library_set = $vars($delay_corner,library_set)\n"
} else {
foreach additional "early_library_set late_library_set" {
if {[info exists vars($delay_corner,$additional)] && ($vars($delay_corner,$additional) != "")} {
append commands "# INFO: $additional = $vars($delay_corner,$additional)\n"
} else {
append commands "# ERROR: Required variable vars($delay_corner,library_set) and vars($delay_corner,$additional) not defined\n"
set errors($error_count) "Required variable vars($delay_corner,library_set) and vars($delay_corner,$additional) not defined\n"
incr error_count
}
}
}
}
foreach optional "opcond opcond_library early_opcond_library late_opcond_library" {
if {[info exists vars($delay_corner,$optional)] && ($vars($delay_corner,$optional) != "")} {
append commands "# INFO: $optional = $vars($delay_corner,$optional)\n"
}
}
}
}
append commands "# ==============================================\n"
append commands "# Delay Corners\n"
append commands "# ==============================================\n"
set good_corners [list]
foreach delay_corner $vars(delay_corners) {
set args 0
append commands "# INFO: $delay_corner:\n"
if {[info exists vars($delay_corner,rc_corner)] && ($vars($delay_corner,rc_corner) != "")} {
append commands "# INFO: rc_corner = $vars($delay_corner,rc_corner)\n"
incr args
} else {
append commands "# ERROR: Required variable vars($delay_corner,rc_corner) not defined\n"
set errors($error_count) "Required variable vars($delay_corner,rc_corner) not defined"
incr error_count
}
if {(![FF::is_lp_flow]) || ([FF::is_lp_flow] && !$vars(cpf_timing))} {
if {[info exists vars(timing_conditions)]} { ; # Don't require this as we can construct ...
if {[info exists vars($delay_corner,timing_condition)] && ($vars($delay_corner,timing_condition) != "")} {
append commands "# INFO: timing_condition = $vars($delay_corner,timing_condition)\n"
incr args
} else {
foreach additional "early_timing_condition late_timing_condition" {
if {[info exists vars($delay_corner,$additional)] && ($vars($delay_corner,$additional) != "")} {
append commands "# INFO: $additional = $vars($delay_corner,$additional)\n"
incr args
} else {
append commands "# ERROR: Required variable vars($delay_corner,timing_condition) and vars($delay_corner,$additional) not defined\n"
set errors($error_count) "Required variable vars($delay_corner,timing_condition) and vars($delay_corner,$additional) not defined\n"
incr error_count
}
}
}
}
}
foreach optional "power_domains" {
if {[info exists vars($delay_corner,$optional)] && ($vars($delay_corner,$optional) != "")} {
append commands "# INFO: $optional = $vars($delay_corner,$optional)\n"
}
}
if {!$vars(cpf_timing) && ($args > 1)} {
lappend good_corners $delay_corner
} else {
if {$args > 0} {
lappend good_corners $delay_corner
}
}
}
set vars(good_corners) $good_corners
set check(constraint_modes) [list]
if {[FF::is_lp_flow]} {
append commands "# ==============================================\n"
append commands "# Constraint Modes\n"
append commands "# ==============================================\n"
if {[info exists vars(constraint_modes)]} {
foreach mode $vars(constraint_modes) {
append commands "# INFO: $mode:\n"
foreach other "pre_cts_sdc incr_cts_sdc post_cts_sdc" {
if {[info exists vars($mode,$other)] && ($vars($mode,$other) != "")} {
append commands "# INFO: $other = $vars($mode,$other)\n"
lappend check(constraint_modes) $vars($mode,$other)
} else {
if {!$vars(cpf_timing)} {
if {($other == "pre_cts_sdc") && $vars(rc)} {
set vars($mode,$other) $vars(dbs_dir)/$vars(design).syn_placed.$mode.sdc
} elseif {($other == "pre_cts_sdc") && !$vars(rc)} {
append commands "# ERROR: Variable vars($mode,$other) not defined\n"
set errors($error_count) "Variable vars($mode,$other) not defined"
incr error_count
} else {
if {($other == "pre_cts_sdc") || (($other == "post_cts_sdc") && ![info exists vars($mode,incr_cts_sdc)])} {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
}
}
} else {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
}
}
}
}
} else {
append commands "# INFO: No constraint mode information defined\n"
append commands "# Post CTS latency adjustment must be\n"
append commands "# managed by the user via plug-ins\n"
}
} else {
append commands "# ==============================================\n"
append commands "# Constraint Modes\n"
append commands "# ==============================================\n"
if {$vars(rc)} {
set required_list "synth_sdc pre_cts_sdc"
} else {
set required_list "pre_cts_sdc"
}
foreach mode $vars(constraint_modes) {
set found 0
append commands "# INFO: $mode:\n"
foreach required $required_list {
if {[info exists vars($mode,$required)] && ($vars($mode,$required) != "")} {
append commands "# INFO: $required = $vars($mode,$required)\n"
lappend check(constraint_modes) $vars($mode,$required)
incr found
} else {
if {[llength $required_list] == 1} {
append commands "# ERROR: Required variable vars($mode,$required) not defined\n"
set errors($error_count) "Required variable vars($mode,$required) not defined"
incr error_count
}
}
}
if {([llength $required_list] > 1) && ($found == 0)} {
append commands "# ERROR: One of the required variables ($required_list) not defined\n"
set errors($error_count) "One of the required variables ($required_list) not defined"
incr error_count
}
foreach other "post_cts_sdc incr_cts_sdc" {
if {$other == "post_cts_sdc" && ![info exists vars($other)]} {
if {![info exists vars($mode,$other)]} {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
} else {
append commands "# INFO: $other = $vars($mode,$other)\n"
}
} else {
if {[info exists vars($mode,$other)] && ($vars($mode,$other) != "")} {
append commands "# INFO: $other = $vars($mode,$other)\n"
lappend check(constraint_modes) $vars($mode,$other)
} else {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
}
}
}
}
}
if {![info exists vars(hold_analysis_views)]} {
set vars(hold_analysis_views) ""
}
if {![info exists vars(power_analysis_view)]} {
set vars(power_analysis_view) ""
}
append commands "# ==============================================\n"
append commands "# Analysis Views\n"
append commands "# ==============================================\n"
if {[FF::is_lp_flow]} {
foreach analysis_view [concat $vars(setup_analysis_views) $vars(hold_analysis_views) $vars(power_analysis_view)] {
append commands "# INFO: $analysis_view:\n"
foreach other "delay_corner constraint_mode" {
if {[info exists vars($analysis_view,$other)] && ($vars($analysis_view,$other) != "")} {
append commands "# INFO: $other = $vars($analysis_view,$other)\n"
lappend check(analysis_view) $vars($analysis_view,$other)
}
}
}
} else {
set check(analysis_views) [list]
foreach analysis_view [concat $vars(setup_analysis_views) $vars(hold_analysis_views) $vars(power_analysis_view)] {
append commands "# INFO: $analysis_view:\n"
foreach required "delay_corner constraint_mode" {
if {[info exists vars($analysis_view,$required)] && ($vars($analysis_view,$required) != "")} {
append commands "# INFO: $required = $vars($analysis_view,$required)\n"
lappend check(analysis_view) $vars($analysis_view,$required)
} else {
append commands "# ERROR: Required variable vars($analysis_view,$required) not defined\n"
set errors($error_count) "Required variable vars($analysis_view,$required) not defined"
incr error_count
}
}
}
}
# }
append commands "# ==============================================\n"
append commands "# Recommended Variables\n"
append commands "# ==============================================\n"
foreach recommended "scan_def gds_layer_map" {
if {[info exists vars($recommended)] && ($vars($recommended) != "")} {
lappend check(files) $vars($recommended)
append commands "# INFO: $recommended = $vars($recommended)\n"
}
}
if {[info exists vars(gds_files)] && ($vars(gds_files) != "")} {
append commands "# INFO: gds_files = $vars(gds_files)\n"
foreach file $vars(gds_files) {
lappend check(files) $file
}
}
foreach recommended "max_route_layer filler_cells tie_cells dont_use_list antenna_diode" {
if {[info exists vars($recommended)] && ($vars($recommended) != "")} {
append commands "# INFO: $recommended = $vars($recommended)\n"
if {$recommended == "tie_cells"} {
if {[llength $vars(tie_cells)] > 2} {
append commands "# ERROR: Recommended variable vars($recommended) has more than two cells\n"
set errors($error_count) "Recommended variable vars($recommended) has more than two cells"
incr error_count
}
}
if {$recommended == "antenna_diode"} {
if {[llength $vars(antenna_diode)] > 1} {
append commands "# ERROR: Recommended variable vars($recommended) has more than one cells\n"
set errors($error_count) "Recommended variable vars($recommended) has more than one cells"
incr error_count
}
}
if {$recommended == "max_route_layer"} {
lappend check(integers) "$recommended"
}
} else {
if {($recommended == "dont_use_list")} {
if {![info exists vars(dont_use_file)]} {
append commands "# WARNING: Recommended variables dont_use_list and dont_use_file not defined\n"
set warnings($warning_count) "Recommended variables dont_use_list and dont_use_file not defined"
incr warning_count
}
} else {
append commands "# WARNING: Recommended variable vars($recommended) not defined\n"
set warnings($warning_count) "Recommended variable vars($recommended) not defined"
incr warning_count
}
}
}
foreach optional "size_only_file dont_use_file" {
if {[info exists vars($optional)]} {
lappend check(files) $vars($optional)
}
}
append commands "# ==============================================\n"
append commands "# Other Variables\n"
append commands "# ==============================================\n"
foreach other "jtag_cells jtag_rows spare_cells" {
if {[info exists vars($other)] && ($vars($other) != "")} {
append commands "# INFO: $other = $vars($other)\n"
} else {
append commands "# INFO: Variable vars($other) not defined\n"
}
}
# if {![info exists vars(view_definition_tcl)]} {
append commands "# ==============================================\n"
append commands "# Scale Factors\n"
append commands "# ==============================================\n"
foreach rc_corner $vars(rc_corners) {
set i 0
append commands "# INFO: $rc_corner:\n"
if {[info exists vars($rc_corner,scale_tcl)]} {
if {[file exists $vars($rc_corner,scale_tcl)]} {
incr i
append commands "# INFO: scaling file = $vars($rc_corner,scale_tcl)\n"
} else {
puts "<FF> ERROR: Scaling file $vars($rc_corner,scale_tcl) for rc corner $rc_corner defined but does not exist"
set errors($error_count) "Scaling file $vars($rc_corner,scale_tcl) for rc corner $rc_corner defined but does not exist"
incr error_count
}
} else {
foreach other "pre_route_res_factor post_route_res_factor \
pre_route_cap_factor post_route_cap_factor \
pre_route_clk_res_factor post_route_clk_res_factor \
pre_route_clk_cap_factor post_route_clk_cap_factor \
post_route_xcap_factor" {
if {[info exists vars($rc_corner,$other)]} {
append commands "# INFO: $other = $vars($rc_corner,$other)\n"
incr i
}
}
}
if {$i == 0} {
append commands "# WARNING: No scale factors set for rc corner ($rc_corner)\n"
set warnings($warning_count) "No scale factors set for rc corner ($rc_corner)"
incr warning_count
}
}
append commands "# ==============================================\n"
append commands "# Derating Factors\n"
append commands "# ==============================================\n"
set i 0
if {[info exists vars(derate_tcl)]} {
append commands "# INFO: derate file = $vars(derate_tcl)\n"
lappend check(files) $vars(derate_tcl)
incr i
} else {
foreach delay_corner $vars(delay_corners) {
append commands "# INFO: $delay_corner:\n"
if {[info exists vars($delay_corner,derate_tcl)]} {
append commands "# INFO: derate file = $vars($delay_corner,derate_tcl)\n"
lappend check(files) $vars($delay_corner,derate_tcl)
incr i
} else {
if {[info exists vars(derate_tcl)]} {
append commands "# INFO: derate file = $vars(derate_tcl)\n"
lappend check(files) $vars(derate_tcl)
} else {
foreach other "early_data_cell early_clock_cell early_cell_check \
late_data_cell late_clock_cell late_cell_check \
data_cell_early clock_cell_early cell_check_early \
data_cell_late clock_cell_late cell_check_late" {
if {[info exists vars($delay_corner,$other)]} {
append commands "# INFO: $other = $vars($delay_corner,$other)\n"
incr i
}
}
}
}
if {$i == 0} {
append commands "# WARNING: No derating factors set for delay corner ($delay_corner)\n"
set warnings($warning_count) "No derating factors set for delay corner ($delay_corner)"
incr warning_count
}
}
}
# }
if {![regexp "9.1" $vars(version)]} {
set valid "TRUE FALSE true false auto"
if {[info exists vars(enable_si_aware)]} {
if {[lsearch $valid $vars(enable_si_aware)] == -1} {
append commands "# ERROR: Variable vars(enable_si_aware) has illegal value\n"
set errors($error_count) "Variable vars(enable_si_aware) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
}
set valid [list true false]
foreach var "fix_hold_ignore_ios fix_hold_allow_tns_degradation" {
if {![info exists vars($var)]} {
continue
}
if {[lsearch $valid [string tolower $vars($var)]] == -1} {
append commands "# ERROR: Variable vars($var) has illegal value $vars($var)\n"
set errors($error_count) "Variable vars($var) has illegal value $vars($var)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
set valid "pre_place pre_prects pre_cts pre_postcts pre_postroute pre_postroute_si pre_signoff true false"
foreach option "metalfill enable_ocv enable_ss" {
if {[info exists vars($option)]} {
if {[lsearch $valid $vars($option)] == -1} {
append commands "# ERROR: Variable vars($option) has illegal value ($vars($option))\n"
set errors($error_count) "Variable vars($option) has illegal value ($vars($option))"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
}
set pacs [FF::get_by_suffix vars ",pac_mode"]
set valid "read_only interface all"
foreach pac $pacs {
if {[info exists vars(pac_mode)]} {
if {[lsearch $valid $vars(pac_mode)] == -1} {
append commands "# ERROR: Variable vars(pac_mode) has illegal value\n"
set errors($error_count) "Variable vars(pac_mode) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
}
set valid "default pessimistic"
if {[info exists vars(si_analysis_type)]} {
if {[lsearch $valid $vars(si_analysis_type)] == -1} {
append commands "# ERROR: Variable vars(si_analysis_type) has illegal value\n"
set errors($error_count) "Variable vars(si_analysis_type) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
set valid "post_cts post_route both none"
if {[info exists vars(clock_eco)]} {
if {[lsearch $valid $vars(clock_eco)] == -1} {
append commands "# ERROR: Variable vars(clock_eco) has illegal value\n"
set errors($error_count) "Variable vars(clock_eco) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
# if {$vars(enable_flexilm)} {
# set warnings($warning_count) "Using vars(enable_flexilm) requires the following limited access feature : encFlexILM"
# incr warning_count
# if {$vars(place_opt_design)} {
# set warnings($warning_count) "Setting vars(place_opt_design) to 'false' as vars(enable_flexilm) is true"
# incr warning_count
# set vars(place_opt_design) false
# }
# }
###############################################################################
# The rda_Input(ui_pg_connections) variable is a special case as depending
# on the value of this variable, other 'user defined' variables must be
# dynamically checked
###############################################################################
#if {[info exists vars(pg_connections)]} {
# foreach option $vars(pg_connections) {
# if {![info exists vars($option)]} {
# append commands "# ERROR: The p/g connection definition is incomplete"
# append commands " Please add 'set vars($option) <global_net>' to your setup.tcl"
# set errors($error_count) "The p/g connection definition is incomplete; variable vars($option) is required"
# incr error_count
# }
# }
#}
set check(plugins) [list]
if {[info exists vars(metalfill)] && ($vars(metalfill) != false)} {
set check(plugins) metalfill_tcl
}
append commands "# ==============================================\n"
append commands "# Plug-ins\n"
append commands "# ==============================================\n"
set rc_plugins "syn_init_tcl syn_load_rtl_tcl pre_syn_load_lib_tcl post_syn_load_lib_tcl \
pre_syn_elab_tcl post_syn_elab_tcl syn_dft_setup_tcl pre_syn_gen_tcl \
post_syn_gen_tcl pre_syn_map_tcl post_syn_map_tcl post_syn_dft_tcl \
pre_syn_incr_tcl post_syn_incr_tcl pre_syn_place_tcl postload_syn_place_tcl \
preexport_syn_place_tcl preannotation_syn_place_tcl post_syn_place_tcl pre_syn_exit_tcl"
set edi_plugins "always_source_tcl pre_init_tcl post_init_tcl \
pre_place_tcl place_tcl post_place_tcl pre_cts_tcl cts_tcl post_cts_tcl \
pre_prects_tcl post_prects_tcl pre_postcts_tcl post_postcts_tcl \
pre_postcts_hold_tcl post_postcts_hold_tcl pre_route_tcl post_route_tcl \
pre_postroute_tcl post_postroute_tcl pre_postroute_hold_tcl post_postroute_hold_tcl \
pre_postroute_si_tcl post_postroute_si_tcl pre_postroute_si_hold_tcl
post_postroute_si_hold_tcl pre_signoff_tcl post_signoff_tcl \
pre_rebudget_tcl post_rebudget_tcl pre_flexilm_tcl post_flexilm_tcl \
pre_assemble_tcl post_assemble_tcl pre_model_gen_tcl post_model_gen_tcl \
pre_partition_place_tcl post_partition_place_tcl pre_assemble_flex_ilm_tcl post_assemble_flexilm_tcl \
pre_partition_tcl post_partition_tcl"
set vars(rc_plugins) $rc_plugins
set vars(edi_plugins) $edi_plugins
if {$vars(rc)} {
set plugin_list [join [concat $rc_plugins $edi_plugins]]
} else {
set plugin_list $edi_plugins
}
foreach plugin $plugin_list {
if {[info exists vars($plugin)] && ($vars($plugin) != "")} {
append commands "# INFO: Plug-in $plugin = $vars($plugin)\n"
lappend check(plugins) $plugin
lappend vars(plugins_defined) $plugin
}
}
if {$vars(novus) && [info exists vars(plugins_defined)]} {
FF_NOVUS::convert_plugins
}
set dist(lsf) "queue resource args"
set dist(custom) "script"
set dist(rsh) "host_list"
set dist(local) ""
if {[info exists vars(distribute)]} {
if {[info exists dist($vars(distribute))]} {
append commands "# ==============================================\n"
append commands "# Distribution Setup\n"
append commands "# ==============================================\n"
append commands "# INFO: Mode = $vars(distribute)\n"
foreach option $dist($vars(distribute)) {
if {![info exists vars($vars(distribute),$option)]} {
append commands "# ERROR: Required variable vars($vars(distribute),$option) not defined\n"
set errors($error_count) "Required variable vars($vars(distribute),$option) not defined"
incr error_count
} else {
append commands "# INFO: $option = $vars($vars(distribute),$option)\n"
}
}
} else {
append commands "# ERROR: Distribution mode $vars(distribute) not supported\n"
set errors($error_count) "Distribution mode $vars(distribute) not supported"
incr error_count
}
} else {
if {[info exists vars(hosts)] && ($vars(hosts) > 1)} {
append commands "#WARNING: Variable vars(hosts) > 1 but vars(distribute) not defined\n"
set warnings($warning_count) "Variable vars(hosts) > 1 but vars(distribute) not defined"
incr warning_count
}
}
append commands "# ==============================================\n"
append commands "# Type Check\n"
append commands "# ==============================================\n"
foreach integer $check(integers) {
if {![string is integer -strict $vars($integer)]} {
append commands "# ERROR: Variables is not an integer ($integer) ...\n"
set errors($error_count) "Variables is not an integer ($integer) ..."
incr error_count
}
}
append commands "# ==============================================\n"
append commands "# File Check\n"
append commands "# ==============================================\n"
set files 0
append commands "# INFO: Checking design files ...\n"
foreach file $check(files) {
# append commands "# INFO: $file ...\n"
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file) ...\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
} else {
incr files
}
}
append commands "# INFO: ... found $files files\n"
set files 0
append commands "# INFO: Checking LEF files ...\n"
if {[info exists vars(lef_files)]} {
foreach file $vars(lef_files) {
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file)\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
} else {
incr files
}
}
append commands "# INFO: ... found ($files/[llength $vars(lef_files)]) lef files\n"
}
set files 0
set total 0
# if {![info exists vars(view_definition_tcl)]} {
# if {![info exists vars(cpf_file)]} {
append commands "# INFO: Checking library sets ...\n"
foreach library_set $vars(library_sets) {
if {[info exists vars(enable_ldb)] && $vars(enable_ldb)} {
set temp_list $vars($library_set,timing,orig)
} else {
set temp_list $vars($library_set,timing)
}
foreach file $temp_list {
incr total
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file)\n"
# set errors($error_count) "File does not exist ($file)"
# incr error_count
} else {
incr files
}
}
if {[info exists vars($library_set,si)]} {
foreach file $vars($library_set,si) {
incr total
if {![file exists $file]} {
append commands "# WARNING: CDB file does not exist ($file)\n"
# set warnings($warning_count) "CDB file does not exist ($file)"
# incr warning_count
} else {
incr files
}
}
} else {
if {!$vars(enable_si_aware)} {
append commands "# WARNING: CDB libraries not defined for $library_set library set\n"
set warnings($warning_count) "CDB libraries not defined for $library_set library set"
incr warning_count
}
}
}
append commands "# INFO: ... found ($files/$total) library files\n"
if {$total != $files} {
set errors($error_count) "[expr $total - $files] timing library files were not found "
incr error_count
}
set files 0
# }
append commands "# INFO: Checking rc corners ...\n"
foreach file $check(rc_corners) {
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file)\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
} else {
incr files
}
}
append commands "# INFO: ... found $files files\n"
set files 0
append commands "# INFO: Checking constraint modes ...\n"
foreach file_list $check(constraint_modes) {
foreach file $file_list {
if {![file exists $file]} {
if {![info exists vars(cpf_file)] || ([info exists vars(cpf_file)] && !$vars(cpf_timing))} {
append commands "# ERROR: File does not exist ($file)\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
}
} else {
incr files
}
}
}
# }
append commands "# INFO: ... found $files files\n"
set files 0
append commands "# INFO: Checking plugin files ...\n"
foreach plug $check(plugins) {
set file $vars($plug)
if {![file exists $file] && ![file exists $vars(plug_dir)/$file]} {
append commands "# WARNING: File does not exist ($file) ... continuing\n"
lappend vars(missing_plugins) $plug
} else {
lappend vars(plugins_found) $plug
incr files
if {!$vars(enable_celtic_steps)} {
if {[regexp "postroute_si" $plug]} {
append warnings($warning_count) "Plug-in $plug will be skipped for siAware flow"
incr warning_count
append commands "# WARNING: Plug-in $plug will be skipped for siAware flow\n"
append commands "# To enable celtic based SI flow, use vars(enable_celtic_steps)\n"
}
}
}
}
append commands "# INFO: ... found $files files\n"
append commands "# =====================================================\n"
append commands "# Flow Options\n"
append commands "# =====================================================\n"
if {[info exists vars(partition_list)]} {
set flow hierarchical
} else {
set flow flat
}
set valid [list none default standard express extreme]
if {[lsearch $valid [string tolower $vars(flow_effort)]] == -1} {
append commands "# ERROR: Variable vars(flow_effort) has illegal value $vars(flow_effort)\n"
set errors($error_count) "Variable vars(flow_effort) has illegal value $vars(flow_effort)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
append commands "# Flow = $flow\n"
append commands "# Flavor = $vars(flow)\n"
append commands "# Effort = $vars(flow_effort)\n"
append commands "# -----------------------------------------------------\n"
append commands "# Placement Options\n"
append commands "# -----------------------------------------------------\n"
if {[info exists vars(place_opt_design)]} {
append commands "# Place Opt Design = $vars(place_opt_design)\n"
}
if {[info exists vars(in_place_opt)]} {
append commands "# In Place Opt = $vars(in_place_opt)\n"
}
if {[info exists vars(no_pre_place_opt)]} {
append commands "# No PrePlace Opt = $vars(no_pre_place_opt)\n"
}
if {[info exists vars(place_io_pins)]} {
append commands "# Place IO Pins = $vars(place_io_pins)\n"
}
if {[info exists vars(clock_gate_aware)]} {
append commands "# Clock Gate Aware = $vars(clock_gate_aware)\n"
}
if {[info exists vars(congestion_effort)]} {
if {$vars(congestion_effort) == "none"} {
unset vars(congestion_effort)
} else {
append commands "# Congestion Effort = $vars(congestion_effort)\n"
}
}
append commands "# -----------------------------------------------------\n"
append commands "# Clock Tree Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Route Clock Nets = $vars(route_clock_nets)\n"
if {[info exists vars(clock_eco)]} {
append commands "# Clock ECO = $vars(clock_eco)\n"
}
append commands "# -----------------------------------------------------\n"
append commands "# Optimization Options\n"
append commands "# -----------------------------------------------------\n"
if {[info exists vars(leakage_effort)]} {
append commands "# Leakage Effort = $vars(leakage_effort)\n"
}
if {[info exists vars(preserve_assertions)]} {
append commands "# Preserve Assertions = $vars(preserve_assertions)\n"
}
if {[info exists vars(useful_skew)]} {
append commands "# Useful Skew = $vars(useful_skew)\n"
}
if {[info exists vars(critical_range)]} {
append commands "# Critical Range = $vars(critical_range)\n"
}
if {[info exists vars(all_end_points)]} {
append commands "# All End Points = $vars(all_end_points)\n"
}
if {[info exists vars(size_only_file)]} {
append commands "# Size Only File = $vars(size_only_file)\n"
}
if {[info exists vars(dont_use_file)]} {
append commands "# Don't Use File = $vars(dont_use_file)\n"
}
if {[info exists vars(skew_buffers)]} {
append commands "# Skew Buffers = $vars(skew_buffers)\n"
}
if {[info exists vars(enable_pac)]} {
append commands "# Enable PAC = $vars(enable_pac)\n"
if {[info exists vars(partition_list)]} {
foreach pac $vars(partition_list) {
if {[info exists vars($pac,pac_mode)]} {
append commands "# $pac -> $vars($pac,pac_mode)\n"
}
}
}
}
append commands "# -----------------------------------------------------\n"
append commands "# Hold Fixing Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Fix Hold = $vars(fix_hold)\n"
if {[info exists vars(fix_hold_effort)]} {
append commands "# Fix Hold Effort = $vars(fix_hold_effort)\n"
}
if {[info exists vars(fix_hold_ignore_ios)]} {
append commands "# Ignore IOs = $vars(fix_hold_ignore_ios)\n"
}
if {[info exists vars(fix_hold_allow_tns_degradation)]} {
append commands "# Allow TNS Degradation = $vars(fix_hold_allow_tns_degradation)\n"
}
append commands "# -----------------------------------------------------\n"
append commands "# Timing Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Enable CPPR = $vars(enable_cppr)\n"
append commands "# Enable OCV = $vars(enable_ocv)\n"
append commands "# Enable AOCV = $vars(enable_aocv)\n"
append commands "# Enable SOCV = $vars(enable_socv)\n"
append commands "# Enable SS = $vars(enable_ss)\n"
append commands "# -----------------------------------------------------\n"
append commands "# Routing Options\n"
append commands "# -----------------------------------------------------\n"
if {[info exists vars(track_opt)]} {
append commands "# In Route Optimization = $vars(track_opt)\n"
# if {$vars(track_opt)} {
# set vars(enable_si_aware) true
# if {![info exists vars(tquantus_file)]} {
# set errors($error_count) "tQuantus file - vars(tquantus_file) - required when vars(track_opt) set to true"
# incr error_count
# }
# }
}
if {[info exists vars(multi_cut_effort)]} {
append commands "# Multi-Cut Effort = $vars(multi_cut_effort)\n"
}
if {[info exists vars(litho_driven_routing)]} {
append commands "# Litho Driven Routing = $vars(litho_driven_routing)\n"
}
if {[info exists vars(antenna_diode)] && ($vars(antenna_diode) != "")} {
append commands "# Antenna Diode = $vars(antenna_diode)\n"
}
if {[info exists vars(relative_c_thresh)] || \
[info exists vars(total_c_thresh)] || \
[info exists vars(coupling_c_thresh)] ||\
[info exists vars(postroute_extraction_effort)] ||\
[info exists vars(signoff_extraction_effort)]} {
append commands "# -----------------------------------------------------\n"
append commands "# Extraction Options\n"
append commands "# -----------------------------------------------------\n"
}
if {[info exists vars(relative_c_thresh)]} {
append commands "# Relative C Threshold = $vars(relative_c_thresh)\n"
}
if {[info exists vars(total_c_thresh)]} {
append commands "# Total C Threshold = $vars(total_c_thresh)\n"
}
if {[info exists vars(coupling_c_thresh)]} {
append commands "# Coupling C Threshold = $vars(coupling_c_thresh)\n"
}
if {[info exists vars(postroute_extraction_effort)]} {
append commands "# Postroute Effort Level = $vars(postroute_extraction_effort)\n"
}
if {[info exists vars(signoff_extraction_effort)]} {
append commands "# Signoff Effort Level = $vars(signoff_extraction_effort)\n"
}
append commands "# -----------------------------------------------------\n"
append commands "# DFM Options\n"
append commands "# -----------------------------------------------------\n"
set check_lpa_tech 0
set check_lpa_conf 0
if {[info exists vars(fix_litho)] && $vars(fix_litho)} {
append commands "# Fix Litho = $vars(fix_litho)\n"
set check_lpa_conf 1
set vars(verify_litho) true
}
if {[info exists vars(verify_litho)] && $vars(verify_litho)} {
append commands "# Verify Litho = $vars(verify_litho)\n"
set check_lpa_tech 1
}
if {[info exists vars(lpa_tech_file)]} {
append commands "# LPA Tech File = $vars(lpa_tech_file)\n"
}
if {$check_lpa_tech} {
if {![info exists vars(lpa_tech_file)]} {
set errors($error_count) "LPA tech file not defined ..."
incr error_count
}
}
if {[info exists vars(lpa_conf_file)]} {
append commands "# LPA Conf File = $vars(lpa_conf_file)\n"
}
if {$check_lpa_conf} {
if {![info exists vars(lpa_conf_file)]} {
set errors($error_count) "LPA conf file not defined ..."
incr error_count
}
}
append commands "# -----------------------------------------------------\n"
append commands "# Signal Integrity Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Process = $vars(process)\n"
if {[info exists vars(delta_delay_threshold)]} {
append commands "# Delta Delay Threshold = $vars(delta_delay_threshold)\n"
}
if {[info exists vars(celtic_settings)]} {
append commands "# Celtic Settings = $vars(celtic_settings)\n"
}
if {[info exists vars(si_analysis_type)]} {
append commands "# Analysis Type = $vars(si_analysis_type)\n"
}
if {[info exists vars(acceptable_wns)]} {
append commands "# Analysis Type = $vars(acceptable_wns)\n"
}
if {[info exists vars(distribute)]} {
if {[info exists dist($vars(distribute))]} {
append commands "# -----------------------------------------------------\n"
append commands "# Multiple CPUs\n"
append commands "# -----------------------------------------------------\n"
append commands "# Mode = $vars(distribute)\n"
if {[info exists vars(local_cpus)]} {
append commands "# CPUs On Local Host = $vars(local_cpus)\n"
}
if {[info exists vars(remote_hosts)]} {
append commands "# Number of Remote Hosts = $vars(remote_hosts)\n"
}
if {[info exists vars(cpus_per_remote_host)]} {
append commands "# CPUs Per Remote Host = $vars(cpus_per_remote_host)\n"
}
}
} else {
if {[info exists vars(local_cpus)]} {
append commands "# -----------------------------------------------------\n"
append commands "# Multiple CPUs\n"
append commands "# -----------------------------------------------------\n"
append commands "# CPUs On Local Host = $vars(local_cpus)\n"
}
}
if {$vars(high_timing_effort)} {
if {[lindex [split $vars(version) "."] 0] < 15} {
append commands "# -----------------------------------------------------\n"
append commands "# <<< HIGH EFFORT FLOW ENABLED >>>\n"
append commands "# -----------------------------------------------------\n"
} else {
append commands "# WARNING: Variable vars(high_timing_effort) not supported anymore. Please use vars(flow_effort).\n"
set warnings($warning_count) "Variable vars(high_timing_effort) not supported anymore. Please use vars(flow_effort)."
incr warning_count
}
}
append commands "# =====================================================\n"
append commands "# Abort on Setup Error = $vars(abort)\n"
append commands "# =====================================================\n"
if {[lindex [split $vars(version) "."] 0] > 10} {
foreach var [array names save_vars] {
set vars($var) $save_vars($var)
}
}
set command ""
set vars(info_count) $info_count
if {$info_count > 0} {
append command "# -----------------------------------------------------\n"
append command "# Info Summary\n"
append command "# -----------------------------------------------------\n"
for {set i 0} {$i<$info_count} {incr i} {
append command "# ([expr $i + 1]) $infos($i)\n"
}
append command "# -----------------------------------------------------\n"
append commands $command
}
set vars(warning_count) $warning_count
if {$warning_count > 0} {
append command "# -----------------------------------------------------\n"
append command "# Warning Summary\n"
append command "# -----------------------------------------------------\n"
for {set i 0} {$i<$warning_count} {incr i} {
append command "# ([expr $i + 1]) $warnings($i)\n"
}
append command "# -----------------------------------------------------\n"
append commands $command
}
set vars(error_count) $error_count
if {$error_count > 0} {
append command "# -----------------------------------------------------\n"
append command "# Error Summary\n"
append command "# -----------------------------------------------------\n"
for {set i 0} {$i<$error_count} {incr i} {
append command "# ([expr $i + 1]) $errors($i)\n"
}
append command "# -----------------------------------------------------\n"
append commands $command
} else {
append commands "# SETUP CHECK PASSED\n"
append commands "# =====================================================\n"
}
file mkdir $vars(script_dir)
set op [open $vars(script_dir)/check.rpt w]
# if {$vars(novus)} {
# FF_NOVUS::dump_novus_attributes
# }
puts $op $commands
close $op
if {$vars(abort) && ($error_count > 0)} {
puts "<FF> Aborting due to previous errors ..."
puts "<FF> See $vars(script_dir)/check.rpt for details"
puts ""
puts " Error Summary"
puts " -------------"
for {set i 0} {$i<$error_count} {incr i} {
puts " ([expr $i + 1]) $errors($i)"
}
puts "-------------------------------------------------"
exit -1
}
if {!$vars(codegen)} {
if {![FF::is_lp_flow]} {
return
}
set vars(required_procs) "get_clock_ports get_power_domains modify_power_domains add_power_switches \
route_secondary_pg_nets buffer_always_on_nets insert_welltaps_endcaps"
}
set vars(check_setup) 0
# Record errors for later processing
set vars(check_setup_errors) {}
for {set i 0} {$i<$error_count} {incr i} {
lappend vars(check_setup_errors) $errors($i)
}
}
###############################################################################
# Procedure to determine flow flavor, check for ilms, etc.
###############################################################################
proc check_flow {} {
global vars
set vars(ilm) 0
set vars(top) 0
if {![info exists vars(partition_list)] || ([info exists vars(partition_list)] && \
([file tail [file dirname [pwd]]] != "$vars(partition_dir)"))} {
if {![info exists vars(partition_list)]} {
set vars(flavor) flat
if {![info exists vars(mode)]} {
set vars(mode) "flat"
}
} else {
set vars(flavor) hier
if {![info exists vars(mode)]} {
set vars(mode) "top_down"
}
}
if {[info exists vars(partition_list)] && ($vars(mode) == "bottom_up")} {
set vars(ilm) 1
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
set vars(ilm) 1
} else {
set vars(ilm) 0
}
} else {
if {[info exists vars(partition_list)]} {
set ptn [file tail [pwd]]
set vars(ptn) $ptn
if {([file tail [file dirname [pwd]]] == "$vars(partition_dir)") &&
([lsearch $vars(partition_list) $ptn] == -1)} {
set vars(ilm) 1
set vars(top) 1
# FF_NOVUS::normalize_constraints
}
}
}
if {$vars(debug)} {
puts "<DEBUG> Flow -> $vars(flavor) : Step -> $vars(step) : ILM -> $vars(ilm)"
}
}
proc run_compile {} {
global vars
file mkdir $vars(script_dir)/INNOVUS
set op [open $vars(script_dir)/INNOVUS/run_compile.tcl w]
set commands ""
if {![info exists vars(ldb_dir)]} {
set vars(ldb_dir) LDB
}
file mkdir $vars(ldb_dir)
set done_list [list]
foreach set $vars(library_sets) {
set file_list [list]
foreach file $vars($set,timing) {
if {[lsearch $done_list $file] == -1} {
append commands "write_ldb -library $file -outfile $vars(ldb_dir)/[file tail $file.ldb]\n"
lappend done_list $file
}
lappend file_list $vars(ldb_dir)/[file tail $file].ldb
}
set vars($set,timing,orig) $vars($set,timing)
set vars($set,timing) $file_list
}
puts $op "$commands\nexit\n"
close $op
set vars(ran_compile) 1
}
# # Generate the command to verify geometry. This is verifyGeometry
# # for traditional processes, verify_drc for 20nm and below.
# proc verify_geometry_command {} {
# global vars
# set process [regsub "nm" $vars(process) ""]
# if {$process > 20} {
# return "verifyGeometry"
# } else {
# return "verify_drc"
# }
# }
###############################################################################
# Procedure to initialize the foundation flow
###############################################################################
proc initialize_flow {} {
global vars
global env
set commands ""
FF_NOVUS::seed_variables 1
FF_NOVUS::check_setup
if {[info exist env(VPATH)]} {
file mkdir $env(VPATH)
}
if {[info exists vars(capture_metrics)] && $vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands "\n#-------------------------------------------------------------\n"
append commands "# Loading applets for metrics capture ...\n"
append commands "#-------------------------------------------------------------\n"
if {[file tail [file dirname [exec pwd]]] == $vars(partition_dir)} {
append commands "source $vars(norm_script_path)/ETC/applet.tcl\n"
append commands "source $vars(norm_script_path)/ETC/compatibility.tcl\n"
append commands "set_db applet_search_path $vars(norm_script_path)/ETC/applets\n"
} else {
append commands "source \$vars(script_path)/ETC/applet.tcl\n"
append commands "source \$vars(script_path)/ETC/compatibility.tcl\n"
append commands "set_db applet_search_path \$vars(script_path)/ETC/applets\n"
}
append commands "applet load measure\n"
append commands "applet load time_info\n"
append commands "#-------------------------------------------------------------\n\n"
append commands "if {\[file exists $vars(time_info_db)\]} {\n"
append commands " time_info -quiet -table ff_ext -load $vars(time_info_db)\n"
append commands "}\n"
append commands "#-------------------------------------------------------------\n\n"
}
}
# append commands "#---------------------------------------------------------------------\n"
# append commands "# RUN SCRIPT FOR STEP '[string toupper $vars(step)]'\n"
# append commands "#---------------------------------------------------------------------\n"
if {$vars(report_system_info)} {
append commands "ff_procs::system_info\n"
}
append commands [FF_NOVUS::initialize_multicpu]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc load_design {step {current_step ""} {format 1}} {
global env
global vars
global errors
global warnings
if {[regexp syn_ $step]} {
if {[info exists vars($current_step,starting_dbs)]} {
if {[file isfile $vars($current_step,starting_dbs)]} {
set command "read_db $vars($current_step,starting_dbs) \n"
} else {
puts "<FF> Starting DBS ($vars($current_step,starting_dbs)) defined but does not exist"
set command "read_db $vars($current_step,starting_dbs) \n"
set warnings($vars(warning_count)) "Starting DBS ($vars($current_step,starting_dbs)) defined but does not exist"
incr vars(warning_count)
}
} else {
set command "read_db $vars(dbs_dir)/$step.db\n"
}
return "\n$command"
}
if {[info exists vars(hier)]} {
set hier true
} else {
set hier false
}
if {$current_step == ""} {
set current_step $step
}
# if {$step ==""} {
# set step $vars(step)
# }
# if {![info exists vars(step)]} {
# set vars(step) $step
# }
if {!$vars(codegen)} {
set restore_design true
}
set design $vars(design)
# Build restore_design command string
# ... check first for starting_dbs
# ... if not we need to know the design name as this may be a
# recursive call in a hierarhical flow
if {[info exists vars($current_step,starting_dbs)]} {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
# Interpret the starting DBS as an OA triple
set restore_command "[list read_db -cellview $vars($current_step,starting_dbs)]\n"
} else {
if {[file isdirectory $vars($current_step,starting_dbs)]} {
set restore_command "read_db $vars($current_step,starting_dbs) \n"
} elseif {[file exists $vars($current_step,starting_dbs)]} {
set restore_command "read_db $vars($current_step,starting_dbs) \n"
} else {
puts "<FF> Starting DBS ($vars($current_step,starting_dbs)) defined but does not exist"
set restore_command "read_db $vars($current_step,starting_dbs) \n"
set warnings($vars(warning_count)) "Starting DBS ($vars($current_step,starting_dbs)) defined but does not exist"
incr vars(warning_count)
}
}
} else {
# BCL: Added subst around vars(dbs_dir) to resolve vars(rundir)
set dir [subst $vars(dbs_dir)]
# Adding this for PV ...
if {!$vars(codegen)} {
if {[file exists $dir/$step.enc]} {
# BCL: Changed "DBS" to $dir
if {![catch {set foo [glob $dir/$step.enc/*.conf]}]} {
# BCL: Changed "DBS" to $dir
regsub "\\\.conf" [glob $dir/$step.enc/*.conf] "" temp
} else {
# BCL: Changed "DBS" to $dir
if {![catch {set foo [glob $dir/$step.enc/*.globals]}]} {
# BCL: Changed "DBS" to $dir
regsub "\\\.globals" [glob $dir/$step.enc/*.globals] "" temp
}
}
if {$design != [file tail $temp]} {
set vars(design) [file tail $temp]
puts "<FF> Updating design name to $design"
if {[info exists vars(partition_list)]} {
if {[lsearch $vars(partition_list) [file tail [pwd]]] != -1} {
set design [file tail [pwd]]
}
}
}
} else {
puts "<FF> Starting DBS $dir/$step.enc defined but does not exist"
exit -1
}
}
# Of course, the command will depend on the database format ... and the version
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {$hier} {
set restore_command "read_db -cellview \[list $vars(oa_partition_lib) $design $step\]\n"
} else {
set restore_command "read_db -cellview \[list $vars(oa_design_lib) $design $step\]\n"
}
} else {
if {$vars(user_mode) == "hier" && ($vars(hier_flow_type) == "2pass")} {
if {$vars(step) == "cts" && $vars(enable_flexilm)} {
if {([lsearch $vars(partition_list) $vars(design)] != -1)} {
set restore_command "read_db ${design}_post_eco.enc \n"
} else {
set restore_command "read_db . \n"
}
} elseif {$vars(step) == "postcts" && !$vars(enable_flexilm)} {
set restore_command "read_db . \n"
} else {
set restore_command "read_db $dir/$step.enc \n"
}
} else {
if {$vars(step) != "partition_place"} {
set restore_command "read_db $dir/$step.enc\n"
} else {
if {$vars(use_flexmodels)} {
set restore_command "read_db $dir/$step.enc\n"
} else {
return ""
}
}
}
}
}
# Pass the command through the wrapper and then make it conditional so it can
# be disabled in a single process flow
set restore_command [FF::wrap_command $current_step,restore_design $restore_command]
set cond_restore_command "if {\$vars(restore_design)} {\n$restore_command\n}"
if {!$format} {
if {$vars(codegen)} {
# return $cond_restore_command
return $restore_command
} else {
# eval $cond_restore_command
eval $restore_command
}
} else {
if {$vars(catch_errors)} {
append commands "\nif {\$vars(restore_design)} {\n"
append commands " if {\[catch {\n$restore_command}\]} {\n"
append commands " puts \"<FF> ERROR LOADING DATABASE FROM STEP $step ... EXITING\"\n"
append commands " exit -1\n"
append commands " }\n"
append commands "}\n"
} else {
append commands "$restore_command"
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] > 13} {
if {$vars(step) != "debug"} {
append commands "\nenable_metrics -on\n"
# append commands "push_snapshot_stack\n"
}
}
}
append commands [FF::source_plug always_source_tcl]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
}
############################################################################
# Setup procedure for run* steps
############################################################################
proc initialize_step {step} {
global vars
global env
global errors
global warnings
if {![info exists step]} {
set step $vars(step)
}
if {[info exists vars($step,rpt_dir)]} {
set vars(rpt_dir) $vars($step,rpt_dir)
file mkdir $vars($step,rpt_dir)
} else {
set vars(rpt_dir) $vars(orig_rpt_dir)
}
if {![info exists vars(warning_count)]} {
set vars(warning_count) 0
}
if {![info exists vars(error_count)]} {
set vars(error_count) 0
}
set commands ""
if {$vars(verbose)} {
append commands "#\n"
append commands "# STEP $step\n"
append commands "#\n"
}
if {![info exists vars(only_options)] || ([info exists vars(only_options)] && !$vars(only_options))} {
set update_setup 0
set update_hold 0
set command ""
if {[info exists vars($step,active_setup_views)] && ([llength $vars($step,active_setup_views)]>0)} {
append command "set setup_analysis_views \"$vars($step,active_setup_views)\"\n"
set update_setup 1
}
if {[info exists vars($step,active_hold_views)] && ([llength $vars($step,active_hold_views)]>0)} {
append command "set hold_analysis_views \"$vars($step,active_hold_views)\"\n"
set update_hold 1
}
set comments ""
append comments "# The active analysis views are controlled by the following variables:\n"
append comments "#---------------------------------------------------------------------\n"
append comments "# - vars($step,active_setup_views)\n"
append comments "# - vars($step,active_hold_views)\n"
append comments "#\n"
append comments "######################################################################\n"
if {$update_setup || $update_hold} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# <FF> UPDATING ANALYSIS VIEWS ...\n"
append commands "#\n"
}
if {!$update_setup && $update_hold} {
# append command "set_analysis_view -setup \[all_setup_analysis_views\] -hold \[list \$hold_analysis_views\]\n"
append command "set_analysis_view -setup \[all_setup_analysis_views\] -hold \$hold_analysis_views\n"
}
if {$update_setup && !$update_hold} {
append command "set_analysis_view -setup \$setup_analysis_views -hold \[all_hold_analysis_views\]\n"
}
if {$update_setup && $update_hold} {
# append command "set_analysis_view -setup \[list \$setup_analysis_views\] -hold \[list \$hold_analysis_views\]\n"
append command "set_analysis_view -setup \$setup_analysis_views -hold \$hold_analysis_views\n"
}
append commands $comments
append commands "$command\n"
} else {
append comments "# set_analysis_view -setup \$vars($step,active_setup_views) -hold \$vars($step,active_hold_views)\n"
append comments "#\n"
append commands $comments
}
set process [regsub "nm" $vars(process) ""]
append comments "# - vars(process)\n"
append comments "# - vars(flow_effort)\n"
append commands "set_db design_process_node $process\n"
if {[string tolower $vars(flow_effort)] != "standard"} {
append commands "set_db design_flow_effort [string tolower $vars(flow_effort)]\n"
}
}
#########################################################################
# Check if in top level partition (ilm) flow
#########################################################################
FF_NOVUS::check_flow
# if {$vars(report_run_time)} {
# append commands "set vars($step,start_time) \[clock seconds\]\n"
# }
#########################################################################
# Load the recommended command mode settings for step
#########################################################################
# append commands "#\n"
# append commands "# DEFINING MODE SETTINGS\n"
# append commands "#\n"
set comments ""
set ucomments ""
switch $step {
"place" {
###################################################################
# Set placement options ...
# - Set optimization options if inPlaceOpt is enabled
# - Load the CTS spec for clock gate aware placement
# - Place JTAG cells if requested
###################################################################
set args ""
if {($vars(enable_ocv) == "pre_place") || (($vars(enable_ocv) == "pre_prects") && ($vars(place_opt_design) || $vars(preroute_opt_design)))} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "set_db timing_analysis_socv true\n"
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"$vars(enable_ocv)\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command prects,set_analysis_mode $command]
}
set args ""
if {![catch {set arg $vars(congestion_effort)}]} {
append args "set_db place_global_cong_effort $arg\n"
append comments "# - vars(congestion_effort)\n"
} else {
append ucomments "# - vars(congestion_effort) \"auto low medium high\"\n"
}
# if {[info exists vars(clock_gate_aware)] && $vars(clock_gate_aware)} {
# append comments "# - vars(clock_gate_aware)\n"
# append args " -place_global_clock_gate_aware true"
# }
if {![catch {set arg $vars(clock_gate_aware)}]} {
append comments "# - vars(clock_gate_aware)\n"
append args "set_db place_global_clock_gate_aware $arg\n"
} else {
append ucomments "# - vars(clock_gate_aware) \"true\"\n"
}
if {![catch {set arg $vars(place_global_place_io_pins)}]} {
append comments "# - vars(place_global_place_io_pins)\n"
append args "set_db place_global_place_io_pins $arg\n"
} else {
append ucomments "# - vars(place_global_place_io_pins) \"true\"\n"
}
# set process [regsub "nm" $vars(process) ""]
# if {[expr $process < 28] && [info exists vars(filler_cells,min_gap)]} {
# append comments "# - vars(filler_cells,min_gap)\n"
# append args " -fillerGapMinGap $vars(filler_cells,min_gap) -fillerGapEffort high\n"
# } else {
# append ucomments "# - vars(filler_cells,min_gap) \"<microns>\"\n"
# append ucomments "# - vars(filler_cells,gap_effort) \"<low medium high> \"\n"
# }
if {$args != ""} {
append commands [FF::wrap_command place,set_place_mode $args]
}
set args ""
if {([info exists vars(in_place_opt)] && $vars(in_place_opt)) || $vars(place_opt_design)} {
append comments "# - vars(in_place_opt)\n"
if {[lindex [split $vars(version) "."] 0] < 16} {
if {![catch {set arg $vars(preserve_assertions)}]} {
append comments "# - vars(preserve_assertions)\n"
append args "set_db opt_preserve_pins_with_timing_constraints $arg\n"
} else {
append ucomments "# - vars(preserve_assertions) \"true\"\n"
}
}
if {![catch {set arg $vars(power_effort)}]} {
append comments "# - vars(power_effort)\n"
append args "set_db opt_power_effort $arg\n"
} else {
append ucomments "# - vars(power_effort) \"low or high\"\n"
}
if {![catch {set arg $vars(power_ratio)}]} {
append comments "# - vars(power_ratio)\n"
append args "set_db opt_leakage_to_dynamic_ratio $arg\n"
} else {
append ucomments "# - vars(power_ratio) \"0.0 to 1.0\"\n"
}
# if {![catch {set arg $vars(clock_gate_aware_opt)}]} {
# append comments "# - vars(clock_gate_aware_opt)\n"
# append args "set_db opt_clock_gate_aware $arg\n"
# } else {
# append ucomments "# - vars(clock_gate_aware_opt) \"true\"\n"
# }
if {![catch {set arg $vars(critical_range)}]} {
append comments "# - vars(critical_range)\n"
append args " -criticalRange $arg"
}
if {[info exists vars(all_end_points)] && $vars(all_end_points)} {
append comments "# - vars(all_end_points)\n"
append args "set_db opt_all_end_points true\n"
} else {
append ucomments "# - vars(all_end_points) \"true\"\n"
}
if {![catch {set arg $vars(size_only_file)}]} {
append comments "# - vars(size_only_file)\n"
append args "set_db opt_size_only_file $arg\n"
} else {
append ucomments "# - vars(size_only_file) \"<file>\"\n"
}
if {![catch {set arg $vars(fix_fanout_load)}]} {
append comments "# - vars(fix_fanout_load)\n"
append args "set_db opt_fix_fanout_load $arg\n"
} else {
append ucomments "# - vars(fix_fanout_load) \"<file>\"\n"
}
if {![catch {set arg $vars(useful_skew)}]} {
append comments "# - vars(useful_skew)\n"
if {$vars(ccopt_effort) == "low"} {
append args "set_db opt_useful_skew $arg\n"
append args "set_db opt_useful_skew_delay_pre_cts true\n"
if {$vars(useful_skew) && ![catch {set arg $vars(skew_buffers)}]} {
append comments "# - vars(skew_buffers)\n"
append args "set_db opt_useful_skew_cells $vars(skew_buffers)\n"
append commands [FF::wrap_command prects,set_useful_skew_mode $command]
}
} else {
append commands "# <FF> Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
set warnings($vars(warning_count)) "Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
incr vars(warning_count)
}
} else {
append ucomments "# - vars(useful_skew) \"true\"\n"
append ucomments "# - vars(skew_buffers) \"<list of buffers>\"\n"
}
if {$args != ""} {
append commands [FF::wrap_command place,set_opt_mode $args]
}
}
# set command [FF_NOVUS::add_tie_cells true false]
# append commands [FF::wrap_command place,add_tie_cells $command]
if {[info exists vars(jtag_cells)] &&
[info exists vars(jtag_rows)]} {
append comments "# - vars(jtag_cells), vars(jtag_rows)\n"
# append commands "# PLACING JTAG CELLS\n"
set command ""
foreach inst $vars(jtag_cells) {
append command "specify_jtag -inst $inst\n"
}
append commands [FF::wrap_command place,specify_jtag $command]
set command "place_jtag -nr_row $vars(jtag_rows)\n"
append commands [FF::wrap_command place,place_jtag $command]
}
}
"prects" {
###################################################################
# Set optimization options ...
# Enable signalStorm if requested (required for ECSM/CCS flows)
# For low power flows, make sure always-on buffers are enabled
###################################################################
set args ""
if {$vars(flow) == "mmmc"} {
if {$vars(enable_ocv) == "pre_prects"} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "set_db timing_analysis_socv true\n"
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_prects\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command prects,set_analysis_mode $command]
}
set args ""
if {[lindex [split $vars(version) "."] 0] < 17} {
if {![catch {set arg $vars(preserve_assertions)}]} {
append comments "# - vars(preserve_assertions)\n"
append args "set_db opt_preserve_pins_with_timing_constraints $arg\n"
} else {
append ucomments "# - vars(preserve_assertions) \"true\"\n"
}
}
if {![catch {set arg $vars(leakage_power_effort)}]} {
append comments "# - vars(leakage_power_effort)\n"
append args "set_db opt_leakage_power_effort $arg\n"
} else {
append ucomments "# - vars(leakage_power_effort) \"low or high\"\n"
}
if {![catch {set arg $vars(dynamic_power_effort)}]} {
append comments "# - vars(dynamic_power_effort)\n"
append args "set_db opt_dynamic_power_effort $arg\n"
} else {
append ucomments "# - vars(dynamic_power_effort) \"low or high\"\n"
}
# if {![catch {set arg $vars(clock_gate_aware_opt)}]} {
# append comments "# - vars(clock_gate_aware_opt)\n"
# append args "set_db opt_clock_gate_aware $arg\n"
# } else {
# append ucomments "# - vars(clock_gate_aware_opt) \"true\"\n"
# }
# if {![catch {set arg $vars(critical_range)}]} {
# append comments "# - vars(critical_range)\n"
# append args "set_db opt_critical_range $arg\n"
# }
if {[info exists vars(all_end_points)] && $vars(all_end_points)} {
append comments "# - vars(all_end_points)\n"
append args "set_db opt_all_end_points $vars(all_end_points)\n"
} else {
append ucomments "# - vars(all_end_points) \"true\"\n"
}
if {![catch {set arg $vars(size_only_file)}]} {
append comments "# - vars(size_only_file)\n"
append args "set_db opt_size_only_file $arg\n"
} else {
append ucomments "# - vars(size_only_file) \"<file>\"\n"
}
if {![catch {set arg $vars(fix_fanout_load)}]} {
append comments "# - vars(fix_fanout_load)\n"
append args "set_db opt_fix_fanout_load $arg\n"
} else {
append ucomments "# - vars(fix_fanout_load) \"<file>\"\n"
}
if {![catch {set arg $vars(useful_skew)}]} {
if {$vars(ccopt_effort) == "low"} {
append comments "# - vars(useful_skew)\n"
append args "set_db opt_useful_skew $arg\n"
if {$vars(useful_skew) && ![catch {set arg $vars(skew_buffers)}]} {
append comments "# - vars(skew_buffers)\n"
append args "set_db opt_useful_skew_cells $vars(skew_buffers)\n"
append commands [FF::wrap_command prects,set_useful_skew_mode $command]
}
} else {
append commands "# <FF> Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
set warnings($vars(warning_count)) "Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
incr vars(warning_count)
}
} else {
append ucomments "# - vars(useful_skew) \"true\"\n"
append ucomments "# - vars(skew_buffers) \"<list of buffers>\"\n"
}
if {[FF::is_lp_flow]} {
if {![catch {set arg $vars(resize_shifter_and_iso_insts)}]} {
append comments "# - vars(resize_level_shifter_and_iso_insts)\n"
append args "set_db opt_resize_level_shifter_and_iso_insts $arg\n"
}
}
if {$args != ""} {
append commands [FF::wrap_command prects,set_opt_mode $args]
}
# if {$vars(enable_ss) == "pre_prects"} {
# append comments "# - vars(enable_ss)\n"
# set command "setDelayCalMode -engine signalStorm\n"
# append commands [FF::wrap_command prects,set_delay_cal_mode $command]
# } else {
# append ucomments "# - vars(enable_ss) \"pre_prects\"\n"
# }
if {[FF::is_lp_flow]} {
set command ""
if {[info exists vars(always_on_buffers)]} {
append comments "# - vars(always_on_buffers)\n"
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
foreach buffer $vars(always_on_buffers) {
append command "set_dont_use false $buffer\n"
append command "set_dont_touch false $buffer\n"
}
}
foreach domain [FF::get_by_suffix vars ",always_on_buffers"] {
if {[info exists vars($domain,always_on_buffers)]} {
foreach buffer $vars($domain,always_on_buffers) {
append command "set_dont_use false $buffer\n"
append command "set_dont_touch false $buffer\n"
}
}
}
if {$command != ""} {
append commands [FF::wrap_command prects,set_dont_use $command]
}
}
}
"cts" {
###################################################################
# Set CTS options ... this includes nanoroute options as the clock
# net is typically routed during CTS. For hierarchical flows, the
# clock tree spec is defined per partition .
###################################################################
set args ""
if {$vars(enable_ocv) == "pre_cts"} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "set_db timing_analysis_socv true\n"
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_cts\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postcts,set_analysis_mode $command]
}
set command ""
# if {![catch {set arg $vars(route_clock_nets)}]} {
# append comments "# - vars(route_clock_nets)\n"
# append command "set_db cts_route_clock_tree_nets $arg\n"
# } else {
# append ucomments "# - vars(route_clock_nets)\n"
# }
# if {$vars(cts_engine) == "cts"} {
# if {[info exists vars(clk_tree_top_layer)] && $vars(clk_tree_top_layer) != {}} {
# append comments "# - vars(clk_tree_top_layer)\n"
# append command "set_db cts_route_top_preferred_layer $vars(clk_tree_top_layer)\n"
# } else {
# append ucomments "# - vars(clk_tree_top_layer)\n"
# }
# if {[info exists vars(clk_tree_bottom_layer)] && $vars(clk_tree_bottom_layer) != {}} {
# append comments "# - vars(clk_tree_bottom_layer)\n"
# append command "set_db cts_route_bottom_preferred_layer $vars(clk_tree_bottom_layer)\n"
# } else {
# append ucomments "# - vars(clk_tree_bottom_layer)\n"
# }
# if {[info exists vars(clk_leaf_top_layer)] && $vars(clk_leaf_top_layer) != {}} {
# append comments "# - vars(clk_leaf_top_layer)\n"
# append command "set_db cts_route_leaf_top_preferred_layer $vars(clk_leaf_top_layer)\n"
# } else {
# append ucomments "# - vars(clk_leaf_top_layer)\n"
# }
# if {[info exists vars(clk_leaf_bottom_layer)] && $vars(clk_leaf_bottom_layer) != {}} {
# append comments "# - vars(clk_leaf_bottom_layer)\n"
# append command "set_db cts_route_leaf_bottom_preferred_layer $vars(clk_leaf_bottom_layer)\n"
# } else {
# append ucomments "# - vars(clk_leaf_bottom_layer)\n"
# }
# if {[info exists vars(clk_tree_ndr)] && $vars(clk_tree_ndr) != {}} {
# append comments "# - vars(clk_tree_ndr)\n"
# append command "set_db cts_route_non_default_rule $vars(clk_tree_ndr)\n"
# } else {
# append ucomments "# - vars(clk_tree_ndr)\n"
# }
# if {[info exists vars(clk_tree_extra_space)] && $vars(clk_tree_extra_space) != {}} {
# append comments "# - vars(clk_tree_extra_space)\n"
# append command "set_db cts_route_preferred_extra_space $vars(clk_tree_extra_space)"
# } else {
# append ucomments "# - vars(clk_tree_extra_space)\n"
# }
# if {[info exists vars(clk_leaf_ndr)] && $vars(clk_leaf_ndr) != {}} {
# append comments "# - vars(clk_leaf_ndr)\n"
# append command "set_db cts_route_leaf_non_default_rule $vars(clk_leaf_ndr)"
# } else {
# append ucomments "# - vars(clk_leaf_ndr)\n"
# }
# if {[info exists vars(clk_leaf_extra_space)] && $vars(clk_leaf_extra_space) != {}} {
# append comments "# - vars(clk_leaf_extra_space)\n"
# append command "set_db cts_route_leaf_preferred_extra_space $vars(clk_leaf_extra_space)"
# } else {
# append ucomments "# - vars(clk_leaf_extra_space)\n"
# }
# if {$command != ""} {
# append command "\n"
# append commands [FF::wrap_command cts,set_cts_mode $command]
# }
# } else {
set args ""
set command ""
if {[info exists vars(clk_leaf_top_layer)] && $vars(clk_leaf_top_layer) != {}} {
append comments "# - vars(clk_leaf_top_layer)\n"
append args "-top_preferred_layer $vars(clk_leaf_top_layer) "
} else {
append ucomments "# - vars(clk_leaf_top_layer)\n"
}
if {[info exists vars(clk_leaf_bottom_layer)] && $vars(clk_leaf_bottom_layer) != {}} {
append comments "# - vars(clk_leaf_bottom_layer)\n"
append args "-bottom_preferred_layer $vars(clk_leaf_bottom_layer) "
} else {
append ucomments "# - vars(clk_leaf_bottom_layer)\n"
}
if {[info exists vars(clk_leaf_ndr)] && $vars(clk_leaf_ndr) != {}} {
append comments "# - vars(clk_leaf_ndr)\n"
append args "-non_default_rule $vars(clk_leaf_ndr) "
} else {
append ucomments "# - vars(clk_leaf_ndr)\n"
}
if {$args != ""} {
append command "create_route_type -name leaf "
append command $args
}
set args ""
if {[info exists vars(clk_tree_top_layer)] && $vars(clk_tree_top_layer) != {}} {
append comments "# - vars(clk_tree_top_layer)\n"
append args "-top_preferred_layer $vars(clk_tree_top_layer) "
} else {
append ucomments "# - vars(clk_tree_top_layer)\n"
}
if {[info exists vars(clk_tree_bottom_layer)] && $vars(clk_tree_bottom_layer) != {}} {
append comments "# - vars(clk_tree_bottom_layer)\n"
append args "-bottom_preferred_layer $vars(clk_tree_bottom_layer) "
} else {
append ucomments "# - vars(clk_tree_bottom_layer)\n"
}
if {[info exists vars(clk_tree_ndr)] && $vars(clk_tree_ndr) != {}} {
append comments "# - vars(clk_tree_ndr)\n"
append args "-non_default_rule $vars(clk_tree_ndr) "
} else {
append ucomments "# - vars(clk_tree_ndr)\n"
}
if {$args != ""} {
append command "\ncreate_route_type -name tree "
append command $args
}
if {$command != ""} {
append command "\n"
append commands [FF::wrap_command cts,set_cts_mode $command]
}
# }
set command ""
if {[string tolower $vars(cts_engine)] != "cts"} {
# FF_NOVUS::assign_cts_cells
# foreach corner $vars(rc_corners) {
# if {[info exists vars($corner,atf_file)]} {
# append command "update_ccopt_rc_corner -name $corner -atf $vars($corner,atf_file)\n"
# }
# }
# if {$command != ""} {
# append command "\n"
# append commands [FF::wrap_command cts,update_ccopt_rc_corner $command]
# }
# set command ""
# if {[info exists vars(ccopt_integration)]} {
# append comments "# - vars(ccopt_integration)\n"
# append command "set_db ccopt_integration \"$vars(ccopt_integration)\"\n"
# } else {
# append ucomments "# - vars(ccopt_integration)\n"
# }
if {[info exists vars(cts_inverter_cells)]} {
append comments "# - vars(cts_inverter_cells)\n"
append command "set_db cts_inverter_cells \"$vars(cts_inverter_cells)\"\n"
} else {
append ucomments "# - vars(cts_inverter_cells)\n"
}
if {[info exists vars(cts_buffer_cells)]} {
append comments "# - vars(cts_buffer_cells)\n"
append command "set_db cts_buffer_cells \"$vars(cts_buffer_cells)\"\n"
} else {
append ucomments "# - vars(cts_buffer_cells)\n"
}
if {[info exists vars(clock_gate_cells)]} {
append comments "# - vars(clock_gate_cells)\n"
append command "set_db cts_clock_gating_cells \"$vars(clock_gate_cells)\"\n"
} else {
append ucomments "# - vars(clock_gate_cells)\n"
}
if {[info exists vars(cts_use_inverters)]} {
append comments "# - vars(cts_use_inverters)\n"
append command "set_db cts_use_inverters [string tolower $vars(cts_use_inverters)]\n"
} else {
append ucomments "# - vars(cts_use_inverters)\n"
}
if {[info exists vars(update_io_latency)]} {
append comments "# - vars(update_io_latency)\n"
append command "set_db cts_update_io_latency $vars(update_io_latency)\n"
} else {
append ucomments "# - vars(update_io_latency)\n"
}
# if {[info exists vars(cts_io_opt)]} {
# append comments "# - vars(cts_io_opt)\n"
# append command "set_db ccopt_io_opt [string tolower $vars(cts_io_opt)]\n"
# } else {
# append ucomments "# - vars(cts_io_opt)\n"
# }
if {[info exists vars(ccopt_effort)]} {
append comments "# - vars(ccopt_effort)\n"
if {[string tolower $vars(ccopt_effort)] != "low"} {
append command "set_ccopt_effort $vars(ccopt_effort)\n"
}
} else {
append ucomments "# - vars(ccopt_effort)\n"
}
if {[info exists vars(cts_target_skew)]} {
append comments "# - vars(cts_target_skew)\n"
append command "set_db cts_target_skew $vars(cts_target_skew)\n"
} else {
append ucomments "# - vars(cts_target_skew)\n"
}
if {[info exists vars(cts_target_slew)]} {
append comments "# - vars(cts_target_slew)\n"
append command "set_db cts_target_max_transition_time $vars(cts_target_slew)\n"
} else {
append ucomments "# - vars(cts_target_slew)\n"
}
if {[info exists vars(pre_ccopt_tcl)]} {
append comments "# - vars(pre_ccopt_tcl)\n"
append command "set_db ccopt_pre_tcl \{ source $vars(pre_ccopt_tcl) \}\n"
}
if {[info exists vars(post_ccopt_tcl)]} {
append comments "# - vars(post_ccopt_tcl)\n"
append command "set_db ccopt_post_tcl \{ source $vars(post_ccopt_tcl) \}\n"
}
append command "\n"
append commands [FF::wrap_command cts,set_ccopt_mode $command]
# set command "create_route_type trunk "
# if {[info exists vars(clk_tree_ndr)]} {
# append comments "# - vars(clk_tree_ndr)\n"
# append command "-non_default_rule $vars(clk_tree_ndr)"
# } else {
# append ucomments "# - vars(clk_tree_ndr)\n"
# }
# if {[info exists vars(clk_tree_shield_net)]} {
# append comments "# - vars(clk_tree_shield_net)\n"
# append command "-shield_net $vars(clk_tree_shield_net)"
# } else {
# append ucomments "# - vars(clk_tree_shield_net)\n"
# }
# if {[info exists vars(clk_tree_top_layer)]} {
# append comments "# - vars(clk_tree_top_layer)\n"
# append command "-top_preferred_layer $vars(clk_tree_top_layer)\n"
# } else {
# append ucomments "# - vars(clk_tree_top_layer)\n"
# }
# if {[info exists vars(clk_tree_bottom_layer)]} {
# append command "-bottom_preferred $vars(clk_tree_bottom_layer)\n"
# } else {
# append ucomments "# - vars(clk_tree_bottom_layer)\n"
# }
# if {$command != "create_route_type trunk "} {
# append command "\n"
# append commands [FF::wrap_command cts,create_route_type $command]
# }
}
set args ""
if {![catch {set arg $vars(multi_cut_effort)}]} {
append comments "# - vars(multi_cut_effort)\n"
append args "set_db route_design_detail_use_multi_cut_via_effort $arg\n"
} else {
append ucomments "# - vars(multi_cut_effort)\n"
}
if {![catch {set arg $vars(litho_driven_routing)}]} {
append comments "# - vars(litho_driven_routing)\n"
append args "set_db route_design_with_litho_driven $arg\n"
} else {
append ucomments "# - vars(litho_driven_routing)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command cts,set_nanoroute_mode $command]
}
if {([info exists vars(partition_list)]) &&
([file tail [file dirname [pwd]]] == "$vars(partition_dir)")} {
set ptn [file tail [pwd]]
if {[info exists vars($ptn,cts_spec)]} {
set vars(cts_spec) $vars($ptn,cts_spec)
} else {
if {$ptn != $vars(design)} {
if {[info exists vars(cts_spec)]} {
unset vars(cts_spec)
}
}
}
}
}
"postcts" {
###################################################################
# Optionally enable cppr, signalStorm, and onChipVariation (if
# MMMC)
###################################################################
set args ""
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "set_db timing_analysis_cppr $vars(enable_cppr)\n"
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$vars(flow) == "mmmc"} {
if {$vars(enable_ocv) == "pre_postcts"} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "set_db timing_analysis_socv true\n"
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postcts\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postcts,set_analysis_mode $command]
}
# if {[info exists vars(cts_spec)]} {
# if {![catch {set arg $vars(clock_gate_clone)}]} {
# append comments "# - vars(clock_gate_clone)\n"
# set command "set_db opt_post_cts_clock_gate_cloning $arg\n"
# append commands [FF::wrap_command postcts,set_opt_mode $command]
# }
# }
}
"postcts_hold" {
###################################################################
# Set hold fixing options ...
###################################################################
if {[info exists vars(delay_cells)]} {
append comments "# - vars(delay_cells)\n"
set command ""
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
foreach delay_cell $vars(delay_cells) {
append command "set_dont_use false $delay_cell\n"
}
if {$command != ""} {
append commands [FF::wrap_command postcts_hold,set_dont_use $command]
}
} else {
append ucomments "# - vars(delay_cells)\n"
}
set args ""
if {![catch {set arg $vars(fix_hold_allow_tns_degradation)}]} {
append comments "# - vars(fix_hold_allow_tns_degradation)\n"
append args "#set_db opt_fix_hold_allow_setup_tns_degrade $arg\n"
} else {
append ucomments "# - vars(fix_hold_allow_tns_degradation)\n"
}
if {$vars(fix_hold_ignore_ios)} {
#append commands "setAnalysisMode -honorClockDomains true\n"
append comments "# - vars(fix_hold_ignore_ios)\n"
append args "#set_db opt_fix_hold_ignore_path_groups {in2reg reg2out in2out}\n"
} else {
append ucomments "# - vars(fix_hold_ignore_ios)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postcts_hold,set_opt_mode $command]
}
}
"route" {
###################################################################
# Set routing options ...
# Recommendations for multicut via insertion and litho driven
# routing. These all incur runtime penalties but have yield
# advantages so are included here. The routeWithLithoDriven option
# is recommended for 45nm but may also be used at 65nm. The
# -drouteUseMultiCutViaEffort can be set to high if needed;
# expect an average of 5% coverage improvement with an average 10%
# runtime hit versus medium
###################################################################
if {($vars(enable_cppr) != "false") && $vars(track_opt)} {
append comments "# - vars(enable_cppr)\n"
append args "set_db timing_analysis_cppr $vars(enable_cppr)\n"
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$vars(enable_si_aware)} {
set command "set_db delaycal_enable_si true\n "
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
append comments "# - vars(enable_si_aware)\n"
} else {
append ucomments "# - vars(enable_si_aware)\n"
}
set args ""
if {![catch {set arg $vars(multi_cut_effort)}]} {
append comments "# - vars(multi_cut_effort)\n"
append args "set_db route_design_detail_use_multi_cut_via_effort $arg\n"
} else {
append ucomments "# - vars(multi_cut_effort)\n"
}
if {![catch {set arg $vars(litho_driven_routing)}]} {
append comments "# - vars(litho_driven_routing)\n"
append args "set_db route_design_with_litho_driven $arg\n"
} else {
append ucomments "# - vars(litho_driven_routing)\n"
}
if {![catch {set arg $vars(antenna_diode)}]} {
if {$vars(antenna_diode) != ""} {
append comments "# - vars(antenna_diode)\n"
append args "set_db route_design_antenna_cell_name $arg\n"
append args "set_db route_design_antenna_diode_insertion true\n"
} else {
append ucomments "# - vars(antenna_diode)\n"
}
} else {
append ucomments "# - vars(antenna_diode)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command route,set_nanoroute_mode $command]
}
}
"postroute" {
###################################################################
# Set extraction effort for postroute optimization
# Enable signalStorm if requested
###################################################################
set command "set_db extract_rc_engine post_route\n"
if {![catch {set arg $vars(postroute_extraction_effort)}]} {
append comments "# - vars(postroute_extraction_effort)\n"
append command "set_db extract_rc_effort_level $arg\n"
} else {
append ucomments "# - vars(postroute_extraction_effort)\n"
}
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command "set_db extract_rc_total_cap_threshold $arg\n"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command "set_db extract_rc_relative_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command "set_db extract_rc_coupling_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command "set_db extract_rc_lef_tech_file_map $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute,set_extract_rc_mode $command]
set args ""
if {($vars(enable_ocv) == "pre_postroute") || ($vars(enable_ocv) == "pre_postcts")} {
if {$vars(flow) != "default"} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
}
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "set_db timing_analysis_socv true\n"
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "set_db timing_analysis_cppr $vars(enable_cppr)\n"
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postroute,set_analysis_mode $command]
}
if {[regexp "9.1" $vars(version)]} {
if {$vars(enable_ss) == "pre_postroute"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm -signoff true "
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_postroute\"\n"
}
} else {
if {$vars(enable_si_aware)} {
set command "set_db delaycal_enable_si true\n "
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
append comments "# - vars(enable_si_aware)\n"
if {$vars(enable_ss) == "pre_postroute"} {
append commands "# <FF> Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
set warnings($vars(warning_count)) "Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
incr vars(warning_count)
}
} else {
append ucomments "# - vars(enable_si_aware)\n"
if {$vars(enable_ss) == "pre_postroute"} {
append comments "# - vars(enable_ss)\n"
# set command "setDelayCalMode -engine signalStorm -signoff true -siAware false\n"
# append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
} else {
set command "#set_db delaycal_enable_si false\n"
# append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
append ucomments "# - vars(enable_ss) \"pre_postroute\"\n"
}
}
}
}
"postroute_hold" {
###################################################################
# Set hold fixing options ...
###################################################################
set command "set_db extract_rc_engine post_route\n"
if {![catch {set arg $vars(postroute_extraction_effort)}]} {
append comments "# - vars(postroute_extraction_effort)\n"
append command "set_db extract_rc_effort_level $arg\n"
} else {
append ucomments "# - vars(postroute_extraction_effort)\n"
}
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command "set_db extract_rc_total_cap_threshold $arg\n"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command "set_db extract_rc_relative_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command "set_db extract_rc_coupling_cap_threshold $arg\n"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command "set_db extract_rc_lef_tech_file_map $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute_hold,set_extract_rc_mode $command]
set command ""
if {[info exists vars(delay_cells)]} {
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
append comments "# - vars(delay_cells)\n"
foreach delay_cell $vars(delay_cells) {
append command "set_dont_use false $delay_cell\n"
}
} else {
append ucomments "# - vars(delay_cells)\n"
}
if {$command != ""} {
append commands [FF::wrap_command postroute_hold,set_dont_use_mode $command]
}
set args ""
if {![catch {set arg $vars(fix_hold_allow_tns_degradation)}]} {
append comments "# - vars(fix_hold_allow_tns_degradation)\n"
append args "#set_db opt_fix_hold_allow_setup_tns_degrade $arg\n"
} else {
append ucomments "# - vars(fix_hold_allow_tns_degradation)\n"
}
if {$vars(fix_hold_ignore_ios)} {
#append commands "setAnalysisMode -honorClockDomains true\n"
append comments "# - vars(fix_hold_ignore_ios)\n"
append args "#set_db opt_fix_hold_ignore_path_groups {in2reg reg2out in2out}"
} else {
append ucomments "# - vars(fix_hold_ignore_ios)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postroute_hold,set_opt_mode $command]
}
}
"postroute_si" {
###################################################################
# Set noise, extraction, and SI options ...
# Enable signalStorm if requested
# Enable onChipVariation (if MMMC)
###################################################################
set command "set_db extract_rc_coupled true\n"
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command "set_db extract_rc_total_cap_threshold $arg\n"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command "set_db extract_rc_relative_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command "set_db extract_rc_coupling_cap_threshold $arg\n"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command "set_db extract_rc_lef_tech_file_map $arg\n"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute_si,set_extract_rc_mode $command]
set args ""
if {![catch {set arg $vars(delta_delay_threshold)}]} {
append comments "# - vars(delta_delay_threshold)\n"
append args "set_db si_delay_delta_threshold $arg\n"
} else {
append ucomments "# - vars(delta_delay_threshold)\n"
}
# if {![catch {set arg $vars(celtic_settings)}]} {
# append comments "# - vars(celtic_settings)\n"
# append args " -insCeltICPreTcl \"$arg\""
# } else {
# append ucomments "# - vars(celtic_settings)\n"
# }
# if {![catch {set arg $vars(si_analysis_type)}]} {
# append comments "# - vars(si_analysis_type)\n"
# append args " -analysisType $arg"
# } else {
# append ucomments "# - vars(si_analysis_type)\n"
# }
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
# append comments "# - vars(high_timing_effort)\n"
append args "set_db si_acceptable_wns 0\n"
} elseif {[info exists vars(acceptable_wns)]} {
append args "set_db si_acceptable_wns $vars(acceptable_wns)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postroute_si,set_si_mode $command]
}
set args ""
if {$vars(enable_ocv) == "pre_postroute_si"} {
if {$vars(flow) != "default"} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
}
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "set_db timing_analysis_socv true\n"
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute_si\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "set_db timing_analysis_cppr $vars(enable_cppr)\n"
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postroute_si,set_analysis_mode $command]
}
# if {$vars(enable_ss) == "pre_postroute_si"} {
# append comments "# - vars(enable_ss)\n"
# set command "setDelayCalMode -engine signalStorm\n"
# append commands [FF::wrap_command postroute_si,set_delay_cal_mode $command]
# } else {
# append ucomments "# - vars(enable_ss) \"pre_postroute_si\"\n"
# }
# }
"postroute_si_hold" {
###################################################################
# Set hold fixing options ...
###################################################################
set command ""
if {[info exists vars(delay_cells)]} {
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
append comments "# - vars(delay_cells)\n"
foreach delay_cell $vars(delay_cells) {
append command "set_dont_use false $delay_cell\n"
}
} else {
append ucomments "# - vars(delay_cells)\n"
}
if {$command != ""} {
append commands [FF::wrap_command postroute_hold,set_dont_use_mode $command]
}
set args ""
if {![catch {set arg $vars(fix_hold_allow_tns_degradation)}]} {
append comments "# - vars(fix_hold_allow_tns_degradation)\n"
append args "#set_db opt_fix_hold_allow_setup_tns_degrade $arg\n"
} else {
append ucomments "# - vars(fix_hold_allow_tns_degradation)\n"
}
if {$vars(fix_hold_ignore_ios)} {
#append commands "setAnalysisMode -honorClockDomains true\n"
append comments "# - vars(fix_hold_ignore_ios)\n"
append args "#set_db opt_fix_hold_ignore_path_groups {in2reg reg2out in2out}"
} else {
append ucomments "# - vars(fix_hold_ignore_ios)\n"
}
set command ""
if {[info exists vars(delay_cells)]} {
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
append comments "# - vars(delay_cells)\n"
foreach delay_cell $vars(delay_cells) {
append command "set_dont_use false $delay_cell\n"
}
} else {
append ucomments "# - vars(delay_cells)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command postroute_si_hold,set_opt_mode $command]
}
###################################################################
# Set noise, extraction, and SI options ...
# Enable signalStorm if requested
# Enable onChipVariation (if MMMC)
###################################################################
set command "set_db extract_rc_coupled true\n"
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command "set_db extract_rc_total_cap_threshold $arg\n"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command "set_db extract_rc_relative_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command "set_db extract_rc_coupling_cap_threshold $arg\n"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command "set_db extract_rc_lef_tech_file_map $arg\n"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute_si_hold,set_extract_rc_mode $command]
set args ""
if {![catch {set arg $vars(delta_delay_threshold)}]} {
append comments "# - vars(delta_delay_threshold)\n"
append args "set_db si_delay_delta_threshold $arg\n"
} else {
append ucomments "# - vars(delta_delay_threshold)\n"
}
# if {![catch {set arg $vars(celtic_settings)}]} {
# append comments "# - vars(celtic_settings)\n"
# append args " -insCeltICPreTcl \"$arg\""
# } else {
# append ucomments "# - vars(celtic_settings)\n"
# }
# if {![catch {set arg $vars(si_analysis_type)}]} {
# append comments "# - vars(si_analysis_type)\n"
# append args " -analysisType $arg"
# } else {
# append ucomments "# - vars(si_analysis_type)\n"
# }
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
# append comments "# - vars(high_timing_effort)\n"
append args "set_db si_acceptable_wns 0\n"
} elseif {[info exists vars(acceptable_wns)]} {
append args "set_db si_acceptable_wns $vars(acceptable_wns)\n"
}
if {$args != ""} {
set command "setSIMode $args\n"
append commands [FF::wrap_command postroute_si_hold,set_si_mode $command]
}
if {$vars(enable_ss) == "pre_postroute_si"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm\n"
append commands [FF::wrap_command postroute_si_hold,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_postroute_si\"\n"
}
if {$vars(enable_ocv) == "pre_postroute_si"} {
append comments "# - vars(enable_ocv)\n"
if {$vars(flow) != "default"} {
set command "set_db timing_analysis_type ocv\n"
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append command "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
append commands [FF::wrap_command postroute_si_hold,set_analysis_mode $command]
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute_si\"\n"
append ucomments "# - vars(enable_ocv) \"true\"\n"
}
}
"signoff" {
###################################################################
# For the default flow, switch to MMMC for final STA to support
# multiple RC corners. Also, enable CCE (signoff) extraction if
# the QRC techfile exists
###################################################################
if {$vars(flow) == "default"} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# <FF> UPDATING TIMING ENVIRONMENT"
append commands "#\n"
}
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command signoff,initialize_timing $command]
}
###################################################################
# Set noise, extraction, and SI options ...
# Enable signalStorm if requested
# Enable onChipVariation (if MMMC)
###################################################################
set command "set_db extract_rc_coupled true\n"
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command "set_db extract_rc_total_cap_threshold $arg\n"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command "set_db extract_rc_relative_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command "set_db extract_rc_coupling_cap_threshold $arg\n"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command "set_db extract_rc_lef_tech_file_map $arg\n"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
set args ""
if {![catch {set arg $vars(delta_delay_threshold)}]} {
append comments "# - vars(delta_delay_threshold)\n"
append args "set_db si_delay_delta_threshold $arg"
} else {
append ucomments "# - vars(delta_delay_threshold)\n"
}
# if {![catch {set arg $vars(celtic_settings)}]} {
# append comments "# - vars(celtic_settings)\n"
# append args " -insCeltICPreTcl \"$arg\""
# } else {
# append ucomments "# - vars(celtic_settings)\n"
# }
# if {![catch {set arg $vars(si_analysis_type)}]} {
# append comments "# - vars(si_analysis_type)\n"
# append args " -analysisType $arg"
# } else {
# append ucomments "# - vars(si_analysis_type)\n"
# }
set args ""
if {$vars(enable_ocv) != "false"} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "set_db timing_analysis_socv true\n"
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_signoff\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "set_db timing_analysis_cppr $vars(enable_cppr)\n"
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command signoff,set_analysis_mode $command]
}
if {[regexp "9.1" $vars(version)]} {
if {$vars(enable_ss) == "pre_signoff"} {
set command "setDelayCalMode -engine signalStorm -signoff true\n"
append commands [FF::wrap_command signoff,set_delay_cal_mode $command]
append comments "# - vars(enable_ss)\n"
} else {
append ucomments "# - vars(enable_ss) \"pre_signoff\"\n"
}
} else {
# if {$vars(enable_si_aware)} {
# append comments "# - vars(enable_si_aware)\n"
# append command "-siAware true -engine aae\n "
if {$vars(enable_ss) == "pre_signoff"} {
set command "setDelayCalMode -engine signalStorm -signoff true\n"
append commands [FF::wrap_command signoff,set_delay_cal_mode $command]
# append commands "<FF> Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
# set warnings($vars(warning_count)) "Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
# incr vars(warning_count)
} else {
append ucomments "# - vars(enable_ss) \"pre_signoff\"\n"
}
# } else {
# append ucomments "# - vars(enable_si_aware)\n"
# if {$vars(enable_ss) == "pre_signoff"} {
# append comments "# - vars(enable_ss)\n"
# append command "-engine signalStorm -signoff true "
# } else {
# append ucomments "# - vars(enable_ss) \"pre_signoff\"\n"
# }
# }
}
if {$vars(skip_signoff_checks)} {
set command "set_db extract_rc_engine post_route\nset_db extract_rc_effort_level $vars(signoff_extraction_effort)\nset_db extract_rc_coupled true\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
} else {
append commands "set vars(active_rc_corners) \[list\]\n"
append commands "foreach view \[all_analysis_views\] {\n"
append commands " set corner \[get_delay_corner \[get_analysis_view \$view -delay_corner\] -rc_corner\]\n"
append commands " if {\[lsearch \$vars(active_rc_corners) \$corner\] == -1 } {\n"
append commands " lappend vars(active_rc_corners) \$corner\n"
append commands " }\n"
append commands "}\n"
append commands "puts \"<FF> ACTIVE RC CORNER LIST: \$vars(active_rc_corners)\"\n"
append commands "set empty_corners \[list\]\n"
append commands "foreach corner \$vars(active_rc_corners) {\n"
append commands " if {!\[file exists \[get_rc_corner \$corner -qrc_tech\]\]} {\n"
append commands " lappend empty_corners \$corner\n"
append commands " }\n"
append commands "}\n"
append commands "if {\[llength \$empty_corners\] == 0} {\n"
set command " set_db extract_rc_engine post_route\n set_db extract_rc_effort_level $vars(signoff_extraction_effort)\n set_db extract_rc_coupled true\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
append commands "} else {\n"
append commands " puts \"<FF> CAN'T RUN SIGNOFF EXTRACTION BECAUSE qx_tech_file IS NOT DEFINED FOR these corners: \$empty_corners\"\n"
set command " set_db extract_rc_engine post_route\n set_db extract_rc_effort_level low\n set_db extract_rc_coupled true\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
append commands "}\n"
}
}
}
if {[info exists ucomments]} {
if {$ucomments == ""} {
if {[info exists vars(ucomments)]} {
unset vars(ucomments)
}
} else {
set vars(ucomments) $ucomments
}
}
if {[info exists comments]} {
if {$comments == ""} {
if {[info exists vars(comments)]} {
unset vars(comments)
}
} else {
set vars(comments) $comments
}
}
return $commands
}
proc save_results {{step ""} {format 0}} {
global vars
global errors
global env
if {[regexp syn_ $step]} {
set commands ""
if {$vars(report_run_time)} {
append commands "ff_procs::report_time\n"
}
return $commands
}
if {[info exists vars(hier)]} {
set hier true
} else {
set hier false
}
if {$step != ""} {
set vars(step) $step
}
if {$vars(debug)} {
puts "<DEBUG> Saving results for $vars(step) ..."
}
set commands ""
if {$vars(batch)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SAVING RESULTS\n"
append commands "#\n"
}
# if {[regexp _hold $vars(step)] && (![lsearch $vars(fix_hold) $vars(step)] <0)} {
#
# if {!$format} {
# set commands ""
# } else {
# if {$vars(report_run_time)} {
# append commands "FF_NOVUS::report_time $vars(step)\n"
# }
# }
# if {$vars(codegen)} {
# return $commands
# } else {
# uplevel #0 eval $commands
# }
# }
set header "#---------------------------------------------------------------------\n"
append header "# <FF> GENERATING REPORTS\n"
append header "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -out_file $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -out_file $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
append commands $header
set header ""
######################################################################
# Verify power domain
######################################################################
# set command "check_power_domains -bind -gconn"
# append command " -iso_net_pd $vars(rpt_dir)/$vars(step).isonets.rpt"
# append command " -x_net_pd $vars(rpt_dir)/$vars(step).xnets.rpt\n"
# append commands [FF::wrap_command $step,check_power_domain $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "run_clp "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $step,run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
set map(init) unplaced
set map(place) placed
set map(partition_place) placed
set map(model_gen) placed
set map(assign_pin) placed
#set map(partition) {}
set map(prects) placed
set map(cts) clock_synthesized
set map(postcts) clock_synthesized
set map(postcts_hold) clock_synthesized
set map(route) clock_synthesized_routed
set map(postroute) clock_synthesized_routed
set map(postroute_hold) clock_synthesized_routed
set map(signoff) clock_synthesized_routed
set map(assemble) placed_routed
if {$vars(capture_metrics) && ($vars(step) != "debug")} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append commands "pop_snapshot_stack\n"
if {[lindex [split $vars(version) "."] 0] > 16} {
if {[info exists map($step)]} {
if {[info exists vars(compute_metrics)] && $vars(compute_metrics)} {
append commands "create_snapshot -name $vars(step) -categories \[dict get \[get_db metric_category_status_map\] $map($step)\]\n"
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
append commands "report_metric -file $vars(rpt_dir)/metrics.html -format html\n"
}
}
if {($step != "partition") && ($step != "rebudget") && ($step != "flexilm")} {
set args ""
if {[info exists vars(save_rc)] && $vars(save_rc)} {
if {[regexp "route" $vars(step)]} {
append args " -rc"
}
}
if {[info exists vars(save_constraints)] && $vars(save_constraints)} {
append args " -tcon"
}
# BCL: Added subst around vars(dbs_dir) to resolve vars(rundir)
set dir [subst $vars(dbs_dir)]
set design $vars(design)
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
if {$hier} {
set command "write_db $args -oa_lib_cell_view {$vars(oa_partition_lib) $vars(design) $vars(step)}\n"
} else {
set command "write_db $args -oa_lib_cell_view {$vars(oa_design_lib) $vars(design) $vars(step)}\n"
}
}
} else {
if {[info exists vars(relative_path)] && $vars(relative_path)} {
append args " -relative_path"
}
if {[info exists vars(absolute_lib_path)] && $vars(absolute_lib_path)} {
append args " -absolute_lib_path"
}
set command "write_db $args $dir/$vars(step).enc\n"
}
if {!(($vars(step) == "model_gen") && $vars(use_flexmodels) && $vars(flexmodel_art_based))} {
append commands [FF::wrap_command $step,save_design $command]
append commands [FF::wrap_command $step,save_lec_netlist "write_netlist $vars(dbs_dir)/LEC/$step.v.gz\n"]
}
}
if {![info exists env(VPATH)]} {
set env(VPATH) "make"
}
if {!$vars(generate_flow_steps)} {
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
}
# append commands "#\n"
# append commands "# HOUSEKEEPING\n"
# append commands "#\n"
if {[info exists vars(mail,to)]} {
switch $vars(step) {
init { set summary_file preplace.summary }
assemble { set summary_file signoff.summary }
default { set summary_file $vars(step).summary }
}
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " gunzip -c $vars(rpt_dir)/${summary_file}.gz \| exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
# append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
if {$format} {
if {$vars(report_run_time)} {
append commands "ff_procs::report_time\n"
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [eval FF::capture_metrics]
}
}
}
if {$vars(enable_qor_check)} {
# if {[info exists vars($step,qor_tcl]} {
# set qor_file $vars($step,qor_tcl)
# if {[file exists $qor_file]} {
# set qor [catch {exec $qor_file} msg]
# set make_file [open $this_semaphore w]
# puts $make_file "$qor"
# close $make_file
# }
# }
if {[info exists vars($step,qor_tcl)]} {
if {[file exists $vars($step,qor_tcl)]} {
append commands [FF::source_plug ${step},qor_tcl]
} else {
append commands "<FF> WARNING: QOR file $vars($step,qor_tcl) does not exist"
set warnings($warning_count) "WARNING: QOR file $vars($step,qor_tcl) does not exist"
incr warning_count
}
} else {
if {$vars(makefile) && !$vars(generate_flow_steps)} {
append commands "\nif {\[info exists env(VPATH)\]} {\n"
append commands " exec /bin/touch \$env(VPATH)/${step}_qor\n"
append commands "}\n"
}
}
}
append commands [FF::source_plug final_always_source_tcl]
} else {
append commands "puts \"<FF> =================================================\"\n"
append commands "puts \"<FF> INFO: Running in interactive mode ...\"\n"
append commands "puts \"<FF> Please run 'FF_NOVUS::save_results <current_step>' \"\n"
append commands "puts \"<FF> to prepare a database for the next step\"\n"
append commands "puts \"<FF> =================================================\"\n"
if {$vars(makefile) && !$vars(generate_flow_steps)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc initialize_multicpu {} {
global vars
set commands ""
# append commands "#\n"
# append commands "# SETTING UP MULTI PROCESS DISTRIBUTION AND THREADING\n"
# append commands "#\n"
global vars
if {[regexp syn_ $vars(step)]} {
return ""
}
if {[info exists vars(distribute_timeout)]} {
set command "set_distributed_hosts -time_out $vars(distribute_timeout) "
} else {
set command "set_distributed_hosts "
}
if {[info exists vars(distribute)]} {
switch $vars(distribute) {
"rsh" {
# append commands "# RUNNING RSH on $vars(rsh,host_list)\n"
append command "-rsh -add \[list $vars(rsh,host_list)\]\n"
set vars(remote_hosts) [llength $vars(rsh,host_list)]
}
"local" {
append command "-local\n"
}
"custom" {
# append commands "# RUNNING CUSTOM ($vars(custom,script))\n"
append command "-custom -custom_script { $vars(custom,script) }\n"
}
"lsf" {
# append commands "# RUNNING LSF ($vars(lsf,queue), $vars(lsf,resource), $vars(lsf,args)\n"
append command "-lsf -queue $vars(lsf,queue) -resource { $vars(lsf,resource) } -lsf_args { $vars(lsf,args) }\n"
}
default {
puts "<FF> DISTRIBUTION TYPE $vars(distribute) NOT SUPPORTED\n"
}
}
# append commands $command
append commands [FF::wrap_command $vars(step),set_distributed_hosts $command]
set command "set_multi_cpu_usage "
append command "-local_cpu $vars(local_cpus) "
append command "-remote_host $vars(remote_hosts) "
append command "-cpu_per_remote_host $vars(cpus_per_remote_host)\n"
append commands [FF::wrap_command $vars(step),set_multi_cpu_usage $command]
} else {
append command "-local\n"
append commands [FF::wrap_command $vars(step),set_distributed_hosts $command]
set command "set_multi_cpu_usage -local_cpu $vars(local_cpus)\n"
append commands [FF::wrap_command $vars(step),set_multi_cpu_usage $command]
}
return $commands
}
proc derate_timing {{type minmax}} {
global vars
global errors
# if {[info exists vars(view_definition_tcl)]} {
# return ""
# }
# if {$vars(enable_aocv)} {
# set commands ""
# foreach corner $vars(delay_corners) {
# append commands "reset_timing_derate -delay_corner $corner\n"
# }
# return $commands
# }
set commands "puts \"<FF> DERATING DELAY CORNERS ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# DERATING DELAY CORNERS ($type) ...\n"
append commands "#\n"
}
switch $type {
"mmmc" {
set found_corner 0
foreach corner $vars(delay_corners) {
set derate_file 0
set command($corner) ""
if {[info exists vars($corner,derate_tcl)]} {
set derate_file 1
incr found_corner 1
if {[file exists $vars($corner,derate_tcl)]} {
if {$command($corner) == ""} {
append command($corner) [FF::source_plug "$corner,derate_tcl"]
}
}
}
if {!$derate_file} {
foreach object "cell net" {
foreach mode "early late" {
foreach type "data clock" {
if {[info exists vars($corner,${type}_${object}_${mode})]} {
append command($corner) " set_timing_derate -$type -${object}_delay -$mode -delay_corner $corner $vars($corner,${type}_${object}_${mode})\n"
set found_corner 1
}
if {[info exists vars($corner,${object}_${type}_${mode})]} {
append command($corner) " set_timing_derate -$type -${object}_delay -$mode -delay_corner $corner $vars($corner,${object}_${type}_${mode})\n"
set found_corner 1
}
}
if {[info exists vars($corner,cell_check_${mode})]} {
append command($corner) " set_timing_derate -cell_check -$mode -delay_corner $corner $vars($corner,cell_check_${mode})\n"
set found_corner 1
}
if {[info exists vars($corner,check_cell_${mode})]} {
append command($corner) " set_timing_derate -cell_check -$mode -delay_corner $corner $vars($corner,check_cell_${mode})\n"
set found_corner 1
}
}
}
}
}
#########################################################################
# There can only be one ilm_non_sdc_file, so need to combine them with
# the timing derate commands if both exists
#########################################################################
if {$found_corner>0} {
if $vars(ilm) {
set op [open .ilm_non_sdc_file.tcl w]
if {[info exists vars(ilm_non_sdc_file)] && [file exists $vars(ilm_non_sdc_file)]} {
set fhr [open $vars(ilm_non_sdc_file) r]
puts $op "#"
puts $op "# Contents of $vars(ilm_non_sdc_file)"
puts $op "#"
while {[gets $fhr line]>=0} {
puts $op " $line"
}
close $fhr
puts $op "# -------------------------------------------"
set vars(save_ilm_non_sdc_file) $vars(ilm_non_sdc_file)
unset vars(ilm_non_sdc_file)
}
if {[info exists vars(derate_tcl)]} {
puts $op "source $vars(derate_tcl)"
} else {
foreach corner $vars(delay_corners) {
puts $op $command($corner)
}
}
close $op
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# append commands "loadTimingCon -ilmNonSdcFile .ilm_non_sdc_file.tcl\n"
# } else {
# append commands "setIlmNonSdcConstraintFile .ilm_non_sdc_file.tcl\n"
# }
} else {
if {[info exists vars(derate_tcl)]} {
append commands [FF::source_plug derate_tcl]
append commands "\n"
} else {
append commands "set active_corners \[all_delay_corners\]\n"
foreach corner $vars(delay_corners) {
if {$command($corner) != ""} {
append commands "if {\[lsearch \$active_corners $corner\] != -1} {\n"
append commands $command($corner)
append commands "}\n"
}
}
}
}
} else {
if {[info exists vars(derate_tcl)]} {
append commands [FF::source_plug derate_tcl]
append commands "\n"
}
}
}
"minmax" {
set corners(min) $vars($vars(default_hold_view),delay_corner)
set corners(max) $vars($vars(default_setup_view),delay_corner)
################################################################################
# Derate timing if derating factors are defined
################################################################################
foreach object "cell net" {
foreach corner "min max" {
foreach type "data clock" {
foreach mode "early late" {
if {[info exists vars($corners($corner),${type}_${object}_${mode})]} {
append commands "set_timing_derate -$corner -$type -${object}_delay -$mode $vars($corners($corner),${type}_${object}_${mode})\n"
}
if {[info exists vars($corners($corner),${object}_${type}_${mode})]} {
append commands "set_timing_derate -$corner -$type -${object}_delay -$mode $vars($corners($corner),${object}_${type}_${mode})\n"
}
}
}
}
}
foreach corner "min max" {
foreach mode "early late" {
if {[info exists vars($corners($corner),cell_check_${mode})]} {
append commands "set_timing_derate -cell_check -$mode $vars($corners($corner),cell_check_${mode})\n"
}
if {[info exists vars($corners($corner),check_cell_${mode})]} {
append commands "set_timing_derate -cell_check -$mode $vars($corners($corner),check_cell_${mode})\n"
}
}
}
}
default {
puts "<FF> INVALID OPTION ... MUST BE EITHER minmax OR mmmc"
}
}
if {[lindex [split $vars(version) "."] 0] > 10} {
set op [open $vars(script_dir)/timingderate.sdc w]
puts $op $commands
close $op
if {!$vars(novus) && ([file tail [file dirname [pwd]]] != "$vars(partition_dir)")} {
set commands "source $vars(script_dir)/timingderate.sdc\n"
}
}
return $commands
}
#####################################################################################
# The code below updates timing depending on whether the current module is
# - top partition in a hierarchical flow
# - partition in a hierarchical flow
# - chip or block in a flat flow
# Timing is updated by incrementally adding the vars(incr_cts_sdc) to each
# constraint mode that has one defined
#####################################################################################
proc update_timing {{type mmmc} {switch_to_propagated true}} {
global vars
if {![info exists vars(constraint_modes)]} {
return
}
set commands "puts \"<FF> UPDATING TIMING ...\"\n"
set ptn [file tail [pwd]]
set parent [file tail [file dirname [pwd]]]
set update true
set top false
if {[info exists vars(partition_list)] && ($parent == "$vars(partition_dir)")} {
if {[lsearch $vars(partition_list) $ptn] != -1} {
# set ilm false
set update false
} else {
set top true
}
}
# append commands "# ILM $vars(ilm), UPDATE $update\n"
if {$switch_to_propagated} {
append commands "set op \[open prop.sdc w\]\n"
append commands "puts \$op \"set_propagated_clock \\\[all_clocks\\\]\"\n"
if {$vars(ilm)} {
if {$vars(flat) != "none"} {
append commands [FF_EDI::get_clock_ports]
} else {
append commands "set clock_ports \[FF_EDI::get_clock_ports\]\n"
}
append commands "if {\[llength \$clock_ports\] > 0} {\n"
append commands " foreach port \$clock_ports {\n"
append commands " puts \$op \"set_propagated_clock \$port\"\n"
append commands " }\n"
append commands "}\n"
}
append commands "close \$op\n"
}
switch $type {
"minmax" {
if {$vars(ilm) && $update} {
if {[info exists vars(incr_cts_sdc)]} {
foreach file $vars(incr_cts_sdc) {
append commands "loadTimingCon -ilm -incr $file\n"
}
} elseif {[info exists vars(post_cts_sdc)]} {
append command "unloadTimingCon\n"
append commands "loadTimingCon [lindex $vars(post_cts_sdc) 0]\n"
foreach sdc [lrange $vars(post_cts_sdc) 1 end] {
append commands "loadTimingCon -ilm -incr $sdc\n"
}
}
if {$switch_to_propagated} {
append commands "loadTimingCon -ilm -incr prop.sdc\n"
}
} else {
if {$update} {
if {[info exists vars(incr_cts_sdc)]} {
foreach file $vars(incr_cts_sdc) {
append commands "loadTimingCon -incr $file\n"
}
} elseif {[info exists vars(post_cts_sdc)]} {
append commands "unloadTimingCon\n"
append commands "loadTimingCon [lindex $vars(post_cts_sdc) 0]\n"
foreach sdc [lrange $vars(post_cts_sdc) 1 end] {
append commands "loadTimingCon -incr $sdc\n"
}
}
}
if {$switch_to_propagated} {
append commands "loadTimingCon -incr prop.sdc\n"
}
}
}
"mmmc" {
# if {[info exists vars(update_io_latency)] && $vars(update_io_latency)} {
# update_io_latency
# }
if {$switch_to_propagated} {
set prop_sdc "prop.sdc"
} else {
set prop_sdc ""
}
foreach mode $vars(constraint_modes) {
append commands "if {\[lsearch \[all_constraint_modes\] $mode\] != -1} {\n"
if {$update} {
if {[info exists vars($mode,incr_cts_sdc)]} {
if {$vars(ilm)} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -ilm_sdc_files\] $vars($mode,incr_cts_sdc) $prop_sdc\]\n"
} else {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -sdc_files\] $vars($mode,incr_cts_sdc) $prop_sdc\]\n"
}
if {[info exists vars($mode,post_cts_sdc)]} {
puts "<FF> WARNING: BOTH vars($mode,incr_cts_sdc) AND vars($mode,post_cts_sdc) ARE DEFINED ..."
puts "<FF> USING vars($mode,incr_cts_sdc)"
}
} else {
if {[info exists vars($mode,post_cts_sdc)]} {
append commands "set vars($mode,post_cts_sdc_list) \[concat $vars($mode,post_cts_sdc) $prop_sdc\]\n"
} else {
if {$vars(ilm)} {
if {$vars(cts_engine) == "cts" || ($vars(step) == "assemble")} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -ilm_sdc_files\] $prop_sdc\]\n"
} else {
if {$vars(step) != "assemble"} {
return ""
}
}
} else {
if {$vars(cts_engine) == "cts" || ($vars(step) == "assemble")} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -sdc_files\] $prop_sdc\]\n"
} else {
if {$vars(step) != "assemble"} {
return ""
}
}
}
}
}
} else {
if {$vars(ilm)} {
if {$vars(cts_engine) == "cts"} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -ilm_sdc_files\] $prop_sdc\]\n"
} else {
if {[regexp "^assemble" $vars(step)]} {
return ""
}
}
} else {
if {$vars(cts_engine) == "cts"} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -sdc_files\] $prop_sdc\]\n"
} else {
# if {[regexp "^assemble" $vars(step)]} {
return ""
}
}
}
}
append commands "}\n"
}
if {!$vars(ilm)} {
append commands "set restore \[get_db timing_defer_mmmc_obj_updates\]\n"
append commands "set_db timing_defer_mmmc_obj_updates true\n"
}
if {$vars(ilm)} {
exec /bin/touch empty.sdc
append commands "foreach mode \[all_constraint_modes\] {\n"
append commands " if {\[info exists vars(\$mode,post_cts_sdc_list)\]} {\n"
append commands " update_constraint_mode -name \$mode -ilm_sdc_files \$vars(\$mode,post_cts_sdc_list)\n"
append commands " } else {\n"
append commands " foreach view \[all_analysis_views] {\n"
append commands " set m \[regsub _\$view \$mode \"\"\]\n"
append commands " if {\[info exists vars(\$m,post_cts_sdc_list)\]} {\n"
append commands " update_constraint_mode -name \$mode -ilm_sdc_files \$vars(\$m,post_cts_sdc_list)\n"
append commands " }\n"
append commands " } \n"
append commands " } \n"
append commands "} \n"
} else {
append commands "foreach mode \[all_constraint_modes\] \{\n"
append commands " if \{\[info exists vars(\$mode,post_cts_sdc_list)\]\} \{\n"
append commands " update_constraint_mode -name \$mode -sdc_files \$vars(\$mode,post_cts_sdc_list)\n"
append commands " \} else \{\n"
append commands " foreach view \[all_analysis_views] \{\n"
append commands " set m \[regsub _\$view \$mode \"\"\]\n"
append commands " if \{\[info exists vars(\$m,post_cts_sdc_list)\]\} \{\n"
append commands " update_constraint_mode -name \$mode -sdc_files \$vars(\$m,post_cts_sdc_list)\n"
append commands " \}\n"
append commands " \} \n"
append commands " \} \n"
append commands "\} \n"
}
if {!$vars(ilm)} {
append commands "set_analysis_view -update_timing\n"
append commands "set_db timing_defer_mmmc_obj_updates \$restore\n"
}
set this_index [lsearch $vars(steps) $vars(step)]
set prior [lindex $vars(steps) [expr $this_index - 1]]
# BCL: Added subst around vars(dbs_dir)
if {[file isfile [subst $vars(dbs_dir)]/$prior.enc.dat/mmmc/pathgroup.sdc]} {
# BCL: Added subst around vars(dbs_dir)
set vars(path_group_sdc) [subst $vars(dbs_dir)]/$prior.enc.dat/mmmc/pathgroup.sdc
append commands "ff_procs::load_path_groups $vars(path_group_sdc)\n"
}
}
default {
puts $vars(codgen_log) "<FF> INVALID OPTION ... MUST BE EITHER minmax OR mmmc"
}
}
return $commands
}
proc initialize_timing {{type mmmc}} {
global vars
global env
global init
global warnings
# if {[info exists vars(view_definition_tcl)]} {
# return ""
# }
if {$vars(verbose)} {
append commands "#\n"
append commands "# INITIALIZING [string toupper $type] TIMING\n"
append commands "#\n"
}
if {$vars(debug)} {
puts "<DEBUG> Executing proc: initialize_timing ..."
}
switch $type {
minmax {
# if {([llength $vars(rc_corners)] > 1)} {
# puts "<FF> WARNING: THE \"default\" FLOW SHOULD ONLY HAVE A SINGLE RC CORNER"
# puts "<FF> BUT [llength $vars(rc_corners)] CORNERS ARE DEFINED ($vars(rc_corners))"
# }
###################################################################
# Define RC corners and set the appropriate temperatures. This
# requires that the cap tables use -best/-worst syntax in the
# configuration file. Scaling factors should be derived using
# Ostrich Values for the default timing environment is derived
# from the default setup and hold analysis views
###################################################################
set corners(min) $vars($vars(default_hold_view),delay_corner)
set corners(max) $vars($vars(default_setup_view),delay_corner)
set corner $vars($corners(max),rc_corner)
# if {[info exists env(FF_KIT_PATH)]} {
if {![catch {set max $vars($vars($corners(max),rc_corner),T)}] &&
![catch {set min $vars($vars($corners(min),rc_corner),T)}]} {
append commands \
"defineRCCorner -late worst $max -early best $min\n"
}
# } else {
# puts "<FF> USING SINGLE RC CORNER $vars($corners(max),rc_corner)"
# if {[info exists vars($vars($corners(max),rc_corner),T)]} {
# setExtractRCMode -scOpTemp $vars($vars($corners(max),rc_corner),T)
# }
# }
###################################################################
# Set scaling factors ... for pre-route optimization, the detailed
# cap factor is set to the detailed clock cap factor. This will
# be reset post-route
###################################################################
set args ""
if {![catch {set arg $vars($corner,pre_route_res_factor)}]} {
append args " -preRoute_res $arg"
}
if {![catch {set arg $vars($corner,pre_route_cap_factor)}]} {
append args " -preRoute_cap $arg"
}
if {![catch {set arg $vars($corner,pre_route_clk_res_factor)}]} {
append args " -preRoute_clkres $arg"
}
if {![catch {set arg $vars($corner,pre_route_clk_cap_factor)}]} {
append args " -preRoute_clkcap $arg"
}
if {![catch {set arg $vars($corner,post_route_res_factor)}]} {
append args " -postRoute_res "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_cap_factor)}]} {
append args " -postRoute_cap "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_clk_res_factor)}]} {
append args " -postRoute_clkres "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_clk_cap_factor)}]} {
append args " -postRoute_clkcap "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_xcap_factor)}]} {
append args " -postRoute_xcap "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {$args != ""} {
set command "setRCFactor $args\n"
append commands [FF::wrap_command $vars(step),set_rc_factor $command]
}
set command [FF_NOVUS::derate_timing minmax]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
mmmc {
if {$vars(verbose)} {
append commands "#\n"
append commands "# CREATING RC CORNERS ...\n"
append commands "#\n"
}
foreach rc $vars(rc_corners) {
# set command "\n"
set command ""
set non_command ""
if {[info exists vars($rc,scale_tcl)]} {
append command "create_rc_corner -name $rc"
# append command " -cap_table $vars($rc,cap_table) "
foreach option "cap_table temperature qrc_tech" {
if {![catch {set arg $vars($rc,$option)}]} {
append command " -$option $arg"
}
}
append command "\n"
append command [FF::source_plug "$rc,scale_tcl"]
} else {
append command "create_rc_corner -name $rc"
foreach option "cap_table temperature qrc_tech" {
if {![catch {set arg $vars($rc,$option)}]} {
append command " -$option $arg"
}
}
# append command "\n"
# append command " -cap_table $vars($rc,cap_table) "
if {![catch {set arg $vars($rc,pre_route_res_factor)}]} {
append command " -pre_route_res $arg"
} else {
append non_command "# -pre_route_res \$vars($rc,pre_route_res_factor)\n"
}
if {![catch {set arg $vars($rc,pre_route_cap_factor)}]} {
append command " -pre_route_cap $arg"
} else {
append non_command "# -pre_route_cap \$vars($rc,pre_route_cap_factor)\n"
}
if {![catch {set arg $vars($rc,pre_route_clk_res_factor)}]} {
append command " -pre_route_clock_res $arg"
} else {
append non_command "# -pre_route_clock_res \$vars($rc,pre_route_clk_res_factor)\n"
}
if {![catch {set arg $vars($rc,pre_route_clk_cap_factor)}]} {
append command " -pre_route_clock_cap $arg"
} else {
append non_command "# -pre_route_clock_cap \$vars($rc,pre_route_clk_cap_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_res_factor)}]} {
append command " -post_route_res "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -post_route_res \$vars($rc,post_route_res_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_cap_factor)}]} {
append command " -post_route_cap "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -post_route_res \$vars($rc,post_route_cap_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_clk_res_factor)}]} {
append command " -post_route_clock_res "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -post_route_clock_res \$vars($rc,post_route_clk_res_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_clk_cap_factor)}]} {
append command " -post_route_clock_cap "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -post_route_clock_cap \$vars($rc,post_route_clk_cap_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_cross_cap)}]} {
append command " -post_route_cross_cap "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -post_route_cross_cap \$vars($rc,post_route_xcap_factor)\n"
}
}
append command "\n"
append commands [FF::wrap_command $vars(step),create_rc_corner $command]
if {$non_command != ""} {
append commands "#------------------------------------------------\n"
append commands "# Additional (unused) options ....\n"
append commands "#------------------------------------------------\n"
append commands $non_command
append commands "#------------------------------------------------\n"
}
}
if {![info exists vars(view_definition_tcl)]} {
if {![info exists vars(cpf_file)] || ([info exists vars(cpf_file)] && !$vars(cpf_timing))} {
################################################################
# CPF_TIMING == FALSE
################################################################
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING LIBRARY SETS ...\n"
append command "#\n"
}
append commands $command
foreach set $vars(library_sets) {
set command ""
append command "create_library_set -name $set -timing \[list "
append command "$vars($set,timing) "
append command "\]\n"
append commands [FF::wrap_command $vars(step),create_library_set $command]
}
if {[info exists vars(opconds)]} {
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING OPERATING CONDITIONS ...\n"
append command "#\n"
}
foreach opcond $vars(opconds) {
set command "create_opcond -name $opcond"
# We already checked so we know these options exist
set map(P) process
set map(V) voltage
set map(T) temperature
foreach option "P V T" {
append command " -$map($option) $vars($opcond,$option)"
}
append command "\n"
append commands [FF::wrap_command $vars(step),create_opcond $command]
}
}
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING DELAY CORNERS ...\n"
append command "#\n"
}
append commands $command
foreach c $vars(delay_corners) {
set command "create_timing_condition -name t_$c"
set dcommand "create_delay_corner -name $c"
if {![catch {set arg $vars($c,library_set)}]} {
append command " -library_set $arg"
} elseif {![catch {set early $vars($c,early_library_set)}] &&
![catch {set late $vars($c,late_library_set)}]} {
append command " -early_library_set $early"
append command " -late_library_set $late"
} else {
puts "<FF> ERROR: Library sets for timing condition $c not defined properly"
}
append dcommand " -rc_corner $vars($c,rc_corner)"
if {![catch {set opcond $vars($c,opcond)}] && ![catch {set library $vars($c,opcond_library)}]} {
append command " -opcond_library $library"
append command " -opcond $opcond"
} else {
if {![catch {set early $vars($c,early_opcond_library)}] &&
![catch {set late $vars($c,late_opcond_library)}]} {
append command " -early_opcond_library $early"
append command " -late_opcond_library $late"
}
if {![catch {set early_opcond $vars($c,early_opcond)}] &&
![catch {set late_opcond $vars($c,late_opcond)}]} {
append command " -early_opcond $early_opcond"
append command " -late_opcond $late_opcond"
}
}
append command "\n"
append dcommand " -timing_condition {"
if {[catch {set domains $vars($c,power_domains)}]} {
append dcommand "t_$c"
} else {
set attribute_list "library_set opcond_library opcond irdrop_file \
late_library_set early_library_set \
late_opcond_library early_opcond_library \
late_opcond early_opcond late_irdrop_file early_irdrop_file"
foreach domain $domains {
append dcommand " t_$c"
append dcommand " $domain@t_$c"
# append command " update_delay_corner -name $c -power_domain \"$domain\""
# foreach attr $attribute_list {
# if {[info exists vars($c,$domain,$attr)]} {
# append command " -$attr $vars($c,$domain,$attr)"
# }
# }
}
# if {![catch {set opcond $vars($domain,opcond)}] &&
# ![catch {set library $vars($domain,opcond_library)}]} {
# append command " -opcond_library $library"
# append command " -opcond $opcond"
# }
}
append dcommand " }\n"
append commands [FF::wrap_command $vars(step),create_timing_condition $command]
append commands [FF::wrap_command $vars(step),create_delay_corner $dcommand]
}
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING CONSTRAINT MODES ...\n"
append command "#\n"
}
append commands $command
# Variable ccommand captures the constraint creation for the view_definition.tcl
# Variable ucommand capture the constraint updates for hier/ilm flows
#------------------------------------------------------------------------------------
set ccommand ""
set active_views [list]
set active_modes [list]
# Get modes actually used ... (changed from active to all views)
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
if {[lsearch $active_views $view] == -1} {
# lappend active_views $view
if {[lsearch $active_modes $vars($view,constraint_mode)] == -1} {
lappend active_modes $vars($view,constraint_mode)
}
}
}
set flatten_ilm 0
foreach constraint_mode $active_modes {
if {!$vars(ilm)} {
# Default flat flow
if {[info exists vars($constraint_mode,pre_cts_sdc)]} {
set command "create_constraint_mode -name $constraint_mode "
append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
append command "\n"
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
} else {
if {![info exists vars($constraint_mode,synth_sdc)] && $vars(rc)} {
puts "Constraint file not found for $constraint_mode ..."
}
}
if {$vars(rc)} {
if {[info exists vars($constraint_mode,synth_sdc)]} {
set command "create_constraint_mode -name $constraint_mode "
append command "-sdc_files \[list $vars($constraint_mode,synth_sdc)\] "
append command "\n"
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
set vars(default_synthesis_mode) $constraint_mode
} else {
if {![info exists vars($constraint_mode,pre_cts_sdc)]} {
puts "Constraint file not found for $constraint_mode ..."
}
}
if {![info exists vars(default_synthesis_mode)]} {
puts "<ERROR> : Please define a synth_sdc for one of the constraint modes"
exit
}
}
} else {
# ILM flow
if {[info exists vars(partition_list)]} {
set sdcs ""
# Hierarchy + ILMs
if {[info exists vars($constraint_mode,pre_cts_ilm_sdc)]} {
# append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_ilm_sdc)\]\n"
} else {
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\]\n"
}
if {$vars(top)} {
if {![info exists ucommand]} { set ucommand ""}
set command "update_constraint_mode -name $constraint_mode "
append command $sdcs
append ucommand [FF::wrap_command $vars(step),update_constraint_mode $command]
set dynamic_update 1
# continue
} else {
set command "create_constraint_mode -name $constraint_mode "
append command $sdcs
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
}
} else {
# ILM only
set command "create_constraint_mode -name $constraint_mode "
if {[info exists vars($constraint_mode,pre_cts_ilm_sdc)]} {
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_ilm_sdc)\]\n"
} else {
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\]\n"
}
append command $sdcs
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
}
}
}
append commands $ccommand
if {[info exists dynamic_update] && $dynamic_update} {
# set command ""
# append command "foreach mode \[all_constraint_modes\] {\n"
# append command " update_constraint_mode -name \$mode -sdc_files empty.sdc \\\n"
# append command " -ilm_sdc_files \[get_constraint_mode \$mode -sdc_files\]\n"
# append command "}\n"
# append ucommand [FF::wrap_command $vars(step),update_constraint_mode $command]
set command ""
append command "foreach mode \[all_constraint_modes] \{\n"
append command " foreach view \[all_analysis_views] \{\n"
append command " set m \[regsub _\$view \$mode \"\"\]\n"
append command " if \{( \$m != \$mode ) && ( \[lsearch \[all_constraint_modes\] \$m\] != -1) \} \{\n"
append command " update_constraint_mode -name \$mode -sdc_files empty.sdc -ilm_sdc_files \[get_constraint_mode \$m -ilm_sdc_files\]\n"
append command " \}\n"
append command " \} \n"
append command "\} \n"
append ucommand [FF::wrap_command $vars(step),dynamic_update $command]
if {$vars(ilm)} {
append ucommand [FF::wrap_command $vars(step),flatten_ilm "flatten_ilm\n"]
}
}
if {($vars(user_mode) == "hier") && ![info exists vars(view_definition_tcl)]} {
if {($vars(step) == "assemble") || ($vars(step) == "rebudget") || ($vars(step) == "assemble_flexilm") || ($vars(step) == "partition_place") || ($vars(step) == "model_gen")} {
# Create mmmc file for partition and assemble step
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
}
}
#return $commands
} else {
# Return only constraint mode updates for top level flow
if {[info exists ucommand]} {
return $ucommand
}
}
} else {
if {[info exists vars(view_definition_tcl)]} {
if {[info exists ucommand]} {
return $ucommand
}
}
}
if {![info exists vars(power_analysis_view)]} {
set vars(power_analysis_view) ""
}
set vars(all_analysis_views) \
[lsort -unique [concat $vars(setup_analysis_views) \
$vars(hold_analysis_views) \
$vars(power_analysis_view)]]
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING ANALYSIS VIEWS ...\n"
append command "#\n"
}
foreach view $vars(all_analysis_views) {
# append command "if {\[lsearch \[all_analysis_views\] $view\] == -1} {\n"
if {[info exists vars(default_synthesis_mode)] && ($vars($view,constraint_mode) == $vars(default_synthesis_mode))} {
set vars(default_synthesis_view) $view
}
append command "create_analysis_view"
append command " -name $view"
append command " -constraint_mode $vars($view,constraint_mode)"
append command " -delay_corner $vars($view,delay_corner)\n"
# append command "}\n"
}
append commands [FF::wrap_command $vars(step),create_analysis_view $command]
if {![info exists vars(gen_postload)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command ""
foreach c $vars(delay_corners) {
if {![catch {set domains $vars($c,power_domains)}]} {
foreach domain $domains {
append command " update_delay_corner -name $c -power_domain \"$domain\"\n"
# if {![catch {set opcond $vars($domain,opcond)}] &&
# ![catch {set library $vars($domain,opcond_library)}]} {
# append command " -opcond_library $library"
# append command " -opcond $opcond"
# }
}
}
}
append commands [FF::wrap_command init,update_delay_corner $command]
}
}
} else {
################################################################
# CPF_TIMING == TRUE
# Since the delay corner names are derived from the CPF, they
# are not known. However, they can be retrieved from the
# analysis_views
################################################################
# if {$vars(verbose)} {
# append commands "# UPDATING DELAY CORNERS ...\n"
# }
if {![info exists vars(delay_corners)]} {
set vars(delay_corners) [FF::[get_by_suffix vars ",rc_corner"]]
}
set command ""
foreach corner $vars(delay_corners) {
append command "if {\[lsearch -exact \[all_delay_corners\] $corner\] != -1} {\n"
append command " update_delay_corner -name $corner -rc_corner $vars($corner,rc_corner)\n"
append command "}\n"
}
append commands [FF::wrap_command $vars(step),update_delay_corner $command]
###################################################################
# Update constraints modes if an ILM flow
###################################################################
set ccommand ""
foreach constraint_mode $vars(constraint_modes) {
if {$vars(ilm)} {
if {[info exists vars(partition_list)]} {
set command "update_constraint_mode -name $constraint_mode "
} else {
set command "create_constraint_mode -name $constraint_mode "
}
if {[info exists vars($constraint_mode,pre_cts_ilm_sdc)]} {
append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
append command "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_ilm_sdc)\] "
} else {
exec /bin/touch empty.sdc
append command "-sdc_files empty.sdc "
append command "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
}
append command "\n"
if {[info exists vars(partition_list)]} {
append ccommand [FF::wrap_command $vars(step),update_constraint_mode $command]
} else {
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
}
}
}
###################################################################
# Return early for partition implementation flows ...
###################################################################
if {(($vars(mode) == "hier") || ([info exists vars(hier)] && $vars(hier))) && ($vars(step) != "partition")} {
set commands $ccommand
return $commands
} else {
append commands $ccommand
}
}
}
###################################################################
# Update library_sets with SI libraries if defined
###################################################################
# if {$vars(verbose)} {
# append commands "# UPDATING LIBRARY SETS ...\n"
# }
set command ""
foreach set $vars(library_sets) {
if {([info exists vars($set,si)] && ($vars($set,si) != "")) || \
([info exists vars($set,socv)] && ($vars($set,socv) != "")) || \
([info exists vars($set,aocv)] && ($vars($set,aocv) != ""))} {
append command "update_library_set -name $set"
}
if {[info exists vars($set,socv)] && ($vars($set,socv) != "")} {
append command " -socv \[list"
foreach file $vars($set,socv) {
append command " $file"
}
append command "\]"
}
if {[info exists vars($set,aocv)] && ($vars($set,aocv) != "")} {
append command " -aocv \[list"
foreach file $vars($set,aocv) {
append command " $file"
}
append command "\]"
}
if {[info exists vars($set,si)] && ($vars($set,si) != "")} {
append command " -si \[list"
foreach file $vars($set,si) {
append command " $file"
}
append command "\]"
}
append command "\n"
}
append commands [FF::wrap_command $vars(step),update_library_set $command]
# if {$vars(flow) != "mmmc"} {
# append commands [FF_NOVUS::update_timing mmmc]
# }
# set command [FF_NOVUS::derate_timing mmmc]
# append commands [FF::wrap_command $vars(step),derate_timing $command]
###################################################################
# Define setup / hold analysis views and enable the default views
# for each
###################################################################
append commands "set_analysis_view"
append commands " -setup \[list $vars(active_setup_views)\]"
append commands " -hold \[list $vars(active_hold_views)\]\n"
file mkdir $vars(script_dir)
if {[lindex [split $vars(version) "."] 0] <= 10} {
if {$vars(flat) != "full"} {
set op [open $vars(script_dir)/mmmc.tcl w]
puts $op [FF::pretty_print $commands 1]
close $op
set commands "source \$vars(script_dir)/mmmc.tcl\n"
}
} else {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
set vars(view_definition_tcl) $mmmc_file
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
}
}
return
}
}
default {
puts "<FF> INVALID OPTION ... MUST BE EITHER minmax OR mmmc"
}
}
return $commands
}
proc update_rc_corners {} {
global vars
foreach rc_corner [all_rc_corners] {
if {$rc_corner != "default_rc_corner"} {
set update false
set command "update_rc_corner -name $rc_corner "
if {[get_rc_corner $rc_corner -cap_table] != $vars($rc_corner,cap_table)} {
set update true
append command "-cap_table $vars($rc_corner,cap_table) "
}
if {[get_rc_corner $rc_corner -preRoute_res] != $vars($rc_corner,pre_route_res_factor)} {
set update true
append command "-preRoute_res $vars($rc_corner,pre_route_res_factor) "
}
if {[get_rc_corner $rc_corner -preRoute_cap] != $vars($rc_corner,pre_route_cap_factor)} {
set update true
append command "-preRoute_cap $vars($rc_corner,pre_route_cap_factor) "
}
if {[get_rc_corner $rc_corner -postRoute_res] != $vars($rc_corner,post_route_res_factor)} {
set update true
append command "-postRoute_res \"$vars($rc_corner,post_route_res_factor)\" "
}
if {[get_rc_corner $rc_corner -postRoute_cap] != $vars($rc_corner,post_route_cap_factor)} {
set update true
append command "-postRoute_cap \"$vars($rc_corner,post_route_cap_factor)\" "
}
if {[get_rc_corner $rc_corner -preRoute_clkres] != $vars($rc_corner,pre_route_clk_res_factor)} {
set update true
append command "-preRoute_clkres $vars($rc_corner,pre_route_clk_res_factor) "
}
if {[get_rc_corner $rc_corner -preRoute_clkcap] != $vars($rc_corner,pre_route_clk_cap_factor)} {
set update true
append command "-preRoute_clkcap $vars($rc_corner,pre_route_clk_cap_factor) "
}
if {[get_rc_corner $rc_corner -postRoute_clkres] != $vars($rc_corner,post_route_clk_res_factor)} {
set update true
append command "-postRoute_clkres \"$vars($rc_corner,post_route_clk_res_factor)\" "
}
if {[get_rc_corner $rc_corner -postRoute_clkcap] != $vars($rc_corner,post_route_clk_cap_factor)} {
set update true
append command "-postRoute_clkcap \"$vars($rc_corner,post_route_clk_cap_factor)\" "
}
if {[get_rc_corner $rc_corner -postRoute_xcap] != $vars($rc_corner,post_route_xcap_factor)} {
set update true
append command "-postRoute_xcap \"$vars($rc_corner,post_route_xcap_factor)\" "
}
foreach option "T qx_tech_file qx_conf_file qx_lib_file" {
if {[info exists vars($rc_corner,$option)]} {
if {[get_rc_corner $rc_corner -$option] != $vars($rc_corner,$option)} {
set update true
append command "-$option $vars($rc_corner,$option) "
}
}
}
if {$update} {
uplevel #0 eval $command
}
}
}
}
proc reset_rc_corners {} {
global vars
foreach corner $vars(rc_corners) {
update_rc_corner -name $corner \
-preRoute_res 1.0 \
-preRoute_clkres 1.0 \
-preRoute_cap 1.0 \
-preRoute_clkcap 1.0 \
-postRoute_res 1.0 \
-postRoute_clkres 1.0 \
-postRoute_cap 1.0 \
-postRoute_clk_ap 1.0 \
-postRoute_xcap 1.0
}
}
proc add_views {} {
global vars
puts "<FF> CREATING RC CORNERS ..."
foreach rc_corner $vars(rc_corners) {
if {[lsearch [all_rc_corners] $rc_corner] == -1} {
set command "create_rc_corner -name $rc_corner "
append command "-cap_table $vars($rc_corner,cap_table)\] "
append command "-preRoute_res $vars($rc_corner,pre_route_res_factor) "
append command "-preRoute_clkres $vars($rc_corner,pre_route_clk_res_factor) "
append command "-preRoute_cap $vars($rc_corner,pre_route_cap_factor) "
append command "-preRoute_clkcap $vars($rc_corner,pre_route_clk_cap_factor) "
append command "-postRoute_res \"$vars($rc_corner,post_route_res_factor)\" "
append command "-postRoute_clkres \"$vars($rc_corner,post_route_clk_res_factor)\" "
append command "-postRoute_cap \"$vars($rc_corner,post_route_cap_factor)\" "
append command "-postRoute_clkcap \"$vars($rc_corner,post_route_clk_cap_factor)\" "
append command "-postRoute_xcap $vars($rc_corner,post_route_xcap_factor) "
foreach option "T qx_tech_file qx_conf_file qx_lib_file" {
if {[info exists vars($rc_corner,$option)]} {
append command "-$option $vars($rc_corner,$option) "
}
}
uplevel #0 eval $command
}
}
if {![FF::is_lp_flow] || \
([FF::is_lp_flow] && ([llength [all_analysis_views]] == 2))} {
puts "<FF> CREATING LIBRARY SETS ..."
foreach library_set $vars(library_sets) {
if {[lsearch [all_library_sets] $library_set] == -1} {
create_library_set -name $library_set \
-timing $vars($library_set,timing)
}
}
puts "<FF> CREATING DELAY CORNERS ...\n"
foreach delay_corner $vars(delay_corners) {
if {[lsearch [all_delay_corners] $delay_corner] == -1} {
set command "create_delay_corner -name $delay_corner "
append command "-library_set $vars($delay_corner,library_set) "
append command "-rc_corner $vars($delay_corner,rc_corner) "
if {[info exists vars($delay_corner,opcond)] && [info exists vars($delay_corner,opcond_library)]} {
append command "-opcond_library $vars($delay_corner,opcond_library) "
append command "-opcond $vars($delay_corner,opcond) "
}
uplevel #0 eval $command
if {![catch {set domains $vars($c,power_domains)}]} {
set command " update_delay_corner -name $c -power_domains \"$domains\""
uplevel #0 eval $command
}
}
}
puts "<FF> UPDATING CONSTRAINT MODES ..."
foreach mode $vars(constraint_modes) {
if {[lsearch [all_constraint_modes] $mode] == -1} {
if {[info exists vars($mode,pre_cts_sdc,full)]} {
append commands "create_constraint_mode "
append commands " -name $mode "
append commands " -sdc_files $vars($mode,pre_cts_sdc,full)\n"
} elseif {[info exists vars($mode,pre_cts_sdc)} {
append commands "create_constraint_mode "
append commands " -name $mode "
append commands " -sdc_files $vars($mode,pre_cts_sdc)\n"
}
}
}
set vars(all_analysis_views) [lsort -uniq [concat $vars(setup_analysis_views) $vars(hold_analysis_views)]]
puts "<FF> UPDATING ANALYSIS VIEWS ..."
foreach analysis_view $vars(all_analysis_views) {
if {[lsearch [all_analysis_views] $analysis_view] == -1} {
create_analysis_view -name $analysis_view \
-constraint_mode $vars($analysis_view,constraint_mode) \
-delay_corner $vars($analysis_view,delay_corner)
}
}
} else {
############################################################################
# Since the delay corner names are derived from the CPF, they are not
# known. However, they can be retrieved from the analysis_views
############################################################################
puts "<FF> UPDATING DELAY CORNERS ..."
foreach corner $vars(delay_corners) {
puts "Updating delay corner $corner with RC Corner $vars($corner,rc_corner) ..."
update_delay_corner -name $corner -rc_corner $vars($corner,rc_corner)
}
}
############################################################################
# Update library_sets with SI libraries if defined
############################################################################
puts "<FF> UPDATING LIBRARY SETS ..."
foreach library_set $vars(library_sets) {
if {[info exists vars($library_set,si)] && ($vars($library_set,si) != "")} {
update_library_set -name $library_set \
-si $vars($library_set,si)
}
}
foreach library_set $vars(library_sets) {
if {[info exists vars($library_set,aocv)] && ($vars($library_set,aocv) != "")} {
update_library_set -name $library_set \
-aocv $vars($library_set,aocv)
}
}
foreach library_set $vars(library_sets) {
if {[info exists vars($library_set,socv)] && ($vars($library_set,socv) != "")} {
update_library_set -name $library_set \
-socv $vars($library_set,socv)
}
}
set_interactive_constraint_modes [all_constraint_modes -active]
puts "<FF> DERATING DELAY CORNERS ..."
FF_NOVUS::derate_timing mmmc
# if {$vars(flow) != "mmmc"} {
# FF_NOVUS::update_timing mmmc
# }
############################################################################
# Define setup / hold analysis views and enable the default views for each
############################################################################
set_analysis_view -setup $vars(active_setup_views) -hold $vars(active_hold_views)
set_default_view -setup $vars(default_setup_view) -hold $vars(default_hold_view)
}
proc get_power_domains_code {} {
global vars
set commands "set domains \[list \[get_db power_domains\]\]\n"
# append commands "dbForEachpower_domain \[dbgHead\] domain {\n"
# append commands " if {\[dbGroupHInstList \[dbpower_domainName \$domain\]\] != \"0x0\"} {\n"
# append commands " lappend domains \[dbpower_domainName \$domain\]\n"
# append commands " }\n"
# append commands "}\n"
return $commands
}
proc get_clock_ports {} {
global vars
set commands ""
if {!$vars(codegen) || ($vars(codegen) && ($vars(flat) != "none"))} {
if {$vars(ilm)} {
if {$vars(step) != "cts"} {
append commands "setIlmType -model si\n"
}
}
append commands "set clock_ports \[list\]\n"
append commands "set clocks \[get_clocks *\]\n"
append commands "foreach_in_collection clock \$clocks {\n"
append commands " set sources \[get_property \$clock sources\]\n"
append commands " foreach_in_collection source \$sources {\n"
append commands " set source_name \[get_property \$source hierarchical_name\]\n"
append commands " set source_type \[get_property \$source object_type\]\n"
append commands " if {\$source_type == \"port\"} {\n"
append commands " lappend clock_ports \$source_name\n"
append commands " }\n"
append commands " }\n"
append commands "}\n"
} else {
append commands "FF::get_clock_ports\n"
}
return $commands
}
proc add_tie_cells {{mode true} {add true}} {
#########################################################################
# This procedure inserts tie hi/lo cells based on information in the
# setup.tcl
#########################################################################
global vars
global errors
set commands ""
if {$vars(verbose)} {
append commands "#\n"
append commands "# ADDING TIE CELLS\n"
append commands "#\n"
}
set args ""
if {[info exists vars(tie_cells,max_distance)]} {
append args "set_db add_tieoffs_max_distance $vars(tie_cells,max_distance)\n"
}
if {[info exists vars(tie_cells,max_fanout)]} {
append args "set_db add_tieoffs_max_fanout $vars(tie_cells,max_fanout)\n"
}
if {[FF::is_lp_flow] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 1))} {
# Get the set of tie cells to use, both domain-specific and generic.
set all_tie_cells [list]
set has_default false
if {![catch {set default_cells $vars(tie_cells)}]} {
set has_default true
lappend all_tie_cells $vars(tie_cells)
}
set has_specific false
foreach domain [FF::get_by_suffix vars ",tie_cells"] {
set cells $vars($domain,tie_cells)
lappend all_tie_cells $vars($domain,tie_cells)
if {![llength $cells]} {
continue
}
set has_specific true
# append command "set tie_cells($domain) \[list $cells\]\n"
# append commands $command
}
#
# If there are no tie cells at all, there's nothing to do
#
if {!$has_default && !$has_specific} {
return ""
}
set all_tie_cells [lsort -unique [join $all_tie_cells]]
#
# If there are no domain-specific entries, life is real simple
#
# if {!$has_specific} {
# set command "\nset_db add_tieoffs_cells \"$default_cells\"\n$args"
# append commands [FF::wrap_command $vars(step),set_tie_hi_lo_mode $command]
# if {$add} {
# foreach cell $default_cells {
# append commands "setDontUse $cell false\n"
# }
# if {[llength $vars(power_domains)] > 0} {
# foreach domain $vars(power_domains) {
# append commands " catch {add_tieoffs -power_domain $domain -prefix $domain}\n"
# }
# }
# foreach cell $default_cells {
# append commands "setDontUse $cell true\n"
# }
# }
# } else {
# foreach cell $default_cells {
# append commands "setDontUse $cell false\n"
# }
if {[llength $vars(power_domains)] > 0} {
foreach domain $vars(power_domains) {
if {[info exists vars($domain,tie_cells)]} {
set command "\nset_db add_tieoffs_cells \"$vars($domain,tie_cells)\"\n$args"
} else {
if {[info exists default_cells]} {
set command "\nset_db add_tieoffs_cells \"$default_cells\"\n$args"
} else {
continue
}
}
append commands [FF::wrap_command $vars(step),set_tie_hi_lo_mode $command]
append commands " catch {add_tieoffs -power_domain $domain -prefix $domain}\n"
}
}
# foreach cell $default_cells {
# append commands "setDontUse $cell true\n"
# }
# }
} elseif {![catch {set cells $vars(tie_cells)}]} {
set command "\nset_db add_tieoffs_cells \"$cells\"\n$args"
# if {$mode} {
append commands [FF::wrap_command $vars(step),set_tie_hi_lo_mode $command]
# }
set command ""
# append command "foreach cell \{$cells\} {\n"
# append command " setDontUse \$cell false\n"
# append command "}\n"
append command "add_tieoffs\n"
# append command "foreach cell \{$cells\} {\n"
# append command " setDontUse \$cell true\n"
# append command "}\n"
append commands $command
} else {
set commands ""
}
return $commands
}
proc add_filler_cells {} {
#########################################################################
# This procedure inserts tie hi/lo cells based on information in the
# setup.tcl
#########################################################################
global vars
global errors
set commands ""
set ccommands ""
if {$vars(verbose)} {
append ccommands "#\n"
append ccommands "# ADD FILLER CELLS\n"
append ccommands "#\n"
}
append commands $ccommands
if {[FF::is_lp_flow] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 1))} {
# Get the set of filler cells to use, both domain-specific and generic.
set all_filler_cells [list]
set has_default false
if {![catch {set default_cells $vars(filler_cells)}]} {
set has_default true
lappend all_filler_cells $vars(filler_cells)
}
set has_specific false
foreach domain [FF::get_by_suffix vars ",filler_cells"] {
set cells $vars($domain,filler_cells)
lappend all_filler_cells $vars($domain,filler_cells)
if {![llength $cells]} {
continue
}
set has_specific true
# append command "set filler_cells($domain) \[list $cells\]\n"
# append commands $command
}
#
# If there are no filler cells at all, there's nothing to do
#
if {!$has_default && !$has_specific} {
return ""
}
set all_filler_cells [lsort -unique [join $all_filler_cells]]
#
# If there are no domain-specific entries, life is real simple
#
# if {!$has_specific} {
# set command "set_db add_fillers_cells \"$default_cells\"\nset_db add_fillers_prefix FILL\n"
# append commands [FF::wrap_command $vars(step),set_filler_mode $command]
# if {$add} {
# foreach cell $default_cells {
# append commands "setDontUse $cell false\n"
# }
# if {[llength $vars(power_domains)] > 0} {
# foreach domain $vars(power_domains) {
# append commands " catch {add_fillers -power_domain $domain}\n"
# }
# }
# foreach cell $default_cells {
# append commands "setDontUse $cell true\n"
# }
# }
# } else {
# foreach cell $default_cells {
# append commands "setDontUse $cell false\n"
# }
if {[llength $vars(power_domains)] > 0} {
set default 0
foreach domain $vars(power_domains) {
if {[info exists vars($domain,filler_cells)]} {
set command "set_db add_fillers_cells \"$vars($domain,filler_cells)\"\nset_db add_fillers_prefix FILL\n"
set default 0
} else {
if {[info exists default_cells]} {
if {!$default} {
set command "set_db add_fillers_cells \"$default_cells\"\nset_db add_fillers_prefix FILL\n"
set default 1
} else {
set command ""
}
} else {
continue
}
}
append commands [FF::wrap_command $vars(step),set_filler_mode $command]
append commands " catch {add_fillers -power_domain $domain}\n"
}
}
# foreach cell $default_cells {
# append commands "setDontUse $cell true\n"
# }
# }
} elseif {![catch {set cells $vars(filler_cells)}]} {
set command "set_db add_fillers_cells \"$cells\"\nset_db add_fillers_prefix FILL\n"
append commands [FF::wrap_command $vars(step),set_filler_mode $command]
set command "add_fillers\n"
append commands $command
} else {
set commands ""
}
return $commands
}
proc delete_filler_cells {} {
global vars
#########################################################################
# Remove filler cells
#########################################################################
set command "delete_filler\n"
append commands [FF::wrap_command $vars(step),delete_filler_cells $command]
return $commands
}
proc insert_welltaps_endcaps {{outline false}} {
global vars
#########################################################################
# Insert welltaps and pre/post endcaps
#########################################################################
global vars
global errors
global warnings
set commands ""
if {[FF::is_lp_flow] && ([info exist vars(power_domains)] && ([llength $vars(power_domains)] > 1))} {
if {$vars(flat) == "full"} {
#
# Just like tie and filler cells, we can have power domain-specific
# cells and settings that we need to worry about.
#
append commands [FF_NOVUS::get_power_domains_code]
#
# Get the set of domains that we need to worry about
#
set pre [FF::get_by_suffix vars ",pre_endcap"]
set post [FF::get_by_suffix vars ",post_endcap"]
set endcaps [FF::lintersection $pre $post]
set welltaps [FF::get_by_suffix vars ",welltaps"]
#
# For every domain in the union, we need to issue statements if that
# domain is one of the power domains in the design
#
# NOTE: We really don't need to worry about indenting the commands
# to look nice since the output routine will format it correctly
#
set domains [FF::lunion $endcaps $welltaps]
foreach domain $domains {
append commands "if {\[lsearch \$domains $domain\] != -1} {\n"
#
# Handle the end caps
#
set std_args "-prefix $domain -power_domain $domain"
set add "add_endcaps $std_args"
if {![catch {set pre $vars($domain,pre_endcap)}] &&
![catch {set post $vars($domain,post_endcap)}]} {
append commands "$add -start_row_cap $pre -end_row_cap $post\n"
} elseif {![catch {set pre $vars(pre_endcap)}] &&
![catch {set post $vars(post_endcap)}]} {
append commands "$add -start_row_cap $pre -end_row_cap $post\n"
}
set taps ""
if {[catch {set taps $vars($domain,welltaps)}]} {
catch {set taps $vars(welltaps)}
}
if {$taps == ""} {
append commands "\}\n"
continue
}
#
# Handle well taps
#
append commands "add_well_taps $std_args -cell \[list $taps\]"
if {![catch {set i $vars($domain,welltaps,cell_interval)}]} {
append commands " -cell_interval $i"
} elseif {![catch {set i $vars(welltaps,cell_interval)}]} {
append commands " -cell_interval $i"
}
if {![catch {set offset $vars($domain,welltaps,row_offset)}] ||
![catch {set offset $vars(welltaps,row_offset)}]} {
append commands " -in_row_offset $offset"
}
if {![catch {set checker $vars($domain,welltaps,checkerboard)}] ||
![catch {set checker $vars(welltaps,checkerboard)}]} {
if {$checker} {
append commands " -checker_board"
}
}
append commands "\n"
#
# Add a verify step, if requested
#
# if {![catch {set rule $vars($domain,welltaps,verify_rule)}] ||
# ![catch {set rule $vars(welltaps,verify_rule)}]} {
# append commands "check_well_tap -cells \[list $taps\]"
# append commands " -power_domain $domain"
# append commands " -report $vars(rpt_dir)/$domain.welltap.rpt\n"
# }
append commands "}\n"
}
#
# We've taken care of all of the domains that we have explicit
# settings for. However, we may still have domains in the design
# that we know nothing explicit about. We need to handle these
# with a different set of code.
#
# We are going to cheat. Since the code we need is already written
# (below), we are going to recursively call this routine to get
# the skeleton that we need and wrap it up into a for-loop. This
# should get us something that looks like the following:
# set processed [list domain1 domain2 domain3]
# foreach domain $domains {
# if {[lsearch $processed_domains $domain] == -1} {
# addEndCap -power_domain $domain -prefix $domain ...
# addWellTap -power_domain $domain -prefix $domain ...
# verifyWellTap -power_domain $domain ...
# }
# }
#
# NOTE: The output routine will take care of making this look pretty
# at the end. We don't need to worry about indentation for
# the inserted commands
#
# set save $vars(cpf_file)
# unset vars(cpf_file)
# set default_insert [insert_welltaps_endcaps true]
# if {$default_insert != ""} {
# append commands "set processed_domains \[list $domains\]\n"
# append commands "foreach domain \$domains {\n"
# append commands " if {\[lsearch \$processed_domains \$domain\] == -1} {\n"
# append commands " $default_insert"
# append commands " }\n"
# append commands "}\n"
# }
# set vars(cpf_file) $save
} else {
append commands "ff_procs::insert_welltaps_endcaps\n"
}
} else {
#
# There is no CPF file that we need to worry about. However, if
# $outline is true, it means that the code (above) that handles power
# domains called this routine recursively, and we need to change
# the commands a little bit to include variables for power domains
#
# Start with the simple case: endcaps
#
if {![catch {set pre $vars(pre_endcap)}] &&
![catch {set post $vars(post_endcap)}]} {
append commands "add_endcaps -start_row_cap $pre -end_row_cap $post"
if {!$outline} {
append commands " -prefix ENDCAP\n"
} else {
append commands " -prefix \$domain -power_domain \$domain\n"
}
}
#
# Now process welltaps
#
if {![catch {set taps $vars(welltaps)}]} {
append commands "add_well_taps -cell \[list $taps\]"
if {!$outline} {
append commands " -prefix WELLTAP"
} else {
append commands " -prefix \$domain -power_domain \$domain"
}
if {![catch {set max_gap $vars(welltaps,max_gap)}]} {
append commands " -max_gap $max_gap"
} elseif {![catch {set interval $vars(welltaps,cell_interval)}]} {
append commands " -cell_interval $interval"
}
if {![catch {set offset $vars(welltaps,row_offset)}]} {
append commands " -in_row_offset $offset"
}
if {![catch {set checker $vars(welltaps,checkerboard)}]} {
if {$checker} {
append commands " -checker_board"
}
}
append commands "\n"
#
# If a verify request has been made, create the command to
# do so. Again, take into account the potential for a recursive
# call to this routine.
#
# if {![catch {set rule $vars(welltaps,verify_rule)}]} {
# append commands "check_well_tap -cells \[list $taps\] "
# append commands " -report $vars(rpt_dir)/"
# if {!$outline} {
# append commands "welltap.rpt\n"
# } else {
# append commands "\$domain.welltap.rpt -power_domain \$domain\n"
# }
# } elseif {!$outline} {
## puts "<FF> Cannot run verifyWellTap because vars(welltaps,verify_rule) is not defined"
# set warnings($vars(warning_count)) "Cannot run verifyWellTap because vars(welltaps,verify_rule) is not defined"
# incr vars(warning_count)
# }
}
}
#
# If we created any commands to be executed, prefix the commands with a
# header
#
if {($commands != "") && !$outline} {
set body $commands
set commands ""
if {$vars(verbose)} {
append commands "#\n"
append commands "# INSERTING WELLTAPS AND/OR ENDCAPS\n"
append commands "#\n"
}
append commands $body
}
return $commands
}
proc route_secondary_pg_nets {} {
global vars
global errors
#
# Don't try to route unless the proper flags are in place to do so
#
if {![info exists vars(route_secondary_pg_nets)] ||
!$vars(route_secondary_pg_nets)} {
return ""
}
set commands "# <FF> ROUTING SECONDARY POWER NETS ...\n"
#
# Enable global pin pairs (if defined)
#
if {[catch {set arg $vars(secondary_pg,cell_pin_pairs)}]} {
puts "<FF> =========================================================="
puts "<FF> ERROR: No cell/pin pairs defined. Please define cell/pin"
puts "<FF> pairs in your setup.tcl using the variable"
puts "<FF> vars(secondary_pg,cell_pin_pairs)"
puts "<FF> =========================================================="
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
append commands "set_pg_pins_use_signal_route $arg\n"
#
# Build commands for individual nets (if defined)
#
if {[info exists vars(secondary_pg,nets)]} {
foreach net $vars(secondary_pg,nets) {
if {![catch {set arg $vars($net,cell_pin_pairs)}]} {
append commands "set_pg_pins_use_signal_route $arg\n"
}
}
set nets $vars(secondary_pg,nets)
set netFormat " -nets %s"
} else {
set nets [list "secondary_pg"]
set netFormat ""
}
foreach net $nets {
set route "route_secondary_pg_pins"
append route [format $netFormat $net]
catch {append route " -pattern $vars($net,pattern)"}
catch {append route " -max_pins_per_trunk $vars($net,max_fanout)"}
catch {append route " -non_default_rule $vars($net,non_default_rule)"}
append commands "$route\n"
}
return $commands
}
proc add_power_switches {{domains ""}} {
global vars
global errors
global map
source $vars(script_path)/ETC/INOVUS/map_options.tcl
if {$domains == ""} {
append commands [FF_NOVUS::get_power_domains_code]
# eval [FF::get_power_domains_code]
}
foreach domain $domains {
if {[info exists vars($domain,switchable)] &&
$vars($domain,switchable)} {
set type $vars($domain,switch_type)
deletePowerSwitch -$type -power_domain $domain
set command "addPowerSwitch -power_domain $domain -$type"
if {[info exists vars($domain,checker_board)] &&
$vars($domain,checker_board)} {
append command " -checkerBoard"
}
if {[info exists vars($domain,back_to_back_chain)] &&
$vars($domain,back_to_back_chain)} {
append command " -backToBackChain"
}
if {[info exists vars($domain,loop_back_at_end)] &&
$vars($domain,loop_back_at_end)} {
append command " -loopbackAtEnd"
}
if {[info exists vars($domain,check_height)] &&
!$vars($domain,check_height)} {
append command " -noDoubleHeightCheck"
}
if {[info exists vars($domain,verify_rows)] &&
!$vars($domain,verify_rows)} {
append command " -noRowVerify"
}
if {[info exists vars($domain,enable_chain)] &&
!$vars($domain,enable_chain)} {
append command " -noEnableChain"
}
foreach option [array names map] {
if {[info exists vars($domain,$option)]} {
append command " -$map($option) $vars($domain,$option)"
}
}
uplevel #0 eval $command
}
}
}
proc run_clock_eco {args} {
global vars
global errors
if {[llength $args] != 1} {
puts "<FF> Internal error in run_clock_eco. Wrong number of args."
exit -111
}
set commands ""
# append commands "# <FF> RUNNING CLOCK ECO\n"
switch $args {
"post_route" {
append commands [FF_NOVUS::delete_filler_cells]
append commands "clock_eco -post_route -use_spec_file_cells_only\n"
append commands [FF_NOVUS::add_filler_cells]
append commands "changeClockStatus -all -no_fixed_net_wires\n"
}
"post_cts" {
append commands "clock_eco -post_cts -use_spec_file_cells_only\n"
}
default {
puts "<FF> Internal error in run_clock_eco."
puts "<FF> Invalid argument; valid arguments are post_cts and post_route."
exit -111
}
}
# if {$vars(codegen)} {
return $commands
# } else {
# uplevel #0 eval $commands
# }
}
############################################################################
# Main foundation flow step procedures
############################################################################
proc run_syn_map {{format 1}} {
global vars
global env
global errors
set vars(step) syn_map
set commands ""
# append commands "source $vars(script_dir)/vars.tcl\n"
append commands "proc Puts {args} {puts \$args}\n"
if {$vars(novus)} {
append commands "puts \[get_db program_version /\]\n"
} else {
append commands "puts \[get_attr program_version /\]\n"
}
## enable multi processing
append commands "set hostlist \[lrepeat $vars(local_cpus) localhost\]\n"
append commands "set_db super_thread_servers \$hostlist\n"
# if {$vars(capture_metrics)} {
# append commands "\nenable_metrics -on\n"
# append commands "push_snapshot_stack\n"
# }
append commands [FF::source_plug pre_syn_setup_tcl]
set command "set_db information_level 1\n"
append command "set_db source_verbose false\n"
append command "set_db -quiet print_error_info false\n"
append command "set_db -quiet echo_commands false\n"
append command "set_db mesg_coloring false\n"
append command "set_db qos_report_basic_cost_groups true\n"
set command "set_db lib_lef_consistency_check_enable true\n"
append command "set_db script_search_path {./}\n"
append command "suppress_messages {LBR-30 LBR-31 LBR-170 LBR-72 LBR-155 PHYS-210 PHYS-256 LBR-201 LBR-34 LBR-83 LBR-40 LBR-162 LBR-122}\n"
append command "redirect /dev/null {set map_fancy_names 1}\n"
append commands [FF::source_plug post_syn_setup_tcl]
append commands [FF::source_plug pre_syn_load_lib_tcl]
set command [FF_NOVUS::initialize_step $vars(step)]
set command [FF_NOVUS::initialize_timing]
set command "\nread_mmmc $vars(view_definition_tcl)\n\n"
append commands [FF::wrap_command $vars(step),read_mmmc $command]
set command ""
if {[info exists vars(lef_files)]} {
append command "read_physical -lef \"\\\n"
foreach lef $vars(lef_files) {
append command "\t$lef\\\n"
}
append command "\"\n"
}
append commands [FF::wrap_command $vars(step),read_physical $command]
# foreach lib $vars($vars([string trim $vars($vars($vars(default_setup_view),delay_corner),timing_condition)],library_set),timing) {
# append command " $lib \\\n"
# }
# append command "\"\n"
# append commands [FF::wrap_command $vars(step),read_lib $command]
# set command "\nset_db lef_library \"\\\n"
# foreach lef $vars(lef_files) {
# append command " $lef \\\n"
# }
# append command "\"\n"
# append commands [FF::wrap_command $vars(step),read_lef $command]
# set command "\nset_db qrc_tech_file $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),qx_tech_file)\n"
# append commands [FF::wrap_command $vars(step),read_qrc $command]
if {[info exists vars(dont_use_list)] && $vars(dont_use_list) != "" } {
foreach cell $vars(dont_use_list) {
append commands "set_db avoid true \[find / -libcell $cell\]\n"
}
}
append commands [FF::source_plug post_syn_load_lib_tcl]
if {[info exists vars(cpf_file)]} {
set command "read_power_intent -module $vars(design) -cpf $vars(cpf_file)\n"
append commands [FF::wrap_command $vars(step),read_power_intent $command]
}
if {[info exists vars(ieee1801_file)]} {
set command "read_power_intent -module $vars(design) -1801 $vars(ieee1801_file)\n"
append commands [FF::wrap_command $vars(step),read_power_intent $command]
}
if {[info exists vars(hdl_search_path)]} {
append commands "set_db hdl_search_path \"$vars(hdl_search_path)\"\n"
}
if {[info exists vars(hdl_file_list)]} {
set command "read_hdl -v2001 \"$vars(hdl_file_list)\"\n"
append commands [FF::wrap_command $vars(step),read_hdl $command]
} else {
append commands [FF::source_plug syn_load_rtl_tcl]
}
append commands "\n#set read_def_libcell_mismatch_error 0\n"
set command "#set_db gen_module_prefix _GENUS_\n"
append command "#set_db hdl_array_naming_style %s_%d\n"
append command "#set_db hdl_reg_naming_style %s_reg%s\n"
append command "#set_db hdl_use_if_generate_prefix false\n"
append command "#set_db hdl_use_for_generate_prefix true\n"
append command "#set_db hdl_use_block_prefix false\n"
append command "#set_db hdl_max_loop_limit 8096\n"
append command "#set_db hdl_generate_index_style %s_%d_\n"
append command "#set_db hdl_generate_separator _\n"
append command "#set_db hdl_instance_array_naming_style %s_%d_\n"
append command "#set_db hdl_parameter_naming_style _%s%d\n"
append command "#set_db hdl_record_naming_style %s\[%s\]\n"
append command "#set_db hdl_use_techelt_first true\n"
append command "#set_db hdl_error_on_blackbox true\n"
append command "#set_db hdl_track_filename_row_col false\n"
append command "#set_db hdl_enable_proc_name false\n"
append command "#set_db hdl_error_on_latch false\n"
append command "#set_db hdl_unconnected_input_port_value none\n"
append command "#set_db hdl_undriven_output_port_value none\n"
append command "#set_db hdl_undriven_signal_value none\n"
append commands [FF::wrap_command $vars(step),set_hdl_attributes $command]
append commands [FF::source_plug pre_syn_load_elab_tcl]
append commands "\nelaborate $vars(design)\n"
append commands [FF::wrap_command $vars(step),elaborate $command]
append commands "\ninit_design\n"
append commands [FF::wrap_command $vars(step),init_design $command]
append commands [FF::source_plug post_syn_load_elab_tcl]
append commands "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/elab.db\n"
append commands "check_design -multiple_driver -undriven -unresolved > $vars(rpt_dir)/check_design.rpt\n"
append commands "report datapath -all -max_width {{filename 512}} > $vars(rpt_dir)/report_datapath.rpt\n"
# append commands "#set treat_invalid_from_to_as_through 1\n"
if {[info exists vars(clock_gate_cells)]} {
set command "set_db lp_clock_gating_cell \[find /lib* -libcell $vars(clock_gate_cells)\]\n\n"
append command "set_db lp_insert_clock_gating true\n"
append commands [FF::wrap_command $vars(step),insert_clock_gating $command]
}
if {[info exists vars(leakage_power_effort)] && ($vars(leakage_power_effort) != "none")} {
set command "set_db lp_multi_vt_optimization_effort $vars(leakage_power_effort)\n"
append commands [FF::wrap_command $vars(step),leakage_power_effort $command]
}
append command "#set_db lp_insert_operand_isolation false\n"
append command "#set_db lp_power_analysis_effort low\n"
append command "#set_db lp_clock_gating_hierarchical false\n"
append command "#set_db lp_clock_gating_auto_cost_group_initial_target 0\n"
append command "#set_db lp_clock_gating_max_flops infinity\n"
append command "#set_db lp_clock_gating_min_flops 3\n"
append command "#set_db lp_clock_gating_auto_path_adjust fixed\n"
append command "#set_db lp_clock_gating_auto_path_adjust_fixed_delay 175\n"
append commands [FF::wrap_command $vars(step),set_icg_attributes $command]
# append command "#set_db lp_power_optimization_weight \"\"\n"
#-----------------------------------------------------------------------
# DFT Settings
#-----------------------------------------------------------------------
set command "#set_db dft_scan_map_mode force_all\n"
append command "#set_db dft_scan_style muxed_scan\n"
append command "#set_db dft_prefix DFT_\n"
append command "#set_db use_scan_seqs_for_non_dft true\n"
append command "#set_db dft_scan_map_mode force_all\n"
append command "#set_db dft_connect_shift_enable_during_mapping tie_off\n"
append command "#set_db dft_connect_scan_data_pins_during_mapping loopback\n"
append command "#set_db dft_scan_output_preference non_inverted\n"
append command "#set_db dft_lockup_element_type edge_sensitive\n"
append command "#set_db dft_mix_clock_edges_in_scan_chains false\n"
append commands [FF::wrap_command $vars(step),set_dft_attributes $command]
append commands [FF::source_plug syn_setup_dft_tcl]
set command ""
## RC timing still comes from cpf, Innovus timing comes from setup.tcl
if [info exists vars(cpf_file)] {
append command "apply_power_intent -summary\n"
append commands [FF::wrap_command $vars(step),apply_power_intent $command]
} else {
# append command "set mode [lindex $vars(constraint_modes) 0]\n"
# append command "if { \[find / -mode \$mode \] == \"\"} {\n"
# append command " create_mode -default -name \$mode\n"
# append command "}\n"
# ## Now populate the timing modes
# foreach mode $vars(constraint_modes) {
# if {[info exists vars($mode,synth_sdc)]} {
# append command "if { \[find / -mode $mode\] == \"\" } {\n"
# append command " create_mode -name $mode\n"
# append command "}\n"
# append command "read_sdc -mode $mode $vars($mode,synth_sdc)\n"
# } else {
# if {[info exists vars($mode,pre_cts_sdc)]} {
# append command "if { \[find / -mode $mode\] == \"\" } {\n"
# append command " create_mode -name $mode\n"
# append command "}\n"
# append command "read_sdc -mode $mode $vars($mode,pre_cts_sdc)\n"
# }
# }
# }
# append commands [FF::wrap_command $vars(step),apply_constraints $command]
# append command "puts \"The number of exceptions is \[llength \[find / -exception *\]\]\"\n"
set command "\ndefine_cost_group -name in2out\n"
append command "define_cost_group -name in2reg\n"
append command "define_cost_group -name reg2out\n"
append command "define_cost_group -name reg2reg\n"
# set mode [lindex $vars(constraint_modes) 0]
# set mode $vars(default_synthesis_mode)
set mode $vars(default_synthesis_view)
append command "path_group -mode $mode -from \[all::all_inps\] -to \[all::all_outs\] -group in2out -name in2out\n"
append command "path_group -mode $mode -from \[all::all_inps\] -to \[all::all_seqs\] -group in2reg -name in2reg\n"
append command "path_group -mode $mode -from \[all::all_seqs\] -to \[all::all_outs\] -group reg2out -name reg2out\n"
append command "path_group -mode $mode -from \[all::all_seqs\] -to \[all::all_seqs\] -group reg2reg -name reg2reg\n"
# append command "path_group -from \[all::all_inps\] -to \[all::all_outs\] -group in2out -name in2out\n"
# append command "path_group -from \[all::all_inps\] -to \[all::all_seqs\] -group in2reg -name in2reg\n"
# append command "path_group -from \[all::all_seqs\] -to \[all::all_outs\] -group reg2out -name reg2out\n"
# append command "path_group -from \[all::all_seqs\] -to \[all::all_seqs\] -group reg2reg -name reg2reg\n"
append commands [FF::wrap_command $vars(step),create_path_groups $command]
}
set command ""
set first 1
if {[info exists vars(def_files)]} {
foreach file $vars(def_files) {
if {[file exists $file]} {
if {$first} {
append command "read_def $file\n"
set first 0
} else {
append command "read_def -incr $file\n"
}
}
}
append commands [FF::wrap_command $vars(step),read_def $command]
}
append commands "report timing -lint\n"
if {[info exists vars(max_route_layer)]} {
# append commands "\nset_db number_of_routing_layers $vars(max_route_layer) designs/$vars(design)\n"
}
# append commands "#foreach cg \[find / -cost_group *\] {\n"
# append commands "# report timing -cost_group [list \$cg] >> $vars(rpt_dir)/cost_group.map.rpt\n"
# append commands "#}\n"
# append commands "#set_remove_assign_options -skip_unconstrained_paths -physical\n"
# append commands "#set_db utilization 0 \[find / -layer M1\]\n"
append commands [FF::source_plug pre_syn_gen_tcl]
set command "\nsynthesize -to_generic -effort medium\n\n"
append commands [FF::wrap_command $vars(step),syn2gen $command]
append commands [FF::source_plug post_syn_gen_tcl]
append commands "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/syn_gen.db\n"
set command "\nsynthesize -to_map -effort high -clock_gating_only\n\n"
append commands [FF::wrap_command $vars(step),syn2icg $command]
# set cg_cells "\n"
# foreach i [filter libcell -invert "" [find / -inst instances_seq/*]] {
# if {[get_attr clock_gating_integrated_cell [get_attr libcell $i]] != "" } {
# lappend cg_cells $i
# }
# }
# if { $cg_cells != "" } {
# set CG_ADJUST [path_adjust -delay -150 -to $cg_cells]
# }
append commands [FF::source_plug pre_syn_map_tcl]
# Synthesizing to gates using effort level defined by vars(syn_map_effort).
set command "\nsynthesize -to_mapped -effort high -no_incremental\n\n"
append commands [FF::wrap_command $vars(step),syn2map $command]
set command ""
append command "report_area > $vars(rpt_dir)/$vars(step).area.rpt\n"
append command "report_dp > $vars(rpt_dir)/$vars(step).datapath.rpt\n"
append command "report_timing -max_paths 5 -path_type summary > $vars(rpt_dir)/$vars(step).start_end_slack.rpt\n"
append command "report_timing -max_paths 1 -nworst 1 -path_type full_clock > $vars(rpt_dir)/$vars(step).worst_max_path.rpt\n"
append command "report_timing -max_paths 500 -nworst 1 -path_type full_clock > $vars(rpt_dir)/$vars(step).top_500_paths.rpt\n"
append command "report_gates -power > $vars(rpt_dir)/$vars(step).gates_power.rpt\n"
append command "report_clock_gating > $vars(rpt_dir)/$vars(step).clockgating.rpt\n"
append command "report_power -depth 0 > $vars(rpt_dir)/$vars(step).power.rpt\n"
append commands [FF::wrap_command $vars(step),generate_reports $command]
if {$vars(capture_metrics)} {
append commands "pop_snapshot_stack\n"
if {[lindex [split $vars(version) "."] 0] > 16} {
append commands "create_snapshot -name $vars(step) -categories design\n"
} else {
append commands "create_snapshot -name $vars(step)\n"
}
append commands "write_metric -format tcl -file $vars(dbs_dir)/$vars(step).um\n"
append commands "report_metric -file $vars(rpt_dir)/$vars(design).html -format html\n"
}
append commands "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/syn_map.db\n"
if {[info exists vars(mail,to)]} {
set summary_file $vars(step).summary
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[shell pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " exec gunzip -c $vars(rpt_dir)/${summary_file}.gz \| /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[shell pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
return $commands
}
proc run_syn_incr {{format 1}} {
global vars
global env
global errors
set vars(step) syn_incr
set commands ""
# append commands "source $vars(script_dir)/vars.tcl\n"
append commands "proc Puts {args} {puts \$args}\n"
if {$vars(novus)} {
append commands "puts \[get_db program_version /\]\n"
} else {
append commands "puts \[get_attr program_version /\]\n"
}
## enable multi processing
append commands "set hostlist \[lrepeat $vars(local_cpus) localhost\]\n"
append commands "set_db super_thread_servers \$hostlist\n"
# if {$vars(capture_metrics)} {
# append commands "\nenable_metrics -on\n"
# append commands "push_snapshot_stack\n"
# }
append commands [FF::source_plug pre_syn_incr_tcl]
# append commands "catch { set_remove_assign_options -skip_unconstrained_paths -physical }\n"
# append commands "set_db remove_assigns true\n"
if {$vars(enable_pam)} {
append commands "\nset_db physical_aware_restructuring true\n"
append commands "set_db physical_aware_structuring true\n"
append commands "set_db physical_aware_mapping true\n"
}
#### OPTIMIZATION EFFORT CONTROL
if {$vars(high_timing_effort)} {
set command "\nset_db tns_opto true\n"
append command "set_db iopt_enable_parallelization true\n"
append command "set_db ultra_global_mapping true\n"
append command "set_db iopt_ultra_optimization true\n"
append commands [FF::wrap_command $vars(step),set_high_effort_attributes $command]
}
set command "#set_db optimize_merge_flops false\n"
append command "#set_db optimize_constant_0_flops true\n"
append command "#set_db optimize_constant_1_flops false\n"
append command "#set_db optimize_constant_latches false\n"
append command "#set_db delete_unloaded_seqs true\n"
append command "#set_db optimize_net_area false\n"
append command "#set_db dp_area_mode true\n"
append command "#set_db auto_ungroup none\n"
append command "#set_db auto_ungroup_min_effort low\n"
append command "#set_db ungroup_separator \n"
append commands [FF::wrap_command $vars(step),set_opt_attributes $command]
### Detail Stats while running
# append commands "#set iopt_stats 1\n"
#-----------------------------------------------------------------------
# Max leakage power ?
#-----------------------------------------------------------------------
# append commands "#set_db max_leakage_power ?\n"
set command "\nsynthesize -to_mapped -effort high -incr\n\n"
append commands [FF::wrap_command $vars(step),syn2incr $command]
append commands [FF::source_plug post_syn_incr_tcl]
# append commands "foreach cg \[find / -cost_group *\] {\n"
# append commands " report timing -cost_group \$cg >> $vars(rpt_dir)/syn_incr_\[file tail \$cg\].rpt\n"
# append commands "}\n"
set command ""
append command "report_area > $vars(rpt_dir)/$vars(step).area.rpt\n"
append command "report_dp > $vars(rpt_dir)/$vars(step).datapath.rpt\n"
append command "report_timing -max_paths 5 -path_type summary > $vars(rpt_dir)/$vars(step).start_end_slack.rpt\n"
append command "report_timing -max_paths 1 -nworst 1 -path_type full_clock > $vars(rpt_dir)/$vars(step).worst_max_path.rpt\n"
append command "report_timing -max_paths 500 -nworst 1 -path_type full_clock > $vars(rpt_dir)/$vars(step).top_500_paths.rpt\n"
append command "report_gates -power > $vars(rpt_dir)/$vars(step).gates_power.rpt\n"
append command "report_clock_gating > $vars(rpt_dir)/$vars(step).clockgating.rpt\n"
append command "report_power -depth 0 > $vars(rpt_dir)/$vars(step).power.rpt\n"
append commands [FF::wrap_command $vars(step),generate_reports $command]
if {$vars(capture_metrics)} {
append commands "pop_snapshot_stack\n"
if {[lindex [split $vars(version) "."] 0] > 16} {
append commands "create_snapshot -name $vars(step) -categories design\n"
} else {
append commands "create_snapshot -name $vars(step)\n"
}
append commands "write_metric -format tcl -file $vars(dbs_dir)/$vars(step).um\n"
append commands "report_metric -file $vars(rpt_dir)/$vars(design).html -format html\n"
}
set command "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).db\n"
append commands [FF::wrap_command $vars(step),write_db $command]
if {!$vars(enable_rcp)} {
set command "\nwrite_design -innovus -gzip -basename $vars(dbs_dir)/$vars(step)/$vars(step)\n"
append command "set file \[open $vars(dbs_dir)/$vars(step)/$vars(step).novus_setup.tcl w\]\n"
append command "puts \$file \"eval_enc \{source $vars(dbs_dir)/$vars(step)/$vars(step).enc_setup.tcl\}\"\n"
append command "close \$file\n\n"
append commands [FF::wrap_command $vars(step),write_design $command]
}
if {[info exists vars(mail,to)]} {
set summary_file $vars(step).summary
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[shell pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " exec gunzip -c $vars(rpt_dir)/${summary_file}.gz \| /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[shell pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
return $commands
}
proc run_syn_place {{format 1}} {
global vars
global env
global errors
set vars(step) syn_place
set commands ""
# append commands "source $vars(script_dir)/vars.tcl\n"
append commands "proc Puts {args} {puts \$args}\n"
if {$vars(novus)} {
append commands "puts \[get_db program_version\]\n"
} else {
append commands "puts \[get_attr program_version\]\n"
}
## enable multi processing
append commands "set hostlist \[lrepeat $vars(local_cpus) localhost\]\n"
append commands "set_db super_thread_servers \$hostlist\n"
# if {$vars(capture_metrics)} {
# append commands "\nenable_metrics -on\n"
# append commands "push_snapshot_stack\n"
# }
if {[info exists vars(postload_syn_place_tcl)]} {
append commands "set_db enc_postload_script $vars(postload_syn_place_tcl)\n"
}
if {[info exists vars(preexport_syn_place_tcl)]} {
append commands "set_db enc_preexport_script $vars(preexport_syn_place_tcl)\n"
}
if {[info exists vars(preannotation_syn_placed_tcl)]} {
append commands "set_db enc_preannotation_tcl $vars(preannotation_syn_placed_tcl)\n"
}
append commands "set_db enc_temp_dir ./INNOVUS/rcp_run\n"
append commands "set_db enc_gzip_interface_files true\n"
append commands "set_db pqos_placement_effort no_value\n"
# append commands "set ::phys::pqos_tns_opt 1\n"
append commands "set_db iopt_enable_parallelization false\n"
# if {[info exists vars(def_files)]} {
# foreach file $vars(def_files) {
# if {[file exists $file]} {
# set command "read_def $vars(def_files)\n"
# append commands [FF::wrap_command $vars(step),read_def $command]
# }
# }
# }
append commands [FF::source_plug pre_syn_place_tcl]
set command "\nsynthesize -to_placed -effort high -pqos_only\n\n"
append commands [FF::wrap_command $vars(step),syn2place $command]
set command "\nsynthesize -to_placed -effort high -incr\n\n"
append commands [FF::wrap_command $vars(step),syn2place_incr $command]
append commands [FF::source_plug post_syn_place_tcl]
append commands "::phys::qos_stats -quiet -tag syn2placed\n"
append commands "::phys::qos_write_stats_array > $vars(rpt_dir)/qos_stats.qdb\n"
append commands "::phys::qos_summary\n"
append commands "foreach cg \[find / -cost_group *\] {\n"
append commands " report timing -cost_group \$cg >> $vars(rpt_dir)/syn_place_\[file tail \$cg\].rpt\n"
append commands "}\n"
append command "report_area > $vars(rpt_dir)/$vars(step).area.rpt\n"
append command "report_dp > $vars(rpt_dir)/$vars(step).datapath.rpt\n"
append command "report_timing -max_paths 5 -path_type summary > $vars(rpt_dir)/$vars(step).start_end_slack.rpt\n"
append command "report_timing -max_paths 1 -nworst 1 -path_type full_clock > $vars(rpt_dir)/$vars(step).worst_max_path.rpt\n"
append command "report_timing -max_paths 500 -nworst 1 -path_type full_clock > $vars(rpt_dir)/$vars(step).top_500_paths.rpt\n"
append command "report_gates -power > $vars(rpt_dir)/$vars(step).gates_power.rpt\n"
append command "report_clock_gating > $vars(rpt_dir)/$vars(step).clockgating.rpt\n"
append command "report_power -depth 0 > $vars(rpt_dir)/$vars(step).power.rpt\n"
append commands [FF::wrap_command $vars(step),generate_reports $command]
if {$vars(capture_metrics)} {
append commands "pop_snapshot_stack\n"
if {[lindex [split $vars(version) "."] 0] > 16} {
append commands "create_snapshot -name $vars(step) -categories design\n"
} else {
append commands "create_snapshot -name $vars(step)\n"
}
append commands "write_metric -format tcl -file $vars(dbs_dir)/$vars(step).um\n"
append commands "report_metric -file $vars(rpt_dir)/$vars(design).html -format html\n"
}
set command "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).db\n"
append commands [FF::wrap_command $vars(step),write_db $command]
if {$vars(enable_rcp)} {
set command "\nwrite_design -innovus -gzip -basename $vars(dbs_dir)/$vars(step)/$vars(step)\n"
append command "set file \[open $vars(dbs_dir)/$vars(step)/$vars(step).novus_setup.tcl w\]\n"
append command "puts \$file \"eval_enc \{source $vars(dbs_dir)/$vars(step)/$vars(step).enc_setup.tcl\}\"\n"
append command "close \$file\n\n"
append commands [FF::wrap_command $vars(step),write_design $command]
}
if {[info exists vars(mail,to)]} {
set summary_file $vars(step).summary
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[shell pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " exec gunzip -c $vars(rpt_dir)/${summary_file}.gz \| /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[shell pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
append commands [FF::wrap_command $vars(step),schedule_flow $command]
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
return $commands
}
proc run_init {{format 1}} {
global vars
global env
global errors
global warnings
global env
set commands ""
set ucomments ""
set comments ""
if {[info exists vars(view_definition_tcl)]} {
append comments "# - vars(view_definition_tcl)\n"
}
if {![info exists vars(step)] || (($vars(step) != "partition_place") && ($vars(step) != "model_gen") && ($vars(step) != "prototype"))} {
append commands "set vars(step) init\n"
set vars(step) init
}
if {$vars(report_run_time)} {
append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
append comments "# - vars(report_run_time)\n"
} else {
append ucomments "# - vars(report_run_time)\n"
}
if {[info exists vars($vars(step),rpt_dir)]} {
set vars(rpt_dir) $vars($vars(step),rpt_dir)
file mkdir $vars($vars(step),rpt_dir)
} else {
set vars(rpt_dir) $vars(orig_rpt_dir)
}
###############################################################################
# Make sure necessary data is defined
# Create make directory if it doesn't exists
###############################################################################
if {!$vars(codegen)} {
set command "FF_NOVUS::check_setup\n"
append command "sleep 3\n"
uplevel #0 eval $command
}
###############################################################################
# Make sure necessary data is defined
###############################################################################
foreach dir "[subst $vars(dbs_dir)] [subst $vars(rpt_dir)] [subst $vars(log_dir)]" {
set newDir [subst $dir]
if {![file exists $newDir]} {
file mkdir $newDir
}
}
# if {[info exists vars(buffer_tie_assign)] && $vars(buffer_tie_assign)} {
# append commands "set_db init_buffer_tie_assign true\n"
# append comments "# - vars(buffer_tie_assign)\n"
# } else {
# append ucomments "# - vars(buffer_tie_assign)\n"
# }
if {[info exists vars(ground_nets)]} {
append commands "set_db init_ground_nets \"$vars(ground_nets)\"\n"
append comments "# - vars(ground_nets)\n"
} else {
append ucomments "# - vars(ground_nets)\n"
}
if {[info exists vars(power_nets)]} {
append commands "set_db init_power_nets \"$vars(power_nets)\"\n"
append comments "# - vars(power_nets)\n"
} else {
append ucomments "# - vars(power_nets)\n"
}
###############################################################################
# Load pre-initializatiaon plug-in script
###############################################################################
append commands [FF::source_plug pre_init_tcl]
###############################################################################
# These flow scripts support the following:
# - Flat chip or block
# - Hierarchical partition
# - Top level partition
#
# The data loading mechanism are slightly different for each so we determine
# first if we are in a hierarchical flow (i.e. vars(partition_list) is
# defined and, if so, whether we are in a hierarchical partition flow
# or a top partition flow (i.e. cwd == $vars(design) - see below)
#
###############################################################################
FF_NOVUS::check_flow
# append commands "#---------------------------------------------------------------------\n"
# append commands "# EXECUTING FLOW\n"
# append commands "#---------------------------------------------------------------------\n"
set hier 0
if {[info exists vars($vars(step),starting_dbs)]} {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
# Interpret the starting DBS as an OA triple
set restore_command "[list read_db -cellview $vars($vars(step),starting_dbs)]\n"
} else {
if {[file isdirectory $vars($vars(step),starting_dbs)]} {
set restore_command "read_db $vars($vars(step),starting_dbs) \n"
} elseif {[file exists $vars($vars(step),starting_dbs)]} {
set restore_command "read_db $vars($vars(step),starting_dbs) \n"
} else {
puts "<FF> Starting DBS ($vars($vars(step),starting_dbs)) defined but does not exist"
set restore_command "read_db $vars($vars(step),starting_dbs) \n"
set warnings($vars(warning_count)) "Starting DBS ($vars($vars(step),starting_dbs)) defined but does not exist"
incr vars(warning_count)
}
}
append commands [FF::wrap_command $vars(step),read_db $restore_command]
} else {
if {![info exists vars(partition_list)] || ([info exists vars(partition_list)] && \
([file tail [file dirname [pwd]]] != "$vars(partition_dir)"))} {
###############################################################################
# Partition step or flat init step
###############################################################################
if {[info exists vars(partition_list)]} {
set hier 1
}
if {$vars(verbose)} {
if {![info exists vars(partition_list)]} {
append commands "#\n"
append commands "# FLAT IMPLEMENTATION FLOW\n"
append commands "#\n"
} else {
append commands "#\n"
append commands "# PARTITIONING FLOW\n"
append commands "#\n"
}
}
if {$vars(verbose)} {
append commands "#\n"
append commands "# LOADING DESIGN DATA\n"
append commands "#\n"
}
###############################################################################
# Load design configuration file
###############################################################################
if {[lindex [split $vars(version) "."] 0] <= 10} {
source $vars(script_path)/ETC/INNOVUS/generic.conf
}
if {$vars(ilm)} {
set ilm_list $vars(ilm_list)
append comments "# - vars(ilm_list) \"<list of ILMs>\"\n"
if {$vars(mode) == "bottom_up"} {
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)]} {
append comments "# - vars(<ilm>,ilm_dir) \"<path to ILM directory>\"\n"
if {[lsearch $ilm_list $part] == -1} {
lappend ilm_list $part
}
}
}
}
foreach ilm $ilm_list {
if {[info exists vars($ilm,lef_file)] && [file exists $vars($ilm,lef_file)]} {
append comments "# - vars(<ilm>,lef_file) \"<LEF file for block associated with ILM>\"\n"
if {[lindex [split $vars(version) "."] 0] <= 10} {
lappend rda_Input(ui_leffile) $vars($ilm,lef_file)
} else {
if {[string compare $vars(dbs_format) "fe"]==0} {
lappend vars(lef_files) $vars($ilm,lef_file)
}
}
} else {
puts "<FF> WARNING: LEF file either not defined or doesn't exist for $ilm"
puts "<FF> Please make sure it is in your vars(lef_files) list"
set warnings($vars(warning_count)) "LEF file either not defined or doesn't exist for $ilm\n\tPlease make sure it is in your vars(lef_files) list"
incr vars(warning_count)
}
if {[info exists vars($ilm,setup_lib)] && [file exists $vars($ilm,setup_lib)]} {
append comments "# - vars(<ilm>,setup_lib) \"<LIB file for block associated with ILM>\"\n"
if {[lindex [split $vars(version) "."] 0] <= 10} {
lappend rda_Input(ui_timelib) $vars($ilm,setup_lib)
} else {
if {[string compare $vars(dbs_format) "fe"]==0} {
foreach set $vars(library_sets) {
if {[lsearch $vars($set,timing) $vars($ilm,setup_lib)] == -1} {
lappend vars($set,timing) $vars($ilm,setup_lib)
}
}
}
}
} else {
puts "<FF> WARNING: LIB file either not defined or doesn't exist for $ilm"
puts "<FF> Please make sure it is in your library set definitions"
set warnings($vars(warning_count)) "LIB file either not defined or doesn't exist for $ilm\n\tPlease make sure it is in your library set definitions"
incr vars(warning_count)
}
}
} else {
append ucomments "# - vars(ilm_list) \"<list of ILMs>\"\n"
append ucomments "# - vars(<ilm>,ilm_dir) \"<path to ILM directory>\"\n"
append ucomments "# - vars(<ilm>,lef_file) \"<LEF file for block associated with ILM>\"\n"
append ucomments "# - vars(<ilm>,setup_lib) \"<LIB file for block associated with ILM>\"\n"
}
FF_NOVUS::dump_config
if {[string compare -nocase $vars(netlist_type) "verilog"]>=0} {
set command ""
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
append command "read_mmmc $mmmc_file\n"
if {[info exists vars(lef_files)]} {
append command "read_physical -lef \"\\\n"
foreach lef $vars(lef_files) {
# append command "read_physical -lef $lef\n"
append command "\t$lef\\\n"
}
append command "\"\n"
} else {
if {[info exists vars(oa_ref_lib)]} {
append command "read_physical -oa_ref_lib "
foreach lib $vars(oa_ref_lib) {
append command " $lib"
}
append command "\n"
}
}
if {[info exists vars(netlist)]} {
append command "read_netlist $vars(netlist)\n"
}
if {[info exists vars(cpf_file)]} {
append command "read_power_intent -cpf $vars(cpf_file)\n"
}
append command "init_design\n"
append commands [FF::wrap_command $vars(step),init_design $command]
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "set_db power_leakage_power_view $vars(power_analysis_view)\n"
append command "set_db power_dynamic_power_view $vars(power_analysis_view)\n"
append commands [FF::wrap_command $vars(step),set_power_analysis_mode $command]
}
} else {
if {$hier} {
if {$vars(step) == "partition_place"} {
set command "read_db -cellview \[list $vars(oa_design_lib) $vars(oa_design_cell) $vars(oa_design_view)\]\n"
} else {
set command "read_db -cellview \[list $vars(oa_partition_lib) $vars(oa_design_cell) $vars(oa_design_view)\]\n"
}
} else {
set command "read_db -cellview \[list $vars(oa_design_lib) $vars(oa_design_cell) $vars(oa_design_view)\]\n"
}
append commands [FF::wrap_command $vars(step),read_db $command]
}
###############################################################################
# Load "always source" plug-in script
###############################################################################
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Check for the existence of either a floorplan file, a
# DEF file, or both and load them
###############################################################################
set command ""
if {[info exists vars(fp_tcl_file)] || [info exists vars(fp_tcl_proc)]} {
append comments "# - vars(fp_tcl_file)\n"
append comments "# - vars(fp_tcl_proc)\n"
if {[info exists vars(fp_tcl_file)] && ![info exists vars(fp_tcl_proc)]} {
append command "ff_procs::source_file $vars(fp_tcl_file)\n"
} elseif {![info exist vars(fp_tcl_file)] && [info exists vars(fp_tcl_proc)]} {
append command "$vars(fp_tcl_proc)\n"
} else {
append command "# ERROR: Both fp_tcl_file and fp_tcl_proc are defined but are mutually exclusive\n"
set errors($vars(error_count)) "Both fp_tcl_file and fp_tcl_proc are defined but are mutually exclusive"
incr vars(error_count)
}
} else {
append ucomments "# - vars(fp_tcl_file)\n"
append ucomments "# - vars(fp_tcl_proc)\n"
if {[info exists vars(fp_file)]} {
if {[file exists $vars(fp_file)]} {
# append command "puts \"<FF> LOADING FP FILE $vars(fp_file)\"\n"
append command "read_floorplan $vars(fp_file)\n"
}
append comments "# - vars(fp_file)\n"
} else {
append ucomments "# - vars(fp_file)\n"
}
if {[info exists vars(oa_fp)]} {
append command "oaIn $vars(oa_fp)\n"
append comments "# - vars(oa_fp)\n"
} else {
append ucomments "# - vars(oa_fp)\n"
}
if {[info exists vars(def_files)]} {
append comments "# - vars(def_files)\n"
if {$vars(rc)} {
if {$vars(enable_rcp)} {
set vars(netlist) $vars(dbs_dir)/syn_place/syn_place.v.gz
set vars(def_files) $vars(dbs_dir)/syn_place/syn_place.def.gz
if {[info exists vars(insert_dft)] && $vars(insert_dft)} {
lappend vars(def_files) $vars(dbs_dir)/syn_place/syn_place.scan.def.gz
}
} else {
set vars(netlist) $vars(dbs_dir)/syn_incr/syn_incr.v.gz
set vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.def.gz
if {[info exists vars(insert_dft)] && $vars(insert_dft)} {
lappend vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.scan.def.gz
}
}
foreach def_file $vars(def_files) {
append command "read_def $def_file\n"
}
} else {
foreach def_file $vars(def_files) {
if {[file exists $def_file]} {
append command "read_def $def_file\n"
append comments "# - vars(def_files)\n"
} else {
append ucomments "# - vars(def_files)\n"
}
}
}
} else {
append comments "# - vars(def_files)\n"
}
}
append commands [FF::wrap_command $vars(step),read_floorplan $command]
if {($vars(parent) == "rc") && $vars(rc)} {
set commands [FF::source_plug always_source_tcl]
if {$vars(report_run_time)} {
append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
}
append commands [FF::source_plug pre_init_tcl]
}
# if {[info exists vars(guides)]} {
# set command "\nbuild_guides\n"
# append commands [FF::wrap_command init,build_guides $command]
# }
# if {[info exists vars(blockages)]} {
# set command "\nadd_blockages\n"
# append commands [FF::wrap_command init,add_blockages $command]
# }
if {$vars(add_tracks)} {
set command "add_tracks\n"
if {[info exists vars(honor_pitch)] && $vars(honor_pitch)} {
set command " add_tracks -honor_pitch\n"
}
append commands [FF::wrap_command $vars(step),add_tracks $command]
append comments "# - vars(add_tracks)\n"
} else {
append ucomments "# - vars(add_tracks)\n"
}
###############################################################################
# Define power intent if it is defined (low power flow)
###############################################################################
# append commands [FF_NOVUS::load_power_intent]
if {[info exists vars(activity_file)]} {
# append commands $header
# set header ""
set command "readActivityFile -format $vars(activity_file_format) $vars(activity_file)\n"
append commands [FF::wrap_command $vars(step),read_activity_file $command]
append comments "# - vars(activity_file)\n"
append comments "# - vars(activity_file_format)\n"
} else {
append ucomments "# - vars(activity_file)\n"
append ucomments "# - vars(activity_file_format)\n"
}
###############################################################################
# Specify ILMs if defined
###############################################################################
if {[info exists ilm_list] && ($ilm_list != "")} {
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "read_ilm -cell $cell -directory $vars($cell,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "read_ilm -cell $cell -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
} else {
append command "read_ilm -cell $cell -directory $vars($cell,ilm_dir)\n"
}
}
} else {
puts "<FF> ERROR: ilm directory missing for $cell"
set errors($vars(error_count)) "ILM directory missing for $cell"
incr vars(error_count)
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
}
# if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
# if {[file exists $vars(ilm_non_sdc_file)]} {
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
# } else {
# set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
# }
# append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
# }
# append comments "# - vars(ilm_non_sdc_file)\n"
# } else {
# append ucomments "# - vars(ilm_non_sdc_file)\n"
# }
###############################################################################
# Load timing enviroment based on the flow setting in the
# setup.tcl file. If the flow is mmmc, load the mmmc setup
# here else load the default timing environment
###############################################################################
# append commands "#\n"
# append commands "# SETTING UP TIMING ENVIRONMENT\n"
# append commands "#\n"
if {$vars(flow) == "mmmc"} {
set command [FF_NOVUS::initialize_timing mmmc]
} else {
set command [FF_NOVUS::initialize_timing minmax]
}
# foreach var [array name vars] {
# if {($var != "step") && ($var != "mode") && ($var != "ilm") && \
# ($var != "flavor") && ($var != "user_mode") && ($var != "flat") && \
# ($var != "report_run_time") && ($var != "makefile") && ($var != "codegen") && \
# ($var != "backup_data") && ($var != "verbose") && ($var != "format_lines") && \
# ($var != "warning_count") && ($var != "error_count") && ($var != "rc") && \
# ($var != "add_tracks") && ($var != "fix_hold") && ($var != "honor_pitch") && \
# ($var != "script_path") && ($var != "fix_hold") && ($var != "honor_pitch") && \
# ($var != "steps") && ($var != "sourced") && ($var != "version")} {
# set vars($var) "\\\$vars($var)"
# }
# }
append commands [FF::wrap_command $vars(step),initialize_timing $command]
if {$vars(flow) == "mmmc"} {
set command [FF_NOVUS::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
###############################################################################
# Load scan DEF if it exists
###############################################################################
if {[info exists vars(scan_def)]} {
if {[file exists $vars(scan_def)]} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# <FF> LOADING SCAN DEF FILE\n"
append commands "#\n"
}
set command "read_def $vars(scan_def)\n"
append commands [FF::wrap_command $vars(step),load_scan $command]
}
append comments "# - vars(scan_def)\n"
} else {
append ucomments "# - vars(scan_def)\n"
}
###############################################################################
# Specify spare gates for placement and optimization consideration; this assumes
# the spare cells are in the netlist.
###############################################################################
set command ""
if {[info exists vars(spare_cells)]} {
foreach spare_cell $vars(spare_cells) {
append command "specify_spare_gate -inst $spare_cell\n"
}
append comments "# - vars(spare_cells)\n"
} else {
append ucomments "# - vars(spare_cells)\n"
}
append commands [FF::wrap_command $vars(step),specify_spare_gates $command]
###############################################################################
# Load the recommended command mode settings
###############################################################################
if {$vars(verbose)} {
append commands "#\n"
append commands "# DEFINING MODE SETTINGS\n"
append commands "#\n"
}
###############################################################################
# Set don't use cells; disable some (clock buffers, strong buffers, etc.),
# enable others that may have "dont_use true" in the library (like delay cells
# for hold fixing)
###############################################################################
set command ""
if {[info exists vars(dont_use_list)]} {
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
foreach cell $vars(dont_use_list) {
append command "set_dont_use true $cell\n"
}
append comments "# - vars(dont_use_list)\n"
} else {
append ucomments "# - vars(dont_use_list)\n"
}
if {[info exists vars(dont_use_file)] && [file exists $vars(dont_use_file)]} {
append command "source $vars(dont_use_file)\n"
append comments "# - vars(dont_use_file)\n"
} else {
append ucomments "# - vars(dont_use_file)\n"
}
if {[info exists vars(use_list)]} {
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
foreach cell $vars(use_list) {
append command "set_dont_use false $cell\n"
}
append comments "# - vars(use_list)\n"
} else {
append ucomments "# - vars(use_list)\n"
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),set_dont_use $command]
}
###############################################################################
# Set maximum routing layers
###############################################################################
if {[info exists vars(max_route_layer)]} {
set command "set_max_route_layer $vars(max_route_layer)\n"
append commands [FF::wrap_command $vars(step),set_max_route_layer $command]
append comments "# - vars(max_route_layer)\n"
} else {
append ucomments "# - vars(max_route_layer)\n"
}
###############################################################################
# Set design mode
###############################################################################
set process [regsub "nm" $vars(process) ""]
append commands "set_db design_process_node $process\n"
if {[string tolower $vars(flow_effort)] != "standard"} {
append commands "set_db design_flow_effort [string tolower $vars(flow_effort)]\n"
}
###############################################################################
# Insert welltaps and pre/post endcaps
###############################################################################
if {([FF::get_by_suffix vars "welltaps"] != "") ||
(([FF::get_by_suffix vars "pre_endcap"] != "") &&
([FF::get_by_suffix vars "post_endcap"] != ""))} {
set command [FF_NOVUS::insert_welltaps_endcaps]
append commands [FF::wrap_command $vars(step),insert_welltaps_endcaps $command]
append comments "# - vars(welltaps)\n"
append comments "# - vars(pre_endcap)\n"
append comments "# - vars(post_endcap)\n"
} else {
append ucomments "# - vars(welltaps)\n"
append ucomments "# - vars(pre_endcap)\n"
append ucomments "# - vars(post_endcap)\n"
}
} else {
###############################################################################
# Partition init step
###############################################################################
set ptn [file tail [pwd]]
set vars(design) $ptn
set skip_cpf false
# set vars(ilm) 0
###############################################################################
if {[lsearch $vars(partition_list) $ptn] == -1} {
append commands "#------------------------------------------------------------\n"
append commands "# TOP ($ptn) IMPLEMENTATION FLOW\n"
append commands "#------------------------------------------------------------\n"
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadConfig $ptn.conf 0\n"
if {[info exists vars(save_ilm_non_sdc_file)]} {
set vars(ilm_non_sdc_file) $vars(save_ilm_non_sdc_file)
}
append command "global rda_Input\n"
foreach part $vars(partition_list) {
append command "lappend rda_Input(ui_leffile) ../$part/$part.antenna.lef\n"
}
append command "commitConfig\n"
append commands [FF::wrap_command $vars(step),load_config $command]
} else {
if {[string compare $vars(dbs_format) "oa"]==0} {
set command "read_db -cellview \[list $vars(oa_partition_lib) $ptn layout\]\n"
} else {
if {$vars(use_flexmodels)} {
if {$vars(flexmodel_as_ptn)} {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "read_db ${ptn}_proto_eco.enc.dat\n"
} else {
set command "read_db ${ptn}_proto_full.enc.dat\n"
}
} else {
set command "read_db .\n"
append command "ff_replace_flexmodel_with_full_netlist\n"
}
} else {
set command "read_db .\n"
}
# foreach part $vars(partition_list) {
# append command "if {\[file exists ../$part/$part.antenna.lef\]} {\n"
# append command "loadLefFile ../$part/$part.antenna.lef\n"
# append command "}\n"
# }
# set command "source $ptn.globals\n"
# foreach part $vars(partition_list) {
# append command "lappend init_lef_file ../$part/$part.antenna.lef\n"
# }
# append command "init_design\n"
}
append commands [FF::wrap_command $vars(step),read_db $command]
set restore_design true
if {$vars(capture_metrics) && (($vars(step) == "init") || (($vars(step) == "partition_place") && !$vars(use_flexmodels)) || ($vars(step) == "model_gen"))} {
append commands "enable_metrics -on\n"
append commands "push_snapshot_stack\n"
}
# FlexILM flow
if {$vars(top)} {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file [file normalize $vars(view_definition_tcl)]
} else {
set mmmc_file [file normalize $vars(script_dir)/view_definition.tcl]
}
if {$vars(enable_flexilm)} {
set command ""
set dirs ""
foreach block $vars(partition_list) {
append dirs "\\\n -flex_ilm {${block} ../${block}/${block}.flexilm}"
}
set command "commit_module_model $dirs\\\n"
if {[info exists vars(cpf_file)]} {
append command " -mmmc_file $vars(mmmc_file)\\\n"
append command " -cpf_file $vars(cpf_file)\n"
set skip_cpf true
} else {
append command " -mmmc_file $vars(mmmc_file)\n"
}
append commands [FF::wrap_command $vars(step),commit_module_model $command]
}
}
}
} else {
append commands "#------------------------------------------------------------\n"
append commands "# PARTITION ($ptn) IMPLEMENTATION FLOW\n"
append commands "#------------------------------------------------------------\n"
if {$vars(use_flexmodels)} {
if {$vars(flexmodel_as_ptn)} {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "read_db ${ptn}_proto_eco.enc.dat\n"
} else {
set command "read_db ${ptn}_proto_full.enc.dat\n"
}
# append commands [FF::wrap_command $vars(step),restore_design $command]
} else {
set command "ff_replace_flexmodel_with_full_netlist\n"
# append commands [FF::wrap_command $vars(step),ff_replace_flexmodel_with_full_netlist $command]
}
} else {
if {[string compare $vars(dbs_format) "oa"]==0} {
set command "read_db -cell_view \[list $vars(oa_partition_lib) $ptn layout\]\n"
} else {
set command "read_db .\n"
# set command "source $ptn.globals\n"
# append command "init_design\n"
}
append commands [FF::wrap_command $vars(step),restore_design $command]
set restore_design true
}
}
if {$vars(capture_metrics) && (($vars(step) == "init") || (($vars(step) == "partition_place") && !$vars(use_flexmodels)) || ($vars(step) == "model_gen"))} {
append commands "enable_metrics -on\n"
append commands "push_snapshot_stack\n"
}
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load floorplan file or DEF; use defIn to load a DEF file
###############################################################################
if {[string compare $vars(dbs_format) "fe"]==0} {
if {![info exists restore_design]} {
append commands "read_floorplan $ptn.fp\n"
append commands "source $ptn.mode\n"
if {[file exists $ptn.scan.def]} {
append commands "puts \"<FF> LOADING SCAN DEF FILE $ptn.scan.def\"\n"
append commands "read_def $ptn.scan.def\n"
}
}
}
###############################################################################
# Override maximum routing layer if defined for the partition
###############################################################################
if {[info exists vars($ptn,max_route_layer)]} {
append commands "set_max_route_layer ($ptn,max_route_layer)\n"
append comments "# - vars(max_route_layer)\n"
} else {
append ucomments "# - vars(max_route_layer)\n"
}
###############################################################################
# Specify the ILM models for the top partition
###############################################################################
if {$vars(top)} {
if {!$vars(enable_flexilm)} {
set command ""
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)] && ($vars(codegen) || [file isdirectory $vars($part,ilm_dir)])} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "read_ilm -cell $part -dir $vars($part,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "read_ilm -cell $part -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
} else {
append command "read_ilm -cell $part -directory $vars($part,ilm_dir)\n"
}
}
} else {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "read_ilm -cell $part -directory ../$part/$part.ilm\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "read_ilm -cell $part -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
} else {
append command "read_ilm -cell $part -directory ../$part/$part.ilm\n"
}
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
# if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
# if {[file exists $vars(ilm_non_sdc_file)]} {
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
# } else {
# set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
# }
# append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
# }
# }
set command [FF_NOVUS::initialize_timing mmmc]
# if {![info exists vars(cpf_file)]} {
append commands [FF::wrap_command $vars(step),initialize_timing $command]
# } else {
# set defer_commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
}
}
###############################################################################
# Load power intent (if it is defined)
###############################################################################
if {([info exists vars(cpf_file)]) && ($vars(cpf_file) != "") && !$skip_cpf} {
set save $vars(cpf_file)
if {!$vars(top)} {
set vars(cpf_file) "$ptn.cpf"
}
append commands [FF_NOVUS::load_power_intent]
set vars(cpf_file) $save
} elseif {[info exists vars(ieee1801_file)]} {
set save $vars(ieee1801_file)
if {!$vars(top)} {
set vars(ieee1801_file) "$ptn.cpf"
}
append commands [FF_NOVUS::load_power_intent]
set command "read_power_intent $vars(ieee1801_file) -1801\n"
} else {
append ucomments "# - vars(cpf_file)\n"
append ucomments "# - vars(ieee1801_file)\n"
}
}
}
###############################################################################
# Load post-initialization plug-in script
###############################################################################
append commands [FF::source_plug post_init_tcl 0]
###############################################################################
# Check pre-place timing (and generate timing graph for placement)
###############################################################################
if {($vars(step) != "model_gen") && ($vars(step) != "partition_place")} {
if {![info exists vars(time_design_options,setup)]} {
set command "time_design -pre_place -report_prefix preplace -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design -pre_place -report_prefix preplace -report_dir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
append commands [FF::wrap_command $vars(step),time_design $command]
}
###############################################################################
# Check data setup (sanity check)
###############################################################################
set command "check_legacy_design -all\n"
append commands [FF::wrap_command $vars(step),check_design $command]
if {!$vars(ilm)} {
set command "check_timing\n"
append commands [FF::wrap_command $vars(step),check_timing $command]
}
###############################################################################
# Generate reports
#------------------------------------------------------------------------------
# Report power domain for level-shifters, isolation and pg nets
#------------------------------------------------------------------------------
if {[FF::is_lp_flow] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 1))} {
# set command "set domains \[FF_NOVUS::get_power_domains_code\]\n"
# set command [FF_NOVUS::get_power_domains_code]
append command "foreach domain \[get_db power_domains .name\] {\n"
append command " set domain_file \[regsub -all {\[\]\[<>|\\/?*:\]} \$domain _\]\n"
append command " report_power_domains -power_domain \$domain -out_file $vars(rpt_dir)/\${domain_file}.rpt -shifter -iso_inst -pg_nets\n"
append command " report_power_domains -power_domain \$domain -out_file $vars(rpt_dir)/\${domain_file}_binding.rpt -bind_lib\n"
#------------------------------------------------------------------------------
# Report library binding for power domains
#------------------------------------------------------------------------------
# append command " foreach analysis_view \[all_analysis_views\] {\n"
# append command " set_default_view -setup \$analysis_view\n"
# append command " report_power_domains -power_domain \$domain -file $vars(rpt_dir)/\${domain_file}_\$analysis_view.rpt -bind_lib\n"
# append command " }\n"
# append command " set_db timing_analysis_check_type hold\n"
# append command " foreach analysis_view \[all_hold_analysis_views\] {\n"
# append command " set_default_view -hold \$analysis_view\n"
# append command " report_power_domains -power_domain \$domain -file $vars(rpt_dir)/\${domain_file}_\$analysis_view.rpt -bind_lib\n"
# append command " }\n"
# append command " set_db timing_analysis_check_type setup\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),report_power_domains $command]
if {$vars(flow) =="mmmc"} {
append commands "set_default_view -setup $vars(default_setup_view) -hold $vars(default_hold_view)\n"
}
}
if {[info exists comments]} {
if {$comments == ""} {
if {[info exists vars(comments)]} {
unset vars(comments)
}
} else {
set vars(comments) $comments
}
}
if {[info exists ucomments]} {
if {$ucomments == ""} {
if {[info exists vars(ucomments)]} {
unset vars(ucomments)
}
} else {
set vars(ucomments) $ucomments
}
}
set fcommands [FF_NOVUS::insert_comments]
append fcommands $commands
if {$vars(codegen)} {
return $fcommands
} else {
uplevel #0 eval $commands
}
}
proc run_place {{format 1}} {
global vars
global env
global errors
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
set vars(step) rcp
} else {
if {$vars(step) != "partition_place"} {
set vars(step) place
}
}
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_NOVUS::initialize_step place]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command $vars(step),initialize_step $command]
append commands "puts \"<FF> RUNNING PLACEMENT ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING PLACEMENT\n"
append commands "#\n"
}
if {[info exists vars(partition_list)] && ($vars(step) != "partition_place") && \
(([lsearch $vars(partition_list) $vars(design)] == -1) && $vars(enable_flexilm))} {
set command ""
append command "set_db opt_hier_opt_stage pre_cts\n"
append commands [FF::wrap_command $vars(step),set_hier_mode $command]
}
#########################################################################
# Load optional pre placement file (plug-in)
#########################################################################
append commands [FF::source_plug pre_place_tcl]
#########################################################################
# Run standard cell placement or load placement plug-in
#########################################################################
set command ""
if {[info exists vars(place_tcl)]} {
if {[file exists $vars(place_tcl)]} {
append command [FF::source_plug place_tcl]
} else {
set errors($vars(error_count)) "Plug-in vars(place_tcl) defined but the file does not exist"
incr vars(error_count)
# set vars(abort) 1
}
} else {
if {[info exists vars(sdp_files)]} {
foreach file $vars(sdp_files) {
append command "#read_sdp_file -file $file -hier_path <instance> -origin <x y> -left_over_group <true | false>\n"
}
append command "#plan_design -user_sdp_group\n"
}
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
append command "place_design \n"
} else {
if {$vars(place_opt_design)} {
# if {[info exists vars(hier)]} {
# if {($vars(top) && $vars(enable_flexilm))} {
# append command "place_design "
# if {[info exists vars(no_pre_place_opt)] && $vars(no_pre_place_opt)} {
# append command " -no_pre_place_opt"
# }
# append command "\n"
# } else {
# append command "place_opt_design -report_dir $vars(rpt_dir) -report_prefix $vars(step)\n"
# }
# } else {
append command "place_opt_design -report_dir $vars(rpt_dir) -report_prefix $vars(step)\n"
# }
} else {
append command "place_design "
if {($vars(step) == "partition_place") && $vars(use_flexmodels)} {
append command " -no_pre_place_opt"
} else {
if {[info exists vars(no_pre_place_opt)] && $vars(no_pre_place_opt)} {
append command " -no_pre_place_opt"
}
}
append command "\n"
}
}
}
if {[info exist vars(parent)] && ($vars(parent) != "rc") && $vars(rc) && $vars(enable_rcp)} {
set command "eco_place\n"
append commands [FF::wrap_command $vars(step),eco_place $command]
} else {
# if {[info exists vars(hier_case)] && [regexp "^1" $vars(hier_case)]} {
# append commands [FF::wrap_command $vars(step),place_design "place_design -no_pre_place_opt\n"]
# } else {
append commands [FF::wrap_command $vars(step),place_design $command]
# }
}
#########################################################################
# Load optional post placement file (plug-in)
#########################################################################
append commands [FF::source_plug post_place_tcl 0]
#########################################################################
# Add tie cells for logic 0/1 nets
#########################################################################
set command [FF_NOVUS::add_tie_cells false true]
append commands [FF::wrap_command $vars(step),add_tie_cells $command]
###############################################################################
# Check post-place timing
###############################################################################
if {![regexp "place_opt_design" $commands] && ($vars(step) == "place")} {
if {![info exists vars(time_design_options,setup)]} {
set command "time_design -pre_cts -report_prefix place -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design %s -pre_cts -report_prefix place -report_dir $vars(rpt_dir)\n" $vars(time_design_options,setup)]
}
}
# if {($vars(step) == "partition_place") && $vars(use_flexmodels)} {
# if {![regexp "proto" $command]} {
# regsub "time_design" $command "time_design -proto" command
# }
# }
# append commands [FF::wrap_command $vars(step),time_design $command]
if {($vars(user_mode) == "hier") && $vars(place_opt_design) && ($vars(step) != "partition_place")} {
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1)} {
if {$vars(enable_flexilm)} {
set command "write_ilm -opt_stage prects -type_flex_ilm flexIlm -to_dir \[get_db designs .name\].flexilm\n"
append commands [FF::wrap_command $vars(step),write_flex_ilm $command]
} else {
if {!$vars(black_box)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "write_ilm -opt_stage prects -type_flex_ilm ilm -model_type timing -to_dir \[get_db designs .name\].ilm -hold\n"
} else {
set command "write_ilm -opt_stage prects -type_flex_ilm ilm -model_type timing -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
}
}
append commands [FF::wrap_command $vars(step),write_ilm $command]
}
} else {
if {$vars(enable_flexilm)} {
# Re-assign pins based on new netlist changes
if {[lindex [split $vars(version) "."] 0] < 16} {
set command ""
append command "route_trial\n"
append commands [FF::wrap_command $vars(step),trial_route1 $command]
} else {
set command ""
append command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route1 $command]
}
set command ""
append command "time_design -pre_cts -report_dir $vars(rpt_dir) -report_prefix assemble_flexilm\n"
append commands [FF::wrap_command $vars(step),time_design $command]
set command ""
append command "assign_partition_pins\n"
append commands [FF::wrap_command $vars(step),assign_partition_pins $command]
set command ""
append command "check_pin_assignment\n"
append commands [FF::wrap_command $vars(step),check_pin_assignment $command]
if {[lindex [split $vars(version) "."] 0] < 16} {
set command ""
append command "set_db route_trial_honor_pin true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode2 $command]
set command ""
append command "route_trial\n"
append commands [FF::wrap_command $vars(step),trial_route2 $command]
} else {
set command ""
append command "set_db route_early_global_honor_partition_pin .\n"
append commands [FF::wrap_command $vars(step),set_route_mode2 $command]
set command ""
append command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route2 $command]
}
set command ""
append command "create_timing_budget\n"
append commands [FF::wrap_command $vars(step),create_timing_budget $command]
set command ""
set dirs ""
foreach block $vars(partition_list) {
append dirs "\\\n -golden_block_dir ../$block/$vars(dbs_dir)/place.enc "
}
# append command "update_partition \\\n -flex_ilm_eco $dirs \\\n -flex_ilm_dir ../../$vars(partition_dir)_PRECTS/ \\\n -post_eco_suffix post_eco -pin_location\n"
append command "update_partition \\\n -flex_ilm_eco $dirs \\\n -flex_ilm_dir ../../$vars(partition_dir)_FLEXILM/ \\\n -post_eco_suffix post_eco -pin_location\n"
append commands [FF::wrap_command $vars(step),update_partition $command]
}
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_prects {{format 1}} {
global vars
global env
global errors
global warnings
if {$vars(place_opt_design)} {
# if {!(($vars(user_mode) == "hier") && ([file tail [pwd]] == $vars(top_cell) && $vars(enable_flexilm)))} {
return ""
# } else {
# set warnings($vars(warning_count)) "Feature vars(place_opt_design) not support for top level implementation when vars(enable_flexilm) is true"
# incr vars(warning_count)
# }
}
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
set vars(step) rcp
} else {
set vars(step) prects
}
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_NOVUS::initialize_step prects]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command $vars(step),initialize_step $command]
append commands "puts \"<FF> RUNNING PRE-CTS OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING PRE-CTS OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load optional pre CTS file (plug-in)
#########################################################################
append commands [FF::source_plug pre_prects_tcl]
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
return $commands
}
#########################################################################
# Run pre-CTS optimization
#########################################################################
if {([info exists vars(partition_list)]) && ([file tail [file dirname [pwd]]] == "$vars(partition_dir)")} {
set ptn [file tail [pwd]]
if {([lsearch $vars(partition_list) $ptn] == -1) && $vars(enable_flexilm)} {
# Top level flow for flexIlm
# Read Power Intent here ...
set command ""
foreach block $vars(partition_list) {
append command "set_partition_pin_status -partition $block -pins * -status unplaced\n"
}
append commands [FF::wrap_command $vars(step),set_partition_pin_status $command]
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "set_db route_trial_honor_pin false\nset_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode1 $command]
} else {
append command "set_db route_early_global_honor_partition_pin {}\nset_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode1 $command]
}
set command ""
append command "set_db opt_hier_opt_stage preCTS\n"
append commands [FF::wrap_command $vars(step),set_hier_mode $command]
# set command ""
# append command "set_db opt_handle_partition_complex true\n"
# append commands [FF::wrap_command $vars(step),set_opt_mode $command]
# set command ""
# append command "opt_design -pre_cts -report_dir $vars(rpt_dir) -report_prefix flexilm\n"
# append commands [FF::wrap_command $vars(step),opt_design $command]
} else {
# Non flexIlm top flow and partition flow
set command "opt_design -pre_cts -report_dir $vars(rpt_dir) -report_prefix prects\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
}
} else {
# Flat flow
set command "opt_design -pre_cts -report_dir $vars(rpt_dir) -report_prefix prects\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
}
#########################################################################
# Load optional post CTS file (plug-in)
#########################################################################
set command ""
append commands [FF::source_plug post_prects_tcl 0]
if {($vars(user_mode) == "hier")} {
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1) && !$vars(place_opt_design)} {
if {$vars(enable_flexilm)} {
set command "write_ilm -opt_stage prects -type_flex_ilm flexIlm -to_dir \[get_db designs .name\].flexilm\n"
append commands [FF::wrap_command $vars(step),create_flex_ilm $command]
} else {
if {!$vars(black_box)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "write_ilm -opt_stage prects -type_flex_ilm ilm -to_dir \[get_db designs .name\].ilm\n"
} else {
set command "write_ilm -opt_stage prects -type_flex_ilm ilm -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
}
}
append commands [FF::wrap_command $vars(step),write_ilm $command]
}
} else { ; # Top level unconditional (no place_opt_design support) ...
if {$vars(enable_flexilm)} {
set command ""
append command "write_db $vars(dbs_dir)/prects_flexilm.enc\n"
append commands [FF::wrap_command $vars(step),save_design $command]
# Re-assign pins based on new netlist changes
if {[lindex [split $vars(version) "."] 0] < 16} {
set command ""
append command "route_trial\n"
append commands [FF::wrap_command $vars(step),trial_route1 $command]
} else {
set command ""
append command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route1 $command]
}
set command ""
append command "time_design -pre_cts -report_dir $vars(rpt_dir) -report_prefix prects_flexilm\n"
append commands [FF::wrap_command $vars(step),time_design $command]
set command ""
append command "assign_partition_pins\n"
append commands [FF::wrap_command $vars(step),assign_partition_pins $command]
set command ""
append command "check_pin_assignment\n"
append commands [FF::wrap_command $vars(step),check_pin_assignment $command]
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "set_db route_trial_honor_pin true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode2 $command]
set command ""
append command "route_trial\n"
append commands [FF::wrap_command $vars(step),trial_route2 $command]
} else {
append command "set_db route_early_global_honor_partition_pin .\n"
append commands [FF::wrap_command $vars(step),set_route_mode2 $command]
set command ""
append command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route2 $command]
}
# set command ""
# append command "set_db budget_enable_mt_budgeting true\n"
# append commands [FF::wrap_command $vars(step),set_budgeting_mode $command]
set command ""
append command "create_timing_budget\n"
append commands [FF::wrap_command $vars(step),create_timing_budget $command]
set command ""
set dirs ""
foreach block $vars(partition_list) {
if {$vars(place_opt_design)} {
append dirs "\\\n -golden_block_dir ../$block/$vars(dbs_dir)/place.enc "
} else {
append dirs "\\\n -golden_block_dir ../$block/$vars(dbs_dir)/prects.enc "
}
}
# append command "update_partition \\\n -flex_ilm_eco $dirs \\\n -flex_ilm_dir ../../$vars(partition_dir)_PRECTS/ \\\n -post_eco_suffix post_eco -pin_location\n"
append command "update_partition \\\n -flex_ilm_eco $dirs \\\n -flex_ilm_dir ../../$vars(partition_dir)_FLEXILM/ \\\n -post_eco_suffix post_eco -pin_location\n"
append commands [FF::wrap_command $vars(step),update_partition $command]
}
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_cts {{format 1}} {
global vars
global errors
if {$vars(skip_cts)} {
return ""
}
set vars(step) cts
set commands ""
set ucomments ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_NOVUS::initialize_step cts]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command cts,initialize_step $command]
set vars(only_options) true
if {[regexp "^ccopt" $vars(cts_engine)]} {
set command [FF_NOVUS::initialize_step postcts]
append commands [FF::wrap_command postcts,initialize_step $command]
if {$vars(postcts_setup_hold)} {
set command [FF_NOVUS::initialize_step postcts_hold]
append commands [FF::wrap_command postcts_hold,initialize_step $command]
}
}
set vars(only_options) false
if {$vars(top) && ($vars(user_mode) == "hier") && ($vars(hier_flow_type) == "2pass") && $vars(enable_flexilm)} {
# Read Power Intent here ...
set command ""
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)] && ($vars(codegen) || [file isdirectory $vars($part,ilm_dir)])} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "read_ilm -cell $part -dir $vars($part,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "read_ilm -cell $part -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
} else {
append command "read_ilm -cell $part -directory $vars($part,ilm_dir)\n"
}
}
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "read_ilm -cell $part\n"
} else {
append command "read_ilm -cell $part -directory ../$part/$part.ilm\n"
}
}
}
if {$command != ""} {
# append commands [FF::wrap_command $vars(step),specify_ilm "$command\nset_db ilm_keep_flatten true\n"]
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
set command [FF_NOVUS::initialize_timing mmmc]
# if {![info exists vars(cpf_file)] || ([info exists vars(cpf_file)] && !$vars(cpf_timing)) } {
append commands [FF::wrap_command $vars(step),initialize_timing $command]
# } else {
# set defer_commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
append commands [FF_NOVUS::load_power_intent]
}
append commands "puts \"<FF> RUNNING CLOCK TREE SYNTHESIS ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING CLOCK TREE SYNTHESIS\n"
append commands "#\n"
}
#########################################################################
# Load pre-CTS file (plug-in)
#########################################################################
if {$vars(cts_engine) == "cts"} {
append commands [FF::source_plug pre_cts_tcl]
}
#########################################################################
# Run CTS
#------------------------------------------------------------------------
# Generate the clock tree using clockDesign which:
# - loads the clock specification file
# - removes existing buffers in the clock tree (not marked don't touch);
# if a clock tree has been previously inserted, use changeClockStatus
# to unfix the tree so that it can be removed
# - unfixes the clock nets after tree insertion
# Need to make sure the clock gating cells are usable during clockDesign.
# Disable them afterwards.
#########################################################################
set clock_gate_cells [list]
set command ""
if {[info exists vars(clock_gate_cells)]} {
append command "set_interactive_constraint_modes \[all_constraint_modes -active\]\n"
set clock_gate_cells $vars(clock_gate_cells)
foreach cell $clock_gate_cells {
append command "set_dont_use false $cell\n"
}
}
append commands [FF::wrap_command cts,enable_clock_gate_cells $command]
#########################################################################
# Run CTS
#########################################################################
set command ""
#########################################################################
# Run ccoptDesign ... convert to propagated timing first in scripted integration
#########################################################################
if {[info exists vars(cts_tcl)]} {
if {[file exists $vars(cts_tcl)]} {
append commands [FF::source_plug pre_cts_tcl]
append commands [FF::source_plug cts_tcl]
} else {
set errors($vars(error_count)) "Plug-in vars(cts_tcl) defined but the file does not exist"
incr vars(error_count)
}
} else {
set is_native [expr {$vars(ccopt_integration) == "native"}]
set command [FF_NOVUS::update_timing mmmc [expr !$is_native]]
append commands [FF::wrap_command cts,update_timing $command]
set command [FF_NOVUS::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
append commands [FF::source_plug pre_cts_tcl]
if {[regexp "^ccopt" $vars(cts_engine)]} {
append commands [FF::source_plug pre_postcts_tcl 0]
if {$vars(postcts_setup_hold)} {
append commands [FF::source_plug pre_postcts_hold_tcl]
}
}
# Create a CCOpt clock tree spec if running with native integration
if {$vars(ccopt_effort) != "low"} {
# append commands [FF::wrap_command $vars(step),set_ccopt_mode "set_ccopt_mode -effort $vars(ccopt_effort)\n"]
append commands [FF::wrap_command $vars(step),set_ccopt_effort "set_ccopt_effort -effort $vars(ccopt_effort)\n"]
}
set ccopt_command "ccopt_design"
if {$vars(postcts_setup_hold)} {
append ccopt_command " -hold"
}
set command "create_clock_tree_spec\n"
append commands [FF::wrap_command cts,create_clock_tree_spec $command]
append ccopt_command "\n"
append commands [FF::wrap_command cts,ccopt_design $ccopt_command]
}
#########################################################################
# Load optional post CTS file (plug-in)
#########################################################################
append commands [FF::source_plug post_cts_tcl 0]
if {[regexp "^ccopt" $vars(cts_engine)]} {
append commands [FF::source_plug post_postcts_tcl 0]
if {$vars(postcts_setup_hold)} {
append commands [FF::source_plug post_postcts_hold_tcl]
}
}
#########################################################################
# Reset clock gating cell usage
#########################################################################
###############################################################################
# Check post-cts timing
###############################################################################
if {![info exists vars(time_design_options,setup)]} {
set command "time_design -postcts -report_prefix cts -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design -postcts -report_prefix cts -report_dir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
append commands [FF::wrap_command cts,time_design $command]
if {($vars(hier_flow_type) == "2pass") && !$vars(enable_flexilm)} {
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "write_ilm -opt_stage postcts -type_flex_ilm ilm -to_dir \[get_db designs .name\].ilm\n"
} else {
set command "write_ilm -opt_stage postcts -type_flex_ilm ilm -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
}
append commands [FF::wrap_command $vars(step),write_ilm $command]
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postcts {{format 1}} {
global vars
global env
global errors
if {$vars(skip_cts)} { return "" }
# if {[regexp "^ccopt" [string tolower $vars(cts_engine)]]} {
# return ""
# }
if {[string tolower $vars(cts_engine)] == "ccopt"} {
return ""
}
set vars(step) postcts
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_NOVUS::initialize_step postcts]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command postcts,initialize_step $command]
###############################################################################
# Specify the ILM models for the top partition (only for 2pass flow)
###############################################################################
if {$vars(top) && ($vars(user_mode) == "hier") && ($vars(hier_flow_type) == "2pass") && !$vars(enable_flexilm)} {
# if {!$(vars(black_box)} {
set command ""
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)] && ($vars(codegen) || [file isdirectory $vars($part,ilm_dir)])} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
}
}
} else {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
}
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
if {$vars(flow) == "mmmc"} {
set command [FF_NOVUS::update_timing mmmc]
append commands [FF::wrap_command postcts,update_timing $command]
set command [FF_NOVUS::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
} else {
set command [FF_NOVUS::update_timing minmax]
append commands [FF::wrap_command postcts,update_timing $command]
set command [FF_NOVUS::derate_timing minmax]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
if {[file exists $vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
# }
# set command [FF_NOVUS::initialize_timing mmmc]
# if {![info exists vars(cpf_file)]} {
# append commands [FF::wrap_command $vars(step),initialize_timing $command]
# } else {
# set defer_commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
}
append commands "puts \"<FF> RUNNING POST-CTS OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-CTS OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load optional pre postCTS file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postcts_tcl]
if {$vars(cts_engine) == "ccopt" && $vars(ccopt_integration) == "native"} {
set command "puts \"<FF> NO POST-CTS OPTIMIZATION REQUIRED FOR CCOPT NATIVE INTEGRATION\"\n"
append commands [FF::wrap_command postcts,opt_design $command]
} else {
#########################################################################
# Run post-CTS optimization
#########################################################################
set command "opt_design -post_cts -report_dir $vars(rpt_dir) -report_prefix postcts\n"
append commands [FF::wrap_command postcts,opt_design $command]
}
#########################################################################
# Load optional post postCTS file (plug-in)
#########################################################################
append commands [FF::source_plug post_postcts_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postcts_hold {{format 1}} {
global vars
global env
global errors
if {$vars(skip_cts) || ([lsearch $vars(fix_hold) postcts] < 0) || $vars(postcts_setup_hold)} {
return ""
}
set vars(step) postcts_hold
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_NOVUS::initialize_step postcts_hold]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command postcts_hold,initialize_step $command]
append commands "puts \"<FF> RUNNING POST-CTS HOLD FIXING ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-CTS HOLD FIXING\n"
append commands "#\n"
}
#########################################################################
# Load pre-postCTS hold file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postcts_hold_tcl]
set command "opt_design -post_cts -hold -report_dir $vars(rpt_dir) -report_prefix postcts_hold\n"
append commands [FF::wrap_command postcts_hold,opt_design $command]
#########################################################################
# Load post-postCTS hold file (plug-in)
#########################################################################
append commands [FF::source_plug post_postcts_hold_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_route {{format 1}} {
global vars
global env
global errors
set vars(step) route
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_NOVUS::initialize_step route]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command route,initialize_step $command]
set command [FF_NOVUS::add_filler_cells]
append commands [FF::wrap_command route,add_filler_cells $command]
append commands "puts \"<FF> RUNNING GLOBAL/DETAIL ROUTING ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING GLOBAL/DETAIL ROUTING\n"
append commands "#\n"
}
#########################################################################
# Load optional pre route file (plug-in)
#########################################################################
append commands [FF::source_plug pre_route_tcl]
set command [FF_NOVUS::route_secondary_pg_nets]
append commands [FF::wrap_command route,route_secondary_pg_nets $command]
set command "check_place $vars(rpt_dir)/$vars(step),check_place.rpt\n"
append commands [FF::wrap_command route,check_place $command]
#########################################################################
# Route the design
#########################################################################
set command ""
set args ""
if {($vars(enable_ocv) == "pre_postroute") || ($vars(enable_ocv) == "pre_postcts")} {
# if {$vars(flow) != "default"} {
append comments "# - vars(enable_ocv)\n"
append args "set_db timing_analysis_type ocv\n"
# }
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "set_db timing_analysis_aocv true\n"
} else {
append ucomments "# - vars(enable_aocv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
}
if {$args != ""} {
set command "$args\n"
append commands [FF::wrap_command route,set_analysis_mode $command]
}
if {[info exists vars(postroute_spread_wires)] && !$vars(postroute_spread_wires)} {
append commands "set_db route_design_detail_post_route_spread_wire false\n"
}
set command "route_design"
if {$vars(track_opt)} {
append comments "# - vars(track_opt)\n"
append command " -track_opt"
} else {
append ucomments "# - vars(track_opt)\n"
}
append commands [FF::wrap_command route,route_design "$command\n"]
#########################################################################
# Run ckECO if requested
#########################################################################
if {[info exists vars(clock_eco)] && (($vars(clock_eco) == "post_route") || ($vars(clock_eco) == "both"))} {
set command [FF_NOVUS::run_clock_eco post_route]
append commands [FF::wrap_command route,run_clock_eco $command]
}
#########################################################################
# Optionally run wire spreading
#########################################################################
if {[regsub "nm" $vars(process) ""] >= 16} {
if {[info exists vars(postroute_spread_wires)] && $vars(postroute_spread_wires)} {
set command "set_db route_design_detail_post_route_spread_wire true\nset_db route_with_timing_driven false\n"
append command "routeDesign -wireOpt\n"
append command "set_db route_design_detail_post_route_spread_wire false\n"
append commands [FF::wrap_command route,spread_wires $command]
}
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
file mkdir $vars(rpt_dir)/LPA/DMC
set command "check_litho -routing_layers_only -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command route,verify_litho $command]
}
#########################################################################
# Set extraction mode to postroute
#########################################################################
set command "set_db extract_rc_engine post_route\n"
if {![catch {set arg $vars(postroute_extraction_effort)}]} {
append comments "# - vars(postroute_extraction_effort)\n"
append command "set_db extract_rc_effort_level $arg\n"
} else {
append ucomments "# - vars(postroute_extraction_effort)\n"
}
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command "set_db extract_rc_total_cap_threshold $arg\n"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command "set_db extract_rc_relative_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command "set_db extract_rc_coupling_cap_threshold $arg\n"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command "set_db extract_rc_lef_tech_file_map $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command route,set_extract_rc_mode $command]
#########################################################################
# Load optional post route file (plug-in)
#########################################################################
append commands [FF::source_plug post_route_tcl 0]
#########################################################################
# Update to MMMC if flow is "pr_mmmc"
#########################################################################
if {$vars(flow) != "default"} {
if {$vars(flow) == "pr_mmmc"} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command route,initialize_timing $command]
}
}
if {![info exists vars(time_design_options,setup)]} {
set command "time_design -post_route -report_prefix route -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design -post_route -report_prefix route -report_dir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
append commands [FF::wrap_command route,time_design $command]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postroute {{format 1}} {
global vars
global env
global errors
set vars(step) postroute
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_NOVUS::initialize_step postroute]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command postroute,initialize_step $command]
if {$vars(metalfill) == "pre_postroute"} {
set command [FF::source_plug metalfill_tcl]
append commands [FF::wrap_command postroute,add_metalfill $command]
}
#########################################################################
# Run ckECO if requested
#########################################################################
if {[info exists vars(clock_eco)] && (($vars(clock_eco) == "post_route") || ($vars(clock_eco) == "both"))} {
set command [FF_NOVUS::run_clock_eco post_route]
append commands "puts \"<FF> RUNNING POST-ROUTE CLOCK ECO ...\"\n"
append commands [FF::wrap_command route,run_clock_eco $command]
}
append commands "puts \"<FF> RUNNING POST-ROUTE OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-ROUTE OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load optional pre postroute file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postroute_tcl]
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
append commands "opt_leakage_power -fix_timing_only\n"
}
if {$vars(postroute_setup_hold)} {
append commands [FF::source_plug pre_postroute_hold_tcl]
set command "opt_design -post_route -report_dir $vars(rpt_dir) -report_prefix postroute -setup -hold\n"
} else {
set command "opt_design -post_route -report_dir $vars(rpt_dir) -report_prefix postroute\n"
}
append commands [FF::wrap_command postroute,opt_design $command]
#########################################################################
# Trim metal fill if added
#########################################################################
if {$vars(metalfill) == "pre_postroute"} {
set command "trim_metal_fill\n"
append commands [FF::wrap_command postroute,trim_metal_fill $command]
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command postroute,verify_litho $command]
}
#########################################################################
# Load optional post postRoute file (plug-in)
#########################################################################
append commands [FF::source_plug post_postroute_tcl 0]
if {$vars(postroute_setup_hold)} {
append commands [FF::source_plug post_postroute_hold_tcl]
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postroute_hold {{format 1}} {
global vars
global env
global errors
if {[lsearch $vars(fix_hold) postroute] < 0} {
return ""
}
#########################################################################
# Initialize step ...
#########################################################################
set vars(step) postroute_hold
set commands ""
# append commands "set vars(step) $vars(step)\n"
set command [FF_NOVUS::initialize_step postroute_hold]
append commands [FF_NOVUS::insert_comments]
append commands [FF::wrap_command postroute_hold,initialize_step $command]
append commands "puts \"<FF> RUNNING POST-ROUTE HOLD FIXING ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-ROUTE HOLD FIXING\n"
append commands "#\n"
}
#########################################################################
# Load optional pre postRoute hold file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postroute_hold_tcl]
set command "opt_design -post_route -hold"
append command " -report_dir $vars(rpt_dir) -report_prefix postroute_hold\n"
append commands [FF::wrap_command postroute_hold,opt_design $command]
#########################################################################
# Trim metal fill if added
#########################################################################
if {$vars(metalfill) == "pre_postroute"} {
set command "trim_metal_fill\n"
append commands [FF::wrap_command postroute_hold,trim_metal_fill $command]
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command postroute_hold,verify_litho $command]
}
#########################################################################
# Load optional post postRoute hold file (plug-in)
#########################################################################
append commands [FF::source_plug post_postroute_hold_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_signoff {{format 1}} {
global vars
global env
global errors
global env
if {$vars(step) != "assemble"} {
set vars(step) signoff
}
set commands ""
###############################################################################
# Optionally verify/fix litho
###############################################################################
if {$vars(fix_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append command "setNanoRouteMode -droutePostRouteLithoRepair true \\\n"
append command " -drouteMinimizeTopologyChange true\n"
append command "globalDetailRoute\n"
append command "writeHif -file $vars(rpt_dir)/LPA/incr_verify.hif\n"
append command "verifyLitho -signOff \\\n"
append command " -dir $vars(dbs_dir)/LPA2 \\\n"
append command " -cpu $vars(local_cpus) \\\n"
append command " -config $vars(lpa_conf_file) \\\n"
append command " -incrCheck $vars(rpt_dir)/LPA/incr_verify.hif\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA2/DMC/merged.hif\n"
append commands [FF::wrap_command signoff,fix_litho $command]
}
###############################################################################
# Load optional metalfill plug-in
###############################################################################
if {$vars(metalfill) == "pre_signoff"} {
set command [FF::source_plug metalfill_tcl]
append commands [FF::wrap_command signoff,add_metalfill $command]
}
set command [FF_NOVUS::initialize_step signoff]
append commands [FF_NOVUS::insert_comments]
# append commands [FF::wrap_command signoff,initialize_step $command]
append commands $command
###############################################################################
# Load optional pre signoff file (plug-in)
###############################################################################
append commands [FF::source_plug pre_signoff_tcl]
###############################################################################
# Run RC Extraction
###############################################################################
append commands "puts \"<FF> RUNNING FINAL SIGNOFF ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING FINAL SIGNOFF\n"
append commands "#\n"
}
set command "extract_rc\n"
append commands [FF::wrap_command signoff,extract_rc $command]
###############################################################################
# Dump SPEF for signoff STA
###############################################################################
if {$vars(skip_signoff_checks)} {
set command ""
foreach corner $vars(rc_corners) {
append command "write_parasitics -rc_corner $corner -spef_file $corner.spef.gz\n"
}
} else {
set command "foreach corner \$vars(active_rc_corners) {\n"
append command " write_parasitics -rc_corner \$corner -spef_file \$corner.spef.gz\n"
append command "}\n"
}
append commands [FF::wrap_command signoff,dump_spef $command]
if {$vars(step) == "assemble" &&
[info exists vars(enable_signoff_eco)] && $vars(enable_signoff_eco)} {
set command "time_signoff -report_only -no_eco_db\n"
append commands [FF::wrap_command signoff,time_signoff $command]
} else {
if {$vars(enable_si_aware)} {
if {![info exists vars(time_design_options,setup)]} {
set command "time_design -report_prefix signoff -sign_off -report_only -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design -report_prefix signoff -sign_off -report_only -report_dir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
} else {
if {![info exists vars(time_design_options,setup)]} {
set command "time_design -report_prefix signoff -sign_off -si -report_only -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design -report_prefix sign_off -signoff -si -report_only -report_dir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
}
append commands [FF::wrap_command signoff,time_design_setup $command]
if {$vars(enable_si_aware)} {
if {![info exists vars(time_design_options,hold)]} {
set command "time_design -report_prefix signoff -sign_off -report_only -hold -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design -report_prefix signoff -sign_off -report_only -hold -report_dir $vars(rpt_dir) %s\n" $vars(time_design_options,hold)]
}
} else {
if {![info exists vars(time_design_options,hold)]} {
set command "time_design -report_prefix signoff -sign_off -si -report_only -hold -report_dir $vars(rpt_dir)\n"
} else {
set command [format "time_design -report_prefix sign_off -signoff -si -report_only -hold -report_dir $vars(rpt_dir) %s\n" $vars(time_design_options,hold)]
}
}
append commands [FF::wrap_command signoff,time_design_hold $command]
}
###############################################################################
# Dump GDS and/or OA data base
###############################################################################
if {[info exists vars(gds_layer_map)]} {
set command "write_stream $vars(design).gds.gz -map_file $vars(gds_layer_map) "
if {[info exists vars(gds_files)]} {
append command "-merge { "
foreach file $vars(gds_files) {
if {[file exists $file]} {
append command "$file "
} else {
puts "<FF> WARNING: GDS FILE $file DOES NOT EXIST .... SKIPPING\n"
}
}
append command "}"
}
append command "\n"
append commands [FF::wrap_command signoff,stream_out $command]
}
if {[info exists vars(oasis_layer_map)]} {
set command "write_oasis $vars(design).oasis.gz -map_file $vars(oasis_layer_map) "
if {[info exists vars(oasis_files)]} {
append command "-merge { "
foreach file $vars(oasis_files) {
if {[file exists $file]} {
append command "$file "
} else {
puts "<FF> WARNING: OASIS FILE $file DOES NOT EXIST .... SKIPPING\n"
}
}
append command "}"
}
append command "\n"
append commands [FF::wrap_command signoff,oasis_out $command]
}
###############################################################################
# Dump Model for Top Level (Hierarchical Flow Only)
###############################################################################
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)]} {
if {([lsearch $vars(partition_list) $ptn] != -1)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "write_ilm -opt_stage postcts -type_flex_ilm ilm -to_dir \[get_db designs .name\].ilm\n"
} else {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "write_ilm -opt_stage postcts -type_flex_ilm ilm -oa_cellview {$vars(oa_partition_lib) \[get_db designs .name\] ilm}\n"
} else {
set command "write_ilm -opt_stage postcts -type_flex_ilm ilm -to_dir \[get_db designs .name\].ilm\n"
}
}
append commands [FF::wrap_command signoff,write_ilm $command]
} elseif {$vars(step) != "assemble"} {
append commands [FF::wrap_command signoff,unflatten_ilm "unflatten_ilm\n"]
}
}
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING VERIFY COMMANDS\n"
append commands "#\n"
}
###############################################################################
# Run verify commands
###############################################################################
if {!([info exists vars(enable_signoff_eco)] && $vars(enable_signoff_eco))} {
set command "report_summary -out_dir $vars(rpt_dir)\n"
append commands [FF::wrap_command signoff,report_summary $command]
}
set command "check_connectivity\n"
append commands [FF::wrap_command signoff,check_connectivity $command]
set command "check_drc\n"
append commands [FF::wrap_command signoff,check_drc $command]
set command "check_metal_density\n"
append commands [FF::wrap_command signoff,check_metal_density $command]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1)} {
if {[string compare $vars(dbs_format) "fe"]==0} {
set command "check_process_antenna -lef_file $ptn.antenna.lef\n"
} else {
set command "check_process_antenna\n"
# Not sure yet how save_abstract would be called- skip this for now.
}
} else {
set command "check_process_antenna\n"
}
append commands [FF::wrap_command signoff,verify_process_antenna $command]
if {([info exists vars(enable_lvs)] && $vars(enable_lvs)) && ($vars(dbs_format) == "oa")} {
append commands [FF_EDI::create_lvs_data]
}
if {$vars(novus)} {
append commands "set_flowkit_write_db_args -def\n"
}
###############################################################################
# Load optional post signoff file (plug-in)
###############################################################################
append commands [FF::source_plug post_signoff_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_assemble {{format 1}} {
global vars
global errors
global env
set vars(step) assemble
set commands ""
append commands "set vars(step) $vars(step)\n"
FF_NOVUS::initialize_step assemble
# if {$vars(report_run_time)} {
# append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
# }
if {$vars(verbose)} {
append commands "#\n"
append commands "# ASSEMBLING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre assemble" plug-in script
###############################################################################
append commands [FF::source_plug pre_assemble_tcl]
###############################################################################
# Assemble the design
###############################################################################
set vars(ilm) false
set ilm_list [list]
set pac_list [list]
if {$vars(enable_pac)} {
foreach part $vars(partition_list) {
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "ilm"} {
lappend ilm_list $part
} else {
lappend pac_list $part
}
}
}
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
foreach ilm $vars(ilm_list) {
if {([lsearch $ilm_list $ilm] == -1) && ([lsearch $pac_list $ilm] == -1)} {
lappend ilm_list $ilm
}
}
}
if {$ilm_list != ""} {
set vars(ilm) true
}
if {$vars(hier_flow_type) == "2pass"} {
set partition_dir $vars(partition_dir_pass2)
} else {
set partition_dir $vars(partition_dir)
}
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_NOVUS::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
if {([string compare -nocase $vars(dbs_format) "oa"]==0) && ([lindex [split $vars(version) "."] 0] > 10)} {
if {[info exists vars($vars(design),assemble_step)]} {
set command "assemble_design -top_design {$vars(oa_partition_lib) $vars(design) $vars($vars(design),assemble_step)} -mmmc_file $mmmc_file"
} else {
set command "assemble_design -top_design {$vars(oa_partition_lib) $vars(design) signoff} -mmmc_file $mmmc_file"
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,assemble_step)]} {
append command "\\\n -block {$vars(oa_partition_lib) $part $vars($vars($part),assemble_step)}"
} else {
append command "\\\n -block {$vars(oa_partition_lib) $part signoff}"
}
}
}
} else {
# append commands [FF::wrap_command assemble,initialize_timing $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set assemble_command "assemble_design -power_intent_file $vars(cpf_file)"
} else {
set assemble_command "assemble_design -mmmc_file $mmmc_file"
}
} else {
set assemble_command "assemble_design"
}
if {[info exists vars($vars(design),assemble_dbs)]} {
set command "$assemble_command -top_dir $vars($vars(design),assemble_dbs)"
} elseif {[info exists vars($vars(design),assemble_step)]} {
set command "$assemble_command $partition_dir/$vars(design)/$dir/$vars($vars(design),assemble_step).enc"
} else {
if {$vars(generate_flow_steps)} {
set command "$assemble_command -top_dir $partition_dir/$vars(design)/$dir/top.top_signoff.enc "
} else {
set command "$assemble_command -top_dir $partition_dir/$vars(design)/$dir/signoff.enc "
}
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,assemble_dbs)]} {
append command "\\\n -block_dir $vars($part,assemble_dbs)"
} elseif {[info exists vars($part,assemble_step)]} {
append command "\\\n -block_dir $partition_dir/$part/$dir/$vars($part,assemble_step).enc"
} else {
if {$vars(generate_flow_steps)} {
append command "\\\n -block_dir $partition_dir/$part/$dir/block.signoff.enc"
} else {
append command "\\\n -block_dir $partition_dir/$part/$dir/signoff.enc"
}
}
}
}
}
if {$vars(enable_pac)} {
append command "\\\n -hierDir $vars(pac_scratch_dir)"
}
append command "\n\n"
append commands [FF::wrap_command assemble,assemble_design $command]
if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
append commands "source $mmmc_file\n"
}
if {$vars(flow) == "mmmc"} {
set command [FF_NOVUS::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] > 13} {
if {$vars(step) != "debug"} {
append commands "enable_metrics -on\n"
append commands "push_snapshot_stack\n"
}
}
}
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load "post assemble" plug-in script
###############################################################################
append commands [FF::source_plug post_assemble_tcl 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command assemble,specify_ilm $command]
if {[info exists vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command assemble,load_ilm_non_sdc_file $command]
}
}
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# if {[info exists vars(cpf_file)]} {
# set command "loadCPF $vars(cpf_file)\n"
# append commands [FF::wrap_command assemble,load_cpf $command]
# set command "commitCPF"
# if {$vars(cpf_keep_rows)} {
# append command " -keepRows"
# }
# if {$vars(cpf_power_domain)} {
# append command " -power_domain"
# }
# if {$vars(cpf_isolation)} {
# append command " -isolation"
# }
# if {$vars(cpf_state_retention)} {
# append command " -state_retention"
# }
# if {$vars(cpf_level_shifter)} {
# append command " -level_shifter"
# }
# if {$vars(cpf_power_switch)} {
# append command " -power_switch"
# }
# append command "\n"
# append commands [FF::wrap_command assemble,commit_cpf $command]
# }
# }
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command assemble,initialize_timing $command]
} elseif {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command assemble,initialize_timing $command]
}
set command [FF_NOVUS::update_timing mmmc ]
append commands [FF::wrap_command assemble,update_timing $command]
if {[info exists vars(enable_signoff_eco)] && $vars(enable_signoff_eco)} {
append commands [FF::source_plug pre_signoff_eco_tcl 0]
set command "check_connectivity\n"
append commands [FF::wrap_command assemble,pre_signoff_eco_verify_connectivity $command]
set command "check_drc\n"
append commands [FF::wrap_command assemble,pre_signoff_eco_verify_geometry $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING SIGN-OFF ECO\n"
append commands "#\n"
}
set command [FF_NOVUS::delete_filler_cells]
append commands [FF::wrap_command assemble,delete_filler_cells $command]
set command "extract_rc\n"
append commands [FF::wrap_command assemble,extract_rc $command]
set op [open ptn.txt w]
foreach ptn $vars(partition_list) {
puts $op "$ptn"
}
close $op
set command "set_db opt_signoff_partition_list_file \"ptn.txt\"\n"
append command "set_db opt_signoff_optimize_replicated_modules true\n"
append commands [FF::wrap_command assemble,set_signoff_mode $command]
set command "time_signoff -report_only\n"
append commands [FF::wrap_command assemble,time_signoff $command]
set command "opt_design_signoff -setup -no_eco_route\n"
append commands [FF::wrap_command assemble,signoff_opt_design $command]
set command "add_filler\n"
append commands [FF::wrap_command assemble,add_filler_cells $command]
set command "eco_route -handle_partition\n"
append commands [FF::wrap_command assemble,eco_route $command]
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command assemble,verify_litho $command]
}
append commands [FF::source_plug post_signoff_eco_tcl 0]
set command "check_connectivity\n"
append commands [FF::wrap_command assemble,post_signoff_eco_verify_connectivity $command]
set command "check_drc\n"
append commands [FF::wrap_command assemble,post_signoff_eco_verify_geometry $command]
} elseif {$vars(enable_pac)} {
set command "check_connectivity\n"
append commands [FF::wrap_command assemble,pre_pac_verify_connectivity $command]
set command "check_drc\n"
append commands [FF::wrap_command assemble,pre_pac_verify_geometry $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# DEFINING PAC MODES\n"
append commands "#\n"
}
append commands [FF::source_plug pre_pac_tcl 0]
set command ""
foreach part $pac_list {
append command "set hinst \[dbHInstName \[dbCellHInst \[dbGetCellByName $part\]\]\]\n"
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "read_only"} { set vars($part,pac_mode) "readOnly" }
append command "setModuleView -hinst \$hinst -type $vars($part,pac_mode)\n"
}
}
append command "getModuleView\n"
append commands [FF::wrap_command assemble,set_module_view $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST ASSEMBLY CLOSURE\n"
append commands "#\n"
}
# set command [FF_NOVUS::delete_filler_cells]
# append commands [FF::wrap_command assemble,delete_filler_cells $command]
set command "opt_design -post_route -report_dir $vars(rpt_dir) -report_prefix pac\n"
append commands [FF::wrap_command assemble,opt_design $command]
# set command [FF_NOVUS::add_filler_cells]
# append commands [FF::wrap_command assemble,add_filler_cells $command]
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command assemble,verify_litho $command]
}
append commands [FF::source_plug post_pac_tcl 0]
set command "check_connectivity\n"
append commands [FF::wrap_command assemble,post_pac_verify_connectivity $command]
set command "check_drc\n"
append commands [FF::wrap_command assemble,post_pac_verify_geometry $command]
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
append commands [FF_NOVUS::run_signoff $format]
# if {$vars(makefile)} {
# append commands "if {\[info exists env(VPATH)\]} {\n"
# append commands "exec /bin/touch \$env(VPATH)/assemble\n"
# append commands "}\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_rebudget {{format 1}} {
global vars
global errors
global env
set vars(step) rebudget
set commands ""
# append commands "set vars(step) $vars(step)\n"
FF_NOVUS::initialize_step $vars(step)
# if {$vars(report_run_time)} {
# append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
# }
if {!$vars(enable_flexilm)} {
append commands "\nif {\[file isfile $vars(pac_scratch_dir)/.pacFlowLock\]} {\n"
append commands " file delete $vars(pac_scratch_dir)/.pacFlowLock\n"
append commands "}\n"
} else {
# append commands "if {\[file isfile $vars(script_dir)/view_definition.tcl]} {\n"
# append commands " file copy -force $vars(script_dir)/view_definition.tcl $vars(partition_dir)/$vars(design)/viewDefinition.tcl\n"
# append commands "}\n"
}
if {$vars(verbose)} {
append commands "#\n"
append commands "# ASSEMBLING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre rebudget" plug-in script
###############################################################################
append commands [FF::source_plug pre_rebudget_tcl]
###############################################################################
# Get the FlexILM ECO paths
###############################################################################
if {$vars(enable_flexilm)} {
append commands "if {\[file isfile \$env(VPATH)/flexilm\]} {\n"
append commands " source \$env(VPATH)/flexilm\n"
append commands "}\n"
}
###############################################################################
# Assemble the design
###############################################################################
set vars(ilm) false
set ilm_list [list]
set pac_list [list]
if {$vars(enable_pac)} {
foreach part $vars(partition_list) {
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "ilm"} {
lappend ilm_list $part
} else {
lappend pac_list $part
}
}
}
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
foreach ilm $vars(ilm_list) {
if {([lsearch $ilm_list $ilm] == -1) && ([lsearch $pac_list $ilm] == -1)} {
lappend ilm_list $ilm
}
}
}
if {$ilm_list != ""} {
set vars(ilm) true
}
# BCL: Added tail of subst of vars(dbs_dir)
# Note - EDIFF Hierarchical flow is currently INCOMPATIBLE with FF dir structure
# The following code appears to rely on vars(dbs_dir) always being under $vars(partition_dir)/$vars(design)
# This needs to be reconciled
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_NOVUS::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
if {([string compare -nocase $vars(dbs_format) "oa"]==0) && ([lindex [split $vars(version) "."] 0] > 10)} {
if {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "assemble_design -top_design {$vars(oa_partition_lib) $vars(design) $vars($vars(design),rebudget_assemble_step)} -mmmc_file $mmmc_file"
} else {
set command "assemble_design -top_design {$vars(oa_partition_lib) $vars(design) cts} -mmmc_file $mmmc_file"
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -block {$vars(oa_partition_lib) $part $vars($vars($part),rebudget_assemble_step)}"
} else {
append command "\\\n -block {$vars(oa_partition_lib) $part cts}"
}
}
}
} else {
# append commands [FF::wrap_command rebudget,initialize_timing $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set assemble_command "assemble_design -power_intent_file $vars(cpf_file)"
} else {
set assemble_command "assemble_design -mmmc_file $mmmc_file"
}
} else {
set assemble_command "assemble_design"
}
if {[info exists vars($vars(design),rebudget_assemble_dbs)]} {
set command "$assemble_command -top_dir $vars($vars(design),rebudget_assemble_dbs)"
} elseif {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "$assemble_command $vars(partition_dir)/$vars(design)/$dir/$vars($vars(design),rebudget_assemble_step).enc"
} else {
if {$vars(enable_flexilm)} {
if {$vars(generate_flow_steps)} {
set command "$assemble_command \\\n -top_dir $vars(partition_dir)_FLEXILM/$vars(design) "
} else {
set command "$assemble_command \\\n -top_dir $vars(partition_dir)_FLEXILM/$vars(design) "
}
} else {
if {$vars(generate_flow_steps)} {
set command "$assemble_command -top_dir $vars(partition_dir)/$vars(design)/$dir/top.cts.enc "
} else {
set command "$assemble_command -top_dir $vars(partition_dir)/$vars(design)/$dir/cts.enc "
}
}
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,rebudget_assemble_dbs)]} {
append command "\\\n -block_dir $vars($part,rebudget_assemble_dbs)"
} elseif {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -block_dir $vars(partition_dir)/$part/$dir/$vars($part,rebudget_assemble_step).enc"
} else {
if {$vars(enable_flexilm)} {
append command "\\\n -block_dir \$vars($part,cdtv) "
} else {
if {$vars(generate_flow_steps)} {
append command "\\\n -block_dir $vars(partition_dir)/$part/$dir/block.cts.enc"
} else {
append command "\\\n -block_dir $vars(partition_dir)/$part/$dir/cts.enc"
}
}
}
}
}
}
if {$vars(enable_pac)} {
append command "\\\n -hierDir $vars(pac_scratch_dir)"
}
append command "\n"
append commands [FF::wrap_command $vars(step),assemble_design $command]
if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
append commands "source $mmmc_file\n"
}
if {$vars(flow) == "mmmc"} {
set command [FF_NOVUS::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load "post rebudget" plug-in script
###############################################################################
append commands [FF::source_plug post_rebudget_tcl 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command $vars(step),specify_ilm $command]
if {[info exists vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# if {[info exists vars(cpf_file)]} {
# set command "loadCPF $vars(cpf_file)\n"
# append commands [FF::wrap_command $vars(step),load_cpf $command]
# set command "commitCPF"
# if {$vars(cpf_keep_rows)} {
# append command " -keepRows"
# }
# if {$vars(cpf_power_domain)} {
# append command " -power_domain"
# }
# if {$vars(cpf_isolation)} {
# append command " -isolation"
# }
# if {$vars(cpf_state_retention)} {
# append command " -state_retention"
# }
# if {$vars(cpf_level_shifter)} {
# append command " -level_shifter"
# }
# if {$vars(cpf_power_switch)} {
# append command " -power_switch"
# }
# append command "\n"
# append commands [FF::wrap_command $vars(step),commit_cpf $command]
# }
# }
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
} elseif {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
}
if {!$vars(enable_flexilm)} {
set command [FF_NOVUS::update_timing mmmc ]
append commands [FF::wrap_command $vars(step),update_timing $command]
}
if {$vars(enable_pac)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# DEFINING PAC MODES\n"
append commands "#\n"
}
append commands [FF::source_plug pre_pac_tcl 0]
set command ""
foreach part $pac_list {
append command "set hinst \[dbHInstName \[dbCellHInst \[dbGetCellByName $part\]\]\]\n"
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "read_only"} { set vars($part,pac_mode) "readOnly" }
append command "setModuleView -hinst \$hinst -type $vars($part,pac_mode)\n"
}
}
append command "getModuleView\n"
append commands [FF::wrap_command $vars(step),set_module_view $command]
if {!$vars(enable_flexilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST ASSEMBLY CLOSURE\n"
append commands "#\n"
}
set command "opt_design -post_cts -report_dir $vars(rpt_dir) -report_prefix pac\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
append commands [FF::source_plug post_pac_tcl 0]
}
}
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "set_db route_trial_floorplan_mode true\nset_db route_trial_honor_pin true\n"
append command "route_trial\n"
} else {
set command "set_db route_trial_floorplan_mode true\nset_db route_early_global_honor_partition_pin .\n"
append command "route_early_global\n"
}
append command "create_timing_budget -no_trial_ipo -no_constant_model\n"
append commands [FF::wrap_command $vars(step),create_timing_budget $command]
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "write_db -oa_lib_cell_view {$vars(oa_design_lib) $vars(design) budget}\n"
}
} else {
set command "write_db $vars(dbs_dir)/budget.enc\n"
}
append commands [FF::wrap_command $vars(step),save_budget_dbs $command]
###############################################################################
# Partition and save the partitions into the
# directory PARTITION
###############################################################################
# append commands [FF::source_plug pre_partition_tcl]
# set command "set ptngPtnTimingLibFormat lib\npartition -buildScan\n"
set command "partition -buildScan\n"
append commands [FF::wrap_command $vars(step),partition $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {([string compare $vars(dbs_format) "oa"]==0)} {
if {$vars(hier_flow_type) == "1pass"} {
set command "savePartition -ptnLib $vars(oa_partition_lib) -dir $vars(partition_dir)\n"
} else {
set command "savePartition -ptnLib $vars(oa_partition_lib) -dir $vars(partition_dir_pass2)\n"
}
} else {
if {$vars(hier_flow_type) == "1pass"} {
set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
} else {
set command "savePartition -dir $vars(partition_dir_pass2) -def -scanDef\n"
}
}
} else {
set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
}
append commands [FF::wrap_command $vars(step),save_partition $command]
# append commands [FF::source_plug post_partition_tcl]
if {$vars(use_flexmodels) && $vars(flexmodel_as_ptn)} {
# set command "replace_proto_model \\\n"
# append command " -pre_ft_dir $vars(eco_dir)/pre_ft \\\n"
# append command " -post_ft_dir $vars(eco_dir)/post_ft \\\n"
# append command " -ptn_dir $vars(partition_dir) \\\n"
# append command " -ptn_full_netlist_dir ./temp_netlist_dir \\\n"
# append command " -out_dir $vars(partition_dir)\n"
set command "replace_proto_model \\\n"
append command " -ptn_dir $vars(partition_dir) \\\n"
append command " -out_dir $vars(partition_dir)\n"
append commands [FF::wrap_command $vars(step),replace_proto_model $command]
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
# if {$vars(makefile) && !$vars(generate_flow_steps)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
# }
# if {$vars(enable_flexilm)} {
# append commands "# Copy Makefiles in case they get deleted during the flow ...\n"
# foreach part [concat $vars(design) $vars(partition_list)] {
# append commands "file copy -force $vars(script_dir)/$part.Makefile $vars(partition_dir_pass2)/$part/Makefile\n"
# }
# append commands "file copy -force $vars(partition_dir)/Makefile $vars(partition_dir_pass2)/Makefile\n"
# append commands "file copy -force $vars(partition_dir)/Makefile.partition $vars(partition_dir_pass2)/Makefile.partition\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_assemble_flexilm {{format 1}} {
global vars
global errors
global env
set vars(step) assemble_flexilm
set commands ""
# append commands "set vars(step) $vars(step)\n"
FF_NOVUS::initialize_step $vars(step)
if {$vars(verbose)} {
append commands "#\n"
append commands "# ASSEMBLING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre rebudget" plug-in script
###############################################################################
append commands [FF::source_plug pre_rebudget_tcl]
###############################################################################
# Assemble the design
###############################################################################
set vars(ilm) false
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
set vars(ilm) true
} else {
set vars(ilm_list) ""
}
# BCL: Added tail of subst of vars(dbs_dir)
# Note - EDIFF Hierarchical flow is currently INCOMPATIBLE with FF dir structure
# The following code appears to rely on vars(dbs_dir) always being under $vars(partition_dir)/$vars(design)
# This needs to be reconciled
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_NOVUS::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
if {([string compare -nocase $vars(dbs_format) "oa"]==0) && ([lindex [split $vars(version) "."] 0] > 10)} {
if {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "assemble_design -top_design {$vars(oa_partition_lib) $vars(design) $vars($vars(design),rebudget_assemble_step)} -mmmc_file $mmmc_file"
} else {
set command "assemble_design -top_design {$vars(oa_partition_lib) $vars(design) cts} -mmmc_file $mmmc_file"
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -block {$vars(oa_partition_lib) $part $vars($vars($part),rebudget_assemble_step)}"
} else {
append command "\\\n -block {$vars(oa_partition_lib) $part cts}"
}
}
}
} else {
# append commands [FF::wrap_command rebudget,initialize_timing $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set assemble_command "assemble_design -cpf_file $vars(cpf_file)"
} else {
set assemble_command "assemble_design -mmmc_file $mmmc_file"
}
} else {
set assemble_command "assemble_design"
}
if {[info exists vars($vars(design),rebudget_assemble_dbs)]} {
set command "$assemble_command -def_merge -top_design $vars($vars(design),rebudget_assemble_dbs)"
} elseif {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "$assemble_command -def_merge $vars(partition_dir)/$vars(design)/$dir/$vars($vars(design),rebudget_assemble_step).enc"
} else {
if {$vars(enable_flexilm)} {
# set command "$assemble_command \\\n -top_dir $vars(partition_dir_pass2)/$vars(design) "
set command "$assemble_command \\\n -top_dir $vars(partition_dir)_PRECTS/$vars(design) "
} else {
set command "$assemble_command -top_dir $vars(partition_dir)/$vars(design)/$dir/cts.enc "
}
}
foreach part $vars(partition_list) {
if {[lsearch $vars(ilm_list) $part] == -1} {
if {[info exists vars($part,rebudget_assemble_dbs)]} {
append command "\\\n -block_dir $vars($part,rebudget_assemble_dbs)"
} elseif {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -block_dir $vars(partition_dir)/$part/$dir/$vars($part,rebudget_assemble_step).enc"
} else {
if {$vars(enable_flexilm)} {
append command "\\\n -block_dir $vars(partition_dir)_PRECTS/$part/${part}_post_eco.enc"
} else {
append command "\\\n -block_dir $vars(partition_dir)/$part/$dir/cts.enc"
}
}
}
}
}
append command "\n"
append commands [FF::wrap_command $vars(step),assemble_design $command]
append commands [FF::source_plug always_source_tcl]
set command ""
# Additional timing setup
if {[info exists vars($vars(design),latency_sdc)]} {
append command "foreach mode \[all_constraint_modes -active\] {\n"
append command " set sdc_files \[get_constraint_mode \$mode -sdc_files\]\n"
append command " set sdc_list \[concat \$sdc_files $vars($vars(design),latency_sdc)\]\n"
append command " update_constraint_mode -name \$mode -sdc_files \$sdc_list\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {[info exists vars($ptn,$view,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,$view,latency_sdc)
} elseif {[info exists vars($ptn,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,latency_sdc)
} else {
set latency($view,$ptn) "none"
}
}
}
set command ""
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {$latency($view,$ptn) != "none"} {
append command "set_partition_user_constraints_file -view $view -name $latency($view,$ptn) -partition $ptn\n"
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),set_partition_user_constraints_file $command]
}
if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
append commands "source $mmmc_file\n"
}
if {$vars(flow) == "mmmc"} {
set command [FF_NOVUS::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
###############################################################################
# Load "post assemble_flexilm" plug-in script
###############################################################################
append commands [FF::source_plug post_flexilm 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $vars(ilm_list) {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specify_ilm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command $vars(step),specify_ilm $command]
if {[info exists vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# if {[info exists vars(cpf_file)]} {
# set command "loadCPF $vars(cpf_file)\n"
# append commands [FF::wrap_command $vars(step),load_cpf $command]
# set command "commitCPF"
# if {$vars(cpf_keep_rows)} {
# append command " -keepRows"
# }
# if {$vars(cpf_power_domain)} {
# append command " -power_domain"
# }
# if {$vars(cpf_isolation)} {
# append command " -isolation"
# }
# if {$vars(cpf_state_retention)} {
# append command " -state_retention"
# }
# if {$vars(cpf_level_shifter)} {
# append command " -level_shifter"
# }
# if {$vars(cpf_power_switch)} {
# append command " -power_switch"
# }
# append command "\n"
# append commands [FF::wrap_command $vars(step),commit_cpf $command]
# }
# }
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
} elseif {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
}
if {!$vars(enable_flexilm)} {
set command [FF_NOVUS::update_timing mmmc ]
append commands [FF::wrap_command $vars(step),update_timing $command]
}
set command ""
foreach name $vars(partition_list) {
append command "set_partition_pin_status -partition $name -pins * -status placed\n"
}
append commands [FF::wrap_command $vars(step),set_partition_pin_status $command]
# set command "db_delete_route_trial\n"
# append commands [FF::wrap_command $vars(step),delete_route_trial $command]
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "set_db route_trial_handle_partition_complex true\n"
append command "set_db route_trial_honor_pin false\n"
append command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
} else {
set command "set_db set_db route_early_global_honor_partition_fence .\n"
append command "set_db route_early_global_honor_partition_pin {}\n"
append command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route $command]
}
set command ""
append command "create_active_logic_view -type flat_top\n"
append command "time_design -pre_cts -report_dir $vars(rpt_dir) -report_prefix assemble_prects_flexilm\n"
append command "clear_active_logic_view\n"
append commands [FF::wrap_command $vars(step),create_active_logic_view $command]
# append command "derive_timing_budget -no_trial_ipo -no_constant_model\n"
# append commands [FF::wrap_command $vars(step),derive_timing_budget $command]
# if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
# if {[lindex [split $vars(version) "."] 0] > 10} {
# set command "write_db -cellview {$vars(oa_design_lib) $vars(design) budget}\n"
# } else {
# set command "write_oa_design $vars(oa_design_lib) $vars(design) budget\n"
# }
# } else {
# set command "write_design $vars(dbs_dir)/budget.enc\n"
# }
# append commands [FF::wrap_command $vars(step),save_design,budget $command]
append commands "#---------------------------------------------------------------------\n"
append commands "# <FF> GENERATING REPORTS\n"
append commands "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
######################################################################
# Verify power domain
######################################################################
# set command "check_power_domains -bind -gconn"
# append command " -iso_net_pd $vars(rpt_dir)/$vars(step).isonets.rpt"
# append command " -x_net_pd $vars(rpt_dir)/$vars(step).xnets.rpt\n"
# append commands [FF::wrap_command $vars(step),check_power_domain $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "run_clp "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
if {!$vars(generate_flow_steps)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
}
# if {$vars(enable_flexilm)} {
# append commands "# Copy Makefiles in case they get deleted during the flow ...\n"
# foreach part [concat $vars(design) $vars(partition_list)] {
# append commands "file copy -force $vars(script_dir)/$part.Makefile $vars(partition_dir_pass2)/$part/Makefile\n"
# }
# append commands "file copy -force $vars(partition_dir)/Makefile $vars(partition_dir_pass2)/Makefile\n"
# append commands "file copy -force $vars(partition_dir)/Makefile.partition $vars(partition_dir_pass2)/Makefile.partition\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_flexilm {{format 1}} {
global vars
global errors
global env
set vars(step) flexilm
set commands ""
# append commands "set vars(step) $vars(step)\n"
FF_NOVUS::initialize_step flexilm
# if {$vars(report_run_time)} {
# append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
# }
if {$vars(verbose)} {
append commands "#\n"
append commands "# RESTORING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre flexilm" plug-in script
###############################################################################
append commands [FF::source_plug pre_flexilm_tcl]
###############################################################################
# Restore the design
###############################################################################
set vars(ilm) false
set ilm_list [list]
set pac_list [list]
if {$vars(enable_pac)} {
foreach part $vars(partition_list) {
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "ilm"} {
lappend ilm_list $part
} else {
lappend pac_list $part
}
}
}
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
foreach ilm $vars(ilm_list) {
if {([lsearch $ilm_list $ilm] == -1) && ([lsearch $pac_list $ilm] == -1)} {
lappend ilm_list $ilm
}
}
}
if {$ilm_list != ""} {
set vars(ilm) true
}
# BCL: Added tail of subst of vars(dbs_dir)
# Note - EDIFF Hierarchical flow is currently INCOMPATIBLE with FF dir structure
# The following code appears to rely on vars(dbs_dir) always being under $vars(partition_dir)/$vars(design)
# This needs to be reconciled
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_NOVUS::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
# append commands "setLimitedAccessFeature encFlexILM 1\n"
append commands "file copy -force $vars(script_dir)/view_definition.tcl $vars(partition_dir)/$vars(design)/$vars(dbs_dir)/prects.enc/viewDefinition.tcl\n"
set cwd [exec pwd]
append commands "cd $vars(partition_dir)/$vars(design)\n"
# set command "read_db . $vars(design)\n"
set command "read_db $vars(dbs_dir)/prects.enc \n"
append commands [FF::wrap_command flexilm,read_db $command]
# if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
# append commands "source $mmmc_file\n"
# }
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load "post flexilm" plug-in script
###############################################################################
append commands [FF::source_plug post_flexilm 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command $vars(step),specify_ilm $command]
# if {[info exists vars(ilm_non_sdc_file)]} {
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
# } else {
# set command "set_ilm_non_sdc_constraints_file $vars(ilm_non_sdc_file)\n"
# }
# append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
# }
# }
# if {[lindex [split $vars(version) "."] 0] <= 10} {
# if {[info exists vars(cpf_file)]} {
# set command "loadCPF $vars(cpf_file)\n"
# append commands [FF::wrap_command $vars(step),load_cpf $command]
# set command "commitCPF"
# if {$vars(cpf_keep_rows)} {
# append command " -keepRows"
# }
# if {$vars(cpf_power_domain)} {
# append command " -power_domain"
# }
# if {$vars(cpf_isolation)} {
# append command " -isolation"
# }
# if {$vars(cpf_state_retention)} {
# append command " -state_retention"
# }
# if {$vars(cpf_level_shifter)} {
# append command " -level_shifter"
# }
# if {$vars(cpf_power_switch)} {
# append command " -power_switch"
# }
# append command "\n"
# append commands [FF::wrap_command $vars(step),commit_cpf $command]
# }
}
# if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_NOVUS::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
# set command [FF_NOVUS::update_timing mmmc ]
# append commands [FF::wrap_command $vars(step),update_timing $command]
foreach mode [concat $vars(active_setup_views) $vars(active_hold_views)] {
set command "update_constraint_mode -name $mode -ilm_sdc_files \[get_constraint_mode $mode -sdc_files\]\n"
append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
append commands "cd $cwd\n"
set command ""
foreach part $vars(partition_list) {
append command "set_module_model -cell $part \\\n"
append command "-type flexIlm \\\n"
append command "-dir $vars(partition_dir)/$part/$part.flexilm\n"
}
append commands [FF::wrap_command $vars(step),set_module_model $command]
set command "commit_module_model\n"
append commands [FF::wrap_command $vars(step),commit_module_model $command]
set command ""
foreach part $vars(partition_list) {
append command "setModuleView -partition $part -type interface\n"
}
append commands [FF::wrap_command $vars(step),set_module_view $command]
set command "getModuleView\n"
append commands [FF::wrap_command $vars(step),get_module_view $command]
if {$vars(flow) == "mmmc"} {
set command [FF_NOVUS::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
set command ""
# foreach mode $vars(constraint_modes) {
# append command "update_constraint_mode -name $mode -sdc_files \"$vars($mode,pre_cts_sdc)\"\n"
# }
# append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
#set_analysis_view -setup [all_setup_analysis_views] -hold [all_hold_analysis_views]
#puts "<FF> SETUP -> [all_setup_analysis_views]"
#puts "<FF> HOLD -> [all_hold_analysis_views]"
set command "create_active_logic_view -type top_critical -pre_cts\n"
append commands [FF::wrap_command $vars(step),create_active_logic_view $command]
set command "set_db opt_hier_opt_stage pre_cts\n"
append commands [FF::wrap_command $vars(step),set_hier_mode $command]
# set command "setOptMode -addInstancePreFix FlexILMI_ -addNetPreFix FlexILMN_\n"
# append commands [FF::wrap_command $vars(step),set_opt_mode $command]
append commands [FF::source_plug pre_flexilm_tcl 0]
set command ""
foreach part $pac_list {
append command "set hinst \[dbHInstName \[dbCellHInst \[dbGetCellByName $part\]\]\]\n"
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "read_only"} { set vars($part,pac_mode) "readOnly" }
append command "setModuleView -hinst \$hinst -type $vars($part,pac_mode)\n"
}
}
append command "getModuleView\n"
append commands [FF::wrap_command $vars(step),set_module_view $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING FLEXILM OPTIMIZATION\n"
append commands "#\n"
}
set command "opt_design -pre_cts -report_dir $vars(rpt_dir) -report_prefix flexilm\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
append commands [FF::source_plug post_flexilm_tcl 0]
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "write_db -oa_lib_cell_view {$vars(oa_design_lib) $vars(design) flexilm}\n"
}
} else {
set command "write_db $vars(dbs_dir)/flexilm.enc\n"
}
append commands [FF::wrap_command $vars(step),save_dbs $command]
set command "clear_active_logic_view\n"
append commands [FF::wrap_command $vars(step),clear_active_logic_view $command]
set command "update_partition -flex_ilm_eco \\\n"
foreach part $vars(partition_list) {
append command " -golden_block_dir $vars(partition_dir)/$part/$vars(dbs_dir)/prects.enc \\\n"
}
append command " -flex_ilm_dir $vars(partition_dir)_FLEXILM\n"
append commands [FF::wrap_command $vars(step),update_partition $command]
set command "report_resource -end opt_flexIlm\n"
append commands [FF::wrap_command $vars(step),report_resource $command]
append commands "#---------------------------------------------------------------------\n"
append commands "# <FF> GENERATING REPORTS\n"
append commands "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
######################################################################
# Verify power domain
######################################################################
# set command "check_power_domains -bind -gconn"
# append command " -iso_net_pd $vars(rpt_dir)/$vars(step).isonets.rpt"
# append command " -x_net_pd $vars(rpt_dir)/$vars(step).xnets.rpt\n"
# append commands [FF::wrap_command $vars(step),check_power_domains $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "run_clp "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
# if {$vars(makefile)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "set op \[open $env(VPATH)/flexilm w\]\n"
foreach part $vars(partition_list) {
append commands "puts \$op \"set vars($part,cdtv) \$::Rda_CDTV::ilmDataInfo($part,blockDir)\"\n"
}
append commands "close \$op\n"
# foreach part $vars(partition_list) {
# append commands "file copy -force $vars(partition_dir_pass2)/$part/Makefile $vars(partition_dir_pass2)/$part.Makefile\n"
# }
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_partition_place {{format 1}} {
global vars
global errors
global env
set vars(step) partition_place
set vars(hier) true
if {[info exists vars(time_design_options,setup)]} {
set tmp_time_design_options_setup $vars(time_design_options,setup)
} else {
set vars(time_design_options,setup) ""
}
set commands ""
if {!$vars(use_flexmodels)} {
# Initialise the design if not using flexmodels
if {$vars(codegen)} {
append commands [FF_NOVUS::run_init $format]
} else {
FF_NOVUS::run_init $format
}
}
if {$vars(use_proto_net_delay_model) } {
if {!$vars(use_flexmodels)} {
set command "catch {exec rm -rf proto_model_BACKUP}\ncatch {exec mv -f proto_model proto_model_BACKUP}\n"
append commands [FF::wrap_command $vars(step),proto_model_BACKUP $command]
set command "create_proto_net_delay_model\n"
append commands [FF::wrap_command $vars(step),create_ps_per_micron_model $command]
}
set command "time_design -proto -pre_place -report_prefix preplace -report_dir $vars(rpt_dir)\n"
append commands [FF::wrap_command $vars(step),time_design $command]
} else {
set command "time_design -pre_place -report_prefix preplace -report_dir $vars(rpt_dir)\n"
append commands [FF::wrap_command $vars(step),time_design $command]
}
if {$vars(use_flexmodels)} {
set command "report_proto_models -created\n"
append commands [FF::wrap_command $vars(step),report_proto_models $command]
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "write_db -oa_lib_cell_view {$vars(oa_design_lib) $vars(design) init}\n"
}
} else {
if {$vars(step) != "partition_place"} {
set command "write_db $vars(dbs_dir)/init.enc \n"
} else {
set command ""
}
}
append commands [FF::wrap_command $vars(step),save_design,init $command]
set command ""
# Additional timing setup
if {[info exists vars($vars(design),latency_sdc)]} {
append command "foreach mode \[all_constraint_modes -active\] {\n"
append command " set sdc_files \[get_constraint_mode \$mode -sdc_files\]\n"
append command " set sdc_list \[concat \$sdc_files $vars($vars(design),latency_sdc)\]\n"
append command " update_constraint_mode -name \$mode -sdc_files \$sdc_list\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {[info exists vars($ptn,$view,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,$view,latency_sdc)
} elseif {[info exists vars($ptn,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,latency_sdc)
} else {
set latency($view,$ptn) "none"
}
}
}
set command ""
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {$latency($view,$ptn) != "none"} {
append command "set_partition_user_constraints_file -view $view -name $latency($view,$ptn) -partition $ptn\n"
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),set_partition_user_constraints_file $command]
}
# Insert feedthrough and trial route, as appropriate
set do_trial_route_time_design 1
# Pre-placement
if {[info exists vars(place,set_place_mode,skip)]} {
set cache_skip_place_mode $vars(place,set_place_mode,skip)
}
set vars(place,set_place_mode,skip) 1
if {[info exists vars(place,place_design,skip)]} {
set cache_skip_place_design $vars(place,place_design,skip)
}
set vars(place,place_design,skip) 1
set vars(hier_case) "$vars(use_flexmodels)$vars(placement_based_ptn)$vars(abutted_design)$vars(insert_feedthrough)"
# Disable scan reorder for partitioning flow
# set command "set_db place_reorder_scan false\n"
# append commands [FF::wrap_command $vars(step),set_place_mode $command]
append command "if {\[get_db hinsts .partition.clones\] != \"\"} {\n"
append command " align_partition_clones\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),align_partition_clones $command]
switch $vars(hier_case) {
"0000" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
}
"0001" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0010" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0011" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0100" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0101" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0110" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0111" {
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"1000" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "set_db route_trial_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
}
"1001" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "set_db route_trial_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
}
"1010" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "set_db route_trial_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
}
"1011" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "set_db route_trial_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
}
"1100" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
}
"1101" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
}
"1110" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
}
}
"1111" {
set command "set_db place_global_cong_effort auto\nset_db place_global_clock_gate_aware true\nset_db place_global_place_io_pins true\nset_db place_design_floorplan_mode true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
}
}
if {$vars(use_proto_net_delay_model)} {
set command "set_proto_mode -timing_net_delay_model use_actual_wire\n"
append commands [FF::wrap_command $vars(step),set_proto_model $command]
}
# Place design
set save $vars(place_opt_design)
if {$vars(codegen)} {
append commands [FF_NOVUS::run_place $format]
} else {
uplevel #0 eval $commands
FF_NOVUS::run_place $format
set commands ""
}
set vars(place_opt_design) $save
if {[info exists cache_skip_place_mode]} {
set vars(place,set_place_mode,skip) $cache_skip_place_mode
} else {
set vars(place,set_place_mode,skip) false
}
if {[info exists cache_skip_place_mode]} {
set vars(place,place_design,skip) $cache_skip_place_design
} else {
set vars(place,place_design,skip) false
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "write_db -oa_lib_cell_view {$vars(oa_design_lib) $vars(design) place}\n"
}
} else {
set command "write_db $vars(dbs_dir)/place.enc \n"
}
append commands [FF::wrap_command $vars(step),save_design $command]
# Post-placement
switch $vars(hier_case) {
"0000" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
} else {
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route__mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route $command]
}
}
"0001" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial_1 $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial_2 $command]
} else {
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route_1 $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route_2 $command]
}
}
"0010" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
} else {
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route $command]
}
}
"0011" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial_1 $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial_2 $command]
} else {
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route_1 $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route_2 $command]
}
}
"0100" {
}
"0101" {
}
"0110" {
}
"0111" {
set command "add_partition_feedthrus -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
}
"1000" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
} else {
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),route_early $command]
}
}
"1001" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
} else {
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route_1 $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route__mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route_2 $command]
}
}
"1010" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
} else {
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route $command]
}
}
"1011" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_trial_handle_partition_complex true\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_trial\n"
append commands [FF::wrap_command $vars(step),route_trial $command]
} else {
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),early_route_1 $command]
set command "add_partition_feedthrus -route_based -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "set_db route_early_global_honor_partition_fence .\n"
append commands [FF::wrap_command $vars(step),set_route_trial_mode $command]
set command "route_early_global\n"
append commands [FF::wrap_command $vars(step),route_early_2 $command]
}
}
"1100" {
}
"1101" {
set command "add_partition_feedthrus -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
}
"1110" {
set do_route_trial_time_design 0
}
"1111" {
set command "add_partition_feedthrus -write_topological_file topo.txt -net_mapping netmapping.txt -double_buffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
}
}
if {$vars(use_proto_net_delay_model)} {
set command "time_design -proto -pre_cts -report_prefix place -report_dir $vars(rpt_dir)\n"
} else {
set command "time_design -pre_cts -report_prefix place -report_dir $vars(rpt_dir)\n"
}
append commands [FF::wrap_command $vars(step),time_design $command]
# Output or run the generated commands
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_assign_pin {{format 1}} {
global vars
global errors
global env
set vars(step) assign_pin
set vars(hier) true
set commands ""
###############################################################################
# Assign partition pins via plug-in as this the
# pitch, depth, and layer values are design specific
# Also, verify the pin assignment and fix them
###############################################################################
append commands [FF::source_plug pre_assign_pin_tcl]
set command "assign_partition_pins\n"
append commands [FF::wrap_command $vars(step),assign_partition_pins $command]
append commands [FF::source_plug post_assign_pin_tcl]
set command "check_pin_assignment\n"
append commands [FF::wrap_command $vars(step),check_pin_assignment $command]
set command "report_unaligned_nets -out_file $vars(rpt_dir)/unaligned.rpt\n"
append commands [FF::wrap_command $vars(step),report_unaligned_nets $command]
if {!([info exists vars(placement_based_ptn)] && $vars(placement_based_ptn))} {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "set_db route_trial_handle_partition_complex true\nset_db route_trial_honor_pin true\n"
append command "route_trial\n"
} else {
set command "set_db route_early_global_honor_partition_fence .\nset_db route_early_global_honor_partition_pin .\n"
append command "route_early_global\n"
}
append commands [FF::wrap_command $vars(step),route_trial $command]
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_model_gen {{format 1}} {
global vars
global errors
global env
set vars(step) model_gen
set vars(hier) true
set commands ""
# Initialise the design
if {$vars(codegen)} {
append commands [FF_NOVUS::run_init $format]
} else {
FF_NOVUS::run_init $format
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
set command "write_db -oa_lib_cell_view {$vars(oa_design_lib) $vars(design) init}\n"
} else {
set command "write_db $vars(dbs_dir)/init.enc\n"
}
append commands [FF::wrap_command $vars(step),save_design,init $command]
if {$vars(use_proto_net_delay_model) && $vars(use_flexmodels)} {
set command "catch {exec rm -rf proto_model_BACKUP}\ncatch {exec mv -f proto_model proto_model_BACKUP}\n"
append commands [FF::wrap_command $vars(step),proto_model_BACKUP $command]
set command "create_ps_per_micron_model\n"
append commands [FF::wrap_command $vars(step),create_ps_per_micron_model $command]
}
append commands [FF::source_plug pre_model_gen_tcl]
if {$vars(enable_nrgr)} {
# set command "set_db design_use_turbo_nrgr_flow true\n"
# append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set vars(hier_case) "$vars(flexmodel_as_ptn)$vars(insert_feedthrough)"
switch $vars(hier_case) {
"00" {
set command "identify_proto_model\n"
append commands [FF::wrap_command $vars(step),identify_proto_model $command]
}
"01" {
set command "identify_proto_model\n"
append commands [FF::wrap_command $vars(step),identify_proto_model $command]
}
"10" {
set command "set_db proto_create_partition_as_flexmodel true\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
# if {[info exists vars(partition_list)] && ($vars(partition_list) != "")} {
# foreach ptn $vars(partition_list) {
# set command "set_proto_model -model $ptn -type flex_module\n"
# append commands [FF::wrap_command $vars(step),set_proto_model $command]
# }
# } else {
# puts "<FF> ERROR: Flexmodel partition flow enabled but no partitions are defined"
# set errors($vars(error_count)) "Flexmodel partition flow enabled but no partitions are defined"
# incr vars(error_count)
# }
}
"11" {
set command "set_db proto_create_partition_as_flexmodel true\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
# if {[info exists vars(partition_list)] && ($vars(partition_list) != "")} {
# foreach ptn $vars(partition_list) {
# set command "set_proto_model -model $ptn -type flex_module\n"
# append commands [FF::wrap_command $vars(step),set_proto_model $command]
# }
# } else {
# puts "<FF> ERROR: Flexmodel partition flow enabled but no partitions are defined"
# set errors($vars(error_count)) "Flexmodel partition flow enabled but no partitions are defined"
# incr vars(error_count)
# }
}
}
# if {[info exists vars(model_gen,min_inst)]} {
# set min_inst $vars(model_gen,min_inst)
# } else {
# set min_inst 1000
# }
# set command "set_db ilm_keep_high_fanout_ports false\n"
# append commands [FF::wrap_command $vars(step),setIlmMode $command]
set command "set_db ilm_keep_high_fanout_ports false\n"
append commands [FF::wrap_command $vars(step),set_ilm_mode $command]
if {$vars(flexmodel_art_based)} {
set command "create_proto_model -out_dir $vars(dbs_dir)/model_gen.enc\n"
} else {
set command "create_proto_model -partition_based\ncommit_proto_model\n"
}
append commands [FF::wrap_command $vars(step),create_proto_model $command]
if {$vars(create_flexfiller_blockage)} {
set command "create_flexfiller_route_blockage\n"
append commands [FF::wrap_command $vars(step),create_flexfiller_route_blockage $command]
}
append commands [FF::source_plug post_model_gen_tcl]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_partition {{format 1}} {
global vars
global errors
global env
set vars(step) partition
set vars(hier) true
set commands ""
###############################################################################
# Budget the blocks based on the mode
###############################################################################
set command ""
# append command "set_global timing_support_hierarchical_pin_constraints true\n"
# append command "set_db tbgPrintExceptionInfoInJustify 1\n"
append commands [FF::wrap_command $vars(step),set_budget_vars $command]
if {$vars(budget_mode) == "proto_net_delay_model" && $vars(use_proto_net_delay_model)} {
set command "time_design -proto -report_prefix budget -report_dir $vars(rpt_dir)\n"
append commands [FF::wrap_command $vars(step),time_design $command]
}
# Define budgeting options ...
set command ""
append command "set_db budget_write_latency_per_clock true\n"
append command "if {\[get_db hinsts .partition.clones\] != \"\"} {\n"
append command " set_db budget_merge_clones true\n"
append command "}\n"
if {[info exists vars(abutted_design)] && $vars(abutted_design)} {
append command "set_db budget_abutted true\n"
}
# switch [string tolower $vars(budget_mode)] {
# giga_opt {
# append command "set_db budget_virtual_opt_engine giga_opt\n"
# }
# proto_net_delay_model {
# if {$vars(use_proto_net_delay_model)} {
# append command "set_db budget_virtual_opt_engine none\n"
# }
# }
# }
# append command "set_db budget_enable_mt_budgeting true\n"
append commands [FF::wrap_command $vars(step),set_budgeting_mode $command]
if {([string tolower $vars(budget_mode)] != "proto_net_delay_model") && $vars(use_proto_net_delay_model)} {
set command "set_proto_timing_settings -reset\n"
append commands [FF::wrap_command $vars(step),set_proto_timing_settings $command]
}
set command "create_timing_budget -justify\n"
append commands [FF::wrap_command $vars(step),create_timing_budget $command]
###############################################################################
# Run CLP
###############################################################################
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "run_clp "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
}
}
###############################################################################
# Partition and save the partitions into the
# directory PARTITION
###############################################################################
# if {$vars(use_flexmodels)} {
# set max_layer [getTrialRouteMode -maxRouteLayer]
# setPlaceMode -reset
# setTrialRouteMode -reset
# setTrialRouteMode -maxRouteLayer $max_layer
# }
append commands [FF::source_plug pre_partition_tcl]
set command "commit_partition -build_scan\n"
append commands [FF::wrap_command $vars(step),partition $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {([string compare $vars(dbs_format) "oa"]==0)} {
set command "write_partitions -partition_lib $vars(oa_partition_lib) -dir $vars(partition_dir)\n"
} else {
set command "write_partitions -dir $vars(partition_dir) -def -def_scan\n"
}
} else {
set command "write_partitions -dir $vars(partition_dir) -def -def_scan\n"
}
append commands [FF::wrap_command $vars(step),save_partition $command]
if {$vars(use_flexmodels) && $vars(flexmodel_as_ptn)} {
# set command "replace_proto_model \\\n"
# append command " -pre_ft_dir $vars(eco_dir)/pre_ft \\\n"
# append command " -post_ft_dir $vars(eco_dir)/post_ft \\\n"
# append command " -ptn_dir $vars(partition_dir) \\\n"
# append command " -ptn_full_netlist_dir ./temp_netlist_dir \\\n"
# append command " -out_dir $vars(partition_dir)\n"
set command "replace_proto_model \\\n"
append command " -ptn_dir $vars(partition_dir) \\\n"
append command " -out_dir $vars(partition_dir)\n"
append commands [FF::wrap_command $vars(step),replace_proto_model $command]
}
append commands [FF::source_plug post_partition_tcl]
append commands "#---------------------------------------------------------------------\n"
append commands "# <FF> GENERATING REPORTS\n"
append commands "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
set command ""
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
######################################################################
# Verify power domain
######################################################################
# set command "check_power_domain -bind -gconn"
# append command " -iso_net_pd $vars(rpt_dir)/$vars(step).isonets.rpt"
# append command " -x_net_pd $vars(rpt_dir)/$vars(step).xnets.rpt\n"
# append commands [FF::wrap_command $vars(step),check_power_domain $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "run_clp "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
}
set path [file normalize $vars(script_path)]
file mkdir $vars(partition_dir)
if {![file exists $vars(partition_dir)/Makefile.partition]} {
file copy $vars(script_path)/ETC/INNOVUS/Makefile.partition $vars(partition_dir)
}
set op [open $vars(partition_dir)/Makefile w]
if {![info exists env(VPATH)]} {
set env(VPATH) "make"
}
puts $op "VPATH=$env(VPATH)"
puts $op "BLOCKS = $vars(partition_list)"
puts $op ""
puts $op "include Makefile.partition"
close $op
foreach var [array names vars] {
set svars($var) $vars($var)
}
set vars(mode) flat
# set vars(hier) true
set link [file normalize $vars(script_root)]
foreach block [concat $vars(design) $vars(partition_list)] {
exec mkdir -p $vars(partition_dir)/$block
# if {[file exists .ff.tcl]} {
# file copy -force .ff.tcl $vars(partition_dir)/$block
# }
if {[file exists $vars(partition_dir)/$block/Makefile]} {
file delete $vars(partition_dir)/$block/Makefile
}
if {[info exists vars($block,innovus_config_tcl)] && [file exists $vars($block,innovus_config_tcl)]} {
puts "<FF> Sourcing $vars($block,innovus_config_tcl)"
source $vars($block,innovus_config_tcl)
}
set cwd [pwd]
if {([lindex [split $vars(version) "."] 0] > 10) && ([string compare $vars(dbs_format) "oa"]==0)} {
if {[file exists cds.lib]} {
set ip [open cds.lib r]
set i 0
while {[gets $ip line]>=0} {
set cds_lib($i) $line
incr i
}
close $ip
} else {
puts "<FF> ERROR: A cds.lib file is required for open access flows ..."
}
}
cd $vars(partition_dir)/$block
set vars(design) $block
if {$vars(codegen)} {
if {[info exists vars(proc_file)]} {
unset vars(proc_file)
}
unset vars(steps)
}
if {[info exists vars(cts_spec)]} {
unset vars(cts_spec)
}
if {[info exists vars($block,cts_spec)]} {
set vars(cts_spec) $vars($block,cts_spec)
}
if {!$vars(codegen)} {
exec ln -s $link SCRIPTS
exec ln -s SCRIPTS/Makefile.edi.flat Makefile
} else {
set vars(mode) flat
set vars(hier) true
unset vars(step)
execute_flow all $vars(format_lines)
FF::dump_vars
}
cd $cwd
# set actions $vars(actions)
foreach var [array names vars] {
if {$var != "processed_plugins"} {
unset vars($var)
}
}
# set vars(actions) $actions
foreach var [array names svars] {
if {$var != "processed_plugins"} {
set vars($var) $svars($var)
}
}
}
if {$vars(hier_flow_type) == "2pass"} {
foreach block [concat $vars(design) $vars(partition_list)] {
exec mkdir -p $vars(partition_dir_pass2)/$block/$vars(script_dir)/INNOVUS
exec mkdir -p $vars(partition_dir_pass2)/$block/$vars(rpt_dir)
if {[file isdirectory $vars(partition_dir_pass2)/$block/$vars(script_dir)/ETC]} {
file delete -force $vars(partition_dir_pass2)/$block/$vars(script_dir)/ETC
}
# file copy -force $vars(partition_dir)/$block/$vars(script_dir)/ETC $vars(partition_dir_pass2)/$block/$vars(script_dir)/ETC
foreach file [glob $vars(partition_dir)/Make*] {
if {[file isfile $file]} {
file copy -force $file $vars(partition_dir_pass2)
}
}
foreach file [glob $vars(partition_dir)/$block/$vars(script_dir)/*] {
if {[file isfile $file]} {
file copy -force $file $vars(partition_dir_pass2)/$block/$vars(script_dir)
}
}
if {[file isfile $vars(partition_dir)/$block/.ilm_non_sdc_file.tcl]} {
file copy -force $vars(partition_dir)/$block/.ilm_non_sdc_file.tcl $vars(partition_dir_pass2)/$block
}
if {[file isfile $vars(partition_dir)/$block/empty.sdc]} {
file copy -force $vars(partition_dir)/$block/empty.sdc $vars(partition_dir_pass2)/$block
}
if {[file isfile $vars(partition_dir)/$block/Makefile.pass2]} {
file copy -force $vars(partition_dir)/$block/Makefile.pass2 $vars(partition_dir_pass2)/$block/Makefile
file delete $vars(partition_dir)/$block/Makefile.pass2
}
cd $vars(partition_dir_pass2)/$block
if {$vars(enable_flexilm)} {
set index [lsearch [FF::adjust_steps] cts]
} else {
set index [lsearch [FF::adjust_steps] postcts]
}
cd $cwd
foreach step [lrange $vars(steps) $index end] {
if {[lsearch $vars(fsteps) $step] != -1} {
if {[file isfile $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl]} {
file copy -force $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl \
$vars(partition_dir_pass2)/$block/$vars(script_dir)/INNOVUS
file delete -force $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl
}
}
}
# if {$vars(enable_flexilm)} {
# file copy -force $vars(partition_dir)/$block/Makefile.pass2 $vars(partition_dir_pass2)/$block.Makefile
# } else {
# file copy -force $vars(partition_dir)/$block/Makefile.pass2 $vars(partition_dir_pass2)/$block/Makefile
# }
# cd $vars(partition_dir_pass2)/$block
# set adjusted [FF::adjust_steps]
# FF::gen_makefile [lrange $vars(steps) $index end] flat
# FF::gen_makefile [lrange $adjusted $index end] flat
# cd $cwd
}
}
foreach var [array names vars] {
unset vars($var)
}
foreach var [array names svars] {
set vars($var) $svars($var)
}
if {$vars(codegen)} {
# if {$vars(makefile)} {
# append commands "\nexec /bin/touch $env(VPATH)/partition\n"
# }
return $commands
} else {
exec /bin/touch $env(VPATH)/partition
}
}
proc run_debug {{format 1}} {
global vars
global errors
global env
set commands ""
append commands "\nglobal env\n"
append commands "if {\[info exists env(STEP)\]} {\n"
append commands "[FF_NOVUS::load_design \$env(STEP)]\n"
append commands "}\n"
# append commands "[FF::source_plug always_source_tcl]\n"
append commands "gui_fit\n"
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_lec {} {
global vars
global errors
global env
set commands ""
append commands "vpxmode\n"
append commands "set dofile abort exit\n"
append commands "set undefined cell black_box -noascend -both\n"
append commands "tclmode\n"
append commands "// setup variables \n"
append commands "global vars\n"
append commands "proc Puts {args} {\n"
append commands " puts \$args\n"
append commands "}\n"
append command "// Define the netlist to be verify\n"
append commands "if {\[info exists env(STEP)\] && \[file exists $vars(dbs_dir)/LEC/\$env(STEP).v.gz\]} {\n"
append commands " set revisedNetlist $vars(dbs_dir)/LEC/\$env(STEP).v.gz\n"
append commands "} else {\n"
append commands " puts \"<FF> Failed to find netlist DBS/LEC/\$env(STEP).v.gz\"\n"
append commands "}\n"
if {[info exists vars(threads)]} {
append commands "vpx set compare option -threads $vars(threads)\n"
}
append commands "// read liberty cell definitions\n"
if {[info exists vars($vars(default_setup_view),delay_corner)]} {
if {[info exists vars($vars($vars(default_setup_view),delay_corner),library_set)]} {
set set $vars($vars($vars(default_setup_view),delay_corner),library_set)
} else {
return
}
} else {
return
}
append commands "vpx read library -statetable -both -liberty \[list $vars($set,timing)\]\n"
append commands "// read reference netlist\n"
append commands "vpx read design -verilog -sensitive -golden $vars(netlist)\n"
append commands "// read post-implementation netlist\n"
append commands "vpx read design -verilog -sensitive -revised \$revisedNetlist\n"
append commands "//set top level\n"
append commands "vpx set root module $vars(design) -both\n"
regsub -all "#" [FF::source_plug pre_lec_tcl] "//" temp
append commands $temp
append commands "vpxmode\n"
append commands "report design data\n"
append commands "report black box\n"
append commands "set mapping method -name first\n"
append commands "set flatten model -seq_constant -seq_constant_x_to 0\n"
append commands "set flatten model -nodff_to_dlat_zero -nodff_to_dlat_feedback\n"
append commands "set flatten model -gated_clock\n"
append commands "set system mode lec\n"
append commands "add compare point -all\n"
append commands "compare -gate_to_gate\n"
append commands "usage\n"
append commands "// vpx report compare data"
append commands "report compare data -class nonequivalent -class abort -class notcompared\n"
append commands "report verification -verbose\n"
append commands "report statistics\n"
append commands "tclmode\n"
append commands "set points_count \[get_compare_points -count\]\n"
append commands "set diff_count \[get_compare_points -diff -count\]\n"
append commands "set abort_count \[get_compare_points -abort -count\]\n"
append commands "set unknown_count \[get_compare_points -unknown -count\]\n"
append commands "if {\$points_count == 0} {\n"
append commands " puts \"---------------------------------\"\n"
append commands " puts \"ERROR: No compare points detected\"\n"
append commands " puts \"---------------------------------\"\n"
append commands "}\n"
append commands "if {\$diff_count > 0} {\n"
append commands " puts \"------------------------------------\"\n"
append commands " puts \"ERROR: Different Key Points detected\"\n"
append commands " puts \"------------------------------------\"\n"
append commands "}\n"
append commands "if {\$abort_count > 0} {\n"
append commands " puts \"-----------------------------\"\n"
append commands " puts \"ERROR: Abort Points detected \"\n"
append commands " puts \"-----------------------------\"\n"
append commands "}\n"
append commands "if {\$unknown_count > 0} {\n"
append commands " puts \"----------------------------------\"\n"
append commands " puts \"ERROR: Unknown Key Points detected\"\n"
append commands " puts \"----------------------------------\"\n"
append commands "}\n"
append commands "puts \"No of compare points = \$points_count\"\n"
append commands "puts \"No of diff points = \$diff_count\"\n"
append commands "puts \"No of abort points = \$abort_count\"\n"
append commands "puts \"No of unknown points = \$unknown_count\"\n"
append commands "exit 0\n"
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc dump_config {} {
global vars
global udm
global rda_Input
global rda_defaults
# set commands ""
file mkdir $vars(script_dir)
if {[info command FFF::get_tool] ne "" && [FFF::get_tool] eq "rc"} {
tcl_source $vars(script_path)/ETC/INNOVUS/udm.tcl
} else {
source $vars(script_path)/ETC/INNOVUS/udm.tcl
}
if {[info exists vars(cpf_file)]} {
if {$vars(cpf_timing)} {
unset init(mmmc_file)
} else {
unset init(cpf_file)
}
}
if {[lindex [split $vars(version) "."] 0] > 10} {
if {!$vars(generate_flow_steps) || ([lindex [split $vars(version) "."] 0] < 15)} {
set op [open $vars(script_dir)/init.tcl w]
# BCL: Trying to fix embedded paths...
set relativizeMesgLog ""
set relativizeMesgLog "$relativizeMesgLog [FF::remove_outer_braces [FF::relativizeFileOrDir -arr init -vardir ff_exe_dir -relativePathsOk]]"
#foreach var [array names init] {
# puts $op "set init_$var \"$init($var)\""
#}
foreach var [array names ninit] {
if {$vars(netlist_type) == "verilog"} {
if {$var == "oa_design_lib"} { continue }
if {$var == "oa_design_cell"} { continue }
if {$var == "oa_design_view"} { continue }
}
puts $op "set_db init_$var \"$ninit($var)\""
}
close $op
}
} else {
set op [open $vars(script_dir)/run.conf w]
#BCL: Added .ff.tcl sourcing in run.conf in order to pull in codegen variables
puts $op "# Set up codegen variables (possibly) needed to resolve some conf variables"
#puts $op "if {\[file exists .ff.tcl\]} {"
#puts $op " source .ff.tcl"
#puts $op "}"
#BCL: Only enclose in curlies if subst is not part of the netlist name
foreach var [array names rda_Input] {
# BCL: only use curlies if the variable doesn't contain subst (otherwise subst will not be performed)
if {[regexp {subst} $rda_Input($var)]} {
puts $op "set rda_Input($var) \"$rda_Input($var)\""
} else {
puts $op "set rda_Input($var) \{$rda_Input($var)\}"
}
}
# if {$vars(flat) != "full"} {
# puts $op "set rda_Input(ui_view_definition_file) \"$vars(script_dir)/view_definition.tcl\""
# }
}
}
proc get_required_procs {file} {
#
# Given a list of required procedures, return the lines that represent
# those procedures from the utils.tcl file
#
global vars
global errors
#
# Read the file and gather all of the contents
#
set all_lines ""
set length 0
set ip [open $file]
while {[gets $ip line]>=0} {
set utils_lines($length) $line
incr length
}
close $ip
#
# Iterate across each line and pull out relevant procedures
#
set lines ""
set i 0
while {$i < $length} {
set line [regsub "puts" $utils_lines($i) "puts"]
foreach proc $vars(required_procs) {
if {[regexp "proc $proc" $line] > 0} {
append lines " $line\n"
incr i
while {$i < $length} {
set line $utils_lines($i)
if {[regexp "proc " $line] > 0} {
incr i -1
break
}
if {![regexp "^#" [string trimleft $line] ] && ($i != [expr $length-1])} {
append lines "$line\n"
}
incr i
}
break
}
}
incr i
}
set lines [string trimright $lines]
return "$lines\n"
}
proc normalize_files {} {
global vars
global errors
if {[info exists vars(normalize_files)] && !$vars(normalize_files)} {
return
}
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file [file normalize $vars(view_definition_tcl)]
} else {
set mmmc_file [file normalize $vars(script_dir)/view_definition.tcl]
}
set vars(mmmc_file) $mmmc_file
foreach file_var [list cpf_file def_files netlist cts_spec lef_files \
gds_files activity_file ilm_non_sdc_file ] {
if {[info exists vars($file_var)]} {
set temp [list]
foreach file $vars($file_var) {
lappend temp [file normalize $file]
}
set vars($file_var) $temp
}
}
}
proc normalize_constraints {} {
global vars
set cwd [pwd]
cd $vars(cwd)
foreach mode $vars(constraint_modes) {
foreach var "pre_cts_sdc incr_cts_sdc post_cts_sdc pre_cts_ilm_sdc" {
if {[info exists vars($mode,$var)]} {
set temp [list]
foreach file $vars($mode,$var) {
lappend temp [file normalize $file]
}
set vars($mode,$var) $temp
}
}
}
cd $cwd
}
proc denormalize_files {} {
global vars
global tvars
foreach var [array names vars] {
if {($var != "setup_path") && ($var != "script_dir") && ($var != "script_path") && ($var == "execute_string")} {
set tvars($var) $vars($var)
}
}
# set op [open .setup.ff.tcl w]
catch {unset path_array}
set path_list [list]
set path_vars [list]
foreach var [array names tvars] {
if [file isdirectory $tvars($var)] {
set path_array($tvars($var)) $var
lappend path_vars $var
lappend path_list $tvars($var)
}
}
set sorted_path_list [lsort -decreasing $path_list]
# puts "-> Found [llength $sorted_path_list]"
foreach path $sorted_path_list {
# puts "$path -> $path_array($path) ([string length $path])"
# puts $op "set vars($path_array($path)) $path"
}
foreach var [array names tvars] {
set found 0
foreach path $sorted_path_list {
if {($var == $path_array($path)) || ([string first "\[" $var] != -1)} {
break
}
# puts $op "[format "regsub -all \"%s\" \"%s\" \\$%s" $path [join $tvars($var)] $path_array($path) temp]"
if {[catch {set command [format "regsub -all \"%s\" \"%s\" \\\$vars(%s) temp" $path [join $tvars($var)] $path_array($path)]}]} {
break
}
set foo [eval $command]
if {$foo > 0} {
# puts $op "set vars($var) \"[join $temp]\""
if {[llength $temp] > 1} {
set vars($var) [join $temp]
} else {
set vars($var) $temp
}
set found 1
}
}
# if {!$found} {
# puts $op "set vars($var) \"[join $vars($var)]\""
# }
}
# foreach path $sorted_path_list {
# set vars($path_array($path)) $path
# }
# close $op
# source .setup.ff.tcl
}
proc gen_check {} {
global vars
global errors
set op [open $vars(script_dir)/check_qor.tcl w]
puts $op "#![lindex $vars(execute_string) 0]"
puts $op "if {!\[llength \$argv\]} {"
puts $op " puts \"<FF> ERROR: MISSING QOR RESULT FILE NAME\""
puts $op " exit -1"
puts $op "}"
puts $op "foreach name \$argv {"
puts $op " if {!\[file exists \$name\]} {"
puts $op " puts \"<FF> ERROR: QOR RESULT FILE MISSING (\$name)\""
puts $op " exit -1"
puts $op " }"
puts $op " file stat \$name qor_stat"
puts $op " if {!\$qor_stat(size)} {"
puts $op " continue"
puts $op " }"
puts $op " set qor_file \[open \$name r\]"
puts $op " gets \$qor_file qor_result"
puts $op " if {\[expr \$qor_result\]} {"
puts $op " exit -1"
puts $op " }"
puts $op "}"
puts $op "exit 0"
close $op
exec chmod +x $vars(script_dir)/check_qor.tcl
}
proc source_config_files {} {
global vars
global env
global user_vars
global desc
global errors
puts "<FF> LOADING CONFIGURATION FILES:"
set vars(config_files) [list]
foreach file "setup.tcl innovus_config.tcl lp_config.tcl genus_config.tcl" {
set temp [regsub "\\." $file "_"]
set vars($temp) [list]
if {[file exists $vars(setup_path)/$file]} {
FF::source_file $vars(setup_path)/$file
lappend vars($temp) $vars(setup_path)/$file
lappend vars(config_files) $vars(setup_path)/$file
}
if {($vars(setup_path) != ".") && [file exists $file]} {
FF::source_file $file
lappend vars($temp) $file
lappend vars(config_files) $file
}
if {$vars($temp) != ""} {
puts "<FF> $temp -> $vars($temp)"
}
}
foreach var [array names vars] {
set user_vars($var) $vars($var)
# puts $var
}
if {[FF::is_lp_flow]} {
set vars(required_procs) \
"source_file system_info get_clock_ports get_power_domains modify_power_domains add_power_switches \
route_secondary_pg_nets insert_welltaps_endcaps report_time buffer_always_on_nets \
save_results load_applet get_tool load_path_groups"
} else {
set vars(required_procs) \
"source_file system_info get_clock_ports report_time insert_welltaps_endcaps \
save_results load_applet get_tool load_path_groups "
}
}
proc execute_flow {step {format 1} {abort ""}} {
#
# This is the entry point, responsible for calling functions and
# aggregating results for each step in the flow
#
global vars
global dargs
global fargs
global svars
global env
global errors
if {![info exists vars(sourced)]} { set vars(sourced) 0 }
# if {![info exists vars(single)]} { set vars(single) 0 }
if {![info exists vars(catch_errors)]} { set vars(catch_errors) 0 }
if {![info exists vars(stop_step)]} { set vars(stop_step) "signoff" }
if {![info exists vars(initialized)]} { set vars(initialized) 0 }
if {![info exists vars(loaded)]} { set vars(loaded) 0 }
if {![info exists vars(bsteps)]} { set vars(bsteps) [list] }
if {![info exists env(VPATH)]} { set env(VPATH) make }
#
# If no steps are defined, set the steps to execute based upon the
# mode that the system is running in. We need to do this because the
# hierarchical flow will unset the vars() array before recursively
# calling this routine.
#
if {![info exists vars(steps)]} {
# BCL: Moved the following if / else up (it must always execute)
if {![info exists vars(mode)]} {
if {[info exists fargs(mode)]} {
set vars(mode) $fargs(mode)
} else {
set vars(mode) $dargs(mode)
}
}
# if {[info exists vars(hier)] && !$vars(hier)} {
# FF::set_steps $vars(mode) $format
# unset vars(mode)
# } else {
# FF::set_steps $vars(mode) $format
# }
}
#
# Set the procedures that we will need to include within each file that
# we create to run a step.
#
# set vars(required_procs) \
# "source_plug get_clock_ports get_power_domains report_time"
#
# Make sure that the variables are actually sourced from the
# configuration files
#
if {!$vars(sourced) && ($step != "source")} {
execute_flow "source" $format $abort
}
if {$vars(sourced)} {
if {[info exists vars(hier)] && !$vars(hier)} {
FF::set_steps $vars(mode) $format
unset vars(mode)
} else {
FF::set_steps $vars(mode) $format
}
}
#
# Execute the appropriate step per the command
#
set action ""
switch -- $step {
"source" {
if {!$vars(sourced)} {
FF_NOVUS::source_config_files
if {[info exists fargs(version)]} {
if {![regexp "^10" $fargs(version)] && ![regexp "^9" $fargs(version)]} {
FF_NOVUS::denormalize_files
}
} elseif {[info exists dargs(version)]} {
if {![regexp "^10" $dargs(version)] && ![regexp "^9" $dargs(version)]} {
FF_NOVUS::denormalize_files
}
}
foreach arg [join $vars(arg_list)] {
if {[info exists vars($arg)]} {
if {[info exists fargs($arg)]} {
if {$vars($arg) != $fargs($arg)} {
puts "<FF> WARNING: Overwriting vars($arg) from $vars($arg) to $fargs($arg) ..."
}
set vars($arg) $fargs($arg)
} else {
# Only set the farg if it wasn't set in a config file
if {![info exists vars($arg)]} {
set vars($arg) $dargs($arg)
}
}
} else {
if {[info exists fargs($arg)]} {
set vars($arg) $fargs($arg)
} else {
set vars($arg) $dargs($arg)
}
}
}
FF_NOVUS::seed_variables
# FF_NOVUS::check_setup
# FF_NOVUS::normalize_files
set vars(sourced) true
set vars(top_cell) $vars(design)
}
}
"source_only" {
# BCL: Added this in since i want to source the variables w/out calling check_setup
if {!$vars(sourced)} {
FF_NOVUS::source_config_files
if {[info exists fargs(version)]} {
if {![regexp "^10" $fargs(version)] && ![regexp "^9" $fargs(version)]} {
FF_NOVUS::denormalize_files
}
} elseif {[info exists dargs(version)]} {
if {![regexp "^10" $dargs(version)] && ![regexp "^9" $dargs(version)]} {
FF_NOVUS::denormalize_files
}
}
foreach arg [join $vars(arg_list)] {
if {[info exists vars($arg)]} {
if {[info exists fargs($arg)]} {
if {$vars($arg) != $fargs($arg)} {
puts "<FF> WARNING: Overwriting vars($arg) from $vars($arg) to $fargs($arg) ..."
}
set vars($arg) $fargs($arg)
} else {
# Only set the farg if it wasn't set in a config file
if {![info exists vars($arg)]} {
set vars($arg) $dargs($arg)
}
}
} else {
if {[info exists fargs($arg)]} {
set vars($arg) $fargs($arg)
} else {
set vars($arg) $dargs($arg)
}
}
}
FF_NOVUS::seed_variables
# FF_NOVUS::check_setup
# FF_NOVUS::normalize_files
# set vars(sourced) true
set vars(top_cell) $vars(design)
}
}
"check" {
if {$abort == ""} {
set abort $vars(abort)
}
set save $vars(abort)
set vars(abort) $abort
set vars(abort) $save
if {![info exists vars(mode)]} {
if {[info exists fargs(mode)]} {
set vars(mode) $fargs(mode)
} else {
set vars(mode) $dargs(mode)
}
}
if {$vars(mode) == "hier"} {
if {![info exists vars(partition_list)]} {
puts "<FF> FLOW MODE $vars(mode) SELECTED BUT \$vars(partition_list) NOT DEFINED"
exit 99
}
if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
FF_NOVUS::check_setup
}
} else {
FF_NOVUS::check_setup
}
FF::process_file_lists
}
"all" {
#
# We have already sourced in all of the files. Now execute the
# rest of the steps, including check
#
puts "-------------------------------------------------"
puts "<FF> Generating scripts for $vars(design)"
puts "-------------------------------------------------"
execute_flow check $format $abort
set vars(steps) [join $vars(steps)]
set vars(all) true
set commands ""
if {$vars(mode) == "hier"} {
if {[file tail [file dirname [pwd]]] == "$vars(partition_dir)"} {
set all_steps $vars(fsteps)
} else {
set all_steps $vars(hsteps)
}
} else {
if {!$vars(generate_flow_steps)} {
file mkdir $vars(script_dir)/INNOVUS
set fhr [open $vars(script_path)/INNOVUS/run_all.tcl r]
set fhw [open $vars(script_dir)/INNOVUS/run_all.tcl w]
while {[gets $fhr line]>=0} {
regsub "source FF" $line "source $vars(script_dir)" line
puts $fhw " $line"
}
close $fhr
close $fhw
}
set all_steps $vars(steps)
}
#
# Execute each step of the flow and get a composite list of the
# actual steps that had actions generated for them. Then create
# a Makefile for those steps
#
if {[info exists vars(rc_steps)]} {
set actions $vars(rc_steps)
} else {
set actions [list]
}
#
foreach step $all_steps {
set commands [execute_flow $step $format $abort]
if {$commands != ""} {
lappend actions $commands
}
}
#set vars(make_tool_args) "-nowin -64"
if {($vars(user_mode) == "hier") && ($vars(hier_flow_type) == "2pass")} {
# Only generate steps up to (and including) cts for 2pass flows
# Go ahead and generate both Makefiles as the actions are known
if {$vars(enable_flexilm)} {
if {$vars(place_opt_design)} {
if {[file tail [pwd]] == $vars(top_cell)} {
set index [lsearch $actions "prects"]
} else {
set index [lsearch $actions "place"]
}
} else {
set index [lsearch $actions "prects"]
}
FF::gen_makefile [lrange $actions [expr $index+1] end] $vars(mode)
file copy -force Makefile Makefile.pass2
FF::gen_makefile [lrange $actions 0 $index] $vars(mode)
} else {
set index [lsearch $actions "cts"]
FF::gen_makefile [lrange $actions [expr $index+1] end] $vars(mode)
file copy -force Makefile Makefile.pass2
FF::gen_makefile [lrange $actions 0 $index] $vars(mode)
}
} else {
FF::gen_makefile $actions $vars(mode)
}
if {$vars(enable_qor_check)} {
FF_NOVUS::gen_check
}
execute_flow debug $format $abort
if {[info exists vars(run_lec)] && $vars(run_lec)} {
execute_flow lec $format $abort
}
}
"lec" {
# puts "-------------------------------------------------"
# puts "<FF> Generating scripts for $vars(design)"
puts "-------------------------------------------------"
if {![info exists vars(netlist)]} {
puts "<FF> Cannot generate 'lec' step w/o verilog netlist defined"
} else {
if {!$vars(generate_flow_steps)} {
file mkdir $vars(script_dir)/INNOVUS
set op [open $vars(script_dir)/INNOVUS/run_lec.tcl w]
puts $op "//"
puts $op "// Innovus Foundation Flow Code Generator, [exec date]"
puts $op "//"
if {$step == "lec"} {
puts $op "tclmode"
}
#puts $op "if {\[file exists .ff.tcl\]} {"
#puts $op " source .ff.tcl"
#puts $op "}"
set varsFile [FF::relPathTo [file normalize $vars(script_dir)/vars.tcl] [file normalize $vars(rundir)]]
puts $op "if {\[file exists $varsFile\]} {"
puts $op " source $varsFile"
puts $op "}"
puts $op "source $vars(script_dir)/procs.tcl"
puts "<FF> Generating step $step"
set commands [FF_NOVUS::run_lec]
puts $op [FF::pretty_print $commands $format]
close $op
}
}
# FF::gen_makefile lec $vars(mode)
}
"default" {
#
# Run each step either singuarly or recursively
#
#
# Create the list of commands that happen at the begining of
# each script
#
if {([lsearch $vars(steps) $step] == -1) && ($step != "debug")} {
puts "<FF> ERROR: Unknown Foundation Flow step \"$step\"."
exit 99
}
# if {([lsearch $vars(steps) $step] == -1) && ($step != "debug")} {
# puts "<FF> ERROR: Unknown Foundation Flow step \"$step\"."
# exit 99
# } else {
# if {($vars(fix_hold) || (!$vars(fix_hold) && ![regexp "_hold" $step])) &&
# !($vars(skip_cts) && (($step == "cts") || [regexp "postcts" $step]))} {
# puts "<FF> Generating step $step"
# }
# }
#
# We need to ensure that we check the variable contents and
# initialize the flow at least once in a given run, no matter
# what step the user wants to execute
#
# set header "\n#\n# Commands for $step\n#\n\n"
if {![info exists vars(all)]} {
execute_flow check $format $abort
}
# BCL: Changed to tcl file mkdir
file mkdir $vars(script_dir)/INNOVUS
set commands ""
# set commands "post-10.10-b009\n"
if {!$vars(initialized)} {
set vars(step) $step
append commands [FF_NOVUS::initialize_flow]
# unset vars(step)
set vars(init_commands) $commands
set vars(initialized) 1
if {![info exists vars(warning_count)]} {
set vars(warning_count) 0
}
if {![info exists vars(error_count)]} {
set vars(error_count) 0
}
}
#
# Get the commands to execute the step. We also need to get the
# commands to load the database for that step, assuming that a
# database exists from a prior step. Those load commands are
# prepended to the execution commands. Save commands are
# appended
#
if {[info commands ::FF_NOVUS::run_$step] ne ""} {
set temp_commands [FF_NOVUS::run_$step $format]
if {$temp_commands == ""} {
return ""
} else {
if {$vars(step) != "init"} {
set step_commands "\n#-------------------------------------------------------------\n"
if {$vars(report_run_time)} {
append step_commands "set vars(step) ${step}\n"
append step_commands "set vars(${step},start_time) \[clock seconds\]\n"
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append step_commands "push_snapshot_stack\n"
}
}
append step_commands "#-------------------------------------------------------------\n\n"
}
append step_commands $temp_commands
append step_commands "#-------------------------------------------------------------\n\n"
puts "<FF> Generating step $step"
}
} elseif {[info exists vars(custom_step_dir)]} {
if {[file isfile $vars(custom_step_dir)/run_${step}.tcl]} {
puts "<FF> Generating step $step"
set fhr [open $vars(custom_step_dir)/run_$step.tcl r]
set step_commands "\n#-------------------------------------------------------------\n"
append step_commands "# Sourcing custom script ...\n"
append step_commands "#-------------------------------------------------------------\n"
if {$vars(report_run_time) && ($step != "init")} {
append step_commands "set vars(step) ${step}\n"
append step_commands "set vars(${step},start_time) \[clock seconds\]\n"
}
if {$vars(capture_metrics) && ($vars(step) != "init")} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append step_commands "push_snapshot_stack\n"
}
}
append step_commands "#-------------------------------------------------------------\n\n"
while {[gets $fhr line]>=0} {
append step_commands "$line\n"
}
# append step_commands "source $vars(custom_step_dir)/run_$step.tcl\n"
append step_commands "#-------------------------------------------------------------\n\n"
} else {
puts "<FF> ERROR: Unable to generate step $step"
set errors($vars(error_count)) "Unable to generate step $step - procedure 'run_$step' must be defined or a \$vars(custom_step_dir)/run_$step.tcl file must be provided"
incr vars(error_count)
return ""
}
} else {
puts "<FF> ERROR: Unable to generate step $step"
set errors($vars(error_count)) "Unable to generate step $step - procedure 'run_$step' must be defined or a \$vars(custom_step_dir)/run_$step.tcl file must be provided"
incr vars(error_count)
return ""
}
set this_index [lsearch $vars(steps) $step]
set prior [lindex $vars(steps) [expr $this_index - 1]]
# if {!$vars(fix_hold) && [regexp _hold $prior]} {
# set prior [lindex $vars(steps) [expr $this_index - 2]]
# if {[regexp _hold $prior]} {
# set prior [lindex $vars(steps) [expr $this_index - 3]]
# }
# }
if {[regexp _hold $prior] && ([lsearch $vars(fix_hold) [regsub _hold $prior ""]]<0)} {
set prior [lindex $vars(steps) [expr $this_index - 2]]
if {[regexp _hold $prior] && ([lsearch $vars(fix_hold) [regsub _hold $prior ""]]<0)} {
set prior [lindex $vars(steps) [expr $this_index - 3]]
}
}
if {($step == "cts") && $vars(place_opt_design)} {
set prior "place"
}
if {($step == "route") && $vars(skip_cts)} {
set prior "prects"
}
# if {($step == "route") && [regexp "^ccopt" [string tolower $vars(cts_engine)]]} {
# set prior "cts"
# }
if {[regexp "^ccopt" [string tolower $vars(cts_engine)]]} {
if {([string tolower $vars(fix_hold)] != "false")} {
if {($step == "postcts_hold") && [lsearch $vars(fix_hold) $step]} {
set prior cts
} else {
if {($step == "route")} {
set prior cts
}
}
} else {
if {($step == "route")} {
set prior cts
}
}
}
set this_index [lsearch [FF::adjust_steps] $step]
set prior [lindex [FF::adjust_steps] [expr $this_index - 1]]
set no_db_steps [list "init" "rebudget" "flexilm" "assemble" "assemble_flexilm" "debug"]
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
lappend no_db_steps "model_gen"
} else {
lappend no_db_steps "feedthrough"
}
if {([lsearch $no_db_steps $step] == -1) && ($prior != "")} {
set load_commands [FF_NOVUS::load_design $prior $step]
# set restore_commands [lindex [FF_NOVUS::load_design $format $prior] 1]
} else {
set load_commands ""
# set restore_commands ""
}
if {!$vars(loaded)} {
set vars(loaded) 1
append commands $load_commands
}
# model_gen saves its database explicitly
# set no_save_steps [list "debug" "model_gen"]
set no_save_steps [list "debug"]
if {[lsearch $no_save_steps $step] == -1} {
set save_commands [FF_NOVUS::save_results $step $format]
} else {
set save_commands ""
}
#
# Write the commands to a file, named for the step we are
# executing
#
# if {!$vars(generate_flow_steps)} {
if {[regexp "^syn" $step]} {
file mkdir $vars(script_dir)/GENUS
set op [open $vars(script_dir)/GENUS/run_${step}.tcl w]
} else {
set op [open $vars(script_dir)/INNOVUS/run_${step}.tcl w]
}
# if {$vars(debug)} {
# puts "<DEBUG> Opening file: $vars(script_dir)/INNOVUS/run_${step}.tcl in [exec pwd] -> $op"
# }
puts $op [string repeat "#" 68]
puts $op "# Innovus Foundation Flow Code Generator, [exec date]"
puts $op "# Version : 17.10-p003_1"
puts $op [string repeat "#" 68]
if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
set varsFile [FF::relPathTo [file normalize $vars(script_dir)/vars.tcl] [file normalize $vars(rundir)]]
} else {
set varsFile $vars(script_dir)/vars.tcl
}
puts $op "\nif {\[file exists $varsFile\]} {"
puts $op " source $varsFile"
puts $op "}"
#puts $op "if {\[file exists \$vars(script_dir)/vars.tcl\]} {"
#puts $op " source \$vars(script_dir)/vars.tcl"
#puts $op "}\n"
if {!$vars(freeze_vars)} {
if {([file tail [file dirname [pwd]]] != "$vars(partition_dir)") && ![regexp syn_ $step]} {
puts $op "foreach file \$vars(config_files) {"
puts $op " source \$file"
puts $op "}\n"
}
}
puts $op "source \$vars(script_dir)/procs.tcl"
puts $op "source $vars(script_dir)/procs.tcl"
if {!$format} {
puts $op $header
}
regsub -all "init," $vars(init_commands) "$step," commands
set of [open $vars(script_dir)/INNOVUS/.head w]
puts $of [FF::pretty_print $vars(init_commands) $format]
close $of
append commands $load_commands $step_commands $save_commands
# set commands ""
# if {($step != "partition") && ($step != "rebudget") && ($step != "flexilm")} {
# if {![regexp _hold $step]} {
# append commands $load_commands $step_commands $save_commands
# } else {
## if {!([lsearch $vars(fix_hold) [regsub _hold $step ""]]<0)} {
## append commands $step_commands
## } else {
# append commands $load_commands $step_commands $save_commands
## }
# }
## if {$step == "debug"} {
## set vars(step) debug
## }
# } else {
# append commands $load_commands $step_commands
# }
lappend vars(bsteps) $step
set of [open $vars(script_dir)/INNOVUS/.load_$step w]
# puts $of [FF::pretty_print $restore_commands $format]
puts $of [FF::pretty_print $load_commands $format]
close $of
set of [open $vars(script_dir)/INNOVUS/.$step w]
puts $of [FF::pretty_print $step_commands $format]
puts $of [FF::pretty_print $save_commands $format]
close $of
# if {[regexp "postroute_si" $step] && $skip_commands != ""} {
# set commands $skip_commands
# }
if {!$format} {
set commands [FF::strip_lines $commands [list "puts" "#"]]
}
if {$vars(catch_errors) && ($step != "debug")} {
puts $op "\nif { \[catch {\n"
puts $op [FF::pretty_print $commands $format]
puts $op "} step_error\]} {\n"
puts $op " puts \"<FF> =========== STEP EXECUTION ERROR ============\""
puts $op " puts \"<FF> ERROR RUNNING STEP '$step'\""
if {$vars(save_on_catch)} {
if {[regexp "^syn" $vars(step)]} {
puts $op " write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).catch.db\n"
} else {
puts $op " puts \"<FF> ---------------------------------------------\""
puts $op " puts \"<FF> ... SAVING DESIGN TO $vars(dbs_dir)/$vars(step).catch.enc\""
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
puts $op " write_db -oa_lib_cell_view {$vars(oa_design_lib) $vars(design) $vars(step).catch}\n"
} else {
puts $op " saveOaDesign $vars(oa_design_lib) $vars(design) $vars(step).catch\n"
}
} else {
puts $op " write_db $vars(dbs_dir)/$vars(step).catch.enc\n"
}
}
}
puts $op " puts \"<FF> ---------------------------------------------\""
puts $op " puts \"<FF> \$step_error\""
puts $op " puts \"<FF> ------------------- DETAILS ------------------\""
puts $op " puts \"<FF> \$errorInfo\""
puts $op " puts \"<FF> ==============================================\""
if {$vars(batch)} {
puts $op " exit -1"
}
puts $op "}"
} else {
puts $op [FF::pretty_print $commands $format]
}
if {$vars(batch) && ($step != "debug")} {
puts $op "if {!\[info exists vars(single)\]} {\n exit 0\n}\n"
}
close $op
# }
set scommands [split $commands "\n"]
if {$vars(generate_flow_steps)} {
append vars(flow_steps) "\ncreate_flow_step -name $step \{\n"
if {[info exists vars(hsteps)] && ([lsearch $vars(hsteps) $step] != -1)} {
append vars(flow_steps,hier) "\ncreate_flow_step -name $step \{\n"
} else {
append vars(flow_steps,flat) "\ncreate_flow_step -name $step \{\n"
}
set skip 0
foreach line $scommands {
if {$skip != 0} {
set skip [expr $skip-1]
continue
}
if {[regexp ff_procs $line]} { continue }
# if {[regexp "#" $line]} { continue }
if {[regexp "ERROR LOADING DATABASE" $line]} { continue }
if {[regexp "Plugin ->" $line]} { continue }
# if {[regexp "Puts" $line]} { regsub Puts $line puts line }
# if {[regexp "Puts \"<FF>" $line]} { continue }
if {[regexp "VPATH" $line]} { continue }
if {[regexp "set vars" $line] && ![regexp ",post_cts_sdc" $line] && ![regexp "active_rc_corners" $line]} { continue }
if {($step == "init") && $vars(rc)} {
# if {[regexp "read_mmmc" $line]} { continue }
# if {[regexp "read_netlist" $line]} { continue }
# if {[regexp "read_physical" $line]} { continue }
# if {[regexp "init_design" $line]} { continue }
if {[regexp "read_mmmc" $line]} { regsub read_mmmc $line "#read_mmmc" line }
if {[regexp "read_netlist" $line]} { regsub read_netlist $line "#read_netlist" line }
if {[regexp "read_physical" $line]} { regsub read_physical $line "#read_physical" line }
if {[regexp "init_design" $line]} { regsub init_design $line "#init_design" line }
}
if {$step != "init"} {
if {[regexp "restore_design" $line]} { set skip 7; continue }
if {!(($step == "cts") && $vars(enable_flexilm))} {
if {[regexp "read_db" $line]} { continue }
} else {
if {[regexp "read_db" $line]} {
# set line [string trim [lindex $line 2]]
set line "read_db \[file tail \[pwd\]\]_post_eco.enc\n"
}
}
}
if {[regexp "write_db " $line]} { continue }
if {[regexp "metric" $line]} { continue }
if {[regexp "snapshot" $line]} { continue }
if {[regexp "report_metric" $line]} { continue }
if {$line == ""} { continue }
#if {$step == "init"} { puts $line }
append vars(flow_steps) "\t$line\n"
if {[info exists vars(hsteps)] && ([lsearch $vars(hsteps) $step] != -1)} {
append vars(flow_steps,hier) "\t$line\n"
} else {
append vars(flow_steps,flat) "\t$line\n"
}
}
append vars(flow_steps) "\}\n"
if {[info exists vars(hsteps)] && ([lsearch $vars(hsteps) $step] != -1)} {
if {$step == "partition"} {
foreach p $vars(partition_list) {
append vars(flow_steps,hier) "\n\tschedule_flow -flow block -directory $vars(partition_dir)/$p\n"
}
}
if {$step == "assemble_flexilm"} {
foreach p $vars(partition_list) {
append vars(flow_steps,hier) "\n\tschedule_flow -flow block -directory $vars(partition_dir)_PRECTS/$p\n"
}
}
if {($step == "assemble") || ($step == "partition")} {
append vars(flow_steps,hier) "\n\} \n"
} else {
append vars(flow_steps,hier) "\n\}\n"
}
} else {
if {([file tail [file dirname [pwd]]] == "$vars(partition_dir)")} {
if {$step == "signoff"} {
if {[lsearch $vars(partition_list) $vars(design)] == -1} {
append vars(flow_steps,flat) "\n\tschedule_flow -flow final_assembly -directory ../.. -no_db\n"
} else {
if {$vars(enable_flexilm)} {
# append vars(flow_steps,flat) "\n\tschedule_flow -flow top -directory $vars(partition_dir)_PRECTS/$vars(top_cell)\n"
append vars(flow_steps,flat) "\n\tschedule_flow -flow top -directory ../$vars(top_cell) -no_db -sync\n"
} else {
# append vars(flow_steps,flat) "\n\tschedule_flow -flow top -directory $vars(partition_dir)/$vars(top_cell)\n"
append vars(flow_steps,flat) "\n\tschedule_flow -flow top -directory ../$vars(top_cell) -no_db -sync\n"
}
}
}
if {$step == "prects" && $vars(enable_flexilm)} {
if {[lsearch $vars(partition_list) $vars(design)] == -1} {
append vars(flow_steps,flat) "\n\tschedule_flow -flow intermediate_assembly\n"
} else {
append vars(flow_steps,flat) "\n\tschedule_flow -flow top -directory $vars(partition_dir)/$vars(top_cell)\n"
}
}
} else {
if {[regexp syn_ $step]} {
if {$vars(rc)} {
if {$vars(enable_rcp) && ($step == "syn_place")} {
append vars(flow_steps,flat) "\n\tschedule_flow -flow innovus -db \"$vars(dbs_dir)/syn_place/syn_place.enc_setup.tcl\"\n"
} elseif {!$vars(enable_rcp) && ($vars(step) == "syn_incr")} {
append vars(flow_steps,flat) "\n\tschedule_flow -flow innovus -db \"$vars(dbs_dir)/syn_incr/syn_incr.enc_setup.tcl\"\n"
}
}
# append vars(flow_steps,flat) "\}\n"
} else {
# append vars(flow_steps,flat) "\}\n"
}
}
append vars(flow_steps,flat) "\}\n"
}
}
set action $step
}
}
#
# Create a file that sets up all of the variable settings that were
# used in this invocation
#
return $action
}
proc insert_comments {} {
global vars
set comments ""
append comments "######################################################################\n"
append comments "# Variables affecting this step:\n"
append comments "#---------------------------------------------------------------------\n"
if {[info exists vars(comments)]} {
append comments $vars(comments)
unset vars(comments)
} else {
append comments "# No variables defined for this step ...\n"
}
append comments "######################################################################\n"
if {[info exists vars(ucomments)]} {
append comments "# Additional variables for this step:\n"
append comments "#---------------------------------------------------------------------\n"
append comments $vars(ucomments)
append comments "######################################################################\n"
unset vars(ucomments)
}
return $comments
}
proc run_all {} {
global vars
set time 0
set index 0
set stop_step signoff
set vars(codegen) false
if {![info exists vars(vpath)]} { set vars(vpath) make }
foreach step $vars(steps) {
if {[file exists $vars(vpath)/$step]} {
if {[file mtime $vars(vpath)/$step] > $time} {
if {[lindex $vars(steps) $index] == "signoff"} {
puts "<FF> STEP signoff COMPLETE ... NOTHING TO DO"
} else {
set start_step [lindex $vars(steps) [expr $index + 1]]
}
}
} else {
set start_step $step
break
}
incr index
}
puts "<FF> -----------------------------------------------------"
if {$start_step == $stop_step} {
puts "<FF> RUNNING STEP $start_step ..."
} else {
puts "<FF> RUNNING STEP $start_step through $stop_step ..."
}
puts "<FF> -----------------------------------------------------"
sleep 5
#
# Emulate the functionality of the "make" program. If a file doesn't exist,
# or if it's predecessor step has executed more recently, run the current
# step and update the time/date stamps of the files we track progress with
#
set vars(stop_step) $stop_step
set last_step ""
set vars(restore_design) 1
if {$vars(enable_qor_check)} {
set check_qor $vars(script_dir)/check_qor.tcl
}
exec mkdir -p make
foreach step $vars(steps) {
set vars(step) $step
puts "<FF> STEP $vars(step) ..."
set this_semaphore "$vars(vpath)/$step"
set last_semaphore "$vars(vpath)/$last_step"
set run_step false
if {![file exists $this_semaphore]} {
set run_step true
} elseif {$last_step != ""} {
file stat $this_semaphore this_stat
file stat $last_semaphore last_stat
if {$this_stat(mtime) < $last_stat(mtime)} {
set run_step true
}
}
#
# Check the quality of results from the last step. If the results aren't
# as expected, don't proceed to the next step
#
if {$vars(enable_qor_check)} {
if {$step != "init"} {
set qor [catch {exec $check_qor $last_semaphore} msg]
if {$qor} {
puts "<FF> ERROR: QOR RESULT CHECK INDICATES A PROBLEM IN STEP $last_step"
exit -111
}
}
}
set last_step $step
if {!$run_step} {
continue
}
#
# Source the control file that runs the step. If it had an error, exit
# immediately. Otherwise, update the time/date stamp of the corresponding
#
#
if {[catch {FF_NOVUS::run_$step} message]} {
puts $message
exit -111
}
set vars(restore_design) 0
#
# If there is a QOR check file for this step, execute it and place the
# result into the make file. Otherwise just touch the file
#
if {$vars(enable_qor_check)} {
if {[info exists vars($step,qor_tcl]} {
set qor_file $vars($step,qor_tcl)
if {[file exists $qor_file]} {
set qor [catch {exec $qor_file} msg]
set make_file [open $this_semaphore w]
puts $make_file "$qor"
close $make_file
}
}
}
exec /bin/touch $this_semaphore
if {$step == $stop_step} {
puts "<FF> Done"
}
}
}
proc load_power_intent {} {
global vars
set commands ""
if {[info exists vars(cpf_file)]} {
if {[file extension $vars(cpf_file)] == ".cpfdb"} {
set command "read_power_intent -msvDB $vars(cpf_file)\n"
} else {
set command "read_power_intent -cpf $vars(cpf_file)\n"
}
append commands [FF::wrap_command $vars(step),read_power_intent $command]
set command "commit_power_intent"
if {$vars(cpf_power_domain)} {
append command " -power_domain"
}
if {[info exists vars(cpf_keep_rows)] && $vars(cpf_keep_rows)} {
if {$vars(novus)} {
append command " -keep_rows"
} else {
append command " -keepRows"
}
}
if {$vars(cpf_isolation)} {
append command " -isolation"
}
if {$vars(cpf_state_retention)} {
append command " -state_retention"
}
if {$vars(cpf_level_shifter)} {
append command " -level_shifter"
}
if {$vars(cpf_power_switch)} {
append command " -power_switch"
}
append command "\n"
append commands [FF::wrap_command $vars(step),commit_power_intent $command]
} elseif {[info exists vars(ieee1801_file)]} {
set command "read_power_intent $vars(ieee1801_file) -1801\n"
append commands [FF::wrap_command $vars(step),read_power_intent $command]
set command "commit_power_intent"
if {$vars(ieee1801_power_domain)} {
append command " -power_domain"
}
if {[info exists vars(ieee1801_keep_rows)] && $vars(ieee1801_keep_rows)} {
append command " -keepRows"
}
append command "\n"
append commands [FF::wrap_command $vars(step),commit_power_intent $command]
}
return $commands
}
proc dump_novus_attributes {} {
global vars
set map(activity_file_format) "# read_activity_file <file> -format"
set map(assign_buffer) defunct
set map(budget_mode) "set_db budget_virtual_opt_engine"
set map(capture_metrics) "# enable_metrics -on"
set map(ccopt_effort) defunct
set map(ccopt_integration) defunct
set map(cdb_file) defunct
set map(clk_leaf_bottom_layer) "# create_route_type -name leaf -bottom_preferred_layer <layer> -top_preferred_layer <layer> -shield_net <net> -non_default_rule <ndr>"
set map(clk_leaf_top_layer) "# create_route_type -name leaf -bottom_preferred_layer <layer> -top_preferred_layer <layer> -shield_net <net> -non_default_rule <ndr>"
set map(clk_max_skew) "set_db cts_target_skew"
set map(clk_max_slew) "set_db cts_target_max_transition_time"
set map(clk_tree_shield_net) "# create_route_type -name leaf -bottom_preferred_layer <layer> -top_preferred_layer <layer> -shield_net <net> -non_default_rule <ndr>"
set map(clk_tree_shield_thresh) "set_db cts_routing_top_min_fanout"
set map(clk_tree_bottom_layer) "# create_route_type -name top -bottom_preferred_layer <layer> -top_preferred_layer <layer> -shield_net <net> -non_default_rule <ndr>"
set map(clk_tree_top_layer) "# create_route_type -name top -bottom_preferred_layer <layer> -top_preferred_layer <layer> -shield_net <net> -non_default_rule <ndr>"
set map(clock_gate_aware) "set_db place_global_clock_gate_aware"
set map(congestion_effort) "set_db place_global_cong_effort"
set map(cpf_file) "# read_power_intent -cpf <file>"
set map(cpf_isolation) defunct
set map(cpf_keep_rows) defunct
set map(cpf_level_shifter) defunct
set map(cpf_power_domain) defunct
set map(cpf_power_switch) defunct
set map(cpf_state_retention) defunct
set map(cpf_timing) defunct
set map(cpus_per_remote_host) "set_multi_cpu_usage -cpu_per_remote_host"
set map(flexmodel_as_ptn) "set_db proto_create_partition_as_flexmodel"
set map(create_flexfiller_blockage) "set_db proto_flexfiller_route_blockage"
set map(cts_buffer_cells) "set_db cts_buffer_cells"
set map(cts_engine) none
set map(cts_inverter_cells) "set_db cts_inverter_cells"
set map(cts_use_inverters) "set_db cts_use_inverters"
set map(dbs_dir) "set_db flow_database_directory"
set map(delta_delay_threshold) "set_db si_delay_delta_threshold"
set map(enable_aocv) "set_db timing_analysis_aocv"
set map(enable_socv) "set_db timing_analysis_socv"
set map(enable_cppr) "set_db timing_analysis_cppr"
set map(enable_flexilm) "# none : possible future hier flow option"
set map(enable_lvs) "# none : possible future flow option"
set map(enable_nrgr) defunct
set map(enable_ocv) "set_db timing_analysis_type ocv"
set map(enable_pac) defunct
set map(enable_pam) "# none : possible future flow option"
set map(enable_qor_check) defunct
set map(enable_rcp) "# none : current flow template option"
set map(enable_si_aware) "set_db delaycal_enable_si"
set map(enable_signoff_eco) "# none : possible future flow option"
set map(enable_ss) defunct
set map(filler_cells) "set_db add_fillers_cells"
set map(fix_fanout_load) "set_db opt_fix_fanout_load"
set map(fix_hold_ignore_ios) "set_db fix_hold_ignore_path_groups"
set map(fix_litho) "set_db route_design_detail_post_route_litho_repair"
set map(flow_effort) "set_db design_flow_effort"
set map(add_tracks) "# add_tracks"
set map(ground_nets) "set_db init_ground_nets"
set map(high_timing_effort) defunct
set map(ieee1801_file) "# read_power_intent -1801"
set map(ieee1801_isolation) defunct
set map(ieee1801_keep_rows) defunct
set map(ieee1801_level_shifter) defunct
set map(ieee1801_power_domain) defunct
set map(ieee1801_power_switch) defunct
set map(ieee1801_state_retention) defunct
set map(ieee1801_timing) defunct
set map(litho_driven_routing) "set_db route_design_with_litho_driven"
set map(local_cpus) "set_multi_cpu_usage -local_cpu"
set map(log_dir) "set_db flow_log_directory"
set map(max_route_layer) "set_db route_top_routing_layer"
set map(multi_cut_effort) "set_db route_design_detail_use_multi_cut_via_effort"
set map(oa_abstract_name) "set_db init_oa_abstract_views"
set map(oa_layout_name) "set_db init_oa_layout_views"
set map(oa_design_cell) "set_db init_oa_design_cell"
set map(oa_design_lib) "set_db init_oa_design_lib"
set map(oa_design_view) "set_db init_oa_design_view"
set map(place_io_pins) "set_db place_global_place_io_pins"
set map(power_analysis_view) "set_db power_view"
set map(power_effort) "set_db design_power_effort"
set map(power_nets) "set_db init_power_nets"
set map(postroute_extraction_effort) "set_db extract_rc_effort_level"
set map(process) "set_db design_process_node"
set map(remote_hosts) "set_multi_cpu_usage -remote_hosts"
set map(resize_shifter_and_iso_insts) "set_db opt_resize_level_shifter_and_iso_insts"
set map(route_clock_nets) none
set map(signoff_extraction_effort) "set_db extract_rc_effort_level"
set map(skew_buffers) "set_db opt_clock_skew_buffer_cells"
set map(superhosts) defunct
set map(superthreads) defunct
set map(threads) defunct
set map(tie_cells) "set_db add_tieoffs_cells"
set map(tie_cells,max_fanout) "set_db add_tieoffs_max_distance"
set map(top_cell) "# \[get_db designs .name\]"
set map(tquantus_file) defunct
set map(update_io_latency) "set_db cts_update_io_latency"
set map(use_proto_net_delay_model) "set_db proto_use_timing_net_delay_model"
file mkdir $vars(script_dir)
file delete $vars(script_dir)/attributes.tcl
set op [open $vars(script_dir)/.attributes.tcl w]
foreach var [array names vars] {
if {[info exists map($var)]} {
if {($map($var) == "none") || ($vars($var) == "")} {
continue
}
if {$map($var) == "defunct"} {
# puts $op "# vars($var) is $map($var)"
} else {
if {[llength $vars($var)] > 1} {
puts $op "$map($var) \[list $vars($var)\] ; # $var "
} elseif {[regexp "^#" $map($var)]} {
# puts $op "$map($var) ; # $var "
} else {
if {$var == "process"} {
set vars($var) [regsub "nm" $vars(process) ""]
}
if {$var == "enable_ocv"} {
set $vars($var) ""
}
puts $op "$map($var) $vars($var) ; # $var "
}
}
}
}
close $op
exec cat $vars(script_dir)/.attributes.tcl | sort > $vars(script_dir)/attributes.tcl
file delete $vars(script_dir)/.attributes.tcl
}
proc convert_plugins {} {
global vars
global warnings
set anchor(always_source_tcl) "before init_floorplan"
set anchor(final_always_source_tcl) "before block_finish"
set anchor(pre_init_tcl) "before init_design"
set anchor(post_init_tcl) "after add_tracks"
set anchor(pre_place_tcl) "before run_place_opt"
set anchor(post_place_tcl) "after run_place_opt"
if {[lindex [split $vars(version) "."] 0] > 16} {
set anchor(pre_cts_tcl) "before add_clock_spec"
set anchor(post_cts_tcl) "after add_clock_tree"
} else {
set anchor(pre_cts_tcl) "before build_clock_tree"
set anchor(post_cts_tcl) "after build_clock_tree"
}
set anchor(pre_route_tcl) "before run_route"
set anchor(post_route_tcl) "after run_route"
set anchor(pre_postroute_tcl) "before run_opt_postroute"
set anchor(post_postroute_tcl) "after run_opt_postroute"
#set anchor(pre_signoff_tcl) "before run_sta"
#set anchor(post_signoff_tcl) "after run_sta"
set step(pre_init_tcl) "init"
set step(post_init_tcl) "init"
set step(pre_place_tcl) "place"
set step(post_place_tcl) "place"
set step(pre_cts_tcl) "cts"
set step(post_cts_tcl) "cts"
set step(pre_route_tcl) "route"
set step(post_route_tcl) "route"
set step(pre_postroute_tcl) "postroute"
set step(post_postroute_tcl) "postroute"
set step(pre_signoff_tcl) "signoff"
set step(post_signoff_tcl) "signoff"
set cf [open convert_plugins.tcl w]
#file delete -force .fftmp
#file mkdir .fftmp
set new_plugs [list]
set old_plugs [list]
foreach plug $vars(plugins_defined) {
if {[file exists $vars(plug_dir)/$vars($plug)]} {
set plug_file [file normalize $vars(plug_dir)/$vars($plug)]
lappend old_plugs "$plug $vars(plug_dir)/$vars($plug)"
} else {
if {[file exists $vars($plug)]} {
set plug_file $vars($plug)
lappend old_plugs "$plug $vars($plug)"
} else {
continue
}
}
#puts $cf "convert_legacy_to_common_ui $plug_file .fftmp/[file tail $plug_file]"
#lappend new_plugs "$plug .fftmp/[file tail $plug_file]"
#puts $cf "convert_legacy_to_common_ui $plug_file [file dirname $plug_file]_cui/[file tail $plug_file]"
puts $cf "file mkdir converted_plugins"
puts $cf "convert_legacy_to_common_ui $plug_file converted_plugins/[file tail $plug_file]"
lappend new_plugs "$plug cui.$plug_file"
}
puts $cf "exit"
close $cf
if {![info exists vars(convert_plugins)] || ([info exists vars(convert_plugins)] && !$vars(convert_plugins))} {
# Puts "<FF> Converting [llength $vars(plugins_defined)] plugins ..."
# if {[catch {eval "exec innovus -nowin -novus_ui -files .convert_plugins.tcl"}]} {
# puts "<FF> WARNING: Cannot find Innovus in your path so plugins will not be converted"
# set warnings($vars(warning_count)) "Cannot find Innovus in your path so plugins will not be converted"
# incr vars(warning_count)
# return
# }
}
file mkdir $vars(script_dir)
set of [open $vars(script_dir)/plug_steps.tcl w]
set plug_dict [join $new_plugs]
set plug_dict [join $old_plugs]
foreach key [dict keys $plug_dict] {
#puts "$key -> [dict get $plug_dict $key]"
set ip [open [dict get $plug_dict $key] r]
if {[info exists vars(legacy_plugins)] && $vars(legacy_plugins)} {
puts $of "create_flow_step -name [regsub "_tcl" $key "_plug"] -legacy \{"
} else {
puts $of "create_flow_step -name [regsub "_tcl" $key "_plug"] \{"
}
foreach file $vars(config_files) {
puts $of "source $file"
}
if {[info exists step($key)]} {
puts $of "set vars(step) $step($key)"
}
while {[gets $ip line]>=0} {
puts $of " $line"
}
puts $of "\}"
if {[info exists anchor($key)]} {
puts $of "edit_flow -append flow_step:[regsub "_tcl" $key "_plug"] -[lindex $anchor($key) 0] flow_step:[lindex $anchor($key) 1]"
} else {
# puts "<FF> No anchor found for $plug"
set warnings($vars(warning_count)) "No anchor found for $key"
incr vars(warning_count)
}
close $ip
}
close $of
file delete -force .fftmp
if {[file exists scripts/flow_config.template]} {
file copy -force scripts/flow_config.template scripts/flow_config.tcl
}
if {[file exists $vars(script_dir)/view_definition.tcl]} {
file mkdir scripts
file copy -force $vars(script_dir)/view_definition.tcl scripts/mmmc_config.tcl
} else {
set warnings($vars(warning_count)) "File $vars(script_dir)/view_definition.tcl not found"
incr vars(warning_count)
}
# set op [open scripts/flow_config.tcl a]
# puts $op "source $vars(script_dir)/plug_steps.tcl"
# close $op
}
}
namespace eval ff_novus:: {
proc run_init {} {
uplevel #0 eval [FF_NOVUS::run_init]
}
proc run_place {} {
uplevel #0 eval [FF_NOVUS::run_place]
}
proc run_prects {} {
uplevel #0 eval [FF_NOVUS::run_prects]
}
proc run_cts {} {
uplevel #0 eval [FF_NOVUS::run_cts]
}
proc run_postcts {} {
uplevel #0 eval [FF_NOVUS::run_postcts]
}
proc run_postcts_hold {} {
uplevel #0 eval [FF_NOVUS::run_postcts_hold]
}
proc run_route {} {
uplevel #0 eval [FF_NOVUS::run_route]
}
proc run_postroute {} {
uplevel #0 eval [FF_NOVUS::run_postroute]
}
proc run_postroute_hold {} {
uplevel #0 eval [FF_NOVUS::run_postroute_hold]
}
proc run_postroute_si_hold {} {
uplevel #0 eval [FF_NOVUS::run_postroute_si_hold]
}
proc run_postroute_si {} {
uplevel #0 eval [FF_NOVUS::run_postroute_si]
}
proc run_signoff {} {
uplevel #0 eval [FF_NOVUS::run_signoff]
}
proc run_assemble {} {
uplevel #0 eval [FF_NOVUS::run_assemble]
}
proc run_rebudget {} {
uplevel #0 eval [FF_NOVUS::run_rebudget]
}
proc run_flexilm {} {
uplevel #0 eval [FF_NOVUS::run_flexilm]
}
proc run_assemble_flexilm {} {
uplevel #0 eval [FF_NOVUS::run_assemble_flexilm]
}
proc run_partition {} {
uplevel #0 eval [FF_NOVUS::run_partition]
}
proc run_lec {} {
uplevel #0 eval [FF_NOVUS::run_lec]
}
proc run_all {} {
uplevel #0 FF_NOVUS::run_all
}
}
namespace eval FF_EDI:: {
###############################################################################
# Procedure to seed certain flow variables to a known default value as well
# as data variables required to seed the generic configuration file
###############################################################################
proc seed_variables {{force 0}} {
global vars
global rda_defaults
global udm
global env
global infos
global warnings
global errors
global fargs
global dargs
if {$force} {
if {[info exists vars(seed)]} {
unset vars(seed)
}
}
if {![info exists vars(seed)]} {
puts "<FF> Seeding variables ..."
if {![info exists vars(warning_count)]} {
set vars(warning_count) 0
}
if {![info exists vars(error_count)]} {
set vars(error_count) 0
}
if {![info exists vars(info_count)]} {
set vars(info_count) 0
}
###############################################################################
# Set vars(version) to "17.1.0" if not defined
###############################################################################
if {![info exists vars(version)]} {
if {[info exists fargs(version)]} {
# puts "<FF> INFO: Variable vars(version) not defined - setting to '$fargs(version)'"
set vars(version) $fargs(version)
} else {
set vars(version) $dargs(version)
}
set vars(flow) mmmc
} else {
if {([lsearch $FF::valid_versions $vars(version)] < 0)} {
set msg "Version '$vars(version)' not supported - setting to '17.1.0'"
puts "<FF> WARNING: $msg"
append commands "# $msg\n"
set warnings($vars(warning_count)) $msg
incr vars(warning_count)
set vars(flow) mmmc
set vars(version) "17.1.0"
} else {
if {[lindex [split $vars(version) "."] 0] > 10} {
set vars(flow) mmmc
}
}
}
if {$vars(mode) == "top_down"} { set vars(mode) hier }
if {[regexp "9.1" $vars(version)]} {
set vars(enable_ldb) FALSE
}
if {[info exists vars(enable_ldb)] && $vars(enable_ldb)} {
if {![info exists vars(ran_compile)]} {
append commands [FF_EDI::run_compile]
}
}
###############################################################################
# Set vars(flow) to "mmmc" if not defined
###############################################################################
if {![info exists vars(flow)]} {
puts "<FF> INFO: Variable vars(flow) not defined - setting to 'mmmc'"
set vars(flow) mmmc
} else {
if {([lsearch [list "default" "pr_mmmc" "mmmc"] $vars(flow)] < 0)} {
puts "<FF> WARNING: Flow type '$vars(flow)' not supported - setting to 'mmmc'"
append commands "# WARNING: Flow type '$vars(flow)' not supported - setting to 'mmmc'\n"
set warnings($vars(warning_count)) "Flow type '$vars(flow)' not supported - setting to 'mmmc'"
incr vars(warning_count)
set vars(flow) mmmc
}
}
###############################################################################
# Make sure all scaling factors are either set or are 1.0 ... also
# support backwards compatibility of old names
###############################################################################
set map(pre_route_res_factor) def_res_factor
set map(pre_route_clk_res_factor) def_clk_res_factor
set map(pre_route_cap_factor) def_cap_factor
set map(pre_route_clk_cap_factor) def_clk_cap_factor
set map(post_route_res_factor) det_res_factor
set map(post_route_clk_res_factor) det_clk_res_factor
set map(post_route_cap_factor) det_cap_factor
set map(post_route_clk_cap_factor) det_clk_cap_factor
set map(post_route_xcap_factor) xcap_factor
if {[info exists vars(view_definition_tcl)] && ![info exists vars(parsed_view_definition_tcl)]} {
if {![file exists $vars(view_definition_tcl)]} {
puts "<FF> ERROR: View definition file $vars(view_definition_tcl) does not exist ... cannot continue"
exit
}
source $vars(script_path)/ETC/INNOVUS/overlay.tcl
puts "<FF> Parsing user view definition file ..."
set rc [catch {source $vars(view_definition_tcl)}]
# puts "-------------------------------------------------"
foreach var "library_sets rc_corners delay_corners setup_analysis_views hold_analysis_views power_domains" {
if {[info exists vars($var)]} {
set infos($vars(info_count)) "Variable vars($var) has been set to \"$vars($var)\""
incr vars(info_count)
}
}
# puts $rc
# puts "-------------------------------------------------"
set vars(parsed_view_definition_tcl) true
}
# if {![info exists vars(view_definition_tcl)]} {
foreach rc_corner $vars(rc_corners) {
foreach option "pre_route_res_factor pre_route_clk_res_factor \
post_route_res_factor post_route_clk_res_factor \
pre_route_cap_factor pre_route_clk_cap_factor \
post_route_cap_factor post_route_clk_cap_factor \
post_route_xcap_factor" {
if {![info exists vars($rc_corner,$option)] && [info exists vars($rc_corner,$map($option))]} {
append commands "# INFO: Variable $map($option) has been changed to $option ... please update\n"
set infos($vars(info_count)) "Variable $map($option) has been changed to $option ... please update"
incr vars(info_count)
set vars($rc_corner,$option) $vars($rc_corner,$map($option))
}
}
}
###############################################################################
# The following will be used to seed the config file
###############################################################################
if {![FF::is_lp_flow]} {
set max_libs [list]
set min_libs [list]
set count 0
if {[info exists vars($vars($vars(default_setup_view),delay_corner),library_set)]} {
foreach lib $vars($vars($vars($vars(default_setup_view),delay_corner),library_set),timing) {
if {[lsearch $max_libs $lib] == -1} {
lappend max_libs $lib
incr count
}
}
} else {
if {[info exists vars($vars($vars(default_setup_view),delay_corner),late_library_set)]} {
foreach lib $vars($vars($vars($vars(default_setup_view),delay_corner),late_library_set),timing) {
if {[lsearch $max_libs $lib] == -1} {
lappend max_libs $lib
incr count
}
}
}
}
if {![info exists vars(timelib,max)]} {
set vars(timelib,max) $max_libs
}
if {[info exists vars($vars($vars(default_hold_view),delay_corner),library_set)]} {
foreach lib $vars($vars($vars($vars(default_hold_view),delay_corner),library_set),timing) {
if {[lsearch $min_libs $lib] == -1} {
lappend min_libs $lib
incr count
}
}
} else {
if {[info exists vars($vars($vars(default_hold_view),delay_corner),early_library_set)]} {
foreach lib $vars($vars($vars($vars(default_hold_view),delay_corner),early_library_set),timing) {
if {[lsearch $min_libs $lib] == -1} {
lappend min_libs $lib
incr count
}
}
}
}
if {![info exists vars(timelib,min)]} {
set vars(timelib,min) $min_libs
}
if {![info exists vars(timelib)]} {
set vars(timelib) ""
}
set vars(cdb_file) ""
set vars(cdb_file,min) ""
set vars(cdb_file,max) ""
if {[info exists vars($vars($vars(default_setup_view),delay_corner),library_set)]} {
if {[info exists vars($vars($vars($vars(default_setup_view),delay_corner),library_set),si)]} {
set vars(cdb_file,max) $vars($vars($vars($vars(default_setup_view),delay_corner),library_set),si)
}
} elseif {[info exists vars($vars($vars(default_setup_view),delay_corner),late_library_set)]} {
if {[info exists ars($vars($vars($vars(default_setup_view),delay_corner),late_library_set),si)]} {
set vars(cdb_file,max) $vars($vars($vars($vars(default_setup_view),delay_corner),late_library_set),si)
}
} else {
set vars(cdb_file,max) ""
}
if {[info exists vars($vars($vars(default_hold_view),delay_corner),library_set)]} {
if {[info exists vars($vars($vars($vars(default_hold_view),delay_corner),library_set),si)]} {
set vars(cdb_file,min) $vars($vars($vars($vars(default_hold_view),delay_corner),library_set),si)
}
} elseif {[info exists vars($vars($vars(default_hold_view),delay_corner),early_library_set)]} {
if {[info exists vars($vars($vars($vars(default_hold_view),delay_corner),early_library_set),si)]} {
set vars(cdb_file,min) $vars($vars($vars($vars(default_hold_view),delay_corner),early_library_set),si)
}
} else {
set vars(cdb_file,min) ""
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),pre_cts_sdc)]} {
if {$vars(flow) != "mmmc"} {
set vars(timingcon_file) $vars($vars($vars(default_setup_view),constraint_mode),pre_cts_sdc)
}
set vars(pre_cts_sdc) $vars($vars($vars(default_setup_view),constraint_mode),pre_cts_sdc)
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),pre_cts_ilm_sdc)]} {
if {$vars(flow) != "mmmc"} {
set vars(timingcon_file,full) $vars($vars($vars(default_setup_view),constraint_mode),pre_cts_ilm_sdc)
}
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),incr_cts_sdc)]} {
set vars(incr_cts_sdc) $vars($vars($vars(default_setup_view),constraint_mode),incr_cts_sdc)
}
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),post_cts_sdc)]} {
set vars(post_cts_sdc) $vars($vars($vars(default_setup_view),constraint_mode),post_cts_sdc)
}
if {[info exists vars($vars($vars($vars(default_hold_view),delay_corner),rc_corner),cap_table)] &&\
[info exists vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)]} {
set vars(captbl_file) [concat \
"-best" $vars($vars($vars($vars(default_hold_view),delay_corner),rc_corner),cap_table) \
"-worst" $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table) \
]
set vars(wc_cap_table) $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)
} else {
if {[info exists vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)]} {
set vars(captbl_file) [concat \
"-best" $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table) \
"-worst" $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table) \
]
set vars(wc_cap_table) $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),cap_table)
} else {
set vars(captbl_file) ""
}
}
} else {
set vars(timelib) ""
set vars(cdb_file) ""
set vars(timelib,max) ""
set vars(cdb_file,max) ""
set vars(timelib,min) ""
set vars(cdb_file,min) ""
set found_max 0
set found_min 0
if {[info exists vars(setup_analysis_views)] && [info exists vars(hold_analysis_views)]} {
foreach view $vars(setup_analysis_views) {
if {[info exists vars($vars($view,delay_corner),library_set)]} {
if {[info exists vars($vars($vars($view,delay_corner),library_set),timing)]} {
foreach file $vars($vars($vars($view,delay_corner),library_set),timing) {
if {[lsearch $vars(timelib,max) $file] == -1} {
lappend vars(timelib,max) $file
}
set found_max 1
}
} else {
puts "<FF> WARNING: Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
incr vars(warning_count)
}
} else {
if {![info exists vars($vars($view,delay_corner),early_library_set)]} {
puts "<FF> WARNING: Variable vars($vars($view,delay_corner),library_set) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($view,delay_corner),library_set) not defined"
incr vars(warning_count)
}
}
}
foreach view $vars(hold_analysis_views) {
if {[info exists vars($vars($view,delay_corner),library_set)]} {
if {[info exists vars($vars($vars($view,delay_corner),library_set),timing)]} {
foreach file $vars($vars($vars($view,delay_corner),library_set),timing) {
if {[lsearch $vars(timelib,min) $file] == -1} {
lappend vars(timelib,min) $file
}
set found_min 1
}
} else {
puts "<FF> WARNING: vars($vars($vars($view,delay_corner),library_set),timing) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
incr vars(warning_count)
}
} else {
if {![info exists vars($vars($view,delay_corner),early_library_set)]} {
puts "<FF> WARNING: vars($vars($view,delay_corner),early_library_set) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($view,delay_corner),early_library_set) not defined"
incr vars(warning_count)
}
}
}
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set view $vars(power_analysis_view)
if {[info exists vars($vars($view,delay_corner),library_set)]} {
if {![info exists vars($vars($vars($view,delay_corner),library_set),timing)]} {
puts "<FF> WARNING: vars($vars($vars($view,delay_corner),library_set),timing) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($vars($view,delay_corner),library_set),timing) not defined"
incr vars(warning_count)
}
} else {
if {![info exists vars($vars($view,delay_corner),early_library_set)]} {
puts "<FF> WARNING: vars($vars($view,delay_corner),early_library_set) not defined"
set warnings($vars(warning_count)) "Variable vars($vars($view,delay_corner),early_library_set) not defined"
incr vars(warning_count)
}
}
}
}
if {!$found_min || !$found_max} {
append commands "# WARNING: Either setup or hold analysis views inadequately defined"
set warnings($vars(warning_count)) "Either setup or hold analysis views inadequately defined"
incr vars(warning_count)
set vars(timelib,min) ""
set vars(timelib,max) ""
foreach library_set $vars(library_sets) {
if {[info exists vars($library_set,timing)]} {
set vars(timelib) [concat $vars(timelib) $vars($library_set,timing)]
}
if {[info exists vars($library_set,si)]} {
set vars(cdb_file) [concat $vars(cdb_file) $vars($library_set,si)]
}
}
}
set vars(captbl_file) ""
set vars(timingcon_file) ""
# set vars(pre_route_res_factor) 1.0
# set vars(post_route_res_factor) 1.0
# set vars(pre_route_cap_factor) 1.0
# set vars(post_route_cap_factor) 1.0
# set vars(pre_route_clk_res_factor) 1.0
# set vars(post_route_clk_res_factor) 1.0
# set vars(pre_route_clk_cap_factor) 1.0
# set vars(post_route_clk_cap_factor) 1.0
# set vars(post_route_xcap_factor) 1.0
# set vars(qxtech_file) ""
# set vars(qxconf_file) ""
# set vars(qxlib_file) ""
# set vars(qxlayermap_file) ""
}
set map(qx_tech_file) qxtech_file
set map(qx_conf_file) qxconf_file
set map(qx_lib_file) qxlib_file
foreach option "qx_tech_file qx_conf_file qx_lib_file" {
if {[info exists vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),$option)]} {
set vars($map($option)) $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),$option)
} else {
set vars($map($option)) ""
}
}
if {![info exists vars(qx_layermap_file)]} {
if {[info exists vars(qrc_layer_map)]} {
set vars(qxlayermap_file) $vars(qrc_layer_map)
} else {
set vars(qxlayermap_file) ""
}
} else {
set vars(qxlayermap_file) $vars(qx_layermap_file)
set vars(qrc_layer_map) $vars(qx_layermap_file)
}
# }
###############################################################################
# Backwards compatibility
###############################################################################
if {[info exists vars(leakage_effort)] && ![info exists vars(leakage_power_effort)]} {
set vars(leakage_power_effort) $vars(leakage_effort)
}
if {[info exists vars(enable_cppr)] && (($vars(enable_cppr) == 0) || ($vars(enable_cppr) == false))} {
set vars(enable_cppr) none
}
if {[info exists vars(enable_cppr)] && (($vars(enable_cppr) == 1) || ($vars(enable_cppr) == true))} {
set vars(enable_cppr) both
}
if {[info exists vars(def_file)]} {
append commands "# WARNING: Variable def_file has been changed to def_files ... please update\n"
set warnings($vars(warning_count)) "Variable def_file has been changed to def_files ... please update"
incr vars(warning_count)
set vars(def_files) $vars(def_file)
}
###############################################################################
# Seed the rest of the config variables allowing user overrides ...
# Default values for all variables are in defaults.tcl
###############################################################################
if {![info exists vars(script_path)]} {
if {[info exists vars(script_root)]} {
set vars(script_path) $vars(script_root)
} else {
puts "<FF> ERROR: Variable vars(script_root) not defined"
exit 1
}
} else {
if {![info exists vars(script_root)]} {
set vars(script_root) $vars(script_path)
}
}
if {![info exists vars(setup_path)]} {
set vars(setup_path) "."
}
if {[info command FFF::get_tool] ne "" && [FFF::get_tool] eq "rc"} {
tcl_source $vars(script_path)/ETC/INNOVUS/rda_defaults.tcl
} else {
source $vars(script_path)/ETC/common_defaults.tcl
source $vars(script_path)/ETC/INNOVUS/defaults.tcl
source $vars(script_path)/ETC/INNOVUS/rda_defaults.tcl
}
foreach option [array names rda_defaults] {
if {![info exists vars($option)]} {
set vars($option) $rda_defaults($option)
} else {
if {$vars($option) != $rda_defaults($option)} {
# puts "# <FF> INFO: User override of $option to $vars($option)"
}
}
}
if {![info exists vars(cpus_per_remote_host)] && [info exists vars(cpu_per_remote_host)]} {
Puts "<FF> INFO: Setting 'vars(cpus_per_remote_host)' to 'vars(cpu_per_remote_host)'"
Puts "<FF> INFO: ^"
Puts "<FF> INFO: Please update your setup to cpus_per_remote ..."
set vars(cpus_per_remote_host) $vars(cpu_per_remote_host)
}
if {![info exists vars(flexmodel_art_based)]} {
if {[info exists vars(flexmodel_as_ptn)] && $vars(flexmodel_as_ptn)} {
set flow_defaults(flexmodel_art_based) 1
}
}
if {![info exists vars(high_timing_effort)]} {
set vars(high_timing_effort) $flow_defaults(high_timing_effort)
}
if {[info exists vars(clock_eco)] && ($vars(clock_eco) == "postcts")} {
set vars(clock_eco) "post_cts"
}
if {[info exists vars(clock_eco)] && ($vars(clock_eco) == "postroute")} {
set vars(clock_eco) "post_route"
}
if {[regexp "9.1" $vars(version)]} {
if {$vars(high_timing_effort)} {
if {[info exists vars(critical_range)] && ($vars(critical_range) != 1.0)} {
Puts "<FF> High timing effort enabled but critical_range overridden by user settings"
}
if {[info exists vars(clock_eco)] && ($vars(clock_eco) != "post_cts")} {
Puts "<FF> High timing effort enabled but clock_eco overridden by user settings"
}
if {[info exists vars(in_place_opt)] && !$vars(in_place_opt)} {
Puts "<FF> High timing effort enabled but in_place_opt overridden by user settings"
}
}
}
if {[info exists vars(cts_engine)] && ([string tolower $vars(cts_engine)] == "cts")} {
set flow_defaults(update_io_latency) false
# set vars(cts,update_timing,skip) true
}
foreach option [array names flow_defaults] {
if {![info exists vars($option)]} {
set vars($option) $flow_defaults($option)
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
set vars(in_place_opt) true
set vars(critical_range) 1.0
# set vars(useful_skew) true
set vars(clock_eco) post_cts
}
# if {$vars(cts_engine) == "ccopt_design"} {
# set vars(ccopt_effort) low
# }
}
}
if {![info exists vars(time_info_db)]} {
set flow_defaults(time_info_db) $vars(rpt_dir)/time_info.db
}
if {![info exists vars(time_info_full_rpt)]} {
set flow_defaults(time_info_full_rpt) $vars(rpt_dir)/time_info_full.rpt
}
if {![info exists vars(html_summary)]} {
set flow_defaults(html_summary) $vars(rpt_dir)/summary.html
}
if {![info exists vars(enable_si_aware)]} {
# if {[regsub "nm" $vars(process) ""] <= 65} {
# set vars(enable_si_aware) true
# } else {
set vars(enable_si_aware) false
# }
}
if {![info exists vars(dbs_format)]} {
if {[string compare -nocase $vars(netlist_type) "verilog"]>=0} {
set vars(dbs_format) fe
} else {
set vars(dbs_format) oa
}
}
if {![info exists vars(partition_dir)]} {
set vars(partition_dir) PARTITION
}
if {![info exists vars(partition_dir_pass2)]} {
if {$vars(enable_flexilm)} {
set vars(partition_dir_pass2) $vars(partition_dir)_PRECTS
} else {
set vars(partition_dir_pass2) $vars(partition_dir)_CTS
}
}
if {$vars(user_mode) == "hier"} {
FF_EDI::normalize_files
if {$vars(enable_flexilm)} {
# set vars(cts,starting_dbs) "\[glob *_postECO.enc\]"
# # DLM is a two pass flow but user doesn't need to specify it
set vars(hier_flow_type) "2pass"
# set vars(place_opt_design) false
} else {
if {$vars(hier_flow_type) == "2pass"} {
set vars(postcts,starting_dbs) .
}
# }
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {![info exists vars(oa_abstract_name)]} { set vars(oa_abstract_name) abstract}
if {![info exists vars(oa_layout_name)]} { set vars(oa_layout_name) layout}
if {![info exists vars(oa_design_cell)]} { set vars(oa_design_cell) $vars(design)}
if {![info exists vars(oa_design_view)]} { set vars(oa_design_view) ""}
if {![info exists vars(oa_partition_lib)]} { set vars(oa_partition_lib) OA_PTN_LIB}
} else {
if {![info exists vars(oa_abstract_name)]} { set vars(oa_abstract_name) ""}
if {![info exists vars(oa_layout_name)]} { set vars(oa_layout_name) ""}
if {![info exists vars(oa_design_cell)]} { set vars(oa_design_cell) ""}
if {![info exists vars(oa_design_view)]} { set vars(oa_design_view) ""}
if {![info exists vars(oa_design_lib)]} { set vars(oa_design_lib) ""}
}
if {([string tolower $vars(fix_hold)] == "true") || ($vars(fix_hold) == 1)} {
set infos($vars(info_count)) "Changing vars(fix_hold) from $vars(fix_hold) to \"$flow_defaults(fix_hold)\""
incr vars(info_count)
set vars(fix_hold) $flow_defaults(fix_hold)
}
if {([string tolower $vars(enable_ocv)] == "true") || ($vars(enable_ocv) == 1)} {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ss)\" to \"pre_postroute\""
incr vars(info_count)
set vars(enable_ocv) pre_cts
} elseif {($vars(enable_ocv) == "none") || ($vars(enable_ocv) == 0)} {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ocv)\" to \"false\""
incr vars(info_count)
set vars(enable_ocv) false
}
if {[lindex [split $vars(version) "."] 0] > 11} {
if {[string tolower $vars(enable_ocv)] == "false"} {
if {[lindex [split $vars(version) "."] 0] < 15} {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ocv)\" to \"pre_postroute\""
incr vars(info_count)
set vars(enable_ocv) "pre_postroute"
} else {
set infos($vars(info_count)) "Changing vars(enable_ocv) from \"$vars(enable_ocv)\" to \"pre_cts\""
incr vars(info_count)
set vars(enable_ocv) "pre_cts"
}
}
}
if {([string tolower $vars(enable_ss)] == "true") || ($vars(enable_ss) == 1)} {
set infos($vars(info_count)) "Changing vars(enable_ss) from $vars(enable_ss) to \"pre_postroute\""
incr vars(info_count)
set vars(enable_ss) pre_postroute
} elseif {($vars(enable_ss) == "none") || ($vars(enable_ss) == 0)} {
set infos($vars(info_count)) "Changing vars(enable_ss) from $vars(enable_ss) to \"false\""
incr vars(info_count)
set vars(enable_ss) false
}
if {([string tolower $vars(metalfill)] == "none") || ([string tolower $vars(metalfill)] == "false" && $vars(metalfill) != "false") || ($vars(metalfill) == 0)} {
set infos($vars(info_count)) "Changing vars(metalfill) from $vars(metalfill) to \"false\""
incr vars(info_count)
set vars(metalfill) false
}
if {[info exists vars(clock_eco)]} {
if {($vars(clock_eco) == "true") || ($vars(clock_eco) == 1)} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"post_cts\""
incr vars(info_count)
set vars(clock_eco) post_cts
} elseif {($vars(clock_eco) == "false") || ($vars(clock_eco) == 0)} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"none\""
incr vars(info_count)
set vars(clock_eco) none
} elseif {($vars(clock_eco) == "preroute") || ($vars(clock_eco) == "pre_route")} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"post_cts\""
incr vars(info_count)
set vars(clock_eco) post_cts
} elseif {$vars(clock_eco) == "postroute"} {
set infos($vars(info_count)) "Changing vars(clock_eco) from $vars(clock_eco) to \"post_route\""
incr vars(info_count)
set vars(clock_eco) post_route
}
}
if {([string tolower $vars(use_flexmodels)] == "true") || ($vars(use_flexmodels) == 1)} {
set vars(use_flexmodels) 1
} else {
set vars(use_flexmodels) 0
}
# if {$vars(use_flexmodels) && $vars(place_opt_design)} {
# set warnings($vars(warning_count)) "Setting vars(place_opt_design) to 'false' as vars(use_flexmodels) is true"
# incr vars(warning_count)
# set vars(place_opt_design) false
# }
if {([string tolower $vars(flexmodel_as_ptn)] == "true") || ($vars(flexmodel_as_ptn) == 1)} {
set vars(flexmodel_as_ptn) 1
} else {
set vars(flexmodel_as_ptn) 0
}
if {([string tolower $vars(placement_based_ptn)] == "true") || ($vars(placement_based_ptn) == 1)} {
set vars(placement_based_ptn) 1
} else {
set vars(placement_based_ptn) 0
}
if {([string tolower $vars(abutted_design)] == "true") || ($vars(abutted_design) == 1)} {
set vars(abutted_design) 1
} else {
set vars(abutted_design) 0
}
if {([string tolower $vars(insert_feedthrough)] == "true") || ($vars(insert_feedthrough) == 1)} {
set vars(insert_feedthrough) 1
} else {
set vars(insert_feedthrough) 0
}
if {![info exists vars(resize_shifter_and_iso_insts)] || $vars(resize_shifter_and_iso_insts) == ""} {
set vars(resize_shifter_and_iso_insts) true
}
if {![info exists vars(activity_file_format)] || $vars(activity_file_format) == ""} {
set vars(activity_file_format) TCF
}
if {![info exists vars(power_nets)]} {
if {[info exists vars(pwrnet)]} {
append commands "# INFO: Variable pwrnet has been changed to power_nets ... please update\n"
set infos($vars(info_count)) "Variable pwrnet has been changed to power_nets ... please update"
incr vars(info_count)
set vars(power_nets) $vars(pwrnet)
} else {
set vars(power_nets) ""
}
}
if {![info exists vars(ground_nets)]} {
if {[info exists vars(gndnet)]} {
append commands "# INFO: Variable gndnet has been changed to ground_nets ... please update\n"
set infos($vars(info_count)) "Variable gndnet has been changed to ground_nets ... please update"
incr vars(info_count)
set vars(ground_nets) $vars(gndnet)
} else {
set vars(ground_nets) ""
}
}
if {![info exists vars(superhosts)]} {
set vars(superhosts) 0
}
if {![info exists vars(superthreads)]} {
set vars(superthreads) 1
} else {
if {($vars(threads) > 1) && ($vars(superthreads) == 1)} {
set vars(superthreads) $vars(threads)
}
}
if {![info exists vars(makefile)]} {
set vars(makefile) 1
}
if {![info exists vars(flat)]} {
set vars(flat) none
}
if {![info exists vars(abort)]} {
set vars(abort) 0
}
if {![info exists vars(catch_errors)]} {
set vars(catch_errors) 1
}
if {![info exists vars(restore_design)]} {
set vars(restore_design) 1
}
if {$vars(catch_errors)} {
if {![info exists vars(save_on_catch)]} {
set vars(save_on_catch) 1
}
if {![info exists vars(exit_on_error)]} {
set vars(exit_on_error) 1
}
}
if {![info exists env(VPATH)]} {
set env(VPATH) $flow_defaults(vpath)
Puts "<FF> INFO: Setting env(VPATH) to $flow_defaults(vpath)"
}
if {[info exists vars(cpf_file)]} {
if {![info exists vars(cpf_timing)]} {
set vars(cpf_timing) true
# set vars(flat) true
}
} else {
set vars(cpf_timing) false
}
if {!$vars(codegen)} {
if {[FF::is_lp_flow]} {
catch {alias ff_modify_power_domains FF_EDI::modify_power_domains}
catch {alias ff_add_power_switches FF_EDI::add_power_switches}
catch {alias ff_route_secondary_pg_nets FF_EDI::route_secondary_pg_nets}
catch {alias ff_get_power_domains FF_EDI::get_power_domains}
catch {alias ff_buffer_always_on_nets FF_EDI::buffer_always_on_nets}
catch {alias ff_insert_welltaps_endcaps FF_EDI::insert_welltaps_endcaps}
}
set flow_defaults(script_dir) "."
}
# Remember these for step based reporting ...
set vars(orig_rpt_dir) $vars(rpt_dir)
set vars(orig_log_dir) $vars(log_dir)
set vars(orig_dbs_dir) $vars(dbs_dir)
# Add these for get metric
if {![info exists vars(html_summary)]} {
set vars(html_summary) $vars(rpt_dir)/summary.html
}
if {![info exists vars(time_info_db)]} {
set vars(time_info_db) $vars(rpt_dir)/time_info.db
}
if {![info exists vars(time_info_rpt)]} {
set vars(time_info_rpt) $vars(rpt_dir)/time_info.rpt
}
if {[info command FFF::get_tool] ne "" && [FFF::get_tool] eq "rc"} {
tcl_source $vars(script_path)/ETC/INNOVUS/udm.tcl
} else {
source $vars(script_path)/ETC/INNOVUS/udm.tcl
}
if {!$vars(rc) || ($vars(rc) && ![info exists vars(rc_steps)])} {
set vars(seed) 1
}
}
# if {![info exists vars(view_definition_tcl)]} {
FF_EDI::normalize_constraints
# }
# Disable this for 14.20
set vars(generate_flow_steps) 0
if {$vars(generate_flow_steps)} {
set vars(skip_signoff_checks) true
FF_EDI::normalize_files
}
# if {[info exists vars(view_definition_tcl)]} {
# set vars(skip_signoff_checks) false
# }
# RC Stuff ...
# ------------------------------------------------------------------------------
if {$vars(rc)} {
if {![info exists vars(ovf_dir)]} { set vars(ovf_dir) OVF }
if {![info exists vars(lec_dir)]} { set vars(lec_dir) LEC }
if {![info exists vars(enable_rcp)]} { set vars(enable_rcp) 0 }
if {![info exists vars(enable_pam)]} { set vars(enable_pam) 0 }
set vars(syn_map,set_misc_attributes,skip) false
set vars(syn_map,set_lib_attributes,skip) false
set vars(syn_map,set_hdl_attributes,skip) false
set vars(syn_map,set_icg_attributes,skip) true
set vars(syn_map,set_dft_attributes,skip) true
set vars(syn_incr,set_opt_attributes,skip) true
###############################################################################
# Set netlist and def variables when RC / RCP enabled
###############################################################################
if {$vars(enable_rcp)} {
set vars(netlist) $vars(dbs_dir)/syn_place/syn_place.v.gz
set vars(def_files) $vars(dbs_dir)/syn_place/syn_place.def.gz
} else {
set vars(netlist) $vars(dbs_dir)/syn_incr/syn_incr.v.gz
# set vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.def.gz
}
}
}
###############################################################################
# Procedure to check the flow variables defined in the setup.tcl
###############################################################################
proc check_setup {} {
global vars
global tvars
global errors
global warnings
global infos
global check
if {[info exists vars(check_setup)] && !$vars(check_setup)} {
return
}
if {[info exists vars(warning_count)]} {
set warning_count $vars(warning_count)
} else {
set warning_count 0
}
if {[info exists vars(error_count)]} {
set error_count $vars(error_count)
} else {
set error_count 0
}
if {[info exists vars(info_count)]} {
set info_count $vars(info_count)
} else {
set info_count 0
}
if {$vars(place_opt_design) && $vars(enable_flexilm)} {
set warnings($warning_count) "Feature vars(place_opt_design) not support for top level implementation when vars(enable_flexilm) is true"
incr warning_count
}
if {[info exists vars(power_analysis_view)]} {
if {[lsearch [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] $vars(power_analysis_view)] == -1} {
append commands "# ERROR: Power analysis view $vars(power_analysis_view) is not a defined view\n"
set errors($error_count) "Power analysis view $vars(power_analysis_view) is not a defined view"
incr error_count
}
}
set valid [list trial_ipo giga_opt proto_net_delay_model]
if {[lsearch $valid [string tolower $vars(budget_mode)]] == -1} {
append commands "# ERROR: Variable vars(budget_mode) has illegal value $vars(budget_mode)\n"
set errors($error_count) "Variable vars(budget_mode) has illegal value $vars(budget_mode)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
if {[info exists vars(cts_engine)]} {
if {[string tolower $vars(cts_engine)] == "ccoptdesign"} {
set vars(cts_engine) ccopt
}
if {[string tolower $vars(cts_engine)] == "clockdesign"} {
set vars(cts_engine) cts
}
set valid [list cts ccopt ccopt_cts]
if {[lsearch $valid [string tolower $vars(cts_engine)]] == -1} {
append commands "# ERROR: Variable vars(cts_engine) has illegal value $vars(cts_engine)\n"
set errors($error_count) "Variable vars(cts_engine) has illegal value $vars(cts_engine)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
# if {[info exists vars(cts_spec)]} {
# append commands "# INFO: Variable cts_spec defined so set cts_engine to cts\n"
# set infos($info_count) "Variable cts_spec defined so set cts_engine to cts"
# incr info_count
# set vars(cts_engine) cts
# foreach file $vars(cts_spec) {
# lappend check(files) $file
# }
# append commands "# INFO: cts_spec = $vars(cts_spec)\n"
# }
if {[info exists vars(ccopt_integration)]} {
set valid {scripted native}
if {[lsearch $valid $vars(ccopt_integration)] == -1} {
append commands "# ERROR: Variable vars(cts_engine) has illegal value $vars(cts_engine)\n"
set errors($error_count) "Variable vars(cts_engine) has illegal value $vars(cts_engine)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
} else {
# Default to native integration
set vars(ccopt_integration) "native"
}
if {[lindex [split $vars(version) "."] 0] > 10} {
foreach var [array names vars] {
set save_vars($var) $vars($var)
if {[info exists tvars($var)]} {
set vars($var) $tvars($var)
}
}
}
set commands ""
set check(files) [list]
set check(integers) [list]
if {![info exists vars(abort)]} {
set vars(abort) 0
}
if {[info exists vars(check_vars)] && $vars(check_vars)} {
source $vars(script_root)/ETC/INNOVUS/check_vars.tcl
}
append commands "# ==============================================\n"
append commands "# Required Variables\n"
append commands "# ==============================================\n"
set count 0
foreach required "fp_tcl_file fp_file def_files" {
if {!$vars(rc)} {
# BCL: Only check for vars(def_files) if not in RC mode
if {[info exists vars($required)] && ($vars($required) != "")} {
if {$required == "def_files"} {
set first 1
# BCL: Added subst around vars(def_files) to resolve vars(rundir)
foreach file [subst $vars(def_files)] {
if {$first == 1} {
append commands "# INFO: $required = $file\n"
set first 0
} else {
append commands "# INFO: $file"
}
if {!$vars(rc)} {
lappend check(files) $file
}
}
} else {
lappend check(files) $vars($required)
append commands "# INFO: $required = $vars($required)\n"
}
incr count
}
}
}
if {[info exists vars(fp_tcl_proc)]} {
append commands "# INFO: fp_tcl_proc = $vars(fp_tcl_proc)\n"
incr count
}
if {[info exists vars(oa_fp)]} {
if {[llength $vars(oa_fp)] == 3} {
append commands "# INFO: oa_fp = $vars(oa_fp)\n"
incr count
} else {
append commands "# ERROR: OA floorplan variable (oa_fp) should be 'lib cell view'"
set errors($error_count) "OA floorplan variable (oa_fp) should be 'lib cell view'"
incr error_count
}
} else {
if {$count == 0} {
append commands "# WARNING: Neither fp_file, def_files, fp_tcl_file, fp_tcl_proc are defined\n"
set warnings($warning_count) "Either fp_file, def_files, fp_tcl_file, fp_tcl_proc should be defined"
incr warning_count
}
}
if {[string compare -nocase $vars(netlist_type) "verilog"]>=0} {
# BCL: Note - This code removed as the RC Foundation Flow will set vars(def_netlist) when it
# isn't defined in the user's setup.tcl
#if {$vars(rc) && ![info exists vars(netlist)]} {
# set vars(netlist) $vars(dbs_dir)/$vars(design).syn_placed.v.gz
#}
if {!$vars(rc)} {
# BCL: Only check for vars(netlist) if not in RC mode
if {[info exists vars(netlist)]} {
# BCL: Added subst around vars(netlist)
foreach file [subst $vars(netlist)] {
if {!$vars(rc)} {
lappend check(files) $file
}
}
append commands "# INFO: netlist = $vars(netlist)\n"
} else {
if {($vars(netlist_type) == "Verilog")} {
append commands "# ERROR: A verilog netlist file must be defined\n"
set errors($error_count) "A verilog netlist file must be defined"
incr error_count
}
}
}
} elseif {[string compare -nocase $vars(netlist_type) "oa"]==0} {
append commands "# INFO: netlist_type = $vars(netlist_type)\n"
foreach required "oa_ref_lib oa_design_lib oa_design_cell oa_design_view" {
if {[info exists vars($required)] && ($vars($required) != "")} {
append commands "# INFO: $required = $vars($required)\n"
} else {
append commands "# ERROR: Variable $required must be defined when netlist_type is open access"
set errors($error_count) "Variable $required must be defined when netlist_type is open access"
incr error_count
}
}
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append commands "# INFO: dbs_format = $vars(dbs_format)\n"
foreach required "oa_ref_lib oa_design_lib oa_abstract_name oa_layout_name" {
if {[info exists vars($required)] && ($vars($required) != "")} {
append commands "# INFO: $required = $vars($required)\n"
} else {
append commands "# ERROR: Variable $required must be defined when dbs_format is open access"
set errors($error_count) "Variable $required must be defined when dbs_format is open access"
incr error_count
}
}
}
if {[info exists vars(enable_lvs)] && $vars(enable_lvs)} {
if {[string compare -nocase $vars(dbs_format) "oa"]!=0} {
append commands "# WARNING: Variable enable_lvs is only allowed when dbs_format is open access"
set warnings($warning_count) "Variable enable_lvs is only allowed when dbs_format is open access"
incr warning_count
set vars(enable_lvs) false
}
}
# if {[info exists vars(netlist)]} {
# foreach file $vars(netlist) {
# lappend check(files) $file
# }
# } else {
# if {$vars(netlist_type) == "Verilog"} {
# append commands "# ERROR: A verilog netlist file must be defined\n"
# set errors($error_count) "A verilog netlist file must be defined"
# incr error_count
#
# }
# }
if {[info exists vars(cts_spec)] && ($vars(cts_engine) == "ccopt")} {
append commands "# ERROR: Variable cts_spec defined and cts_engine is set to ccopt\n"
set errors($error_count) "Variable cts_spec defined and cts_engine is set to ccopt"
incr error_count
foreach file $vars(cts_spec) {
lappend check(files) $file
}
}
# if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
# set required_list "flow process library_sets rc_corners delay_corners"
# } else {
set required_list "flow process library_sets rc_corners delay_corners setup_analysis_views \
hold_analysis_views active_setup_views active_hold_views default_setup_view default_hold_view"
# }
foreach required $required_list {
if {[info exists vars($required)] && ($vars($required) != "")} {
append commands "# INFO: $required = $vars($required)\n"
if {$required == "flow"} {
if {([info exists vars(partition_list)] || ($vars(ilm_list) != "")) && ($vars(flow) != "mmmc")} {
append commands "# ERROR: Flow variable vars(flow) must be \"mmmc\" when ILMs are defined\n"
set errors($error_count) "# ERROR: Flow variable vars(flow) must be \"mmmc\" when ILMs are defined"
incr error_count
}
}
}
}
# if {![info exists vars(view_definition_tcl)]} {
append commands "# ==============================================\n"
append commands "# Library Sets\n"
append commands "# ==============================================\n"
foreach library_set $vars(library_sets) {
append commands "# INFO: $library_set:\n"
foreach required "timing" {
if {[info exists vars($library_set,$required)] && ($vars($library_set,$required) != "")} {
append commands "# INFO: $required = \n"
foreach lib $vars($library_set,$required) {
# lappend check(files) $lib
append commands "# INFO: $lib\n"
}
} else {
if {[FF::is_lp_flow]} {
append commands "# WARNING: Variable vars($library_set,$required) not defined\n"
set warnings($warning_count) "Variable vars($library_set,$required) not defined"
incr warning_count
} else {
append commands "# ERROR: Required variable vars($library_set,$required) not defined or empty\n"
set errors($error_count) "Required variable vars($library_set,$required) not defined or empty"
incr error_count
}
}
}
if {[info exists vars($library_set,aocv)]} {
foreach file $vars($library_set,aocv) {
if {![file exists $file]} {
append commands "# WARNING: AOCV table file does not exist ($file)\n"
set warnings($warning_count) "AOCV table file does not exist ($file)"
incr warning_count
}
}
} else {
if {$vars(enable_aocv)} {
append commands "# WARNING: AOCV enabled, but table not provided for $library_set\n"
set warnings($warning_count) "AOCV enabled, but table not provided for $library_set"
incr warning_count
}
}
if {[info exists vars($library_set,socv)]} {
foreach file $vars($library_set,socv) {
if {![file exists $file]} {
append commands "# WARNING: SOCV table file does not exist ($file)\n"
set warnings($warning_count) "SOCV table file does not exist ($file)"
incr warning_count
}
}
} else {
if {$vars(enable_socv)} {
append commands "# WARNING: SOCV enabled, but table not provided for $library_set\n"
set warnings($warning_count) "SOCV enabled, but table not provided for $library_set"
incr warning_count
}
}
if {[info exists vars($library_set,si)]} {
foreach file $vars($library_set,si) {
if {![file exists $file]} {
append commands "# WARNING: CDB file does not exist ($file)\n"
set warnings($warning_count) "CDB file does not exist ($file)"
incr warning_count
}
}
}
}
# }
append commands "# ==============================================\n"
append commands "# LEF Files\n"
append commands "# ==============================================\n"
if {[info exists vars(lef_files)]} {
foreach file $vars(lef_files) {
# lappend check(files) $file
append commands "# INFO: $file\n"
}
} else {
if {([string tolower $vars(netlist_type)] == "verilog") && (![info exists vars(oa_ref_lib)])} {
append commands "# ERROR: Required variable vars(lef_files) not defined\n"
set errors($error_count) "Required variable vars(lef_files) not defined"
incr error_count
}
}
if {[info exists vars(partition_list)]} {
append commands "# ==============================================\n"
append commands "# Hierarchical \n"
append commands "# ==============================================\n"
append commands "# INFO: partitions = $vars(partition_list)\n"
set cts_spec [FF::get_by_suffix vars ",cts_spec"]
if {$cts_spec != ""} {
append commands "# CTS Specs : \n"
foreach partition $cts_spec {
lappend check(files) $vars($partition,cts_spec)
append commands "# $partition -> $vars($partition,cts_spec)\n"
}
}
set latency_sdc [FF::get_by_suffix vars ",latency_sdc"]
if {$latency_sdc != ""} {
append commands "# Latency SDCs :\n"
foreach partition $latency_sdc {
lappend check(files) $vars($partition,latency_sdc)
if {[llength [split $partition ","]] == 1} {
append commands "# $partition -> $vars($partition,latency_sdc)\n"
} else {
append commands "# [lindex [split $partition ","] 0] ([lindex [split $partition ","] 1]) -> $vars($partition,latency_sdc)\n"
}
}
}
}
if {[info exists vars(enable_pac)] && $vars(enable_pac)} {
append commands "# WARNING: PAC is obsolete and will be removed in a future version. Consider using Sign-off ECO."
set warnings($warning_count) "PAC is obsolete and will be removed in a future version. Consider using Sign-off ECO."
incr warning_count
set pac_mode [FF::get_by_suffix vars ",pac_mode"]
if {$pac_mode != ""} {
set pac_list [list "read_only" "interface" "ilm" "all"]
foreach pac $pac_mode {
if {[lsearch $pac_list $vars($pac,pac_mode)] == -1} {
append commands "# ERROR: $pac pac_mode invalid value; must be one of \'$pac_list\'\n"
set errors($error_count) "$pac pac_mode invalid value; must be one of \'$pac_list\'"
incr error_count
}
}
}
}
if {[FF::is_lp_flow]} {
append commands "# ==============================================\n"
append commands "# Low Power \n"
append commands "# ==============================================\n"
if {[info exists vars(ieee1801_file)]} {
set warnings($warning_count) "Using vars(ieee1801_file) requires the following limited access feature : mvsSupportIEEE1801"
incr warning_count
}
set num_power_intent_files 0
foreach v {cpf_file ieee1801_file} {
if {[info exists vars($v)]} {
append commands "# INFO: $v = $vars($v)\n"
lappend check(files) $vars($v)
incr num_power_intent_files
}
}
if {$num_power_intent_files > 1} {
set errors($error_count) "vars(cpf_file) and vars(ieee1801_file) may not both be specified."
append commands "# ERROR: $errors($error_count)\n"
incr error_count
}
if {[info exists vars(power_domains)] && ($vars(power_domains) != "")} {
append commands "# INFO: power_domains = $vars(power_domains)\n"
foreach domain $vars(power_domains) {
set print($domain) 1
foreach optional "filler_cells tie_cells endcaps welltaps" {
if {[info exists vars($domain,$optional)] && ($vars($domain,$optional) != "")} {
if {$print($domain)} {
append commands "# INFO: $domain:\n"
set print($domain) 0
}
append commands "# INFO: $optional = $vars($domain,$optional)\n"
}
# if {$optional == "filler_cells} {
# set process [regsub "nm" $vars(process) ""]
# if {[expr $process <= 28)] && [info exists vars(filler_cells,min_gap)]} {
# append commands "# ERROR: For process node < 28nm, variable vars(filler_cells,min_gap) is required\n"
# set errors($error_count) "For process node < 28nm, variable vars(filler_cells,min_gap) is required"
# incr error_count
# }
# }
}
}
} else {
append commands "# WARNING: Recommended variable vars(power_domains) not defined\n"
set warnings($warning_count) "Recommended variable vars(power_domains) not defined"
incr warning_count
}
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
append commands "# INFO: power_analysis_view = $vars(power_analysis_view)\n"
} else {
append commands "# WARNING: Recommended variable vars(power_analysis_view) not defined\n"
append commands "# Will default to the default setup analysis view\n"
set warnings($warning_count) "Recommended variable vars(power_analysis_view) not defined"
incr warning_count
}
}
# if {![info exists vars(view_definition_tcl)]} {
append commands "# ==============================================\n"
append commands "# RC Corners\n"
append commands "# ==============================================\n"
set check(rc_corners) [list]
foreach rc_corner $vars(rc_corners) {
append commands "# INFO: $rc_corner:\n"
if {[info exists vars($rc_corner,cap_table)] && ($vars($rc_corner,cap_table) != "")} {
append commands "# INFO: cap_table = $vars($rc_corner,cap_table)\n"
lappend check(rc_corners) $vars($rc_corner,cap_table)
} else {
if {![info exists vars($rc_corner,qx_tech_file)]} {
append commands "# ERROR: Variable vars($rc_corner,cap_table) or vars($rc_corner,qx_tech_file) must be defined\n"
set errors($error_count) "Variable vars($rc_corner,cap_table) or vars($rc_corner,qx_tech_file) must be defined"
incr error_count
} else {
if {[lindex [split $vars(version) "."] 0] < 15} {
append commands "# INFO: Variable vars($rc_corner,cap_table) not defined\n"
set infos($info_count) "Variable vars($rc_corner,cap_table) not defined"
incr info_count
}
}
}
# if {$vars(cts_engine) != "cts"} {
# if {[info exists vars($rc_corner,atf_file)] && ($vars($rc_corner,atf_file) != "")} {
# append commands "# INFO: atf_file = $vars($rc_corner,atf_file)\n"
# lappend check(rc_corners) $vars($rc_corner,atf_file)
# } else {
# append commands "# WARNING: Recommended variable vars($rc_corner,atf_file) not defined\n"
# set warnings($warning_count) "Recommended variable vars($rc_corner,atf_file) not defined"
# incr warning_count
# }
# }
if {[info exists vars($rc_corner,T)] && ($vars($rc_corner,T) != "")} {
append commands "# INFO: temperature = $vars($rc_corner,T)\n"
lappend check(integers) "$rc_corner,T"
} else {
append commands "# WARNING: Recommended variable vars($rc_corner,T) not defined\n"
set warnings($warning_count) "Recommended variable vars($rc_corner,T) not defined"
incr warning_count
}
if {[info exists vars($rc_corner,qx_tech_file)] && ($vars($rc_corner,qx_tech_file) != "")} {
append commands "# INFO: qx_tech_file = $vars($rc_corner,qx_tech_file)\n"
lappend check(rc_corners) $vars($rc_corner,qx_tech_file)
} else {
if {[info exists vars(postroute_extraction_effort)] && ($vars(postroute_extraction_effort) != "low")} {
append commands "# ERROR: qx_tech_file not defined for $rc_corner and postroute_extraction_effort is set to $vars(postroute_extraction_effort)\n"
set errors($error_count) "qx_tech_file not defined for $rc_corner and postroute_extraction_effort is set to $vars(postroute_extraction_effort)"
incr error_count
}
if {[info exists vars(signoff_extraction_effort)] && ($vars(signoff_extraction_effort) != "low")} {
append commands "# ERROR: qx_tech_file not defined for $rc_corner and signoff_extraction_effort is set to $vars(signoff_extraction_effort)\n"
set errors($error_count) "qx_tech_file not defined for $rc_corner and signoff_extraction_effort is set to $vars(signoff_extraction_effort)"
# set errors($error_count) "Required variable vars($rc_corner,cap_table) not defined"
incr error_count
}
}
}
if {[info exists vars(opconds)]} {
append commands "# ==============================================\n"
append commands "# Operating Conditions\n"
append commands "# ==============================================\n"
foreach opcond $vars(opconds) {
append commands "# INFO: $opcond:\n"
foreach required "library_file P V T" {
if {[info exists vars($opcond,$required)] && ($vars($opcond,$required) != "")} {
append commands "# INFO: $required = $vars($opcond,$required)\n"
} else {
append commands "# ERROR: Required variable vars($opcond,$required) not defined\n"
set errors($error_count) "Required variable vars($opcond,$required) not defined"
incr error_count
}
}
}
}
append commands "# ==============================================\n"
append commands "# Delay Corners\n"
append commands "# ==============================================\n"
set good_corners [list]
foreach delay_corner $vars(delay_corners) {
set args 0
append commands "# INFO: $delay_corner:\n"
if {[info exists vars($delay_corner,rc_corner)] && ($vars($delay_corner,rc_corner) != "")} {
append commands "# INFO: rc_corner = $vars($delay_corner,rc_corner)\n"
incr args
} else {
append commands "# ERROR: Required variable vars($delay_corner,rc_corner) not defined\n"
set errors($error_count) "Required variable vars($delay_corner,rc_corner) not defined"
incr error_count
}
if {(![FF::is_lp_flow]) || ([FF::is_lp_flow] && !$vars(cpf_timing))} {
if {[info exists vars($delay_corner,library_set)] && ($vars($delay_corner,library_set) != "")} {
append commands "# INFO: library_set = $vars($delay_corner,library_set)\n"
incr args
} else {
foreach additional "early_library_set late_library_set" {
if {[info exists vars($delay_corner,$additional)] && ($vars($delay_corner,$additional) != "")} {
append commands "# INFO: $additional = $vars($delay_corner,$additional)\n"
incr args
} else {
append commands "# ERROR: Required variable vars($delay_corner,library_set) and vars($delay_corner,$additional) not defined\n"
set errors($error_count) "Required variable vars($delay_corner,library_set) and vars($delay_corner,$additional) not defined\n"
incr error_count
}
}
}
}
foreach optional "opcond opcond_library early_opcond_library late_opcond_library" {
if {[info exists vars($delay_corner,$optional)] && ($vars($delay_corner,$optional) != "")} {
incr args
append commands "# INFO: $optional = $vars($delay_corner,$optional)\n"
}
}
foreach optional "power_domains" {
if {[info exists vars($delay_corner,$optional)] && ($vars($delay_corner,$optional) != "")} {
append commands "# INFO: $optional = $vars($delay_corner,$optional)\n"
}
}
if {!$vars(cpf_timing) && ($args > 1)} {
lappend good_corners $delay_corner
} else {
if {$args > 0} {
lappend good_corners $delay_corner
}
}
}
set vars(good_corners) $good_corners
set check(constraint_modes) [list]
if {[FF::is_lp_flow]} {
append commands "# ==============================================\n"
append commands "# Constraint Modes\n"
append commands "# ==============================================\n"
if {[info exists vars(constraint_modes)]} {
foreach mode $vars(constraint_modes) {
append commands "# INFO: $mode:\n"
foreach other "pre_cts_sdc incr_cts_sdc post_cts_sdc" {
if {[info exists vars($mode,$other)] && ($vars($mode,$other) != "")} {
append commands "# INFO: $other = $vars($mode,$other)\n"
lappend check(constraint_modes) $vars($mode,$other)
} else {
if {!$vars(cpf_timing)} {
if {($other == "pre_cts_sdc") && $vars(rc)} {
set vars($mode,$other) $vars(dbs_dir)/$vars(design).syn_placed.$mode.sdc
} elseif {($other == "pre_cts_sdc") && !$vars(rc)} {
append commands "# ERROR: Variable vars($mode,$other) not defined\n"
set errors($error_count) "Variable vars($mode,$other) not defined"
incr error_count
} else {
if {($other == "pre_cts_sdc") || (($other == "post_cts_sdc") && ![info exists vars($mode,incr_cts_sdc)])} {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
}
}
} else {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
}
}
}
}
} else {
append commands "# INFO: No constraint mode information defined\n"
append commands "# Post CTS latency adjustment must be\n"
append commands "# managed by the user via plug-ins\n"
}
} else {
append commands "# ==============================================\n"
append commands "# Constraint Modes\n"
append commands "# ==============================================\n"
if {$vars(rc)} {
set required_list "synth_sdc pre_cts_sdc"
} else {
set required_list "pre_cts_sdc"
}
foreach mode $vars(constraint_modes) {
set found 0
append commands "# INFO: $mode:\n"
foreach required $required_list {
if {[info exists vars($mode,$required)] && ($vars($mode,$required) != "")} {
append commands "# INFO: $required = $vars($mode,$required)\n"
lappend check(constraint_modes) $vars($mode,$required)
incr found
} else {
if {[llength $required_list] == 1} {
append commands "# ERROR: Required variable vars($mode,$required) not defined\n"
set errors($error_count) "Required variable vars($mode,$required) not defined"
incr error_count
}
}
}
if {([llength $required_list] > 1) && ($found == 0)} {
append commands "# ERROR: One of the required variables ($required_list) not defined\n"
set errors($error_count) "One of the required variables ($required_list) not defined"
incr error_count
}
foreach other "post_cts_sdc incr_cts_sdc" {
if {$other == "post_cts_sdc" && ![info exists vars($other)]} {
if {![info exists vars($mode,$other)]} {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
} else {
append commands "# INFO: $other = $vars($mode,$other)\n"
}
} else {
if {[info exists vars($mode,$other)] && ($vars($mode,$other) != "")} {
append commands "# INFO: $other = $vars($mode,$other)\n"
lappend check(constraint_modes) $vars($mode,$other)
} else {
append commands "# INFO: Variable vars($mode,$other) not defined\n"
}
}
}
}
}
if {![info exists vars(hold_analysis_views)]} {
set vars(hold_analysis_views) ""
}
if {![info exists vars(power_analysis_view)]} {
set vars(power_analysis_view) ""
}
append commands "# ==============================================\n"
append commands "# Analysis Views\n"
append commands "# ==============================================\n"
if {[FF::is_lp_flow]} {
foreach analysis_view [concat $vars(setup_analysis_views) $vars(hold_analysis_views) $vars(power_analysis_view)] {
append commands "# INFO: $analysis_view:\n"
foreach other "delay_corner constraint_mode" {
if {[info exists vars($analysis_view,$other)] && ($vars($analysis_view,$other) != "")} {
append commands "# INFO: $other = $vars($analysis_view,$other)\n"
lappend check(analysis_view) $vars($analysis_view,$other)
}
}
}
} else {
set check(analysis_views) [list]
foreach analysis_view [concat $vars(setup_analysis_views) $vars(hold_analysis_views) $vars(power_analysis_view)] {
append commands "# INFO: $analysis_view:\n"
foreach required "delay_corner constraint_mode" {
if {[info exists vars($analysis_view,$required)] && ($vars($analysis_view,$required) != "")} {
append commands "# INFO: $required = $vars($analysis_view,$required)\n"
lappend check(analysis_view) $vars($analysis_view,$required)
} else {
append commands "# ERROR: Required variable vars($analysis_view,$required) not defined\n"
set errors($error_count) "Required variable vars($analysis_view,$required) not defined"
incr error_count
}
}
}
}
# }
append commands "# ==============================================\n"
append commands "# Recommended Variables\n"
append commands "# ==============================================\n"
foreach recommended "scan_def gds_layer_map" {
if {[info exists vars($recommended)] && ($vars($recommended) != "")} {
lappend check(files) $vars($recommended)
append commands "# INFO: $recommended = $vars($recommended)\n"
}
}
if {[info exists vars(gds_files)] && ($vars(gds_files) != "")} {
append commands "# INFO: gds_files = $vars(gds_files)\n"
foreach file $vars(gds_files) {
lappend check(files) $file
}
}
foreach recommended "max_route_layer filler_cells tie_cells dont_use_list antenna_diode" {
if {[info exists vars($recommended)] && ($vars($recommended) != "")} {
append commands "# INFO: $recommended = $vars($recommended)\n"
if {$recommended == "tie_cells"} {
if {[llength $vars(tie_cells)] > 2} {
append commands "# ERROR: Recommended variable vars($recommended) has more than two cells\n"
set errors($error_count) "Recommended variable vars($recommended) has more than two cells"
incr error_count
}
}
if {$recommended == "antenna_diode"} {
if {[llength $vars(antenna_diode)] > 1} {
append commands "# ERROR: Recommended variable vars($recommended) has more than one cells\n"
set errors($error_count) "Recommended variable vars($recommended) has more than one cells"
incr error_count
}
}
if {$recommended == "max_route_layer"} {
lappend check(integers) "$recommended"
}
} else {
if {($recommended == "dont_use_list")} {
if {![info exists vars(dont_use_file)]} {
append commands "# WARNING: Recommended variables dont_use_list and dont_use_file not defined\n"
set warnings($warning_count) "Recommended variables dont_use_list and dont_use_file not defined"
incr warning_count
}
} else {
append commands "# WARNING: Recommended variable vars($recommended) not defined\n"
set warnings($warning_count) "Recommended variable vars($recommended) not defined"
incr warning_count
}
}
}
foreach optional "size_only_file dont_use_file" {
if {[info exists vars($optional)]} {
lappend check(files) $vars($optional)
}
}
append commands "# ==============================================\n"
append commands "# Other Variables\n"
append commands "# ==============================================\n"
foreach other "jtag_cells jtag_rows spare_cells" {
if {[info exists vars($other)] && ($vars($other) != "")} {
append commands "# INFO: $other = $vars($other)\n"
} else {
append commands "# INFO: Variable vars($other) not defined\n"
}
}
# if {![info exists vars(view_definition_tcl)]} {
append commands "# ==============================================\n"
append commands "# Scale Factors\n"
append commands "# ==============================================\n"
foreach rc_corner $vars(rc_corners) {
set i 0
append commands "# INFO: $rc_corner:\n"
if {[info exists vars($rc_corner,scale_tcl)]} {
if {[file exists $vars($rc_corner,scale_tcl)]} {
incr i
append commands "# INFO: scaling file = $vars($rc_corner,scale_tcl)\n"
} else {
puts "<FF> ERROR: Scaling file $vars($rc_corner,scale_tcl) for rc corner $rc_corner defined but does not exist"
set errors($error_count) "Scaling file $vars($rc_corner,scale_tcl) for rc corner $rc_corner defined but does not exist"
incr error_count
}
} else {
foreach other "pre_route_res_factor post_route_res_factor \
pre_route_cap_factor post_route_cap_factor \
pre_route_clk_res_factor post_route_clk_res_factor \
pre_route_clk_cap_factor post_route_clk_cap_factor \
post_route_xcap_factor" {
if {[info exists vars($rc_corner,$other)]} {
append commands "# INFO: $other = $vars($rc_corner,$other)\n"
incr i
}
}
}
if {$i == 0} {
append commands "# WARNING: No scale factors set for rc corner ($rc_corner)\n"
set warnings($warning_count) "No scale factors set for rc corner ($rc_corner)"
incr warning_count
}
}
append commands "# ==============================================\n"
append commands "# Derating Factors\n"
append commands "# ==============================================\n"
set i 0
if {[info exists vars(derate_tcl)]} {
append commands "# INFO: derate file = $vars(derate_tcl)\n"
lappend check(files) $vars(derate_tcl)
incr i
} else {
foreach delay_corner $vars(delay_corners) {
append commands "# INFO: $delay_corner:\n"
if {[info exists vars($delay_corner,derate_tcl)]} {
append commands "# INFO: derate file = $vars($delay_corner,derate_tcl)\n"
lappend check(files) $vars($delay_corner,derate_tcl)
incr i
} else {
if {[info exists vars(derate_tcl)]} {
append commands "# INFO: derate file = $vars(derate_tcl)\n"
lappend check(files) $vars(derate_tcl)
} else {
foreach other "early_data_cell early_clock_cell early_cell_check \
late_data_cell late_clock_cell late_cell_check \
data_cell_early clock_cell_early cell_check_early \
data_cell_late clock_cell_late cell_check_late" {
if {[info exists vars($delay_corner,$other)]} {
append commands "# INFO: $other = $vars($delay_corner,$other)\n"
incr i
}
}
}
}
if {$i == 0} {
append commands "# WARNING: No derating factors set for delay corner ($delay_corner)\n"
set warnings($warning_count) "No derating factors set for delay corner ($delay_corner)"
incr warning_count
}
}
}
# }
if {![regexp "9.1" $vars(version)]} {
set valid "TRUE FALSE true false auto"
if {[info exists vars(enable_si_aware)]} {
if {[lsearch $valid $vars(enable_si_aware)] == -1} {
append commands "# ERROR: Variable vars(enable_si_aware) has illegal value\n"
set errors($error_count) "Variable vars(enable_si_aware) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
}
# set valid "postcts postroute postroute_si true false"
# foreach var "fix_hold" {
# if {[lsearch $valid [string tolower $vars($var)]] == -1} {
# append commands "# ERROR: Variable vars($var) has illegal value $vars($var)\n"
# set errors($error_count) "Variable vars($var) has illegal value $vars($var)"
# incr error_count
# append commands "# Must be one of '$valid'\n"
# }
# }
set valid [list true false]
foreach var "fix_hold_ignore_ios fix_hold_allow_tns_degradation" {
if {![info exists vars($var)]} {
continue
}
if {[lsearch $valid [string tolower $vars($var)]] == -1} {
append commands "# ERROR: Variable vars($var) has illegal value $vars($var)\n"
set errors($error_count) "Variable vars($var) has illegal value $vars($var)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
set valid "pre_place pre_prects pre_cts pre_postcts pre_postroute pre_postroute_si pre_signoff true false"
foreach option "metalfill enable_ocv enable_ss" {
if {[info exists vars($option)]} {
if {[lsearch $valid $vars($option)] == -1} {
append commands "# ERROR: Variable vars($option) has illegal value ($vars($option))\n"
set errors($error_count) "Variable vars($option) has illegal value ($vars($option))"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
}
set pacs [FF::get_by_suffix vars ",pac_mode"]
set valid "read_only interface all"
foreach pac $pacs {
if {[info exists vars(pac_mode)]} {
if {[lsearch $valid $vars(pac_mode)] == -1} {
append commands "# ERROR: Variable vars(pac_mode) has illegal value\n"
set errors($error_count) "Variable vars(pac_mode) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
}
set valid "default pessimistic"
if {[info exists vars(si_analysis_type)]} {
if {[lsearch $valid $vars(si_analysis_type)] == -1} {
append commands "# ERROR: Variable vars(si_analysis_type) has illegal value\n"
set errors($error_count) "Variable vars(si_analysis_type) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
set valid "post_cts post_route both none"
if {[info exists vars(clock_eco)]} {
if {[lsearch $valid $vars(clock_eco)] == -1} {
append commands "# ERROR: Variable vars(clock_eco) has illegal value\n"
set errors($error_count) "Variable vars(clock_eco) has illegal value"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
# if {$vars(enable_flexilm)} {
# set warnings($warning_count) "Using vars(enable_flexilm) requires the following limited access feature : encFlexILM"
# incr warning_count
# if {$vars(place_opt_design)} {
# set warnings($warning_count) "Variable vars(place_opt_design) not supported when vars(enable_flexilm) is true"
# incr warning_count
# }
# }
if {$vars(use_flexmodels) && $vars(flexmodel_prototype)} {
set valid [list flat multi_level top_to_bottom]
if {[info exists vars(flexmodel_prototype_flow_style)]} {
if {[lsearch $valid $vars(flexmodel_prototype_flow_style)] == -1} {
append commands "# ERROR: Variable vars(flexmodel_prototype_flow_style) has illegal value ($vars(flexmodel_prototype_flow_style))\n"
set errors($error_count) "Variable vars(flexmodel_prototype_flow_style) has illegal value ($vars(flexmodel_prototype_flow_style))"
incr error_count
append commands "# Must be one of '$valid'\n"
}
}
}
set check(plugins) [list]
if {[info exists vars(metalfill)] && ($vars(metalfill) != false)} {
set check(plugins) metalfill_tcl
}
append commands "# ==============================================\n"
append commands "# Plug-ins\n"
append commands "# ==============================================\n"
set rc_plugins "syn_init_tcl syn_load_rtl_tcl pre_syn_load_lib_tcl post_syn_load_lib_tcl \
pre_syn_elab_tcl post_syn_elab_tcl syn_dft_setup_tcl pre_syn_gen_tcl \
post_syn_gen_tcl pre_syn_map_tcl post_syn_map_tcl post_syn_dft_tcl \
pre_syn_incr_tcl post_syn_incr_tcl pre_syn_place_tcl postload_syn_place_tcl \
preexport_syn_place_tcl preannotation_syn_place_tcl post_syn_place_tcl pre_syn_exit_tcl"
set edi_plugins "always_source_tcl pre_init_tcl post_init_tcl \
pre_place_tcl place_tcl post_place_tcl pre_cts_tcl cts_tcl post_cts_tcl \
pre_prects_tcl post_prects_tcl pre_postcts_tcl post_postcts_tcl \
pre_postcts_hold_tcl post_postcts_hold_tcl pre_route_tcl post_route_tcl \
pre_postroute_tcl post_postroute_tcl pre_postroute_hold_tcl post_postroute_hold_tcl \
pre_postroute_si_tcl post_postroute_si_tcl pre_postroute_si_hold_tcl
post_postroute_si_hold_tcl pre_signoff_tcl post_signoff_tcl \
pre_rebudget_tcl post_rebudget_tcl pre_flexilm_tcl post_flexilm_tcl \
pre_assemble_tcl post_assemble_tcl pre_prototype_tcl post_prototype_tcl pre_model_gen_tcl post_model_gen_tcl \
pre_partition_place_tcl post_partition_place_tcl pre_assemble_flex_ilm_tcl post_assemble_flexilm_tcl"
if {$vars(rc)} {
set plugin_list [join [concat $rc_plugins $edi_plugins]]
} else {
set plugin_list $edi_plugins
}
foreach plugin $plugin_list {
if {[info exists vars($plugin)] && ($vars($plugin) != "")} {
append commands "# INFO: Plug-in $plugin = $vars($plugin)\n"
lappend check(plugins) $plugin
lappend vars(plugins_defined) $plugin
}
}
set dist(lsf) "queue resource args"
set dist(custom) "script"
set dist(rsh) "host_list"
set dist(local) ""
if {[info exists vars(distribute)]} {
if {[info exists dist($vars(distribute))]} {
append commands "# ==============================================\n"
append commands "# Distribution Setup\n"
append commands "# ==============================================\n"
append commands "# INFO: Mode = $vars(distribute)\n"
foreach option $dist($vars(distribute)) {
if {![info exists vars($vars(distribute),$option)]} {
append commands "# ERROR: Required variable vars($vars(distribute),$option) not defined\n"
set errors($error_count) "Required variable vars($vars(distribute),$option) not defined"
incr error_count
} else {
append commands "# INFO: $option = $vars($vars(distribute),$option)\n"
}
}
} else {
append commands "# ERROR: Distribution mode $vars(distribute) not supported\n"
set errors($error_count) "Distribution mode $vars(distribute) not supported"
incr error_count
}
} else {
if {[info exists vars(hosts)] && ($vars(hosts) > 1)} {
append commands "#WARNING: Variable vars(hosts) > 1 but vars(distribute) not defined\n"
set warnings($warning_count) "Variable vars(hosts) > 1 but vars(distribute) not defined"
incr warning_count
}
}
append commands "# ==============================================\n"
append commands "# Type Check\n"
append commands "# ==============================================\n"
foreach integer $check(integers) {
if {![string is integer -strict $vars($integer)]} {
append commands "# ERROR: Variables is not an integer ($integer) ...\n"
set errors($error_count) "Variables is not an integer ($integer) ..."
incr error_count
}
}
append commands "# ==============================================\n"
append commands "# File Check\n"
append commands "# ==============================================\n"
set files 0
append commands "# INFO: Checking design files ...\n"
foreach file $check(files) {
# append commands "# INFO: $file ...\n"
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file) ...\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
} else {
incr files
}
}
append commands "# INFO: ... found $files files\n"
set files 0
append commands "# INFO: Checking LEF files ...\n"
if {[info exists vars(lef_files)]} {
foreach file $vars(lef_files) {
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file)\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
} else {
incr files
}
}
append commands "# INFO: ... found ($files/[llength $vars(lef_files)]) lef files\n"
}
set files 0
set total 0
# if {![info exists vars(view_definition_tcl)]} {
# if {![info exists vars(cpf_file)]} {
append commands "# INFO: Checking library sets ...\n"
foreach library_set $vars(library_sets) {
# if {[info exists vars(enable_ldb)] && $vars(enable_ldb)} {
# set temp_list $vars($library_set,timing,orig)
# } else {
set temp_list $vars($library_set,timing)
# }
foreach file $temp_list {
incr total
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file)\n"
# set errors($error_count) "File does not exist ($file)"
# incr error_count
} else {
incr files
}
}
if {[info exists vars($library_set,si)]} {
foreach file $vars($library_set,si) {
incr total
if {![file exists $file]} {
append commands "# WARNING: CDB file does not exist ($file)\n"
# set warnings($warning_count) "CDB file does not exist ($file)"
# incr warning_count
} else {
incr files
}
}
} else {
if {!$vars(enable_si_aware)} {
append commands "# WARNING: CDB libraries not defined for $library_set library set\n"
set warnings($warning_count) "CDB libraries not defined for $library_set library set"
incr warning_count
}
}
}
append commands "# INFO: ... found ($files/$total) library files\n"
if {$total != $files} {
set errors($error_count) "[expr $total - $files] timing library files were not found "
incr error_count
}
set files 0
# }
append commands "# INFO: Checking rc corners ...\n"
foreach file $check(rc_corners) {
if {![file exists $file]} {
append commands "# ERROR: File does not exist ($file)\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
} else {
incr files
}
}
append commands "# INFO: ... found $files files\n"
set files 0
append commands "# INFO: Checking constraint modes ...\n"
foreach file_list $check(constraint_modes) {
foreach file $file_list {
if {![file exists $file]} {
if {![info exists vars(cpf_file)] || ([info exists vars(cpf_file)] && !$vars(cpf_timing))} {
append commands "# ERROR: File does not exist ($file)\n"
set errors($error_count) "File does not exist ($file)"
incr error_count
}
} else {
incr files
}
}
}
# }
append commands "# INFO: ... found $files files\n"
set files 0
append commands "# INFO: Checking plugin files ...\n"
foreach plug $check(plugins) {
set file $vars($plug)
if {![file exists $file] && ![file exists $vars(plug_dir)/$file]} {
append commands "# WARNING: File does not exist ($file) ... continuing\n"
lappend vars(missing_plugins) $plug
} else {
lappend vars(plugins_found) $plug
incr files
if {!$vars(enable_celtic_steps)} {
if {[regexp "postroute_si" $plug]} {
append warnings($warning_count) "Plug-in $plug will be skipped for siAware flow"
incr warning_count
append commands "# WARNING: Plug-in $plug will be skipped for siAware flow\n"
append commands "# To enable celtic based SI flow, use vars(enable_celtic_steps)\n"
}
}
}
}
append commands "# INFO: ... found $files files\n"
append commands "# =====================================================\n"
append commands "# Flow Options\n"
append commands "# =====================================================\n"
if {[info exists vars(partition_list)]} {
set flow hierarchical
} else {
set flow flat
}
set valid [list none default standard express extreme]
if {[lsearch $valid [string tolower $vars(flow_effort)]] == -1} {
append commands "# ERROR: Variable vars(flow_effort) has illegal value $vars(flow_effort)\n"
set errors($error_count) "Variable vars(flow_effort) has illegal value $vars(flow_effort)"
incr error_count
append commands "# Must be one of '$valid'\n"
} else {
if {([string tolower $vars(flow_effort)] == "none") || ([string tolower $vars(flow_effort)] == "default")} {
append warnings($warning_count) "Changing vars(flow_effort) from '$vars(flow_effort)' to 'standard'"
incr warning_count
set vars(flow_effort) standard
}
}
set valid [list none low high]
if {[lsearch $valid [string tolower $vars(power_effort)]] == -1} {
append commands "# ERROR: Variable vars(power_effort) has illegal value $vars(power_effort)\n"
set errors($error_count) "Variable vars(power_effort) has illegal value $vars(power_effort)"
incr error_count
append commands "# Must be one of '$valid'\n"
}
append commands "# Flow = $flow\n"
append commands "# Power = $vars(power_effort)\n"
append commands "# Flavor = $vars(flow)\n"
append commands "# Effort = $vars(flow_effort)\n"
append commands "# -----------------------------------------------------\n"
append commands "# Placement Options\n"
append commands "# -----------------------------------------------------\n"
if {[info exists vars(place_opt_design)]} {
append commands "# Place Opt Design = $vars(place_opt_design)\n"
}
if {[info exists vars(in_place_opt)]} {
append commands "# In Place Opt = $vars(in_place_opt)\n"
}
if {[info exists vars(no_pre_place_opt)]} {
append commands "# No PrePlace Opt = $vars(no_pre_place_opt)\n"
}
if {[info exists vars(place_io_pins)]} {
append commands "# Place IO Pins = $vars(place_io_pins)\n"
}
if {[info exists vars(clock_gate_aware)]} {
append commands "# Clock Gate Aware = $vars(clock_gate_aware)\n"
}
if {[info exists vars(congestion_effort)]} {
if {$vars(congestion_effort) == "none"} {
unset vars(congestion_effort)
} else {
append commands "# Congestion Effort = $vars(congestion_effort)\n"
}
}
append commands "# -----------------------------------------------------\n"
append commands "# Clock Tree Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Route Clock Nets = $vars(route_clock_nets)\n"
if {[info exists vars(clock_eco)]} {
append commands "# Clock ECO = $vars(clock_eco)\n"
}
append commands "# -----------------------------------------------------\n"
append commands "# Optimization Options\n"
append commands "# -----------------------------------------------------\n"
if {[info exists vars(leakage_effort)]} {
append commands "# Leakage Effort = $vars(leakage_effort)\n"
}
if {[info exists vars(preserve_assertions)]} {
append commands "# Preserve Assertions = $vars(preserve_assertions)\n"
}
if {[info exists vars(useful_skew)]} {
append commands "# Useful Skew = $vars(useful_skew)\n"
}
if {[info exists vars(critical_range)]} {
append commands "# Critical Range = $vars(critical_range)\n"
}
if {[info exists vars(all_end_points)]} {
append commands "# All End Points = $vars(all_end_points)\n"
}
if {[info exists vars(size_only_file)]} {
append commands "# Size Only File = $vars(size_only_file)\n"
}
if {[info exists vars(dont_use_file)]} {
append commands "# Don't Use File = $vars(dont_use_file)\n"
}
if {[info exists vars(skew_buffers)]} {
append commands "# Skew Buffers = $vars(skew_buffers)\n"
}
if {[info exists vars(enable_pac)]} {
append commands "# Enable PAC = $vars(enable_pac)\n"
if {[info exists vars(partition_list)]} {
foreach pac $vars(partition_list) {
if {[info exists vars($pac,pac_mode)]} {
append commands "# $pac -> $vars($pac,pac_mode)\n"
}
}
}
}
append commands "# -----------------------------------------------------\n"
append commands "# Hold Fixing Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Fix Hold = $vars(fix_hold)\n"
if {[info exists vars(fix_hold_effort)]} {
append commands "# Fix Hold Effort = $vars(fix_hold_effort)\n"
}
if {[info exists vars(fix_hold_ignore_ios)]} {
append commands "# Ignore IOs = $vars(fix_hold_ignore_ios)\n"
}
if {[info exists vars(fix_hold_allow_tns_degradation)]} {
append commands "# Allow TNS Degradation = $vars(fix_hold_allow_tns_degradation)\n"
}
append commands "# -----------------------------------------------------\n"
append commands "# Timing Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Enable CPPR = $vars(enable_cppr)\n"
append commands "# Enable OCV = $vars(enable_ocv)\n"
append commands "# Enable AOCV = $vars(enable_aocv)\n"
append commands "# Enable SOCV = $vars(enable_socv)\n"
append commands "# Enable SS = $vars(enable_ss)\n"
append commands "# -----------------------------------------------------\n"
append commands "# Routing Options\n"
append commands "# -----------------------------------------------------\n"
if {[info exists vars(track_opt)]} {
append commands "# In Route Optimization = $vars(track_opt)\n"
# if {$vars(track_opt)} {
# set vars(enable_si_aware) true
# if {![info exists vars(tquantus_file)]} {
# set errors($error_count) "tQuantus file - vars(tquantus_file) - required when vars(track_opt) set to true"
# incr error_count
# }
# }
}
if {[info exists vars(multi_cut_effort)]} {
append commands "# Multi-Cut Effort = $vars(multi_cut_effort)\n"
}
if {[info exists vars(litho_driven_routing)]} {
append commands "# Litho Driven Routing = $vars(litho_driven_routing)\n"
}
if {[info exists vars(antenna_diode)] && ($vars(antenna_diode) != "")} {
append commands "# Antenna Diode = $vars(antenna_diode)\n"
}
if {[info exists vars(relative_c_thresh)] || \
[info exists vars(total_c_thresh)] || \
[info exists vars(coupling_c_thresh)] ||\
[info exists vars(postroute_extraction_effort)] ||\
[info exists vars(signoff_extraction_effort)]} {
append commands "# -----------------------------------------------------\n"
append commands "# Extraction Options\n"
append commands "# -----------------------------------------------------\n"
}
if {[info exists vars(relative_c_thresh)]} {
append commands "# Relative C Threshold = $vars(relative_c_thresh)\n"
}
if {[info exists vars(total_c_thresh)]} {
append commands "# Total C Threshold = $vars(total_c_thresh)\n"
}
if {[info exists vars(coupling_c_thresh)]} {
append commands "# Coupling C Threshold = $vars(coupling_c_thresh)\n"
}
if {[info exists vars(postroute_extraction_effort)]} {
append commands "# Postroute Effort Level = $vars(postroute_extraction_effort)\n"
}
if {[info exists vars(signoff_extraction_effort)]} {
append commands "# Signoff Effort Level = $vars(signoff_extraction_effort)\n"
}
append commands "# -----------------------------------------------------\n"
append commands "# DFM Options\n"
append commands "# -----------------------------------------------------\n"
set check_lpa_tech 0
set check_lpa_conf 0
if {[info exists vars(fix_litho)] && $vars(fix_litho)} {
append commands "# Fix Litho = $vars(fix_litho)\n"
set check_lpa_conf 1
set vars(verify_litho) true
}
if {[info exists vars(verify_litho)] && $vars(verify_litho)} {
append commands "# Verify Litho = $vars(verify_litho)\n"
set check_lpa_tech 1
}
if {[info exists vars(lpa_tech_file)]} {
append commands "# LPA Tech File = $vars(lpa_tech_file)\n"
}
if {$check_lpa_tech} {
if {![info exists vars(lpa_tech_file)]} {
set errors($error_count) "LPA tech file not defined ..."
incr error_count
}
}
if {[info exists vars(lpa_conf_file)]} {
append commands "# LPA Conf File = $vars(lpa_conf_file)\n"
}
if {$check_lpa_conf} {
if {![info exists vars(lpa_conf_file)]} {
set errors($error_count) "LPA conf file not defined ..."
incr error_count
}
}
append commands "# -----------------------------------------------------\n"
append commands "# Signal Integrity Options\n"
append commands "# -----------------------------------------------------\n"
append commands "# Process = $vars(process)\n"
if {[info exists vars(delta_delay_threshold)]} {
append commands "# Delta Delay Threshold = $vars(delta_delay_threshold)\n"
}
if {[info exists vars(celtic_settings)]} {
append commands "# Celtic Settings = $vars(celtic_settings)\n"
}
if {[info exists vars(si_analysis_type)]} {
append commands "# Analysis Type = $vars(si_analysis_type)\n"
}
if {[info exists vars(acceptable_wns)]} {
append commands "# Analysis Type = $vars(acceptable_wns)\n"
}
if {[info exists vars(distribute)]} {
if {[info exists dist($vars(distribute))]} {
append commands "# -----------------------------------------------------\n"
append commands "# Multiple CPUs\n"
append commands "# -----------------------------------------------------\n"
append commands "# Mode = $vars(distribute)\n"
if {[info exists vars(local_cpus)]} {
append commands "# CPUs On Local Host = $vars(local_cpus)\n"
}
if {[info exists vars(remote_hosts)]} {
append commands "# Number of Remote Hosts = $vars(remote_hosts)\n"
}
if {[info exists vars(cpus_per_remote_host)]} {
append commands "# CPUs Per Remote Host = $vars(cpus_per_remote_host)\n"
}
}
} else {
if {[info exists vars(local_cpus)]} {
append commands "# -----------------------------------------------------\n"
append commands "# Multiple CPUs\n"
append commands "# -----------------------------------------------------\n"
append commands "# CPUs On Local Host = $vars(local_cpus)\n"
}
}
if {$vars(high_timing_effort)} {
if {[lindex [split $vars(version) "."] 0] < 15} {
append commands "# -----------------------------------------------------\n"
append commands "# <<< HIGH EFFORT FLOW ENABLED >>>\n"
append commands "# -----------------------------------------------------\n"
} else {
append commands "# WARNING: Variable vars(high_timing_effort) not supported anymore. Please use vars(flow_effort).\n"
set warnings($warning_count) "Variable vars(high_timing_effort) not supported anymore. Please use vars(flow_effort)."
incr warning_count
}
}
append commands "# =====================================================\n"
append commands "# Abort on Setup Error = $vars(abort)\n"
append commands "# =====================================================\n"
if {[lindex [split $vars(version) "."] 0] > 10} {
foreach var [array names save_vars] {
set vars($var) $save_vars($var)
}
}
set command ""
set vars(info_count) $info_count
if {$info_count > 0} {
append command "# -----------------------------------------------------\n"
append command "# Info Summary\n"
append command "# -----------------------------------------------------\n"
for {set i 0} {$i<$info_count} {incr i} {
append command "# ([expr $i + 1]) $infos($i)\n"
}
append command "# -----------------------------------------------------\n"
append commands $command
}
set vars(warning_count) $warning_count
if {$warning_count > 0} {
append command "# -----------------------------------------------------\n"
append command "# Warning Summary\n"
append command "# -----------------------------------------------------\n"
for {set i 0} {$i<$warning_count} {incr i} {
append command "# ([expr $i + 1]) $warnings($i)\n"
}
append command "# -----------------------------------------------------\n"
append commands $command
}
set vars(error_count) $error_count
if {$error_count > 0} {
append command "# -----------------------------------------------------\n"
append command "# Error Summary\n"
append command "# -----------------------------------------------------\n"
for {set i 0} {$i<$error_count} {incr i} {
append command "# ([expr $i + 1]) $errors($i)\n"
}
append command "# -----------------------------------------------------\n"
append commands $command
} else {
append commands "# SETUP CHECK PASSED\n"
append commands "# =====================================================\n"
}
file mkdir $vars(script_dir)
set op [open $vars(script_dir)/check.rpt w]
puts $op $commands
close $op
if {$vars(abort) && ($error_count > 0)} {
puts "<FF> Aborting due to previous errors ..."
puts "<FF> See $vars(script_dir)/check.rpt for details"
puts ""
puts " Error Summary"
puts " -------------"
for {set i 0} {$i<$error_count} {incr i} {
puts " ([expr $i + 1]) $errors($i)"
}
puts "-------------------------------------------------"
exit -1
}
if {!$vars(codegen)} {
if {![FF::is_lp_flow]} {
return
}
set vars(required_procs) "get_clock_ports get_power_domains modify_power_domains add_power_switches \
route_secondary_pg_nets buffer_always_on_nets insert_welltaps_endcaps"
}
set vars(check_setup) 0
# Record errors for later processing
set vars(check_setup_errors) {}
for {set i 0} {$i<$error_count} {incr i} {
lappend vars(check_setup_errors) $errors($i)
}
}
###############################################################################
# Procedure to determine flow flavor, check for ilms, etc.
###############################################################################
proc check_flow {} {
global vars
set vars(ilm) 0
set vars(top) 0
if {![info exists vars(partition_list)] || ([info exists vars(partition_list)] && \
([file tail [file dirname [pwd]]] != "$vars(partition_dir)"))} {
if {![info exists vars(partition_list)]} {
set vars(flavor) flat
if {![info exists vars(mode)]} {
set vars(mode) "flat"
}
} else {
set vars(flavor) hier
if {![info exists vars(mode)]} {
set vars(mode) "top_down"
}
}
if {[info exists vars(partition_list)] && ($vars(mode) == "bottom_up")} {
set vars(ilm) 1
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
set vars(ilm) 1
} else {
set vars(ilm) 0
}
} else {
if {[info exists vars(partition_list)]} {
set ptn [file tail [pwd]]
set vars(ptn) $ptn
if {([file tail [file dirname [pwd]]] == "$vars(partition_dir)") &&
([lsearch $vars(partition_list) $ptn] == -1)} {
set vars(ilm) 1
set vars(top) 1
# FF_EDI::normalize_constraints
}
}
}
if {$vars(debug)} {
puts "<DEBUG> Flow -> $vars(flavor) : Step -> $vars(step) : ILM -> $vars(ilm)"
}
}
proc run_compile {} {
global vars
file mkdir $vars(script_dir)/INNOVUS
set op [open $vars(script_dir)/INNOVUS/run_compile.tcl w]
set commands ""
if {![info exists vars(ldb_dir)]} {
set vars(ldb_dir) LDB
}
file mkdir $vars(ldb_dir)
set done_list [list]
foreach set $vars(library_sets) {
set file_list [list]
foreach file $vars($set,timing) {
if {[lsearch $done_list $file] == -1} {
append commands "write_ldb -library $file -outfile $vars(ldb_dir)/[file tail $file.ldb]\n"
lappend done_list $file
}
lappend file_list $vars(ldb_dir)/[file tail $file].ldb
}
set vars($set,timing,orig) $vars($set,timing)
set vars($set,timing) $file_list
}
puts $op "$commands\nexit\n"
close $op
set vars(ran_compile) 1
}
# Generate the command to verify geometry. This is verifyGeometry
# for traditional processes, verify_drc for 20nm and below.
proc verify_geometry_command {} {
global vars
set process [regsub "nm" $vars(process) ""]
if {([lindex [split $vars(version) "."] 0] > 16) || (([lindex [split $vars(version) "."] 0] == 16) && ([lindex [split $vars(version) "."] 1] > 1))} {
return "verify_drc"
} else {
if {$process > 28} {
return "verifyGeometry"
} else {
return "verify_drc"
}
}
}
###############################################################################
# Procedure to initialize the foundation flow
###############################################################################
proc initialize_flow {} {
global vars
global env
set commands ""
FF_EDI::seed_variables 1
FF_EDI::check_setup
if {[info exist env(VPATH)]} {
file mkdir $env(VPATH)
}
if {[info exists vars(capture_metrics)] && $vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands "\n#-------------------------------------------------------------\n"
append commands "# Loading applets for metrics capture ...\n"
append commands "#-------------------------------------------------------------\n"
if {[file tail [file dirname [exec pwd]]] == $vars(partition_dir)} {
append commands "source $vars(norm_script_path)/ETC/applet.tcl\n"
append commands "source $vars(norm_script_path)/ETC/compatibility.tcl\n"
append commands "set_attribute applet_search_path $vars(norm_script_path)/ETC/applets /\n"
} else {
append commands "source \$vars(script_path)/ETC/applet.tcl\n"
append commands "source \$vars(script_path)/ETC/compatibility.tcl\n"
append commands "set_attribute applet_search_path \$vars(script_path)/ETC/applets /\n"
}
append commands "applet load measure\n"
append commands "applet load time_info\n"
append commands "#-------------------------------------------------------------\n\n"
append commands "if {\[file exists $vars(time_info_db)\]} {\n"
append commands " time_info -quiet -table ff_ext -load $vars(time_info_db)\n"
append commands "}\n"
append commands "#-------------------------------------------------------------\n\n"
}
}
# append commands "#---------------------------------------------------------------------\n"
# append commands "# RUN SCRIPT FOR STEP '[string toupper $vars(step)]'\n"
# append commands "#---------------------------------------------------------------------\n"
if {$vars(report_system_info)} {
append commands "ff_procs::system_info\n"
}
append commands [FF_EDI::initialize_multicpu]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc load_design {step {current_step ""} {format 1}} {
global env
global vars
global errors
global warnings
if {[info exists vars(hier)]} {
set hier true
} else {
set hier false
}
if {$current_step == ""} {
set current_step $step
}
# if {$step ==""} {
# set step $vars(step)
# }
# if {![info exists vars(step)]} {
# set vars(step) $step
# }
if {!$vars(codegen)} {
set restore_design true
}
set design $vars(design)
if {[regexp "^syn" $current_step]} {
return "\nread_db $vars(dbs_dir)/$step.db\n"
}
# Build restore_design command string
# ... check first for starting_dbs
# ... if not we need to know the design name as this may be a
# recursive call in a hierarhical flow
if {[info exists vars($current_step,starting_dbs)]} {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
# Interpret the starting DBS as an OA triple
set restore_command "[list restoreDesign -cellview $vars($current_step,starting_dbs)]\n"
} else {
if {[file isdirectory $vars($current_step,starting_dbs)]} {
set restore_command "restoreDesign $vars($current_step,starting_dbs) $design\n"
} elseif {[file exists $vars($current_step,starting_dbs)]} {
set restore_command "restoreDesign $vars($current_step,starting_dbs).dat $design\n"
} else {
puts "<FF> Starting DBS ($vars($current_step,starting_dbs)) defined but does not exist"
set restore_command "restoreDesign $vars($current_step,starting_dbs).dat $design\n"
set warnings($vars(warning_count)) "Starting DBS ($vars($current_step,starting_dbs)) defined but does not exist"
incr vars(warning_count)
}
}
} else {
# BCL: Added subst around vars(dbs_dir) to resolve vars(rundir)
set dir [subst $vars(dbs_dir)]
# Adding this for PV ...
if {!$vars(codegen)} {
if {[file exists $dir/$step.enc]} {
# BCL: Changed "DBS" to $dir
if {![catch {set foo [glob $dir/$step.enc.dat/*.conf]}]} {
# BCL: Changed "DBS" to $dir
regsub "\\\.conf" [glob $dir/$step.enc.dat/*.conf] "" temp
} else {
# BCL: Changed "DBS" to $dir
if {![catch {set foo [glob $dir/$step.enc.dat/*.globals]}]} {
# BCL: Changed "DBS" to $dir
regsub "\\\.globals" [glob $dir/$step.enc.dat/*.globals] "" temp
}
}
if {$design != [file tail $temp]} {
set vars(design) [file tail $temp]
Puts "<FF> Updating design name to $design"
if {[info exists vars(partition_list)]} {
if {[lsearch $vars(partition_list) [file tail [pwd]]] != -1} {
set design [file tail [pwd]]
}
}
}
} else {
Puts "<FF> Starting DBS $dir/$step.enc defined but does not exist"
exit -1
}
}
# Of course, the command will depend on the database format ... and the version
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
if {$hier} {
set restore_command "restoreDesign -cellview \[list $vars(oa_partition_lib) $design $step\]\n"
} else {
set restore_command "restoreDesign -cellview \[list $vars(oa_design_lib) $design $step\]\n"
}
} else {
set restore_command "restoreOaDesign $vars(oa_design_lib) $design $step\n"
}
} else {
if {$vars(user_mode) == "hier" && ($vars(hier_flow_type) == "2pass")} {
if {$vars(step) == "cts" && $vars(enable_flexilm)} {
if {([lsearch $vars(partition_list) $vars(design)] != -1)} {
set restore_command "restoreDesign ${design}_postECO.enc.dat $design\n"
} else {
set restore_command "restoreDesign . $design\n"
}
} elseif {([lsearch [FF::adjust_steps] $vars(step)] == [expr [lsearch [FF::adjust_steps] cts]+1]) && !$vars(enable_flexilm)} {
set restore_command "restoreDesign . $design\n"
} else {
set restore_command "restoreDesign $dir/$step.enc.dat $design\n"
}
} else {
if {$vars(step) != "partition_place"} {
set restore_command "restoreDesign $dir/$step.enc.dat $design\n"
} else {
if {$vars(use_flexmodels)} {
set restore_command "restoreDesign $dir/$step.enc.dat $design\n"
} else {
return ""
}
}
}
}
}
# Pass the command through the wrapper and then make it conditional so it can
# be disabled in a single process flow
set restore_command [FF::wrap_command $current_step,restore_design $restore_command]
set cond_restore_command "if {\$vars(restore_design)} { $restore_command }"
if {!$format} {
if {$vars(codegen)} {
return $cond_restore_command
} else {
eval $cond_restore_command
}
} else {
if {$vars(catch_errors)} {
append commands "\nif {\$vars(restore_design)} {\n"
append commands " if {\[catch {\n$restore_command}\]} {\n"
append commands " Puts \"<FF> ERROR LOADING DATABASE FROM STEP $step ... EXITING\"\n"
append commands " exit -1\n"
append commands " }\n"
append commands "}\n"
} else {
append commands "\nif {\$vars(restore_design)} { [string trim $restore_command] }\n"
}
if {$vars(capture_metrics)} {
append commands "\num::enable_metrics -on\n"
# if {![info exists vars(pushed)] || ([info exists vars(pushed)] && !$vars(pushed)) } {
# # GG1
# append commands "um::push_snapshot_stack\n"
# set vars(pushed) true
# }
}
append commands [FF::source_plug always_source_tcl]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
}
############################################################################
# Setup procedure for run* steps
############################################################################
proc initialize_step {step} {
global vars
global env
global errors
global warnings
if {![info exists step]} {
set step $vars(step)
}
if {[info exists vars($step,rpt_dir)]} {
set vars(rpt_dir) $vars($step,rpt_dir)
file mkdir $vars($step,rpt_dir)
} else {
set vars(rpt_dir) $vars(orig_rpt_dir)
}
set vars($step,commands) ""
if {![info exists vars(warning_count)]} {
set vars(warning_count) 0
}
if {![info exists vars(error_count)]} {
set vars(error_count) 0
}
set commands ""
if {$vars(verbose)} {
append commands "#\n"
append commands "# STEP $step\n"
append commands "#\n"
}
# if {$vars(enable_qor_check)} {
# set qor [catch {exec $check_qor $env(VPATH)/$last_step} msg]
# if {$qor} {
# puts "<FF> ERROR: QOR RESULT CHECK INDICATES A PROBLEM IN STEP $last_step"
# exit -111
# }
# }
set update_setup 0
set update_hold 0
set command ""
if {[info exists vars($step,active_setup_views)] && ([llength $vars($step,active_setup_views)]>0)} {
append command "set setup_analysis_views \"$vars($step,active_setup_views)\"\n"
set update_setup 1
}
if {[info exists vars($step,active_hold_views)] && ([llength $vars($step,active_hold_views)]>0)} {
append command "set hold_analysis_views \"$vars($step,active_hold_views)\"\n"
set update_hold 1
}
set comments ""
append comments "# The active analysis views are controlled by the following variables:\n"
append comments "#---------------------------------------------------------------------\n"
append comments "# - vars($step,active_setup_views)\n"
append comments "# - vars($step,active_hold_views)\n"
append comments "#\n"
append comments "######################################################################\n"
if {$update_setup || $update_hold} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# <FF> UPDATING ANALYSIS VIEWS ...\n"
append commands "#\n"
}
if {!$update_setup && $update_hold} {
# append command "set_analysis_view -setup \[all_setup_analysis_views\] -hold \[list \$hold_analysis_views\]\n"
append command "set_analysis_view -setup \[all_setup_analysis_views\] -hold \$hold_analysis_views\n"
}
if {$update_setup && !$update_hold} {
append command "set_analysis_view -setup \$setup_analysis_views -hold \[all_hold_analysis_views\]\n"
}
if {$update_setup && $update_hold} {
# append command "set_analysis_view -setup \[list \$setup_analysis_views\] -hold \[list \$hold_analysis_views\]\n"
append command "set_analysis_view -setup \$setup_analysis_views -hold \$hold_analysis_views\n"
}
append commands $comments
append commands "$command\n"
} else {
append comments "# set_analysis_view -setup \$vars($step,active_setup_views) -hold \$vars($step,active_hold_views)\n"
append comments "#\n"
append commands $comments
}
#########################################################################
# Check if in top level partition (ilm) flow
#########################################################################
FF_EDI::check_flow
# if {$vars(report_run_time)} {
# append commands "set vars($step,start_time) \[clock seconds\]\n"
# }
#########################################################################
# Load the recommended command mode settings for step
#########################################################################
# append commands "#\n"
# append commands "# DEFINING MODE SETTINGS\n"
# append commands "#\n"
set comments ""
set ucomments ""
switch $step {
"place" {
###################################################################
# Set placement options ...
# - Set optimization options if inPlaceOpt is enabled
# - Load the CTS spec for clock gate aware placement
# - Place JTAG cells if requested
###################################################################
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
set args ""
if {$vars(flow) == "mmmc"} {
if {($vars(enable_ocv) == "pre_place") || (($vars(enable_ocv) == "pre_prects") && ($vars(place_opt_design) || $vars(preroute_opt_design)))} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"$vars(enable_ocv)\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command prects,set_analysis_mode $command]
}
if {$vars(enable_ss) == "pre_place"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm\n"
append commands [FF::wrap_command place,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_place\"\n"
}
set args ""
if {![catch {set arg $vars(congestion_effort)}]} {
append args " -place_global_cong_effort $arg"
append comments "# - vars(congestion_effort)\n"
} else {
append ucomments "# - vars(congestion_effort) \"auto low medium high\"\n"
}
# if {[info exists vars(clock_gate_aware)] && $vars(clock_gate_aware)} {
# append comments "# - vars(clock_gate_aware)\n"
# append args " -place_global_clock_gate_aware true"
# }
if {![catch {set arg $vars(clock_gate_aware)}]} {
append comments "# - vars(clock_gate_aware)\n"
append args " -place_global_clock_gate_aware $arg"
} else {
append ucomments "# - vars(clock_gate_aware) \"true\"\n"
}
if {![catch {set arg $vars(place_io_pins)}]} {
append comments "# - vars(place_io_pins)\n"
append args " -place_global_place_io_pins $arg"
} else {
append ucomments "# - vars(place_io_pins) \"true\"\n"
}
# set process [regsub "nm" $vars(process) ""]
# if {[expr $process < 28] && [info exists vars(filler_cells,min_gap)]} {
# append comments "# - vars(filler_cells,min_gap)\n"
# append args " -fillerGapMinGap $vars(filler_cells,min_gap) -fillerGapEffort high\n"
# } else {
# append ucomments "# - vars(filler_cells,min_gap) \"<microns>\"\n"
# append ucomments "# - vars(filler_cells,gap_effort) \"<low medium high> \"\n"
# }
if {$args != ""} {
set command "setPlaceMode $args\n"
append commands [FF::wrap_command place,set_place_mode $command]
}
set args ""
# if {![catch {set arg $vars(size_only_file)}]} {
# append comments "# - vars(size_only_file)\n"
# append args " -sizeOnlyFile $arg"
# } else {
# append ucomments "# - vars(size_only_file) \"<file>\"\n"
# }
if {([info exists vars(in_place_opt)] && $vars(in_place_opt)) || $vars(place_opt_design)} {
if {![catch {set arg $vars(size_only_file)}]} {
append comments "# - vars(size_only_file)\n"
append args " -sizeOnlyFile $arg"
} else {
append ucomments "# - vars(size_only_file) \"<file>\"\n"
}
append comments "# - vars(in_place_opt)\n"
# set args ""
if {[lindex [split $vars(version) "."] 0] < 17} {
if {![catch {set arg $vars(preserve_assertions)}]} {
append comments "# - vars(preserve_assertions)\n"
append args " -preserveAssertions $arg"
} else {
append ucomments "# - vars(preserve_assertions) \"true\"\n"
}
}
if {![catch {set arg $vars(leakage_power_effort)}]} {
append comments "# - vars(leakage_power_effort)\n"
append args " -leakagePowerEffort $arg"
} else {
append ucomments "# - vars(leakage_power_effort) \"low or high\"\n"
}
if {![catch {set arg $vars(dynamic_power_effort)}]} {
append comments "# - vars(dynamic_power_effort)\n"
append args " -dynamicPowerEffort $arg"
} else {
append ucomments "# - vars(dynamic_power_effort) \"low or high\"\n"
}
if {![catch {set arg $vars(clock_gate_aware_opt)}]} {
append comments "# - vars(clock_gate_aware_opt)\n"
append args " -clkGateAware $arg"
} else {
append ucomments "# - vars(clock_gate_aware_opt) \"true\"\n"
}
if {![catch {set arg $vars(critical_range)}]} {
append comments "# - vars(critical_range)\n"
append args " -criticalRange $arg"
}
if {[info exists vars(all_end_points)] && $vars(all_end_points)} {
append comments "# - vars(all_end_points)\n"
append args " -allEndPoints true"
} else {
append ucomments "# - vars(all_end_points) \"true\"\n"
}
if {![catch {set arg $vars(fix_fanout_load)}]} {
append comments "# - vars(fix_fanout_load)\n"
append args " -fixFanoutLoad $arg"
} else {
append ucomments "# - vars(fix_fanout_load) \"<file>\"\n"
}
if {![catch {set arg $vars(useful_skew)}]} {
if {$vars(ccopt_effort) == "low"} {
append comments "# - vars(useful_skew)\n"
append args " -usefulSkew $arg"
if {$vars(useful_skew) && ![catch {set arg $vars(skew_buffers)}]} {
append comments "# - vars(skew_buffers)\n"
set command "setUsefulSkewMode -delayPreCTS true -useCells \[list $arg\]\n"
append commands [FF::wrap_command prects,set_useful_skew_mode $command]
}
} else {
append commands "# <FF> Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
set warnings($vars(warning_count)) "Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
incr vars(warning_count)
}
} else {
append ucomments "# - vars(useful_skew) \"true\"\n"
append ucomments "# - vars(skew_buffers) \"<list of buffers>\"\n"
}
}
if {$args != ""} {
set command "setOptMode $args\n"
append commands [FF::wrap_command place,set_opt_mode $command]
}
# set command [FF_EDI::add_tie_cells true false]
# append commands [FF::wrap_command place,add_tie_cells $command]
if {[info exists vars(cts_spec)]} {
set command "cleanupSpecifyClockTree\n"
append commands [FF::wrap_command place,cleanup_specify_clock_tree $command]
set command ""
foreach spec $vars(cts_spec) {
append command "specifyClockTree -file $spec\n"
}
append commands [FF::wrap_command place,specify_clock_tree $command]
}
if {[info exists vars(jtag_cells)] &&
[info exists vars(jtag_rows)]} {
append comments "# - vars(jtag_cells), vars(jtag_rows)\n"
# append commands "# PLACING JTAG CELLS\n"
set command ""
foreach inst $vars(jtag_cells) {
append command "specifyJtag -inst $inst\n"
}
append commands [FF::wrap_command place,specify_jtag $command]
set command "placeJtag -nrRow $vars(jtag_rows)\n"
append commands [FF::wrap_command place,place_jtag $command]
}
}
"prects" {
###################################################################
# Set optimization options ...
# Enable signalStorm if requested (required for ECSM/CCS flows)
# For low power flows, make sure always-on buffers are enabled
###################################################################
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
set args ""
if {$vars(flow) == "mmmc"} {
if {$vars(enable_ocv) == "pre_prects"} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_prects\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command prects,set_analysis_mode $command]
}
if {[info exists vars(clock_gate_clone)] && $vars(clock_gate_clone)} {
if {([info exists vars(partition_list)])} {
if {[file tail [file dirname [pwd]]] == "$vars(partition_dir)"} {
set ptn [file tail [pwd]]
if {[info exists vars($ptn,cts_spec)]} {
set vars(cts_spec) $vars($ptn,cts_spec)
}
}
}
set scommand ""
if {[info exists vars(cts_spec)]} {
set command "cleanupSpecifyClockTree\n"
append commands [FF::wrap_command prects,cleanup_specify_clock_tree $command]
foreach spec $vars(cts_spec) {
append scommand "specifyClockTree -file $spec\n"
}
} else {
set command "createClockTreeSpec\n"
append commands [FF::wrap_command prects,create_clock_tree_spec $command]
if {[info exists vars(cts_cells)]} {
append scommand "specifyClockTree -update \"AutoCTSRootPin * Buffer $vars(cts_cells)\"\n"
}
}
if {[info exists vars(route_clock_nets)] && $vars(route_clock_nets)} {
append scommand "specifyClockTree -update \"AutoCTSRootPin * RouteClkNet YES\"\n"
}
if {!$vars(ilm)} {
append commands [FF::wrap_command prects,specify_clock_tree $scommand]
}
# if {![info exists vars(cts_spec)]} {
# append commands "clockDesign -genSpecOnly \[pid\].ctstch\n"
# append commands "specifyClockTree -file \[pid\].ctstch\n"
# } else {
# foreach spec $vars(cts_spec) {
# append commands "specifyClockTree -file $spec\n"
# }
# }
}
set args ""
if {[lindex [split $vars(version) "."] 0] < 17} {
if {![catch {set arg $vars(preserve_assertions)}]} {
append comments "# - vars(preserve_assertions)\n"
append args " -preserveAssertions $arg"
} else {
append ucomments "# - vars(preserve_assertions) \"true\"\n"
}
}
if {![catch {set arg $vars(leakage_power_effort)}]} {
append comments "# - vars(leakage_power_effort)\n"
append args " -leakagePowerEffort $arg"
} else {
append ucomments "# - vars(leakage_power_effort) \"low or high\"\n"
}
if {![catch {set arg $vars(dynamic_power_effort)}]} {
append comments "# - vars(dynamic_power_effort)\n"
append args " -dynamicPowerEffort $arg"
} else {
append ucomments "# - vars(dynamic_power_effort) \"low or high\"\n"
}
if {![catch {set arg $vars(clock_gate_aware_opt)}]} {
append comments "# - vars(clock_gate_aware_opt)\n"
append args " -clkGateAware $arg"
} else {
append ucomments "# - vars(clock_gate_aware_opt) \"true\"\n"
}
if {![catch {set arg $vars(critical_range)}]} {
append comments "# - vars(critical_range)\n"
append args " -criticalRange $arg"
}
if {[info exists vars(all_end_points)] && $vars(all_end_points)} {
append comments "# - vars(all_end_points)\n"
append args " -allEndPoints true"
} else {
append ucomments "# - vars(all_end_points) \"true\"\n"
}
if {![catch {set arg $vars(size_only_file)}]} {
append comments "# - vars(size_only_file)\n"
append args " -sizeOnlyFile $arg"
} else {
append ucomments "# - vars(size_only_file) \"<file>\"\n"
}
if {![catch {set arg $vars(fix_fanout_load)}]} {
append comments "# - vars(fix_fanout_load)\n"
append args " -fixFanoutLoad $arg"
} else {
append ucomments "# - vars(fix_fanout_load) \"<file>\"\n"
}
if {![catch {set arg $vars(useful_skew)}]} {
if {$vars(ccopt_effort) == "low"} {
append comments "# - vars(useful_skew)\n"
append args " -usefulSkew $arg"
if {$vars(useful_skew) && ![catch {set arg $vars(skew_buffers)}]} {
append comments "# - vars(skew_buffers)\n"
set command "setUsefulSkewMode -delayPreCTS true -useCells \[list $arg\]\n"
append commands [FF::wrap_command prects,set_useful_skew_mode $command]
}
} else {
append commands "# <FF> Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
set warnings($vars(warning_count)) "Variable vars(useful_skew) ignored when vars(ccopt_effort) is $vars(ccopt_effort)\n"
incr vars(warning_count)
}
} else {
append ucomments "# - vars(useful_skew) \"true\"\n"
append ucomments "# - vars(skew_buffers) \"<list of buffers>\"\n"
}
if {[FF::is_lp_flow]} {
if {![catch {set arg $vars(resize_shifter_and_iso_insts)}]} {
append comments "# - vars(resize_shifter_and_iso_insts)\n"
append args " -resizeShifterAndIsoInsts $arg"
}
}
if {$args != ""} {
set command "setOptMode $args\n"
append commands [FF::wrap_command prects,set_opt_mode $command]
}
if {$vars(enable_ss) == "pre_prects"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm\n"
append commands [FF::wrap_command prects,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_prects\"\n"
}
if {[FF::is_lp_flow]} {
set command ""
if {[info exists vars(always_on_buffers)]} {
append comments "# - vars(always_on_buffers)\n"
foreach buffer $vars(always_on_buffers) {
append command "setDontUse $buffer false\n"
}
}
foreach domain [FF::get_by_suffix vars ",always_on_buffers"] {
if {[info exists vars($domain,always_on_buffers)]} {
foreach buffer $vars($domain,always_on_buffers) {
append command "setDontUse $buffer false\n"
}
}
}
if {$command != ""} {
append commands [FF::wrap_command prects,set_dont_use $command]
}
}
}
"cts" {
###################################################################
# Set CTS options ... this includes nanoroute options as the clock
# net is typically routed during CTS. For hierarchical flows, the
# clock tree spec is defined per partition .
###################################################################
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
set args ""
if {$vars(enable_ocv) == "pre_cts"} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_cts\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command cts,set_analysis_mode $command]
}
set args ""
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "-cppr $vars(enable_cppr) "
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command cts,set_analysis_mode $command]
}
set command "setCTSMode "
if {$vars(cts_engine) == "cts"} {
append comments "# - vars(cts_engine)\n"
append command " -engine ck"
}
if {![catch {set arg $vars(route_clock_nets)}]} {
append comments "# - vars(route_clock_nets)\n"
if {!$vars(route_clock_nets)} {
append command " -routeClkNet $arg"
}
} else {
append ucomments "# - vars(route_clock_nets)\n"
}
if {[info exists vars(clk_tree_top_layer)] && $vars(clk_tree_top_layer) != {}} {
append comments "# - vars(clk_tree_top_layer)\n"
append command " -routeTopPreferredLayer $vars(clk_tree_top_layer)"
} else {
append ucomments "# - vars(clk_tree_top_layer)\n"
}
if {[info exists vars(clk_leaf_top_layer)] && $vars(clk_leaf_top_layer) != {}} {
append comments "# - vars(clk_leaf_top_layer)\n"
append command " -routeLeafTopPreferredLayer $vars(clk_leaf_top_layer)"
} else {
append ucomments "# - vars(clk_leaf_top_layer)\n"
}
if {[info exists vars(clk_tree_bottom_layer)] && $vars(clk_tree_bottom_layer) != {}} {
append comments "# - vars(clk_tree_bottom_layer)\n"
append command " -routeBottomPreferredLayer $vars(clk_tree_bottom_layer)"
} else {
append ucomments "# - vars(clk_tree_bottom_layer)\n"
}
if {[info exists vars(clk_leaf_bottom_layer)] && $vars(clk_leaf_bottom_layer) != {}} {
append comments "# - vars(clk_leaf_bottom_layer)\n"
append command " -routeLeafBottomPreferredLayer $vars(clk_leaf_bottom_layer)"
} else {
append ucomments "# - vars(clk_leaf_bottom_layer)\n"
}
if {[info exists vars(clk_tree_ndr)] && $vars(clk_tree_ndr) != {}} {
append comments "# - vars(clk_tree_ndr)\n"
append command " -routeNonDefaultRule $vars(clk_tree_ndr)"
} else {
append ucomments "# - vars(clk_tree_ndr)\n"
}
if {[info exists vars(clk_tree_extra_space)] && $vars(clk_tree_extra_space) != {}} {
append comments "# - vars(clk_tree_extra_space)\n"
append command " -routePreferredExtraSpace $vars(clk_tree_extra_space)"
} else {
append ucomments "# - vars(clk_tree_extra_space)\n"
}
if {[info exists vars(clk_leaf_ndr)] && $vars(clk_leaf_ndr) != {}} {
append comments "# - vars(clk_leaf_ndr)\n"
append command " -routeLeafNonDefaultRule $vars(clk_leaf_ndr)"
} else {
append ucomments "# - vars(clk_leaf_ndr)\n"
}
if {[info exists vars(clk_leaf_extra_space)] && $vars(clk_leaf_extra_space) != {}} {
append comments "# - vars(clk_leaf_extra_space)\n"
append command " -routeLeafPreferredExtraSpace $vars(clk_leaf_extra_space)"
} else {
append ucomments "# - vars(clk_leaf_extra_space)\n"
}
if {$command != "setCTSMode "} {
append command "\n"
append commands [FF::wrap_command cts,set_cts_mode $command]
}
set command ""
if {[string tolower $vars(cts_engine)] != "cts"} {
# FF_EDI::assign_cts_cells
# foreach corner $vars(rc_corners) {
# if {[info exists vars($corner,atf_file)]} {
# append command "update_ccopt_rc_corner -name $corner -atf $vars($corner,atf_file)\n"
# }
# }
# if {$command != ""} {
# append command "\n"
# append commands [FF::wrap_command cts,update_ccopt_rc_corner $command]
# }
set command "set_ccopt_mode "
if {[info exists vars(ccopt_integration)]} {
append comments "# - vars(ccopt_integration)\n"
append command " -integration \"$vars(ccopt_integration)\""
} else {
append ucomments "# - vars(ccopt_integration)\n"
}
if {[info exists vars(cts_inverter_cells)]} {
append comments "# - vars(cts_inverter_cells)\n"
append command " -cts_inverter_cells \"$vars(cts_inverter_cells)\""
} else {
append ucomments "# - vars(cts_inverter_cells)\n"
}
if {[info exists vars(cts_buffer_cells)]} {
append comments "# - vars(cts_buffer_cells)\n"
append command " -cts_buffer_cells \"$vars(cts_buffer_cells)\""
} else {
append ucomments "# - vars(cts_buffer_cells)\n"
}
if {[info exists vars(clock_gate_cells)]} {
append comments "# - vars(clock_gate_cells)\n"
append command " -cts_clock_gating_cells \"$vars(clock_gate_cells)\""
} else {
append ucomments "# - vars(clock_gate_cells)\n"
}
if {[info exists vars(cts_use_inverters)]} {
append comments "# - vars(cts_use_inverters)\n"
append command " -cts_use_inverters [string tolower $vars(cts_use_inverters)]"
} else {
append ucomments "# - vars(cts_use_inverters)\n"
}
if {[info exists vars(update_io_latency)]} {
append comments "# - vars(update_io_latency)\n"
append command " -ccopt_modify_clock_latency $vars(update_io_latency)"
} else {
append ucomments "# - vars(update_io_latency)\n"
}
if {[info exists vars(cts_io_opt)]} {
append comments "# - vars(cts_io_opt)\n"
append command " -io_opt [string tolower $vars(cts_io_opt)]"
} else {
append ucomments "# - vars(cts_io_opt)\n"
}
if {[info exists vars(ccopt_effort)]} {
append comments "# - vars(ccopt_effort)\n"
# if {$vars(ccopt_effort) != "low"} {
# append command " -effort $vars(ccopt_effort)"
# }
} else {
append ucomments "# - vars(ccopt_effort)\n"
}
if {[info exists vars(cts_target_skew)]} {
append comments "# - vars(cts_target_skew)\n"
append command " -cts_target_skew $vars(cts_target_skew)"
} else {
append ucomments "# - vars(cts_target_skew)\n"
}
if {[info exists vars(cts_target_slew)]} {
append comments "# - vars(cts_target_slew)\n"
append command " -cts_target_slew $vars(cts_target_slew)"
} else {
append ucomments "# - vars(cts_target_slew)\n"
}
if {[info exists vars(pre_ccopt_tcl)]} {
append comments "# - vars(pre_ccopt_tcl)\n"
append command " -pre_tcl \{ source $vars(pre_ccopt_tcl) \}"
}
if {[info exists vars(post_ccopt_tcl)]} {
append comments "# - vars(post_ccopt_tcl)\n"
append command " -post_tcl \{ source $vars(post_ccopt_tcl) \}"
}
if {[info exists vars(ccopt_executable)]} {
append comments "# - vars(ccopt_executable)\n"
append command " -envAdvancedIntegrationLink $vars(ccopt_executable)"
} else {
append ucomments "# - vars(ccopt_executable)\n"
}
if {[info exists vars(clk_tree_ndr)]} {
append command " -route_top_non_default_rule $vars(clk_tree_ndr)"
}
if {[info exists vars(clk_tree_shield_net)]} {
append comments "# - vars(clk_tree_shield_net)\n"
append command " -route_top_shielding_net $vars(clk_tree_shield_net)"
} else {
append ucomments "# - vars(clk_tree_shield_net)\n"
}
if {[info exists vars(clk_tree_top_layer)]} {
append command " -route_top_top_preferred_layer $vars(clk_tree_top_layer)"
}
if {[info exists vars(clk_tree_bottom_layer)]} {
append command " -route_top_bottom_preferred_layer $vars(clk_tree_bottom_layer)"
}
append command "\n"
append commands [FF::wrap_command cts,set_ccopt_mode $command]
}
set args ""
if {![catch {set arg $vars(multi_cut_effort)}]} {
append comments "# - vars(multi_cut_effort)\n"
append args " -drouteUseMultiCutViaEffort $arg"
} else {
append ucomments "# - vars(multi_cut_effort)\n"
}
if {![catch {set arg $vars(litho_driven_routing)}]} {
append comments "# - vars(litho_driven_routing)\n"
append args " -routeWithLithoDriven $arg"
} else {
append ucomments "# - vars(litho_driven_routing)\n"
}
if {$args != ""} {
set command "\nsetNanoRouteMode $args\n"
append commands [FF::wrap_command cts,set_nanoroute_mode $command]
}
if {([info exists vars(partition_list)]) &&
([file tail [file dirname [pwd]]] == "$vars(partition_dir)")} {
set ptn [file tail [pwd]]
if {[info exists vars($ptn,cts_spec)]} {
set vars(cts_spec) $vars($ptn,cts_spec)
} else {
if {$ptn != $vars(design)} {
if {[info exists vars(cts_spec)]} {
unset vars(cts_spec)
}
}
}
}
}
"postcts" {
###################################################################
# Optionally enable cppr, signalStorm, and onChipVariation (if
# MMMC)
###################################################################
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
if {$vars(enable_ss) == "pre_postcts"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm\n"
append commands [FF::wrap_command postcts,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_postcts\"\n"
}
set args ""
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "-cppr $vars(enable_cppr) "
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$vars(flow) == "mmmc"} {
if {$vars(enable_ocv) == "pre_postcts"} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postcts\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command postcts,set_analysis_mode $command]
}
if {[info exists vars(cts_spec)]} {
if {![catch {set arg $vars(clock_gate_clone)}]} {
append comments "# - vars(clock_gate_clone)\n"
set command "setOptMode -postCtsClkGateCloning $arg\n"
append commands [FF::wrap_command postcts,set_opt_mode $command]
}
}
}
"postcts_hold" {
###################################################################
# Set hold fixing options ...
###################################################################
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
if {[info exists vars(delay_cells)]} {
append comments "# - vars(delay_cells)\n"
set command ""
foreach delay_cell $vars(delay_cells) {
append command "setDontUse $delay_cell false\n"
}
if {$command != ""} {
append commands [FF::wrap_command postcts_hold,set_dont_use $command]
}
} else {
append ucomments "# - vars(delay_cells)\n"
}
set args ""
if {![catch {set arg $vars(fix_hold_allow_tns_degradation)}]} {
append comments "# - vars(fix_hold_allow_tns_degradation)\n"
append args " -fixHoldAllowSetupTnsDegrade $arg"
} else {
append ucomments "# - vars(fix_hold_allow_tns_degradation)\n"
}
if {$vars(fix_hold_ignore_ios)} {
#append commands "setAnalysisMode -honorClockDomains true\n"
append comments "# - vars(fix_hold_ignore_ios)\n"
# append args " -ignorePathGroupsForHold {in2reg reg2out in2out}"
append args " -ignorePathGroupsForHold {default}"
} else {
append ucomments "# - vars(fix_hold_ignore_ios)\n"
}
if {$args != ""} {
set command "setOptMode $args\n"
append commands [FF::wrap_command postcts_hold,set_opt_mode $command]
}
}
"route" {
###################################################################
# Set routing options ...
# Recommendations for multicut via insertion and litho driven
# routing. These all incur runtime penalties but have yield
# advantages so are included here. The routeWithLithoDriven option
# is recommended for 45nm but may also be used at 65nm. The
# -drouteUseMultiCutViaEffort can be set to high if needed;
# expect an average of 5% coverage improvement with an average 10%
# runtime hit versus medium
###################################################################
if {($vars(enable_cppr) != "false") || $vars(track_opt)} {
append comments "# - vars(enable_cppr)\n"
append comments "# - vars(track_opt)\n"
set command "setAnalysisMode -cppr both\n"
append commands [FF::wrap_command route,set_analysis_mode $command]
} else {
append ucomments "# - vars(track_opt)\n"
}
if {$vars(enable_si_aware)} {
set command "setDelayCalMode -siAware true -engine aae\n "
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
append comments "# - vars(enable_si_aware)\n"
if {$vars(enable_ss) == "pre_postroute"} {
append commands "# <FF> Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
set warnings($vars(warning_count)) "Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
incr vars(warning_count)
}
} else {
append ucomments "# - vars(enable_si_aware)\n"
if {$vars(enable_ss) == "pre_postroute"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm -signoff true -siAware false\n"
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
} else {
set command "setDelayCalMode -siAware false\n"
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
append ucomments "# - vars(enable_ss) \"pre_postroute\"\n"
}
}
set args ""
if {![catch {set arg $vars(multi_cut_effort)}]} {
append comments "# - vars(multi_cut_effort)\n"
append args " -drouteUseMultiCutViaEffort $arg"
} else {
append ucomments "# - vars(multi_cut_effort)\n"
}
if {![catch {set arg $vars(litho_driven_routing)}]} {
append comments "# - vars(litho_driven_routing)\n"
append args " -routeWithLithoDriven $arg"
} else {
append ucomments "# - vars(litho_driven_routing)\n"
}
if {![catch {set arg $vars(antenna_diode)}]} {
if {$vars(antenna_diode) != ""} {
append comments "# - vars(antenna_diode)\n"
append args " -routeAntennaCellName $arg"
append args " -routeInsertAntennaDiode true"
} else {
append ucomments "# - vars(antenna_diode)\n"
}
} else {
append ucomments "# - vars(antenna_diode)\n"
}
if {$args != ""} {
set command "\nsetNanoRouteMode $args\n"
append commands [FF::wrap_command route,set_nanoroute_mode $command]
}
if {$vars(track_opt)} {
append comments "# - vars(track_opt)\n"
set command "setExtractRCMode -engine postRoute"
if {![catch {set arg $vars(tquantus_file)}]} {
append comments "# - vars(tquantus_file)\n"
append command " -tQuantusModelFile $arg"
} else {
append ucomments "# - vars(tquantus_file)\n"
}
append command " -effortLevel medium"
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command " -total_c_th $arg"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command " -relative_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command " -coupling_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command " -lefTechFileMap $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute,set_extract_rc_mode $command]
}
}
"postroute" {
###################################################################
# Set extraction effort for postroute optimization
# Enable signalStorm if requested
###################################################################
set process [regsub "nm" $vars(process) ""]
append comments "# - vars(process)\n"
if {[lindex [split $vars(version) "."] 0] < 15} {
if {$vars(high_timing_effort)} {
append comments "# - vars(high_timing_effort)\n"
if {![regexp "9.1" $vars(version)]} {
set command "setDesignMode -process $process -flowEffort high\n"
} else {
set command "setDesignMode -process $process\n"
append commands [FF::wrap_command postroute,set_design_mode $command]
append commands "setOptMode -unfixClkInstForOpt true\n"
}
} else {
set command "setDesignMode -process $process\n"
append commands [FF::wrap_command postroute,set_design_mode $command]
}
} else {
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
}
set command "setExtractRCMode -engine postRoute"
if {![catch {set arg $vars(postroute_extraction_effort)}]} {
append comments "# - vars(postroute_extraction_effort)\n"
append command " -effortLevel $arg"
} else {
append ucomments "# - vars(postroute_extraction_effort)\n"
}
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command " -total_c_th $arg"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command " -relative_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command " -coupling_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command " -lefTechFileMap $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute,set_extract_rc_mode $command]
set args ""
if {($vars(enable_ocv) == "pre_postroute") || ($vars(enable_ocv) == "pre_postcts")} {
if {$vars(flow) != "default"} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
}
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "-cppr $vars(enable_cppr) "
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command postroute,set_analysis_mode $command]
}
if {[regexp "9.1" $vars(version)]} {
if {$vars(enable_ss) == "pre_postroute"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm -signoff true "
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_postroute\"\n"
}
} else {
if {$vars(enable_si_aware)} {
set command "setDelayCalMode -siAware true -engine aae\n "
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
append comments "# - vars(enable_si_aware)\n"
if {$vars(enable_ss) == "pre_postroute"} {
append commands "# <FF> Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
set warnings($vars(warning_count)) "Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
incr vars(warning_count)
}
} else {
append ucomments "# - vars(enable_si_aware)\n"
if {$vars(enable_ss) == "pre_postroute"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm -signoff true -siAware false\n"
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
} else {
set command "setDelayCalMode -siAware false\n"
append commands [FF::wrap_command postroute,set_delay_cal_mode $command]
append ucomments "# - vars(enable_ss) \"pre_postroute\"\n"
}
}
}
}
"postroute_hold" {
###################################################################
# Set hold fixing options ...
###################################################################
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
set command "setExtractRCMode -engine postRoute"
if {![catch {set arg $vars(postroute_extraction_effort)}]} {
append comments "# - vars(postroute_extraction_effort)\n"
append command " -effortLevel $arg"
} else {
append ucomments "# - vars(postroute_extraction_effort)\n"
}
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command " -total_c_th $arg"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command " -relative_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command " -coupling_c_th $arg"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command " -lefTechFileMap $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute_hold,set_extract_rc_mode $command]
set command ""
if {[info exists vars(delay_cells)]} {
append comments "# - vars(delay_cells)\n"
foreach delay_cell $vars(delay_cells) {
append command "setDontUse $delay_cell false\n"
}
} else {
append ucomments "# - vars(delay_cells)\n"
}
if {$command != ""} {
append commands [FF::wrap_command postroute_hold,set_dont_use_mode $command]
}
set args ""
if {![catch {set arg $vars(fix_hold_allow_tns_degradation)}]} {
append comments "# - vars(fix_hold_allow_tns_degradation)\n"
append args " -fixHoldAllowSetupTnsDegrade $arg"
} else {
append ucomments "# - vars(fix_hold_allow_tns_degradation)\n"
}
if {$vars(fix_hold_ignore_ios)} {
#append commands "setAnalysisMode -honorClockDomains true\n"
append comments "# - vars(fix_hold_ignore_ios)\n"
# append args " -ignorePathGroupsForHold {in2reg reg2out in2out}"
append args " -ignorePathGroupsForHold {default}"
} else {
append ucomments "# - vars(fix_hold_ignore_ios)\n"
}
if {$args != ""} {
set command "setOptMode $args\n"
append commands [FF::wrap_command postroute_hold,set_opt_mode $command]
}
}
"postroute_si" {
###################################################################
# Set noise, extraction, and SI options ...
# Enable signalStorm if requested
# Enable onChipVariation (if MMMC)
###################################################################
set process [regsub "nm" $vars(process) ""]
append comments "# - vars(process)\n"
if {$vars(high_timing_effort)} {
append comments "# - vars(high_timing_effort)\n"
if {![regexp "9.1" $vars(version)]} {
set command "setDesignMode -process $process -flowEffort high\n"
} else {
set command "setDesignMode -process $process\n"
}
} else {
set command "setDesignMode -process $process\n"
}
append commands [FF::wrap_command postroute_si,set_design_mode $command]
set command "setExtractRCMode -coupled true"
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command " -total_c_th $arg"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command " -relative_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command " -coupling_c_th $arg"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command " -lefTechFileMap $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute_si,set_extract_rc_mode $command]
set args ""
if {![catch {set arg $vars(delta_delay_threshold)}]} {
append comments "# - vars(delta_delay_threshold)\n"
append args " -deltaDelayThreshold $arg"
} else {
append ucomments "# - vars(delta_delay_threshold)\n"
}
if {![catch {set arg $vars(celtic_settings)}]} {
append comments "# - vars(celtic_settings)\n"
append args " -insCeltICPreTcl \"$arg\""
} else {
append ucomments "# - vars(celtic_settings)\n"
}
if {![catch {set arg $vars(si_analysis_type)}]} {
append comments "# - vars(si_analysis_type)\n"
append args " -analysisType $arg"
} else {
append ucomments "# - vars(si_analysis_type)\n"
}
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
# append comments "# - vars(high_timing_effort)\n"
append args " -acceptableWNS 0"
} elseif {[info exists vars(acceptable_wns)]} {
append args " -acceptableWNS $vars(acceptable_wns)"
}
if {$args != ""} {
set command "setSIMode $args\n"
append commands [FF::wrap_command postroute_si,set_si_mode $command]
}
set args ""
if {$vars(enable_ocv) == "pre_postroute_si"} {
if {$vars(flow) != "default"} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
}
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute_si\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "-cppr $vars(enable_cppr) "
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command postroute_si,set_analysis_mode $command]
}
if {$vars(enable_ss) == "pre_postroute_si"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm\n"
append commands [FF::wrap_command postroute_si,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_postroute_si\"\n"
}
}
"postroute_si_hold" {
###################################################################
# Set hold fixing options ...
###################################################################
set process [regsub "nm" $vars(process) ""]
append comments "# - vars(process)\n"
if {[lindex [split $vars(version) "."] 0] < 15} {
if {$vars(high_timing_effort)} {
append comments "# - vars(high_timing_effort)\n"
if {![regexp "9.1" $vars(version)]} {
set command "setDesignMode -process $process -flowEffort high\n"
} else {
set command "setDesignMode -process $process\n"
}
} else {
set command "setDesignMode -process $process\n"
}
} else {
if {[string tolower $vars(flow_effort)] != "standard"} {
set command "setDesignMode -process $process -flowEffort [string tolower $vars(flow_effort)]\n"
append comments "# - vars(flow_effort)\n"
} else {
set command "setDesignMode -process $process\n"
}
}
append commands [FF::wrap_command postroute_si_hold,set_design_mode $command]
set command ""
if {[info exists vars(delay_cells)]} {
append comments "# - vars(delay_cells)\n"
foreach delay_cell $vars(delay_cells) {
append command "setDontUse $delay_cell false\n"
}
} else {
append ucomments "# - vars(delay_cells)\n"
}
if {$command != ""} {
append commands [FF::wrap_command postroute_si_hold,set_dont_use $command]
}
set args ""
if {![catch {set arg $vars(fix_hold_allow_tns_degradation)}]} {
append comments "# - vars(fix_hold_allow_tns_degradation)\n"
append args " -fixHoldAllowSetupTnsDegrade $arg"
} else {
append ucomments "# - vars(fix_hold_allow_tns_degradation)\n"
}
if {$vars(fix_hold_ignore_ios)} {
#append commands "setAnalysisMode -honorClockDomains true\n"
append comments "# - vars(fix_hold_ignore_ios)\n"
# append args " -ignorePathGroupsForHold {in2reg reg2out in2out}"
append args " -ignorePathGroupsForHold {default}"
} else {
append ucomments "# - vars(fix_hold_ignore_ios)\n"
}
if {$args != ""} {
set command "setOptMode $args\n"
append commands [FF::wrap_command postroute_si_hold,set_opt_mode $command]
}
###################################################################
# Set noise, extraction, and SI options ...
# Enable signalStorm if requested
# Enable onChipVariation (if MMMC)
###################################################################
set command "setExtractRCMode -coupled true"
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command " -total_c_th $arg"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command " -relative_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command " -coupling_c_th $arg"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command " -lefTechFileMap $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command postroute_si_hold,set_extract_rc_mode $command]
set args ""
if {![catch {set arg $vars(delta_delay_threshold)}]} {
append comments "# - vars(delta_delay_threshold)\n"
append args " -deltaDelayThreshold $arg"
} else {
append ucomments "# - vars(delta_delay_threshold)\n"
}
if {![catch {set arg $vars(celtic_settings)}]} {
append comments "# - vars(celtic_settings)\n"
append args " -insCeltICPreTcl \"$arg\""
} else {
append ucomments "# - vars(celtic_settings)\n"
}
if {![catch {set arg $vars(si_analysis_type)}]} {
append comments "# - vars(si_analysis_type)\n"
append args " -analysisType $arg"
} else {
append ucomments "# - vars(si_analysis_type)\n"
}
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
# append comments "# - vars(high_timing_effort)\n"
append args " -acceptableWNS 0"
} elseif {[info exists vars(acceptable_wns)]} {
append args " -acceptableWNS $vars(acceptable_wns)"
}
if {$args != ""} {
set command "setSIMode $args\n"
append commands [FF::wrap_command postroute_si_hold,set_si_mode $command]
}
if {$vars(enable_ss) == "pre_postroute_si"} {
append comments "# - vars(enable_ss)\n"
set command "setDelayCalMode -engine signalStorm\n"
append commands [FF::wrap_command postroute_si_hold,set_delay_cal_mode $command]
} else {
append ucomments "# - vars(enable_ss) \"pre_postroute_si\"\n"
}
if {$vars(enable_ocv) == "pre_postroute_si"} {
append comments "# - vars(enable_ocv)\n"
if {$vars(flow) != "default"} {
set command "setAnalysisMode -analysisType onChipVariation\n"
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append command "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append command "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
append commands [FF::wrap_command postroute_si_hold,set_analysis_mode $command]
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute_si\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
}
"signoff" {
###################################################################
# For the default flow, switch to MMMC for final STA to support
# multiple RC corners. Also, enable CCE (signoff) extraction if
# the QRC techfile exists
###################################################################
if {$vars(flow) == "default"} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# <FF> UPDATING TIMING ENVIRONMENT"
append commands "#\n"
}
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command signoff,initialize_timing $command]
}
set process [regsub "nm" $vars(process) ""]
append comments "# - vars(process)\n"
set command "setDesignMode -process $process\n"
append commands [FF::wrap_command signoff,set_design_mode $command]
###################################################################
# Set noise, extraction, and SI options ...
# Enable signalStorm if requested
# Enable onChipVariation (if MMMC)
###################################################################
set command "setExtractRCMode -coupled true"
if {![catch {set arg $vars(signoff_extraction_effort)}]} {
append comments "# - vars(signoff_extraction_effort)\n"
append command " -effortLevel $arg"
} else {
append command " -effortLevel high"
}
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command " -total_c_th $arg"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command " -relative_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command " -coupling_c_th $arg"
} else {
append ucomments "# - vars(coupling_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command " -lefTechFileMap $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
set args ""
if {![catch {set arg $vars(delta_delay_threshold)}]} {
append comments "# - vars(delta_delay_threshold)\n"
append args " -deltaDelayThreshold $arg"
} else {
append ucomments "# - vars(delta_delay_threshold)\n"
}
if {![catch {set arg $vars(celtic_settings)}]} {
append comments "# - vars(celtic_settings)\n"
append args " -insCeltICPreTcl \"$arg\""
} else {
append ucomments "# - vars(celtic_settings)\n"
}
if {![catch {set arg $vars(si_analysis_type)}]} {
append comments "# - vars(si_analysis_type)\n"
append args " -analysisType $arg"
} else {
append ucomments "# - vars(si_analysis_type)\n"
}
set args ""
if {$vars(enable_ocv) != "false"} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_signoff\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$vars(enable_cppr) != "false"} {
append comments "# - vars(enable_cppr)\n"
append args "-cppr $vars(enable_cppr) "
} else {
append ucomments "# - vars(enable_cppr)\n"
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command signoff,set_analysis_mode $command]
}
if {[regexp "9.1" $vars(version)]} {
if {$vars(enable_ss) == "pre_signoff"} {
set command "setDelayCalMode -engine signalStorm -signoff true\n"
append commands [FF::wrap_command signoff,set_delay_cal_mode $command]
append comments "# - vars(enable_ss)\n"
} else {
append ucomments "# - vars(enable_ss) \"pre_signoff\"\n"
}
} else {
# if {$vars(enable_si_aware)} {
# append comments "# - vars(enable_si_aware)\n"
# append command "-siAware true -engine aae\n "
if {$vars(enable_ss) == "pre_signoff"} {
set command "setDelayCalMode -engine signalStorm -signoff true\n"
append commands [FF::wrap_command signoff,set_delay_cal_mode $command]
# append commands "<FF> Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
# set warnings($vars(warning_count)) "Variable vars(enable_ss) ignored when vars(enable_si_aware) is set\n"
# incr vars(warning_count)
} else {
append ucomments "# - vars(enable_ss) \"pre_signoff\"\n"
}
# } else {
# append ucomments "# - vars(enable_si_aware)\n"
# if {$vars(enable_ss) == "pre_signoff"} {
# append comments "# - vars(enable_ss)\n"
# append command "-engine signalStorm -signoff true "
# } else {
# append ucomments "# - vars(enable_ss) \"pre_signoff\"\n"
# }
# }
}
if {$vars(skip_signoff_checks)} {
set command "setExtractRCMode -engine postRoute -effortLevel $vars(signoff_extraction_effort) -coupled true\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
} else {
append commands "set vars(active_rc_corners) \[list\]\n"
append commands "foreach view \[concat \[all_setup_analysis_views\] \[all_hold_analysis_views\]\] {\n"
append commands " set corner \[get_delay_corner \[get_analysis_view \$view -delay_corner\] -rc_corner\]\n"
append commands " if {\[lsearch \$vars(active_rc_corners) \$corner\] == -1 } {\n"
append commands " lappend vars(active_rc_corners) \$corner\n"
append commands " }\n"
append commands "}\n"
append commands "Puts \"<FF> ACTIVE RC CORNER LIST: \$vars(active_rc_corners)\"\n"
append commands "set empty_corners \[list\]\n"
append commands "foreach corner \$vars(active_rc_corners) {\n"
append commands " if {!\[file exists \[get_rc_corner \$corner -qx_tech_file\]\]} {\n"
append commands " lappend empty_corners \$corner\n"
append commands " }\n"
append commands "}\n"
append commands "if {\[llength \$empty_corners\] == 0} {\n"
set command " setExtractRCMode -engine postRoute -effortLevel $vars(signoff_extraction_effort) -coupled true\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
append commands "} else {\n"
append commands " Puts \"<FF> CAN'T RUN SIGNOFF EXTRACTION BECAUSE qx_tech_file IS NOT DEFINED FOR these corners: \$empty_corners\"\n"
set command " setExtractRCMode -engine postRoute -effortLevel low -coupled true\n"
append commands [FF::wrap_command signoff,set_extract_rc_mode $command]
append commands "}\n"
}
}
}
if {[info exists ucomments]} {
if {$ucomments == ""} {
if {[info exists vars(ucomments)]} {
unset vars(ucomments)
}
} else {
set vars(ucomments) $ucomments
}
}
if {[info exists comments]} {
if {$comments == ""} {
if {[info exists vars(comments)]} {
unset vars(comments)
}
} else {
set vars(comments) $comments
}
}
set vars($step,commands) $commands
return $commands
}
proc save_results {{step ""} {format 0}} {
if {[regexp "^syn" $step]} {
return ""
}
global vars
global errors
global env
if {[info exists vars(hier)]} {
set hier true
} else {
set hier false
}
if {$step != ""} {
set vars(step) $step
}
if {$vars(debug)} {
puts "<DEBUG> Saving results for $vars(step) ..."
}
set commands ""
if {$vars(batch)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SAVING RESULTS\n"
append commands "#\n"
}
# if {[regexp _hold $vars(step)] && (![lsearch $vars(fix_hold) $vars(step)] <0)} {
#
# if {!$format} {
# set commands ""
# } else {
# if {$vars(report_run_time)} {
# append commands "FF_EDI::report_time $vars(step)\n"
# }
# }
# if {$vars(codegen)} {
# return $commands
# } else {
# uplevel #0 eval $commands
# }
# }
if {$vars(step) != "partition"} {
set header "#---------------------------------------------------------------------\n"
append header "# <FF> GENERATING REPORTS\n"
append header "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
append commands $header
set header ""
######################################################################
# Verify power domain
######################################################################
set command "verifyPowerDomain -bind -gconn"
append command " -isoNetPD $vars(rpt_dir)/$vars(step).isonets.rpt"
append command " -xNetPD $vars(rpt_dir)/$vars(step).xnets.rpt\n"
append commands [FF::wrap_command $step,verify_power_domain $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "runCLP "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $step,run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
}
set map(init) unplaced
set map(partition_place) placed
set map(model_gen) placed
set map(assign_pin) placed
#set map(partition) {}
set map(place) placed
set map(prects) placed
set map(cts) clock_synthesized
set map(postcts) clock_synthesized
set map(postcts_hold) clock_synthesized
set map(route) clock_synthesized_routed
set map(postroute) clock_synthesized_routed
set map(postroute_hold) clock_synthesized_routed
set map(signoff) clock_synthesized_routed
set map(assemble) placed_routed
if {$vars(capture_metrics) && ($vars(step) != "debug")} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append commands "um::pop_snapshot_stack\n"
if {[lindex [split $vars(version) "."] 0] > 16} {
if {[info exists map($step)]} {
if {[info exists vars(compute_metrics)] && $vars(compute_metrics)} {
append commands "create_snapshot -name $vars(step) -categories \[dict get \$metric_category_status_map $map($step)\]\n"
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
append commands "report_metric -file $vars(rpt_dir)/metrics.html -format html\n"
}
}
# append commands "#\n"
# append commands "# HOUSEKEEPING\n"
# append commands "#\n"
if {[info exists vars(mail,to)]} {
switch $vars(step) {
init { set summary_file preplace.summary }
assemble { set summary_file signoff.summary }
default { set summary_file $vars(step).summary }
}
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "Puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " exec gunzip -c $vars(rpt_dir)/${summary_file}.gz \| /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
if {($step != "partition") && ($step != "rebudget") && ($step != "flexilm")} {
set args ""
if {[info exists vars(save_rc)] && $vars(save_rc)} {
if {[regexp "route" $vars(step)]} {
append args " -rc"
}
}
if {[info exists vars(save_constraints)] && $vars(save_constraints)} {
append args " -tcon"
}
# BCL: Added subst around vars(dbs_dir) to resolve vars(rundir)
set dir [subst $vars(dbs_dir)]
set design $vars(design)
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
if {$hier} {
set command "saveDesign $args -cellview {$vars(oa_partition_lib) $vars(design) $vars(step)}\n"
} else {
set command "saveDesign $args -cellview {$vars(oa_design_lib) $vars(design) $vars(step)}\n"
}
} else {
set command "saveOaDesign $vars(oa_design_lib) $design $vars(step)\n"
}
} else {
if {[info exists vars(relative_path)] && $vars(relative_path)} {
append args " -relativePath"
}
if {[info exists vars(absolute_lib_path)] && $vars(absolute_lib_path)} {
append args " -absoluteLibPath"
}
set command "saveDesign $args $dir/$vars(step).enc -compress\n"
}
if {!(($vars(step) == "model_gen") && $vars(use_flexmodels) && $vars(flexmodel_art_based))} {
append commands [FF::wrap_command $step,save_design $command]
if {$vars(run_lec)} {
append commands [FF::wrap_command $step,save_lec_netlist "saveNetlist $vars(dbs_dir)/LEC/$step.v.gz\n"]
}
}
}
if {![info exists env(VPATH)]} {
set env(VPATH) "make"
}
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
if {$format} {
if {$vars(report_run_time)} {
append commands "ff_procs::report_time\n"
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [eval FF::capture_metrics]
}
}
}
if {$vars(enable_qor_check)} {
# if {[info exists vars($step,qor_tcl]} {
# set qor_file $vars($step,qor_tcl)
# if {[file exists $qor_file]} {
# set qor [catch {exec $qor_file} msg]
# set make_file [open $this_semaphore w]
# puts $make_file "$qor"
# close $make_file
# }
# }
if {[info exists vars($step,qor_tcl)]} {
if {[file exists $vars($step,qor_tcl)]} {
append commands [FF::source_plug ${step},qor_tcl]
} else {
append commands "<FF> WARNING: QOR file $vars($step,qor_tcl) does not exist"
set warnings($warning_count) "WARNING: QOR file $vars($step,qor_tcl) does not exist"
incr warning_count
}
} else {
if {$vars(makefile)} {
append commands "\nif {\[info exists env(VPATH)\]} {\n"
append commands " exec /bin/touch \$env(VPATH)/${step}_qor\n"
append commands "}\n"
}
}
}
append commands [FF::source_plug final_always_source_tcl]
} else {
append commands "Puts \"<FF> =================================================\"\n"
append commands "Puts \"<FF> INFO: Running in interactive mode ...\"\n"
append commands "Puts \"<FF> Please run 'ff_procs::save_results <current_step>' \"\n"
append commands "Puts \"<FF> to prepare a database for the next step\"\n"
append commands "Puts \"<FF> =================================================\"\n"
if {$vars(makefile)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc initialize_multicpu {} {
global vars
if {[regexp "^syn" $vars(step)]} { return "" }
set commands ""
# append commands "#\n"
# append commands "# SETTING UP MULTI PROCESS DISTRIBUTION AND THREADING\n"
# append commands "#\n"
if {[info exists vars(distribute_timeout)]} {
set command "setDistributeHost -timeOut $vars(distribute_timeout) "
} else {
set command "setDistributeHost "
}
if {[info exists vars(distribute)]} {
switch $vars(distribute) {
"rsh" {
# append commands "# RUNNING RSH on $vars(rsh,host_list)\n"
append command "-rsh -add \[list $vars(rsh,host_list)\]\n"
set vars(remote_hosts) [llength $vars(rsh,host_list)]
}
"local" {
append command "-local\n"
}
"custom" {
# append commands "# RUNNING CUSTOM ($vars(custom,script))\n"
append command "-custom -custom_script { $vars(custom,script) }\n"
}
"lsf" {
# append commands "# RUNNING LSF ($vars(lsf,queue), $vars(lsf,resource), $vars(lsf,args)\n"
append command "-lsf -queue $vars(lsf,queue) -resource { $vars(lsf,resource) } -lsf_args { $vars(lsf,args) }\n"
}
default {
puts "<FF> DISTRIBUTION TYPE $vars(distribute) NOT SUPPORTED\n"
}
}
# append commands $command
append commands [FF::wrap_command $vars(step),set_distributed_hosts $command]
set command "setMultiCpuUsage "
append command "-localCpu $vars(local_cpus) "
append command "-remoteHost $vars(remote_hosts) "
append command "-cpuPerRemoteHost $vars(cpus_per_remote_host)\n"
append commands [FF::wrap_command $vars(step),set_multi_cpu_usage $command]
} else {
append command "-local\n"
append commands [FF::wrap_command $vars(step),set_distribute_host $command]
set command "setMultiCpuUsage -localCpu $vars(local_cpus)\n"
append commands [FF::wrap_command $vars(step),set_multi_cpu_usage $command]
}
return $commands
}
proc derate_timing {{type minmax}} {
global vars
global errors
# if {[info exists vars(view_definition_tcl)]} {
# return ""
# }
# if {$vars(enable_aocv)} {
# set commands ""
# foreach corner $vars(delay_corners) {
# append commands "reset_timing_derate -delay_corner $corner\n"
# }
# return $commands
# }
set commands "Puts \"<FF> DERATING DELAY CORNERS ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# DERATING DELAY CORNERS ($type) ...\n"
append commands "#\n"
}
switch $type {
"mmmc" {
set found_corner 0
foreach corner $vars(delay_corners) {
set derate_file 0
set command($corner) ""
if {[info exists vars($corner,derate_tcl)]} {
set derate_file 1
incr found_corner 1
if {[file exists $vars($corner,derate_tcl)]} {
if {$command($corner) == ""} {
append command($corner) [FF::source_plug "$corner,derate_tcl"]
}
}
}
if {!$derate_file} {
foreach object "cell net" {
foreach mode "early late" {
foreach type "data clock" {
if {[info exists vars($corner,${type}_${object}_${mode})]} {
append command($corner) " set_timing_derate -$type -${object}_delay -$mode -delay_corner $corner $vars($corner,${type}_${object}_${mode})\n"
set found_corner 1
}
if {[info exists vars($corner,${object}_${type}_${mode})]} {
append command($corner) " set_timing_derate -$type -${object}_delay -$mode -delay_corner $corner $vars($corner,${object}_${type}_${mode})\n"
set found_corner 1
}
}
if {[info exists vars($corner,cell_check_${mode})]} {
append command($corner) " set_timing_derate -cell_check -$mode -delay_corner $corner $vars($corner,cell_check_${mode})\n"
set found_corner 1
}
if {[info exists vars($corner,check_cell_${mode})]} {
append command($corner) " set_timing_derate -cell_check -$mode -delay_corner $corner $vars($corner,check_cell_${mode})\n"
set found_corner 1
}
}
}
}
}
#########################################################################
# There can only be one ilm_non_sdc_file, so need to combine them with
# the timing derate commands if both exists
#########################################################################
if {$found_corner>0} {
if $vars(ilm) {
set op [open .ilm_non_sdc_file.tcl w]
if {[info exists vars(ilm_non_sdc_file)] && [file exists $vars(ilm_non_sdc_file)]} {
set fhr [open $vars(ilm_non_sdc_file) r]
puts $op "#"
puts $op "# Contents of $vars(ilm_non_sdc_file)"
puts $op "#"
while {[gets $fhr line]>=0} {
puts $op " $line"
}
close $fhr
puts $op "# -------------------------------------------"
set vars(save_ilm_non_sdc_file) $vars(ilm_non_sdc_file)
unset vars(ilm_non_sdc_file)
}
if {[info exists vars(derate_tcl)]} {
puts $op "source $vars(derate_tcl)"
} else {
foreach corner $vars(delay_corners) {
puts $op $command($corner)
}
}
close $op
if {[lindex [split $vars(version) "."] 0] <= 10} {
append commands "loadTimingCon -ilmNonSdcFile .ilm_non_sdc_file.tcl\n"
} else {
append commands "setIlmNonSdcConstraintFile .ilm_non_sdc_file.tcl\n"
}
} else {
if {[info exists vars(derate_tcl)]} {
append commands [FF::source_plug derate_tcl]
append commands "\n"
} else {
append commands "set active_corners \[all_delay_corners\]\n"
foreach corner $vars(delay_corners) {
if {$command($corner) != ""} {
append commands "if {\[lsearch \$active_corners $corner\] != -1} {\n"
append commands $command($corner)
append commands "}\n"
}
}
}
}
} else {
if {[info exists vars(derate_tcl)]} {
append commands [FF::source_plug derate_tcl]
append commands "\n"
}
}
}
"minmax" {
set corners(min) $vars($vars(default_hold_view),delay_corner)
set corners(max) $vars($vars(default_setup_view),delay_corner)
################################################################################
# Derate timing if derating factors are defined
################################################################################
foreach object "cell net" {
foreach corner "min max" {
foreach type "data clock" {
foreach mode "early late" {
if {[info exists vars($corners($corner),${type}_${object}_${mode})]} {
append commands "set_timing_derate -$corner -$type -${object}_delay -$mode $vars($corners($corner),${type}_${object}_${mode})\n"
}
if {[info exists vars($corners($corner),${object}_${type}_${mode})]} {
append commands "set_timing_derate -$corner -$type -${object}_delay -$mode $vars($corners($corner),${object}_${type}_${mode})\n"
}
}
}
}
}
foreach corner "min max" {
foreach mode "early late" {
if {[info exists vars($corners($corner),cell_check_${mode})]} {
append commands "set_timing_derate -cell_check -$mode $vars($corners($corner),cell_check_${mode})\n"
}
if {[info exists vars($corners($corner),check_cell_${mode})]} {
append commands "set_timing_derate -cell_check -$mode $vars($corners($corner),check_cell_${mode})\n"
}
}
}
}
default {
Puts "<FF> INVALID OPTION ... MUST BE EITHER minmax OR mmmc"
}
}
if {[lindex [split $vars(version) "."] 0] > 10} {
set op [open $vars(script_dir)/timingderate.sdc w]
puts $op $commands
close $op
# set commands "source \$vars(script_dir)/timingderate.sdc\n"
set commands "source $vars(script_dir)/timingderate.sdc\n"
}
return $commands
}
#####################################################################################
# The code below updates timing depending on whether the current module is
# - top partition in a hierarchical flow
# - partition in a hierarchical flow
# - chip or block in a flat flow
# Timing is updated by incrementally adding the vars(incr_cts_sdc) to each
# constraint mode that has one defined
#####################################################################################
proc update_timing {{type minmax} {switch_to_propagated true}} {
global vars
if {![info exists vars(constraint_modes)]} {
return
}
set commands "Puts \"<FF> UPDATING TIMING ...\"\n"
set ptn [file tail [pwd]]
set parent [file tail [file dirname [pwd]]]
set update true
set top false
if {[info exists vars(partition_list)] && ($parent == "$vars(partition_dir)")} {
if {[lsearch $vars(partition_list) $ptn] != -1} {
# set ilm false
set update false
} else {
set top true
}
}
# append commands "# ILM $vars(ilm), UPDATE $update\n"
if {$switch_to_propagated} {
append commands "set op \[open prop.sdc w\]\n"
append commands "puts \$op \"set_propagated_clock \\\[all_clocks\\\]\"\n"
if {$vars(ilm)} {
if {$vars(flat) != "none"} {
append commands [FF_EDI::get_clock_ports]
} else {
append commands "set clock_ports \[FF_EDI::get_clock_ports\]\n"
}
append commands "if {\[llength \$clock_ports\] > 0} {\n"
append commands " foreach port \$clock_ports {\n"
append commands " puts \$op \"set_propagated_clock \$port\"\n"
append commands " }\n"
append commands "}\n"
}
append commands "close \$op\n"
}
switch $type {
"minmax" {
if {$vars(ilm) && $update} {
if {[info exists vars(incr_cts_sdc)]} {
foreach file $vars(incr_cts_sdc) {
append commands "loadTimingCon -ilm -incr $file\n"
}
} elseif {[info exists vars(post_cts_sdc)]} {
append command "unloadTimingCon\n"
append commands "loadTimingCon [lindex $vars(post_cts_sdc) 0]\n"
foreach sdc [lrange $vars(post_cts_sdc) 1 end] {
append commands "loadTimingCon -ilm -incr $sdc\n"
}
}
if {$switch_to_propagated} {
append commands "loadTimingCon -ilm -incr prop.sdc\n"
}
} else {
if {$update} {
if {[info exists vars(incr_cts_sdc)]} {
foreach file $vars(incr_cts_sdc) {
append commands "loadTimingCon -incr $file\n"
}
} elseif {[info exists vars(post_cts_sdc)]} {
append commands "unloadTimingCon\n"
append commands "loadTimingCon [lindex $vars(post_cts_sdc) 0]\n"
foreach sdc [lrange $vars(post_cts_sdc) 1 end] {
append commands "loadTimingCon -incr $sdc\n"
}
}
}
if {$switch_to_propagated} {
append commands "loadTimingCon -incr prop.sdc\n"
}
}
}
"mmmc" {
# if {[info exists vars(update_io_latency)] && $vars(update_io_latency)} {
# update_io_latency
# }
if {$switch_to_propagated} {
set prop_sdc "prop.sdc"
} else {
set prop_sdc ""
}
foreach mode $vars(constraint_modes) {
append commands "if {\[lsearch \[all_constraint_modes\] $mode\] != -1} {\n"
if {$update} {
if {[info exists vars($mode,incr_cts_sdc)]} {
if {$vars(ilm)} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -ilm_sdc_files\] $vars($mode,incr_cts_sdc) $prop_sdc\]\n"
} else {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -sdc_files\] $vars($mode,incr_cts_sdc) $prop_sdc\]\n"
}
if {[info exists vars($mode,post_cts_sdc)]} {
puts "<FF> WARNING: BOTH vars($mode,incr_cts_sdc) AND vars($mode,post_cts_sdc) ARE DEFINED ..."
puts "<FF> USING vars($mode,incr_cts_sdc)"
}
} else {
if {[info exists vars($mode,post_cts_sdc)]} {
append commands "set vars($mode,post_cts_sdc_list) \[concat $vars($mode,post_cts_sdc) $prop_sdc\]\n"
} else {
if {$vars(ilm)} {
if {$vars(cts_engine) == "cts" || ($vars(step) == "assemble")} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -ilm_sdc_files\] $prop_sdc\]\n"
} else {
if {$vars(step) != "assemble"} {
return ""
}
}
} else {
if {$vars(cts_engine) == "cts" || ($vars(step) == "assemble")} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -sdc_files\] $prop_sdc\]\n"
} else {
if {$vars(step) != "assemble"} {
return ""
}
}
}
}
}
} else {
if {$vars(ilm)} {
if {$vars(cts_engine) == "cts"} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -ilm_sdc_files\] $prop_sdc\]\n"
} else {
if {[regexp "^assemble" $vars(step)]} {
return ""
}
}
} else {
if {$vars(cts_engine) == "cts"} {
append commands "set vars($mode,post_cts_sdc_list) \[concat \[get_constraint_mode $mode -sdc_files\] $prop_sdc\]\n"
} else {
# if {[regexp "^assemble" $vars(step)]} {
return ""
}
}
}
}
append commands "}\n"
}
if {!$vars(ilm)} {
append commands "set restore \[get_global timing_defer_mmmc_object_updates\]\n"
append commands "set_global timing_defer_mmmc_object_updates true\n"
}
if {$vars(ilm)} {
exec /bin/touch empty.sdc
append commands "foreach mode \[all_constraint_modes\] {\n"
append commands " if {\[info exists vars(\$mode,post_cts_sdc_list)\]} {\n"
append commands " update_constraint_mode -name \$mode -ilm_sdc_files \$vars(\$mode,post_cts_sdc_list)\n"
append commands " } else {\n"
append commands " foreach view \[all_analysis_views] {\n"
append commands " set m \[regsub _\$view \$mode \"\"\]\n"
append commands " if {\[info exists vars(\$m,post_cts_sdc_list)\]} {\n"
append commands " update_constraint_mode -name \$mode -ilm_sdc_files \$vars(\$m,post_cts_sdc_list)\n"
append commands " }\n"
append commands " } \n"
append commands " } \n"
append commands "} \n"
} else {
append commands "foreach mode \[all_constraint_modes\] \{\n"
append commands " if \{\[info exists vars(\$mode,post_cts_sdc_list)\]\} \{\n"
append commands " update_constraint_mode -name \$mode -sdc_files \$vars(\$mode,post_cts_sdc_list)\n"
append commands " \} else \{\n"
append commands " foreach view \[all_analysis_views] \{\n"
append commands " set m \[regsub _\$view \$mode \"\"\]\n"
append commands " if \{\[info exists vars(\$m,post_cts_sdc_list)\]\} \{\n"
append commands " update_constraint_mode -name \$mode -sdc_files \$vars(\$m,post_cts_sdc_list)\n"
append commands " \}\n"
append commands " \} \n"
append commands " \} \n"
append commands "\} \n"
}
if {!$vars(ilm)} {
append commands "set_analysis_view -update_timing\n"
append commands "set_global timing_defer_mmmc_object_updates \$restore\n"
}
set this_index [lsearch $vars(steps) $vars(step)]
set prior [lindex $vars(steps) [expr $this_index - 1]]
# BCL: Added subst around vars(dbs_dir)
if {[file isfile [subst $vars(dbs_dir)]/$prior.enc.dat/mmmc/pathgroup.sdc]} {
# BCL: Added subst around vars(dbs_dir)
set vars(path_group_sdc) [subst $vars(dbs_dir)]/$prior.enc.dat/mmmc/pathgroup.sdc
append commands "ff_procs::load_path_groups $vars(path_group_sdc)\n"
}
}
default {
puts $vars(codgen_log) "<FF> INVALID OPTION ... MUST BE EITHER minmax OR mmmc"
}
}
return $commands
}
proc initialize_timing {{type mmmc}} {
global vars
global env
global init
global warnings
set vars(delay_corners) $vars(good_corners)
# if {[info exists vars(view_definition_tcl)]} {
# return ""
# }
if {$vars(verbose)} {
append commands "#\n"
append commands "# INITIALIZING [string toupper $type] TIMING\n"
append commands "#\n"
}
if {$vars(debug)} {
puts "<DEBUG> Executing proc: initialize_timing ..."
}
switch $type {
minmax {
# if {([llength $vars(rc_corners)] > 1)} {
# puts "<FF> WARNING: THE \"default\" FLOW SHOULD ONLY HAVE A SINGLE RC CORNER"
# puts "<FF> BUT [llength $vars(rc_corners)] CORNERS ARE DEFINED ($vars(rc_corners))"
# }
###################################################################
# Define RC corners and set the appropriate temperatures. This
# requires that the cap tables use -best/-worst syntax in the
# configuration file. Scaling factors should be derived using
# Ostrich Values for the default timing environment is derived
# from the default setup and hold analysis views
###################################################################
set corners(min) $vars($vars(default_hold_view),delay_corner)
set corners(max) $vars($vars(default_setup_view),delay_corner)
set corner $vars($corners(max),rc_corner)
# if {[info exists env(FF_KIT_PATH)]} {
if {![catch {set max $vars($vars($corners(max),rc_corner),T)}] &&
![catch {set min $vars($vars($corners(min),rc_corner),T)}]} {
append commands \
"defineRCCorner -late worst $max -early best $min\n"
}
# } else {
# Puts "<FF> USING SINGLE RC CORNER $vars($corners(max),rc_corner)"
# if {[info exists vars($vars($corners(max),rc_corner),T)]} {
# setExtractRCMode -scOpTemp $vars($vars($corners(max),rc_corner),T)
# }
# }
###################################################################
# Set scaling factors ... for pre-route optimization, the detailed
# cap factor is set to the detailed clock cap factor. This will
# be reset post-route
###################################################################
set args ""
if {![catch {set arg $vars($corner,pre_route_res_factor)}]} {
append args " -preRoute_res $arg"
}
if {![catch {set arg $vars($corner,pre_route_cap_factor)}]} {
append args " -preRoute_cap $arg"
}
if {![catch {set arg $vars($corner,pre_route_clk_res_factor)}]} {
append args " -preRoute_clkres $arg"
}
if {![catch {set arg $vars($corner,pre_route_clk_cap_factor)}]} {
append args " -preRoute_clkcap $arg"
}
if {![catch {set arg $vars($corner,post_route_res_factor)}]} {
append args " -postRoute_res "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_cap_factor)}]} {
append args " -postRoute_cap "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_clk_res_factor)}]} {
append args " -postRoute_clkres "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_clk_cap_factor)}]} {
append args " -postRoute_clkcap "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {![catch {set arg $vars($corner,post_route_xcap_factor)}]} {
append args " -postRoute_xcap "
if {[llength $arg] > 1} {
append args "\"[lindex $arg 2],[lindex $arg 1],[lindex $arg 0]\""
} else {
append args $arg
}
}
if {$args != ""} {
set command "setRCFactor $args\n"
append commands [FF::wrap_command $vars(step),set_rc_factor $command]
}
set command [FF_EDI::derate_timing minmax]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
mmmc {
if {$vars(verbose)} {
append commands "#\n"
append commands "# CREATING RC CORNERS ...\n"
append commands "#\n"
}
foreach rc $vars(rc_corners) {
# set command "\n"
set command ""
set non_command ""
if {[info exists vars($rc,scale_tcl)]} {
append command "create_rc_corner -name $rc"
# append command " -cap_table $vars($rc,cap_table) "
foreach option "cap_table T qx_tech_file qx_conf_file qx_lib_file" {
if {![catch {set arg $vars($rc,$option)}]} {
append command " -$option $arg"
}
}
append command "\n"
append command [FF::source_plug "$rc,scale_tcl"]
} else {
append command "create_rc_corner -name $rc"
foreach option "cap_table T qx_tech_file qx_conf_file qx_lib_file" {
if {![catch {set arg $vars($rc,$option)}]} {
append command " -$option $arg"
}
}
# append command "\n"
# append command " -cap_table $vars($rc,cap_table) "
if {![catch {set arg $vars($rc,pre_route_res_factor)}]} {
append command " -preRoute_res $arg"
} else {
append non_command "# -preRoute_res \$vars($rc,pre_route_res_factor)\n"
}
if {![catch {set arg $vars($rc,pre_route_cap_factor)}]} {
append command " -preRoute_cap $arg"
} else {
append non_command "# -preRoute_cap \$vars($rc,pre_route_cap_factor)\n"
}
if {![catch {set arg $vars($rc,pre_route_clk_res_factor)}]} {
append command " -preRoute_clkres $arg"
} else {
append non_command "# -preRoute_clkres \$vars($rc,pre_route_clk_res_factor)\n"
}
if {![catch {set arg $vars($rc,pre_route_clk_cap_factor)}]} {
append command " -preRoute_clkcap $arg"
} else {
append non_command "# -preRoute_clkcap \$vars($rc,pre_route_clk_cap_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_res_factor)}]} {
append command " -postRoute_res "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -postRoute_res \$vars($rc,post_route_res_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_cap_factor)}]} {
append command " -postRoute_cap "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -postRoute_cap \$vars($rc,post_route_cap_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_clk_res_factor)}]} {
append command " -postRoute_clkres "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -postRoute_res \$vars($rc,post_route_clk_res_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_clk_cap_factor)}]} {
append command " -postRoute_clkcap "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -postRoute_clkcap \$vars($rc,post_route_clk_cap_factor)\n"
}
if {![catch {set arg $vars($rc,post_route_xcap_factor)}]} {
append command " -postRoute_xcap "
if {[llength $arg] > 1} {
append command "\"$arg\""
} else {
append command $arg
}
} else {
append non_command "# -postRoute_xcap \$vars($rc,post_route_xcap_factor)\n"
}
}
append command "\n"
append commands [FF::wrap_command $vars(step),create_rc_corner $command]
if {$non_command != ""} {
append commands "#------------------------------------------------\n"
append commands "# Additional (unused) options ....\n"
append commands "#------------------------------------------------\n"
append commands $non_command
append commands "#------------------------------------------------\n"
}
}
if {![info exists vars(cpf_file)] || ([info exists vars(cpf_file)] && !$vars(cpf_timing))} {
################################################################
# CPF_TIMING == FALSE
################################################################
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING LIBRARY SETS ...\n"
append command "#\n"
}
append commands $command
foreach set $vars(library_sets) {
set command ""
append command "create_library_set -name $set -timing \[list "
append command "$vars($set,timing) "
append command "\]\n"
append commands [FF::wrap_command $vars(step),create_library_set $command]
}
if {[info exists vars(opconds)]} {
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING OPERATING CONDITIONS ...\n"
append command "#\n"
}
foreach opcond $vars(opconds) {
set command "create_op_cond -name $opcond"
# We already checked so we know these options exist
foreach option "library_file P V T" {
append command " -$option $vars($opcond,$option)"
}
append command "\n"
append commands [FF::wrap_command $vars(step),create_op_cond $command]
}
}
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING DELAY CORNERS ...\n"
append command "#\n"
}
append commands $command
foreach c $vars(delay_corners) {
# if {![info exists vars($c,rc_corner)]} {
# puts "Skipping delay corners $c"
# Puts "<FF> ERROR: RC corner for delay corner $c missing"
# continue
# }
set command ""
append command "create_delay_corner -name $c"
if {![catch {set arg $vars($c,library_set)}]} {
append command " -library_set $arg"
} elseif {![catch {set early $vars($c,early_library_set)}] &&
![catch {set late $vars($c,late_library_set)}]} {
append command " -early_library_set $early"
append command " -late_library_set $late"
} else {
Puts "<FF> ERROR: Library sets for delay corner $c not defined properly"
}
append command " -rc_corner $vars($c,rc_corner)"
if {![catch {set opcond $vars($c,opcond)}] &&
![catch {set library $vars($c,opcond_library)}]} {
append command " -opcond_library $library"
append command " -opcond $opcond"
} else {
if {![catch {set early $vars($c,early_opcond_library)}] &&
![catch {set late $vars($c,late_opcond_library)}]} {
append command " -early_opcond_library $early"
append command " -late_opcond_library $late"
}
if {![catch {set early_opcond $vars($c,early_opcond)}] &&
![catch {set late_opcond $vars($c,late_opcond)}]} {
append command " -early_opcond $early_opcond"
append command " -late_opcond $late_opcond"
}
}
append command "\n"
if {![catch {set domains $vars($c,power_domains)}]} {
set attribute_list "library_set opcond_library opcond irdrop_file \
late_library_set early_library_set \
late_opcond_library early_opcond_library \
late_opcond early_opcond late_irdrop_file early_irdrop_file"
foreach domain $domains {
append command " update_delay_corner -name $c -power_domain \"$domain\""
foreach attr $attribute_list {
if {[info exists vars($c,$domain,$attr)]} {
append command " -$attr $vars($c,$domain,$attr)"
}
}
append command "\n"
}
# if {![catch {set opcond $vars($domain,opcond)}] &&
# ![catch {set library $vars($domain,opcond_library)}]} {
# append command " -opcond_library $library"
# append command " -opcond $opcond"
# }
}
append commands [FF::wrap_command $vars(step),create_delay_corner $command]
}
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING CONSTRAINT MODES ...\n"
append command "#\n"
}
append commands $command
# Variable ccommand captures the constraint creation for the view_definition.tcl
# Variable ucommand capture the constraint updates for hier/ilm flows
#------------------------------------------------------------------------------------
set ccommand ""
set active_views [list]
set active_modes [list]
# Get modes actually used ... (changed from active to all views)
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
if {[lsearch $active_views $view] == -1} {
# lappend active_views $view
if {[lsearch $active_modes $vars($view,constraint_mode)] == -1} {
lappend active_modes $vars($view,constraint_mode)
}
}
}
set flatten_ilm 0
foreach constraint_mode $active_modes {
if {!$vars(ilm)} {
# Default flat flow
if {[info exists vars($constraint_mode,pre_cts_sdc)]} {
set command "create_constraint_mode -name $constraint_mode "
append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
append command "\n"
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
} else {
puts "Constraint file not found for $constraint_mode ..."
}
if {$vars(rc)} {
if {[info exists vars($constraint_mode,synth_sdc)]} {
set command "create_constraint_mode -name $constraint_mode "
append command "-sdc_files \[list $vars($constraint_mode,synth_sdc)\] "
append command "\n"
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
} else {
puts "Constraint file not found for $constraint_mode ..."
}
}
} else {
set sdcs ""
# ILM flow
if {[info exists vars(partition_list)]} {
# Hierarchy + ILMs
if {[info exists vars($constraint_mode,pre_cts_ilm_sdc)]} {
# append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_ilm_sdc)\]\n"
} else {
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\]\n"
}
if {$vars(top)} {
if {![info exists ucommand]} { set ucommand ""}
set command "update_constraint_mode -name $constraint_mode "
append command $sdcs
append ucommand [FF::wrap_command $vars(step),update_constraint_mode $command]
# append ucommand [FF::wrap_command $vars(step),flatten_ilm "flattenIlm\nsetIlmMode -keepFlatten true\n"]
set dynamic_update 1
# continue
} else {
set command "create_constraint_mode -name $constraint_mode "
append command $sdcs
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
}
} else {
# ILM only
set command "create_constraint_mode -name $constraint_mode "
if {[info exists vars($constraint_mode,pre_cts_ilm_sdc)]} {
# append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_ilm_sdc)\]\n"
} else {
exec /bin/touch empty.sdc
append sdcs "-sdc_files empty.sdc "
append sdcs "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\]\n"
}
# if {[info exists vars($constraint_mode,pre_cts_sdc)]} {
# set command "create_constraint_mode -name $constraint_mode "
# append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
# append command "\n"
# append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
# } else {
# puts "Constraint file not found for $constraint_mode ..."
# }
append command $sdcs
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
# append ccommand [FF::wrap_command $vars(step),flatten_ilm "flattenIlm\nsetIlmMode -keepFlatten true\n"]
}
}
}
append commands $ccommand
if {[info exists dynamic_update] && $dynamic_update} {
# set command ""
# append command "foreach mode \[all_constraint_modes\] {\n"
# append command " update_constraint_mode -name \$mode -sdc_files empty.sdc \\\n"
# append command " -ilm_sdc_files \[get_constraint_mode \$mode -sdc_files\]\n"
# append command "}\n"
# append ucommand [FF::wrap_command $vars(step),update_constraint_mode $command]
set command ""
append command "foreach mode \[all_constraint_modes] \{\n"
append command " foreach view \[all_analysis_views] \{\n"
append command " set m \[regsub _\$view \$mode \"\"\]\n"
append command " if \{( \$m != \$mode ) && ( \[lsearch \[all_constraint_modes\] \$m\] != -1) \} \{\n"
append command " update_constraint_mode -name \$mode -sdc_files empty.sdc -ilm_sdc_files \[get_constraint_mode \$m -ilm_sdc_files\]\n"
append command " \}\n"
append command " \} \n"
append command "\} \n"
append ucommand [FF::wrap_command $vars(step),dynamic_update $command]
if {$vars(ilm)} {
# append ucommand [FF::wrap_command $vars(step),flatten_ilm "flattenIlm\nsetIlmMode -keepFlatten true\n"]
append ucommand [FF::wrap_command $vars(step),flatten_ilm "flattenIlm\n"]
}
}
if {($vars(user_mode) == "hier") && ![info exists vars(view_definition_tcl)]} {
if {($vars(step) == "assemble") || ($vars(step) == "rebudget") || ($vars(step) == "assemble_flexilm") || ($vars(step) == "partition_place") || ($vars(step) == "model_gen") || ($vars(step) == "prototype")} {
# Create mmmc file for partition and assemble step
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
}
}
#return $commands
} else {
# Return only constraint mode updates for top level flow
if {[info exists ucommand]} {
return $ucommand
}
}
} else {
if {[info exists vars(view_definition_tcl)]} {
if {[info exists ucommand]} {
return $ucommand
}
}
}
if {![info exists vars(power_analysis_view)]} {
set vars(power_analysis_view) ""
}
set vars(all_analysis_views) \
[lsort -unique [concat $vars(setup_analysis_views) \
$vars(hold_analysis_views) \
$vars(power_analysis_view)]]
set command ""
if {$vars(verbose)} {
append command "#\n"
append command "# <FF> CREATING ANALYSIS VIEWS ...\n"
append command "#\n"
}
foreach view $vars(all_analysis_views) {
# append command "if {\[lsearch \[all_analysis_views\] $view\] == -1} {\n"
append command " create_analysis_view"
append command " -name $view"
append command " -constraint_mode $vars($view,constraint_mode)"
append command " -delay_corner $vars($view,delay_corner)\n"
# append command "}\n"
}
append commands [FF::wrap_command $vars(step),create_analysis_view $command]
if {![info exists vars(gen_postload)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
# Legacy support, so no IEEE 1801 support
# append commands [FF_EDI::load_power_intent]
set command ""
foreach c $vars(delay_corners) {
if {![catch {set domains $vars($c,power_domains)}]} {
foreach domain $domains {
append command " update_delay_corner -name $c -power_domain \"$domain\"\n"
# if {![catch {set opcond $vars($domain,opcond)}] &&
# ![catch {set library $vars($domain,opcond_library)}]} {
# append command " -opcond_library $library"
# append command " -opcond $opcond"
# }
}
}
}
append commands [FF::wrap_command init,update_delay_corner $command]
}
}
} else {
################################################################
# CPF_TIMING == TRUE
# Since the delay corner names are derived from the CPF, they
# are not known. However, they can be retrieved from the
# analysis_views
################################################################
# if {$vars(verbose)} {
# append commands "# UPDATING DELAY CORNERS ...\n"
# }
if {![info exists vars(delay_corners)]} {
set vars(delay_corners) [FF::[get_by_suffix vars ",rc_corner"]]
}
set command ""
foreach corner $vars(delay_corners) {
append command "if {\[lsearch -exact \[all_delay_corners\] $corner\] != -1} {\n"
append command " update_delay_corner -name $corner -rc_corner $vars($corner,rc_corner)\n"
append command "}\n"
}
append commands [FF::wrap_command $vars(step),update_delay_corner $command]
###################################################################
# Update constraints modes if an ILM flow
###################################################################
set ccommand ""
foreach constraint_mode $vars(constraint_modes) {
if {$vars(ilm)} {
if {[info exists vars(partition_list)]} {
set command "update_constraint_mode -name $constraint_mode "
} else {
set command "create_constraint_mode -name $constraint_mode "
}
if {[info exists vars($constraint_mode,pre_cts_ilm_sdc)]} {
append command "-sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
append command "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_ilm_sdc)\] "
} else {
exec /bin/touch empty.sdc
append command "-sdc_files empty.sdc "
append command "-ilm_sdc_files \[list $vars($constraint_mode,pre_cts_sdc)\] "
}
append command "\n"
if {[info exists vars(partition_list)]} {
append ccommand [FF::wrap_command $vars(step),update_constraint_mode $command]
} else {
append ccommand [FF::wrap_command $vars(step),create_constraint_mode $command]
}
}
}
###################################################################
# Return early for partition implementation flows ...
###################################################################
if {(($vars(mode) == "hier") || ([info exists vars(hier)] && $vars(hier))) && ($vars(step) != "partition_place")} {
set commands $ccommand
return $commands
} else {
append commands $ccommand
}
}
###################################################################
# Update library_sets with SI libraries if defined
###################################################################
# if {$vars(verbose)} {
# append commands "# UPDATING LIBRARY SETS ...\n"
# }
set command ""
foreach set $vars(library_sets) {
if {([info exists vars($set,si)] && ($vars($set,si) != "")) || \
([info exists vars($set,socv)] && ($vars($set,socv) != "")) || \
([info exists vars($set,aocv)] && ($vars($set,aocv) != ""))} {
append command "update_library_set -name $set"
}
if {[info exists vars($set,socv)] && ($vars($set,socv) != "")} {
append command " -socv \[list"
foreach file $vars($set,socv) {
append command " $file"
}
append command "\]"
}
if {[info exists vars($set,aocv)] && ($vars($set,aocv) != "")} {
append command " -aocv \[list"
foreach file $vars($set,aocv) {
append command " $file"
}
append command "\]"
}
if {[info exists vars($set,si)] && ($vars($set,si) != "")} {
append command " -si \[list"
foreach file $vars($set,si) {
append command " $file"
}
append command "\]"
}
append command "\n"
}
append commands [FF::wrap_command $vars(step),update_library_set $command]
if {$vars(flow) != "mmmc"} {
append commands [FF_EDI::update_timing mmmc]
}
# set command [FF_EDI::derate_timing mmmc]
# append commands [FF::wrap_command $vars(step),derate_timing $command]
###################################################################
# Define setup / hold analysis views and enable the default views
# for each
###################################################################
append commands "set_analysis_view"
append commands " -setup \[list $vars(active_setup_views)\]"
append commands " -hold \[list $vars(active_hold_views)\]\n"
# set command "set_default_view -setup $vars(default_setup_view) -hold $vars(default_hold_view)\n"
# append commands [FF::wrap_command $vars(step),set_default_view $command]
# set command [FF_EDI::derate_timing mmmc]
# append commands [FF::wrap_command $vars(step),derate_timing $command]
# if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
# set command "set_power_analysis_mode -analysis_view $vars(power_analysis_view)\n"
# append commands [FF::wrap_command $vars(step),set_power_analysis_mode $command]
# }
file mkdir $vars(script_dir)
if {[lindex [split $vars(version) "."] 0] <= 10} {
if {$vars(flat) != "full"} {
set op [open $vars(script_dir)/mmmc.tcl w]
puts $op [FF::pretty_print $commands 1]
close $op
# set commands "source \$vars(script_dir)/mmmc.tcl\n"
set commands "source $vars(script_dir)/mmmc.tcl\n"
}
} else {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
return "source $vars(script_dir)/incr_view_definition.tcl\n"
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
set op [open $mmmc_file w]
puts $op [FF::pretty_print $commands 1]
close $op
}
}
return
# return $commands
}
}
default {
puts "<FF> INVALID OPTION ... MUST BE EITHER minmax OR mmmc"
}
}
return $commands
}
proc update_rc_corners {} {
global vars
foreach rc_corner [all_rc_corners] {
if {$rc_corner != "default_rc_corner"} {
set update false
set command "update_rc_corner -name $rc_corner "
if {[get_rc_corner $rc_corner -cap_table] != $vars($rc_corner,cap_table)} {
set update true
append command "-cap_table $vars($rc_corner,cap_table) "
}
if {[get_rc_corner $rc_corner -preRoute_res] != $vars($rc_corner,pre_route_res_factor)} {
set update true
append command "-preRoute_res $vars($rc_corner,pre_route_res_factor) "
}
if {[get_rc_corner $rc_corner -preRoute_cap] != $vars($rc_corner,pre_route_cap_factor)} {
set update true
append command "-preRoute_cap $vars($rc_corner,pre_route_cap_factor) "
}
if {[get_rc_corner $rc_corner -postRoute_res] != $vars($rc_corner,post_route_res_factor)} {
set update true
append command "-postRoute_res \"$vars($rc_corner,post_route_res_factor)\" "
}
if {[get_rc_corner $rc_corner -postRoute_cap] != $vars($rc_corner,post_route_cap_factor)} {
set update true
append command "-postRoute_cap \"$vars($rc_corner,post_route_cap_factor)\" "
}
if {[get_rc_corner $rc_corner -preRoute_clkres] != $vars($rc_corner,pre_route_clk_res_factor)} {
set update true
append command "-preRoute_clkres $vars($rc_corner,pre_route_clk_res_factor) "
}
if {[get_rc_corner $rc_corner -preRoute_clkcap] != $vars($rc_corner,pre_route_clk_cap_factor)} {
set update true
append command "-preRoute_clkcap $vars($rc_corner,pre_route_clk_cap_factor) "
}
if {[get_rc_corner $rc_corner -postRoute_clkres] != $vars($rc_corner,post_route_clk_res_factor)} {
set update true
append command "-postRoute_clkres \"$vars($rc_corner,post_route_clk_res_factor)\" "
}
if {[get_rc_corner $rc_corner -postRoute_clkcap] != $vars($rc_corner,post_route_clk_cap_factor)} {
set update true
append command "-postRoute_clkcap \"$vars($rc_corner,post_route_clk_cap_factor)\" "
}
if {[get_rc_corner $rc_corner -postRoute_xcap] != $vars($rc_corner,post_route_xcap_factor)} {
set update true
append command "-postRoute_xcap \"$vars($rc_corner,post_route_xcap_factor)\" "
}
foreach option "T qx_tech_file qx_conf_file qx_lib_file" {
if {[info exists vars($rc_corner,$option)]} {
if {[get_rc_corner $rc_corner -$option] != $vars($rc_corner,$option)} {
set update true
append command "-$option $vars($rc_corner,$option) "
}
}
}
if {$update} {
uplevel #0 eval $command
}
}
}
}
proc reset_rc_corners {} {
global vars
foreach corner $vars(rc_corners) {
update_rc_corner -name $corner \
-preRoute_res 1.0 \
-preRoute_clkres 1.0 \
-preRoute_cap 1.0 \
-preRoute_clkcap 1.0 \
-postRoute_res 1.0 \
-postRoute_clkres 1.0 \
-postRoute_cap 1.0 \
-postRoute_clk_ap 1.0 \
-postRoute_xcap 1.0
}
}
proc add_views {} {
global vars
Puts "<FF> CREATING RC CORNERS ..."
foreach rc_corner $vars(rc_corners) {
if {[lsearch [all_rc_corners] $rc_corner] == -1} {
set command "create_rc_corner -name $rc_corner "
append command "-cap_table $vars($rc_corner,cap_table)\] "
append command "-preRoute_res $vars($rc_corner,pre_route_res_factor) "
append command "-preRoute_clkres $vars($rc_corner,pre_route_clk_res_factor) "
append command "-preRoute_cap $vars($rc_corner,pre_route_cap_factor) "
append command "-preRoute_clkcap $vars($rc_corner,pre_route_clk_cap_factor) "
append command "-postRoute_res \"$vars($rc_corner,post_route_res_factor)\" "
append command "-postRoute_clkres \"$vars($rc_corner,post_route_clk_res_factor)\" "
append command "-postRoute_cap \"$vars($rc_corner,post_route_cap_factor)\" "
append command "-postRoute_clkcap \"$vars($rc_corner,post_route_clk_cap_factor)\" "
append command "-postRoute_xcap $vars($rc_corner,post_route_xcap_factor) "
foreach option "T qx_tech_file qx_conf_file qx_lib_file" {
if {[info exists vars($rc_corner,$option)]} {
append command "-$option $vars($rc_corner,$option) "
}
}
uplevel #0 eval $command
}
}
if {![FF::is_lp_flow] || \
([FF::is_lp_flow] && ([llength [all_analysis_views]] == 2))} {
Puts "<FF> CREATING LIBRARY SETS ..."
foreach library_set $vars(library_sets) {
if {[lsearch [all_library_sets] $library_set] == -1} {
create_library_set -name $library_set \
-timing $vars($library_set,timing)
}
}
Puts "<FF> CREATING DELAY CORNERS ...\n"
foreach delay_corner $vars(delay_corners) {
if {[lsearch [all_delay_corners] $delay_corner] == -1} {
set command "create_delay_corner -name $delay_corner "
append command "-library_set $vars($delay_corner,library_set) "
append command "-rc_corner $vars($delay_corner,rc_corner) "
if {[info exists vars($delay_corner,opcond)] && [info exists vars($delay_corner,opcond_library)]} {
append command "-opcond_library $vars($delay_corner,opcond_library) "
append command "-opcond $vars($delay_corner,opcond) "
}
uplevel #0 eval $command
if {![catch {set domains $vars($c,power_domains)}]} {
set command " update_delay_corner -name $c -power_domains \"$domains\""
uplevel #0 eval $command
}
}
}
Puts "<FF> UPDATING CONSTRAINT MODES ..."
foreach mode $vars(constraint_modes) {
if {[lsearch [all_constraint_modes] $mode] == -1} {
if {[info exists vars($mode,pre_cts_sdc,full)]} {
append commands "create_constraint_mode "
append commands " -name $mode "
append commands " -sdc_files $vars($mode,pre_cts_sdc,full)\n"
} elseif {[info exists vars($mode,pre_cts_sdc)} {
append commands "create_constraint_mode "
append commands " -name $mode "
append commands " -sdc_files $vars($mode,pre_cts_sdc)\n"
}
}
}
set vars(all_analysis_views) [lsort -uniq [concat $vars(setup_analysis_views) $vars(hold_analysis_views)]]
Puts "<FF> UPDATING ANALYSIS VIEWS ..."
foreach analysis_view $vars(all_analysis_views) {
if {[lsearch [all_analysis_views] $analysis_view] == -1} {
create_analysis_view -name $analysis_view \
-constraint_mode $vars($analysis_view,constraint_mode) \
-delay_corner $vars($analysis_view,delay_corner)
}
}
} else {
############################################################################
# Since the delay corner names are derived from the CPF, they are not
# known. However, they can be retrieved from the analysis_views
############################################################################
Puts "<FF> UPDATING DELAY CORNERS ..."
foreach corner $vars(delay_corners) {
Puts "Updating delay corner $corner with RC Corner $vars($corner,rc_corner) ..."
update_delay_corner -name $corner -rc_corner $vars($corner,rc_corner)
}
}
############################################################################
# Update library_sets with SI libraries if defined
############################################################################
Puts "<FF> UPDATING LIBRARY SETS ..."
foreach library_set $vars(library_sets) {
if {[info exists vars($library_set,si)] && ($vars($library_set,si) != "")} {
update_library_set -name $library_set \
-si $vars($library_set,si)
}
}
foreach library_set $vars(library_sets) {
if {[info exists vars($library_set,aocv)] && ($vars($library_set,aocv) != "")} {
update_library_set -name $library_set \
-aocv $vars($library_set,aocv)
}
}
set_interactive_constraint_modes [all_constraint_modes -active]
Puts "<FF> DERATING DELAY CORNERS ..."
FF_EDI::derate_timing mmmc
if {$vars(flow) != "mmmc"} {
FF_EDI::update_timing mmmc
}
############################################################################
# Define setup / hold analysis views and enable the default views for each
############################################################################
set_analysis_view -setup $vars(active_setup_views) -hold $vars(active_hold_views)
set_default_view -setup $vars(default_setup_view) -hold $vars(default_hold_view)
}
proc get_power_domains_code {} {
global vars
set commands "set domains \[list\]\n"
append commands "dbForEachPowerDomain \[dbgHead\] domain {\n"
append commands " if {\[dbGroupHInstList \[dbPowerDomainName \$domain\]\] != \"0x0\"} {\n"
append commands " lappend domains \[dbPowerDomainName \$domain\]\n"
append commands " }\n"
append commands "}\n"
return $commands
}
proc get_clock_ports {} {
global vars
set commands ""
if {!$vars(codegen) || ($vars(codegen) && ($vars(flat) != "none"))} {
if {$vars(ilm)} {
if {$vars(step) != "cts"} {
append commands "setIlmType -model si\n"
}
}
append commands "set clock_ports \[list\]\n"
append commands "set clocks \[get_clocks *\]\n"
append commands "foreach_in_collection clock \$clocks {\n"
append commands " set sources \[get_property \$clock sources\]\n"
append commands " foreach_in_collection source \$sources {\n"
append commands " set source_name \[get_property \$source hierarchical_name\]\n"
append commands " set source_type \[get_property \$source object_type\]\n"
append commands " if {\$source_type == \"port\"} {\n"
append commands " lappend clock_ports \$source_name\n"
append commands " }\n"
append commands " }\n"
append commands "}\n"
} else {
append commands "FF::get_clock_ports\n"
}
return $commands
}
proc add_tie_cells {{mode true} {add true}} {
#########################################################################
# This procedure inserts tie hi/lo cells based on information in the
# setup.tcl
#########################################################################
global vars
global errors
set commands ""
if {$vars(verbose)} {
append commands "#\n"
append commands "# ADDING TIE CELLS\n"
append commands "#\n"
}
set args ""
if {[info exists vars(tie_cells,max_distance)]} {
append args " -maxDistance $vars(tie_cells,max_distance)"
}
if {[info exists vars(tie_cells,max_fanout)]} {
append args " -maxFanout $vars(tie_cells,max_fanout)"
}
if {[FF::is_lp_flow] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 1))} {
# Get the set of tie cells to use, both domain-specific and generic.
set all_tie_cells [list]
set has_default false
if {![catch {set default_cells $vars(tie_cells)}]} {
set has_default true
lappend all_tie_cells $vars(tie_cells)
}
set has_specific false
foreach domain [FF::get_by_suffix vars ",tie_cells"] {
set cells $vars($domain,tie_cells)
lappend all_tie_cells $vars($domain,tie_cells)
if {![llength $cells]} {
continue
}
set has_specific true
# append command "set tie_cells($domain) \[list $cells\]\n"
# append commands $command
}
#
# If there are no tie cells at all, there's nothing to do
#
if {!$has_default && !$has_specific} {
return ""
}
set all_tie_cells [lsort -unique [join $all_tie_cells]]
#
# If there are no domain-specific entries, life is real simple
#
# if {!$has_specific} {
# set command "setTieHiLoMode -cell \"$default_cells\" $args\n"
# append commands [FF::wrap_command $vars(step),set_tie_hi_lo_mode $command]
# if {$add} {
# foreach cell $default_cells {
# append commands "setDontUse $cell false\n"
# }
# if {[llength $vars(power_domains)] > 0} {
# foreach domain $vars(power_domains) {
# append commands " catch {addTieHiLo -powerDomain $domain -prefix $domain}\n"
# }
# }
# foreach cell $default_cells {
# append commands "setDontUse $cell true\n"
# }
# }
# } else {
foreach cell $default_cells {
append commands "setDontUse $cell false\n"
}
if {[llength $vars(power_domains)] > 0} {
foreach domain $vars(power_domains) {
if {[info exists vars($domain,tie_cells)]} {
set command "setTieHiLoMode -cell \"$vars($domain,tie_cells)\" $args\n"
} else {
if {[info exists default_cells]} {
set command "setTieHiLoMode -cell \"$default_cells\" $args\n"
} else {
continue
}
}
append commands [FF::wrap_command $vars(step),set_tie_hi_lo_mode $command]
append commands " catch {addTieHiLo -powerDomain $domain -prefix $domain}\n"
}
}
foreach cell $default_cells {
append commands "setDontUse $cell true\n"
}
# }
} elseif {![catch {set cells $vars(tie_cells)}]} {
set command "setTieHiLoMode -cell \"$cells\" $args\n"
# if {$mode} {
append commands [FF::wrap_command $vars(step),set_tie_hi_lo_mode $command]
# }
set command "foreach cell \{$cells\} {\n"
append command " setDontUse \$cell false\n"
append command "}\n"
append command "addTieHiLo\n"
append command "foreach cell \{$cells\} {\n"
append command " setDontUse \$cell true\n"
append command "}\n"
append commands $command
} else {
set commands ""
}
return $commands
}
proc add_filler_cells {} {
#########################################################################
# This procedure inserts tie hi/lo cells based on information in the
# setup.tcl
#########################################################################
global vars
global errors
set commands ""
set ccommands ""
if {$vars(verbose)} {
append ccommands "#\n"
append ccommands "# ADD FILLER CELLS\n"
append ccommands "#\n"
}
append commands $ccommands
if {[FF::is_lp_flow] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 1))} {
# Get the set of filler cells to use, both domain-specific and generic.
set all_filler_cells [list]
set has_default false
if {![catch {set default_cells $vars(filler_cells)}]} {
set has_default true
lappend all_filler_cells $vars(filler_cells)
}
set has_specific false
foreach domain [FF::get_by_suffix vars ",filler_cells"] {
set cells $vars($domain,filler_cells)
lappend all_filler_cells $vars($domain,filler_cells)
if {![llength $cells]} {
continue
}
set has_specific true
# append command "set filler_cells($domain) \[list $cells\]\n"
# append commands $command
}
#
# If there are no filler cells at all, there's nothing to do
#
if {!$has_default && !$has_specific} {
return ""
}
set all_filler_cells [lsort -unique [join $all_filler_cells]]
#
# If there are no domain-specific entries, life is real simple
#
# if {!$has_specific} {
# set command "setFillerMode -core \"$default_cells\" -corePrefix FILL\n"
# append commands [FF::wrap_command $vars(step),set_filler_mode $command]
# if {$add} {
# foreach cell $default_cells {
# append commands "setDontUse $cell false\n"
# }
# if {[llength $vars(power_domains)] > 0} {
# foreach domain $vars(power_domains) {
# append commands " catch {addFiller -powerDomain $domain}\n"
# }
# }
# foreach cell $default_cells {
# append commands "setDontUse $cell true\n"
# }
# }
# } else {
# foreach cell $default_cells {
# append commands "setDontUse $cell false\n"
# }
if {[llength $vars(power_domains)] > 0} {
set default 0
foreach domain $vars(power_domains) {
if {[info exists vars($domain,filler_cells)]} {
set command "setFillerMode -core \"$vars($domain,filler_cells)\" -corePrefix FILL\n"
set default 0
} else {
if {[info exists default_cells]} {
if {!$default} {
set command "setFillerMode -core \"$default_cells\" -corePrefix FILL\n"
set default 1
} else {
set command ""
}
} else {
continue
}
}
append commands [FF::wrap_command $vars(step),set_filler_mode $command]
append commands " catch {addFiller -powerDomain $domain}\n"
}
}
# foreach cell $default_cells {
# append commands "setDontUse $cell true\n"
# }
# }
} elseif {![catch {set cells $vars(filler_cells)}]} {
set command "setFillerMode -core \"$cells\" -corePrefix FILL\n"
append commands [FF::wrap_command $vars(step),set_filler_mode $command]
# set command "foreach cell \{$cells\} {\n"
# append command " setDontUse \$cell false\n"
# append command "}\n"
set command "addFiller\n"
# append command "foreach cell \{$cells\} {\n"
# append command " setDontUse \$cell true\n"
# append command "}\n"
append commands $command
} else {
set commands ""
}
return $commands
}
proc delete_filler_cells {} {
global vars
#########################################################################
# Remove filler cells
#########################################################################
set command "deleteFiller\n"
append commands [FF::wrap_command $vars(step),delete_filler_cells $command]
return $commands
}
proc insert_welltaps_endcaps {{outline false}} {
global vars
#########################################################################
# Insert welltaps and pre/post endcaps
#########################################################################
global vars
global errors
global warnings
set commands ""
if {[FF::is_lp_flow] && ([info exist vars(power_domains)] && ([llength $vars(power_domains)] > 0))} {
if {$vars(flat) == "full"} {
#
# Just like tie and filler cells, we can have power domain-specific
# cells and settings that we need to worry about.
#
# append commands [FF_EDI::get_power_domains_code]
#
# Get the set of domains that we need to worry about
#
set pre [FF::get_by_suffix vars ",pre_endcap"]
set post [FF::get_by_suffix vars ",post_endcap"]
set endcaps [FF::lintersection $pre $post]
set welltaps [FF::get_by_suffix vars ",welltaps"]
#
# For every domain in the union, we need to issue statements if that
# domain is one of the power domains in the design
#
# NOTE: We really don't need to worry about indenting the commands
# to look nice since the output routine will format it correctly
#
set domains [FF::lunion $endcaps $welltaps]
foreach domain $domains {
# append commands "if {\[lsearch \$domains $domain\] != -1} {\n"
#
# Handle the end caps
#
set std_args "-prefix $domain -powerDomain $domain"
set add " addEndCap $std_args"
if {![catch {set pre $vars($domain,pre_endcap)}] &&
![catch {set post $vars($domain,post_endcap)}]} {
append commands "$add -preCap $pre -postCap $post\n"
} elseif {![catch {set pre $vars(pre_endcap)}] &&
![catch {set post $vars(post_endcap)}]} {
append commands "$add -preCap $pre -postCap $post\n"
}
set taps ""
if {[catch {set taps $vars($domain,welltaps)}]} {
catch {set taps $vars(welltaps)}
}
if {$taps == ""} {
append commands "\}\n"
continue
}
#
# Handle well taps
#
append commands " addWellTap $std_args -cell \[list $taps\]"
if {![catch {set i $vars($domain,welltaps,cell_interval)}]} {
append commands " -cellInterval $i"
} elseif {![catch {set i $vars(welltaps,cell_interval)}]} {
append commands " -cellInterval $i"
}
if {![catch {set offset $vars($domain,welltaps,row_offset)}] ||
![catch {set offset $vars(welltaps,row_offset)}]} {
append commands " -inRowOffset $offset"
}
if {![catch {set checker $vars($domain,welltaps,checkerboard)}] ||
![catch {set checker $vars(welltaps,checkerboard)}]} {
if {$checker} {
append commands " -checkerboard"
}
}
append commands "\n"
#
# Add a verify step, if requested
#
if {![catch {set rule $vars($domain,welltaps,verify_rule)}] ||
![catch {set rule $vars(welltaps,verify_rule)}]} {
append commands "verifyWellTap -cells \[list $taps\]"
append commands " -powerDomain $domain"
append commands " -report $vars(rpt_dir)/$domain.welltap.rpt"
append commands " -rule $rule\n"
}
# append commands "}\n"
}
#
# We've taken care of all of the domains that we have explicit
# settings for. However, we may still have domains in the design
# that we know nothing explicit about. We need to handle these
# with a different set of code.
#
# We are going to cheat. Since the code we need is already written
# (below), we are going to recursively call this routine to get
# the skeleton that we need and wrap it up into a for-loop. This
# should get us something that looks like the following:
# set processed [list domain1 domain2 domain3]
# foreach domain $domains {
# if {[lsearch $processed_domains $domain] == -1} {
# addEndCap -powerDomain $domain -prefix $domain ...
# addWellTap -powerDomain $domain -prefix $domain ...
# verifyWellTap -powerDomain $domain ...
# }
# }
#
# NOTE: The output routine will take care of making this look pretty
# at the end. We don't need to worry about indentation for
# the inserted commands
#
# set save $vars(cpf_file)
# unset vars(cpf_file)
# set default_insert [insert_welltaps_endcaps true]
# if {$default_insert != ""} {
# append commands "set processed_domains \[list $domains\]\n"
# append commands "foreach domain \$domains {\n"
# append commands " if {\[lsearch \$processed_domains \$domain\] == -1} {\n"
# append commands " $default_insert"
# append commands " }\n"
# append commands "}\n"
# }
# set vars(cpf_file) $save
} else {
append commands "ff_procs::insert_welltaps_endcaps\n"
}
} else {
#
# There is no CPF file that we need to worry about. However, if
# $outline is true, it means that the code (above) that handles power
# domains called this routine recursively, and we need to change
# the commands a little bit to include variables for power domains
#
# Start with the simple case: endcaps
#
if {![catch {set pre $vars(pre_endcap)}] &&
![catch {set post $vars(post_endcap)}]} {
append commands "addEndCap -preCap $pre -postCap $post"
if {!$outline} {
append commands " -prefix ENDCAP\n"
} else {
append commands " -prefix \$domain -powerDomain \$domain\n"
}
}
#
# Now process welltaps
#
if {![catch {set taps $vars(welltaps)}]} {
append commands "addWellTap -cell \[list $taps\]"
if {!$outline} {
append commands " -prefix WELLTAP"
} else {
append commands " -prefix \$domain -powerDomain \$domain"
}
if {![catch {set max_gap $vars(welltaps,max_gap)}]} {
append commands " -maxGap $max_gap"
} elseif {![catch {set interval $vars(welltaps,cell_interval)}]} {
append commands " -cellInterval $interval"
}
if {![catch {set offset $vars(welltaps,row_offset)}]} {
append commands " -inRowOffset $offset"
}
if {![catch {set checker $vars(welltaps,checkerboard)}]} {
if {$checker} {
append commands " -checkerboard"
}
}
append commands "\n"
#
# If a verify request has been made, create the command to
# do so. Again, take into account the potential for a recursive
# call to this routine.
#
if {![catch {set rule $vars(welltaps,verify_rule)}]} {
append commands "verifyWellTap -cells \[list $taps\] "
append commands " -report $vars(rpt_dir)/"
if {!$outline} {
append commands "welltap.rpt"
} else {
append commands "\$domain.welltap.rpt -powerDomain \$domain"
}
append commands " -rule $rule\n"
} elseif {!$outline} {
# puts "<FF> Cannot run verifyWellTap because vars(welltaps,verify_rule) is not defined"
set warnings($vars(warning_count)) "Cannot run verifyWellTap because vars(welltaps,verify_rule) is not defined"
incr vars(warning_count)
}
}
}
#
# If we created any commands to be executed, prefix the commands with a
# header
#
if {($commands != "") && !$outline} {
set body $commands
set commands ""
if {$vars(verbose)} {
append commands "#\n"
append commands "# INSERTING WELLTAPS AND/OR ENDCAPS\n"
append commands "#\n"
}
append commands $body
}
return $commands
}
proc route_secondary_pg_nets {} {
global vars
global errors
#
# Don't try to route unless the proper flags are in place to do so
#
if {![info exists vars(route_secondary_pg_nets)] ||
!$vars(route_secondary_pg_nets)} {
return ""
}
set commands "# <FF> ROUTING SECONDARY POWER NETS ...\n"
#
# Enable global pin pairs (if defined)
#
if {[catch {set arg $vars(secondary_pg,cell_pin_pairs)}]} {
puts "<FF> =========================================================="
puts "<FF> ERROR: No cell/pin pairs defined. Please define cell/pin"
puts "<FF> pairs in your setup.tcl using the variable"
puts "<FF> vars(secondary_pg,cell_pin_pairs)"
puts "<FF> =========================================================="
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
append commands "setPGPinUseSignalRoute $arg\n"
#
# Build commands for individual nets (if defined)
#
if {[info exists vars(secondary_pg,nets)]} {
foreach net $vars(secondary_pg,nets) {
if {![catch {set arg $vars($net,cell_pin_pairs)}]} {
append commands "setPGPinUseSignalRoute $arg\n"
}
}
set nets $vars(secondary_pg,nets)
set netFormat " -nets %s"
} else {
set nets [list "secondary_pg"]
set netFormat ""
}
foreach net $nets {
set route "routePGPinUseSignalRoute"
append route [format $netFormat $net]
catch {append route " -pattern $vars($net,pattern)"}
catch {append route " -maxFanout $vars($net,max_fanout)"}
catch {append route " -nonDefaultRule $vars($net,non_default_rule)"}
append commands "$route\n"
}
return $commands
}
proc add_power_switches {{domains ""}} {
global vars
global errors
global map
source $vars(script_path)/ETC/INNOVUS/map_options.tcl
if {$domains == ""} {
append commands [FF_EDI::get_power_domains_code]
# eval [FF::get_power_domains_code]
}
foreach domain $domains {
if {[info exists vars($domain,switchable)] &&
$vars($domain,switchable)} {
set type $vars($domain,switch_type)
deletePowerSwitch -$type -powerDomain $domain
set command "addPowerSwitch -powerDomain $domain -$type"
if {[info exists vars($domain,checker_board)] &&
$vars($domain,checker_board)} {
append command " -checkerBoard"
}
if {[info exists vars($domain,back_to_back_chain)] &&
$vars($domain,back_to_back_chain)} {
append command " -backToBackChain"
}
if {[info exists vars($domain,loop_back_at_end)] &&
$vars($domain,loop_back_at_end)} {
append command " -loopbackAtEnd"
}
if {[info exists vars($domain,check_height)] &&
!$vars($domain,check_height)} {
append command " -noDoubleHeightCheck"
}
if {[info exists vars($domain,verify_rows)] &&
!$vars($domain,verify_rows)} {
append command " -noRowVerify"
}
if {[info exists vars($domain,enable_chain)] &&
!$vars($domain,enable_chain)} {
append command " -noEnableChain"
}
foreach option [array names map] {
if {[info exists vars($domain,$option)]} {
append command " -$map($option) $vars($domain,$option)"
}
}
uplevel #0 eval $command
}
}
}
proc run_clock_eco {args} {
global vars
global errors
if {[llength $args] != 1} {
puts "<FF> Internal error in run_clock_eco. Wrong number of args."
exit -111
}
set commands ""
# append commands "# <FF> RUNNING CLOCK ECO\n"
switch $args {
"post_route" {
append commands [FF_EDI::delete_filler_cells]
append commands "ckECO -postRoute -useSpecFileCellsOnly\n"
append commands [FF_EDI::add_filler_cells]
append commands "changeClockStatus -all -noFixedNetWires\n"
}
"post_cts" {
append commands "ckECO -postCTS -useSpecFileCellsOnly\n"
}
default {
puts "<FF> Internal error in run_clock_eco."
puts "<FF> Invalid argument; valid arguments are post_cts and post_route."
exit -111
}
}
# if {$vars(codegen)} {
return $commands
# } else {
# uplevel #0 eval $commands
# }
}
############################################################################
# Main foundation flow step procedures
############################################################################
proc run_syn_map {{format 1}} {
global vars
global env
global errors
set vars(step) syn_map
set commands ""
append commands "proc Puts {args} {puts \$args}\n"
append commands "puts \[get_attr program_version /\]\n"
## enable multi processing
append commands "set hostlist \[lrepeat $vars(local_cpus) localhost\]\n"
append commands "set_attribute super_thread_servers \$hostlist /\n"
if {$vars(capture_metrics)} {
append commands "\num::enable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
append commands [FF::source_plug pre_syn_setup_tcl]
set command "set_attribute information_level 1 /\n"
append command "set_attribute source_verbose false /\n"
append command "set_attribute -quiet print_error_info false /\n"
append command "set_attribute -quiet echo_commands false /\n"
append command "set_attribute mesg_coloring false /\n"
append command "set_attribute qos_report_basic_cost_groups true /\n"
set command "set_attribute lib_lef_consistency_check_enable true /\n"
append command "set_attribute script_search_path {./} /\n"
append command "suppress_messages {LBR-30 LBR-31 LBR-170 LBR-72 LBR-155 PHYS-210 PHYS-256 LBR-201 LBR-34 LBR-83 LBR-40 LBR-162 LBR-122}\n"
append command "redirect /dev/null {set map_fancy_names 1}\n"
append commands [FF::source_plug post_syn_setup_tcl]
append commands [FF::source_plug pre_syn_load_lib_tcl]
set command "\nset_attribute library \"\\\n"
foreach lib $vars($vars($vars($vars(default_setup_view),delay_corner),library_set),timing) {
append command " $lib \\\n"
}
append command "\"\n"
append commands [FF::wrap_command $vars(step),read_lib $command]
set command "\nset_attribute lef_library \"\\\n"
foreach lef $vars(lef_files) {
append command " $lef \\\n"
}
append command "\"\n"
append commands [FF::wrap_command $vars(step),read_lef $command]
set command "\nset_attribute qrc_tech_file $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),qx_tech_file)\n"
append commands [FF::wrap_command $vars(step),read_qrc $command]
if {[info exists vars(dont_use_list)] && $vars(dont_use_list) != "" } {
foreach cell $vars(dont_use_list) {
append commands "set_attribute avoid true \[find / -libcell $cell\]\n"
}
}
append commands [FF::source_plug post_syn_load_lib_tcl]
if {[info exists vars(cpf_file)]} {
set command "read_power_intent -module $vars(design) -cpf $vars(cpf_file)\n"
append commands [FF::wrap_command $vars(step),read_power_intent $command]
}
if {[info exists vars(ieee1801_file)]} {
set command "read_power_intent -module $vars(design) -1801 $vars(ieee1801_file)\n"
append commands [FF::wrap_command $vars(step),read_power_intent $command]
}
if {[info exists vars(hdl_search_path)]} {
append commands "set_attribute hdl_search_path \"$vars(hdl_search_path)\" /\n"
}
if {[info exists vars(hdl_file_list)]} {
set command "read_hdl -v2001 \"$vars(hdl_file_list)\"\n"
append commands [FF::wrap_command $vars(step),read_hdl $command]
} else {
append commands [FF::source_plug syn_load_rtl_tcl]
}
append commands "\n#set read_def_libcell_mismatch_error 0\n"
if {0} {
set command "#set_attribute gen_module_prefix _RC_ /\n"
append command "#set_attribute hdl_array_naming_style %s_%d /\n"
append command "#set_attribute hdl_reg_naming_style %s_reg%s /\n"
append command "#set_attribute hdl_use_if_generate_prefix false /\n"
append command "#set_attribute hdl_use_for_generate_prefix true /\n"
append command "#set_attribute hdl_use_block_prefix false /\n"
append command "#set_attribute hdl_max_loop_limit 8096 /\n"
append command "#set_attribute hdl_generate_index_style %s_%d_ /\n"
append command "#set_attribute hdl_generate_separator _ /\n"
append command "#set_attribute hdl_instance_array_naming_style %s_%d_ /\n"
append command "#set_attribute hdl_parameter_naming_style _%s%d /\n"
append command "#set_attribute hdl_record_naming_style %s\[%s\] /\n"
append command "#set_attribute hdl_use_techelt_first true /\n"
append command "#set_attribute hdl_error_on_blackbox true /\n"
append command "#set_attribute hdl_track_filename_row_col false /\n"
append command "#set_attribute hdl_enable_proc_name false /\n"
append command "#set_attribute hdl_error_on_latch false /\n"
append command "#set_attribute hdl_unconnected_input_port_value none /\n"
append command "#set_attribute hdl_undriven_output_port_value none /\n"
append command "#set_attribute hdl_undriven_signal_value none /\n"
}
append commands [FF::wrap_command $vars(step),set_hdl_attributes $command]
append commands [FF::source_plug pre_syn_load_elab_tcl]
append commands "\nelaborate $vars(design)\n"
append commands [FF::source_plug post_syn_load_elab_tcl]
append commands "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/elab.db\n"
append commands "redirect $vars(rpt_dir)/check_design.rpt { check_design -multidriven -undriven -unresolved }\n"
append commands "redirect $vars(rpt_dir)/report_datapath.rpt { report datapath -all -max_width {{filename 512}} }\n"
# append commands "#set treat_invalid_from_to_as_through 1\n"
if {[info exists vars(clock_gate_cells)]} {
set command "set_attribute lp_clock_gating_cell \[find /lib* -libcell $vars(clock_gate_cells)\] /designs/*\n\n"
append command "set_attribute lp_insert_clock_gating true /\n"
append commands [FF::wrap_command $vars(step),insert_clock_gating $command]
}
if {[info exists vars(leakage_power_effort)] && ($vars(leakage_power_effort) != "none")} {
set command "set_attribute lp_multi_vt_optimization_effort $vars(leakage_power_effort) /\n"
append commands [FF::wrap_command $vars(step),leakage_power_effort $command]
}
append command "#set_attribute lp_insert_operand_isolation false /\n"
append command "#set_attribute lp_power_analysis_effort low /\n"
append command "#set_attribute lp_clock_gating_hierarchical false /\n"
append command "#set_attribute lp_clock_gating_auto_cost_group_initial_target 0 /designs/*\n"
append command "#set_attribute lp_clock_gating_max_flops infinity /designs/$vars(design)\n"
append command "#set_attribute lp_clock_gating_min_flops 3 /designs/$vars(design)\n"
append command "#set_attribute lp_clock_gating_auto_path_adjust fixed /designs/*\n"
append command "#set_attribute lp_clock_gating_auto_path_adjust_fixed_delay 175 /designs/*\n"
append commands [FF::wrap_command $vars(step),set_icg_attributes $command]
# append command "#set_attribute lp_power_optimization_weight \"\" /designs/*\n"
#-----------------------------------------------------------------------
# DFT Settings
#-----------------------------------------------------------------------
set command "#set_attribute dft_scan_map_mode force_all /designs/$vars(design)\n"
append command "#set_attribute dft_scan_style muxed_scan /\n"
append command "#set_attribute dft_prefix DFT_ /\n"
append command "#set_attribute use_scan_seqs_for_non_dft true /\n"
append command "#set_attribute dft_scan_map_mode force_all /des*/*\n"
append command "#set_attribute dft_connect_shift_enable_during_mapping tie_off /designs/*\n"
append command "#set_attribute dft_connect_scan_data_pins_during_mapping loopback /designs/*\n"
append command "#set_attribute dft_scan_output_preference non_inverted /designs/*\n"
append command "#set_attribute dft_lockup_element_type edge_sensitive /designs/*\n"
append command "#set_attribute dft_mix_clock_edges_in_scan_chains false /designs/*\n"
append commands [FF::wrap_command $vars(step),set_dft_attributes $command]
append commands [FF::source_plug syn_setup_dft_tcl]
set command ""
## RC timing still comes from cpf, Innovus timing comes from setup.tcl
if {[info exists vars(cpf_file)]} {
append command "apply_power_intent -summary\n"
append commands [FF::wrap_command $vars(step),apply_power_intent $command]
} else {
append command "set mode [lindex $vars(constraint_modes) 0]\n"
append command "if { \[find / -mode \$mode \] == \"\"} {\n"
append command " create_mode -default -name \$mode\n"
append command "}\n"
foreach mode [lrange $vars(constraint_modes) 1 end] {
}
## Now populate the timing modes
foreach mode $vars(constraint_modes) {
if {[info exists vars($mode,synth_sdc)]} {
append command "if { \[find / -mode $mode\] == \"\" } {\n"
append command " create_mode -name $mode\n"
append command "}\n"
append command "read_sdc -mode $mode $vars($mode,synth_sdc)\n"
} else {
if {[info exists vars($mode,pre_cts_sdc)]} {
append command "if { \[find / -mode $mode\] == \"\" } {\n"
append command " create_mode -name $mode\n"
append command "}\n"
append command "read_sdc -mode $mode $vars($mode,pre_cts_sdc)\n"
}
}
}
append commands [FF::wrap_command $vars(step),apply_constraints $command]
append command "puts \"The number of exceptions is \[llength \[find / -exception *\]\]\"\n"
set command "\ndefine_cost_group -name in2out\n"
append command "define_cost_group -name in2reg\n"
append command "define_cost_group -name reg2out\n"
append command "define_cost_group -name reg2reg\n"
set mode [lindex $vars(constraint_modes) 0]
append command "path_group -mode $mode -from \[all::all_inps\] -to \[all::all_outs\] -group in2out -name in2out\n"
append command "path_group -mode $mode -from \[all::all_inps\] -to \[all::all_seqs\] -group in2reg -name in2reg\n"
append command "path_group -mode $mode -from \[all::all_seqs\] -to \[all::all_outs\] -group reg2out -name reg2out\n"
append command "path_group -mode $mode -from \[all::all_seqs\] -to \[all::all_seqs\] -group reg2reg -name reg2reg\n"
append commands [FF::wrap_command $vars(step),create_path_groups $command]
}
set command ""
set first 1
if {[info exists vars(def_files)]} {
foreach file $vars(def_files) {
if {[file exists $file]} {
if {$first} {
append command "read_def $file\n"
set first 0
} else {
append command "read_def -incr $file\n"
}
}
}
append commands [FF::wrap_command $vars(step),read_def $command]
}
append commands "report timing -lint\n"
if {[info exists vars(max_route_layer)]} {
append commands "\nset_attribute number_of_routing_layers $vars(max_route_layer) designs/$vars(design)\n"
}
# append commands "#foreach cg \[find / -cost_group *\] {\n"
# append commands "# report timing -cost_group [list \$cg] >> $vars(rpt_dir)/cost_group.map.rpt\n"
# append commands "#}\n"
# append commands "#set_remove_assign_options -skip_unconstrained_paths -physical\n"
# append commands "#set_attribute utilization 0 \[find / -layer M1\]\n"
append commands [FF::source_plug pre_syn_gen_tcl]
set command "\nsynthesize -to_generic -effort medium\n\n"
append commands [FF::wrap_command $vars(step),syn2gen $command]
append commands [FF::source_plug post_syn_gen_tcl]
append commands "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/syn_gen.db\n"
append commands "redirect -tee $vars(rpt_dir)/report_metric.syn_gen.rpt { report qor -nopower }\n"
append commands "redirect -append $vars(rpt_dir)/report_metric.syn_gen.rpt { report timing -full -num 250 -end }\n"
append commands "redirect -append $vars(rpt_dir)/report_metric.syn_gen.rpt { report timing -full -num 25 }\n"
append commands "generate_reports -tag syn_gen -outdir $vars(rpt_dir)\n"
set command "\nsynthesize -to_map -effort high -clock_gating_only\n\n"
append commands [FF::wrap_command $vars(step),syn2icg $command]
# set cg_cells "\n"
# foreach i [filter libcell -invert "" [find / -inst instances_seq/*]] {
# if {[get_attr clock_gating_integrated_cell [get_attr libcell $i]] != "" } {
# lappend cg_cells $i
# }
# }
# if { $cg_cells != "" } {
# set CG_ADJUST [path_adjust -delay -150 -to $cg_cells]
# }
append commands [FF::source_plug pre_syn_map_tcl]
append commands "if {\[llength \[find -mode *\]\] > 0} {\n"
append commands " redirect $vars(rpt_dir)/report_timing_lint.elab.gz { report timing -lint -verbose -mode \[lindex \[find -mode *\] 0\] }\n"
append commands "} else {\n"
append commands " redirect $vars(rpt_dir)/report_timing_lint.elab.gz { report timing -lint -verbose }\n"
append commands "}\n"
append commands "redirect $vars(rpt_dir)/report_sequential.elab.rpt.gz { report sequential -hier }\n"
append commands "redirect $vars(rpt_dir)/report_cdn_loop_breakers.elab.rpt.gz { report cdn_loop_breaker }\n"
# Synthesizing to gates using effort level defined by vars(syn_map_effort).
set command "\nsynthesize -to_mapped -effort high -no_incremental\n\n"
append commands [FF::wrap_command $vars(step),syn2map $command]
if {$vars(capture_metrics)} {
append commands "um::pop_snapshot_stack\n"
set command ""
if {[lindex [split $vars(version) "."] 0] > 16} {
if {[info exists vars(compute_metrics)] && $vars(compute_metrics)} {
append commands "create_snapshot -name $vars(step) -categories \[dict get \[get_attr metric_category_status_map\] \[get_attr state \[find / -design *\]\]\]\n"
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
} else {
append commands "create_snapshot -name $vars(step)\n"
}
append command "um::save_metric_file $vars(dbs_dir)/$vars(step).um\n"
append command "um::report_metric -file $vars(rpt_dir)/$vars(design).html -format html\n"
append commands [FF::wrap_command $vars(step),create_snapshot $command]
}
# append commands "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/syn_map.db\n"
append commands "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/syn_map.db\n"
append commands "write_hdl \[find / -design $vars(design)\] > $vars(dbs_dir)/syn_map.v.gz\n"
append commands "write_hdl \[find / -design $vars(design)\] -lec > $vars(lec_dir)/syn_map.LECONLY.v.gz\n"
# Write out RTL versus mapped LEC dofile
append commands "write_do_lec -revised $vars(lec_dir)/syn_map.LECONLY.v.gz -logfile rtl2map.log > $vars(lec_dir)/rtl2map.dof\n"
set command "redirect $vars(lec_dir)/deleted_sequentials.rpt {report sequential -deleted_seqs}\n"
append command "redirect -tee $vars(rpt_dir)/syn_map.qor.rpt { report qor -nopower }\n"
append command "redirect -append $vars(rpt_dir)/syn_map.qor.rpt { report timing -full -num 250 -end }\n"
append command "redirect -append $vars(rpt_dir)/syn_map.qor.rpt { report timing -full -num 25 }\n"
append command "generate_reports -tag syn_map -outdir $vars(rpt_dir)\n"
append commands [FF::wrap_command $vars(step),generate_reports $command]
if {[info exists vars(mail,to)]} {
set summary_file $vars(step).qor.rpt
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[sh pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " exec gunzip -c $vars(rpt_dir)/${summary_file}.gz \| /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[sh pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
return $commands
}
proc run_syn_incr {{format 1}} {
global vars
global env
global errors
set vars(step) syn_incr
set commands ""
append commands "proc Puts {args} {puts \$args}\n"
append commands "puts \[get_attr program_version /\]\n"
## enable multi processing
append commands "set hostlist \[lrepeat $vars(local_cpus) localhost\]\n"
append commands "set_attribute super_thread_servers \$hostlist /\n"
if {$vars(capture_metrics)} {
append commands "\num::enable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
append commands [FF::source_plug pre_syn_incr_tcl]
# append commands "catch { set_remove_assign_options -skip_unconstrained_paths -physical }\n"
# append commands "set_attribute remove_assigns true /\n"
if {$vars(enable_pam)} {
append commands "\nset_attribute physical_aware_restructuring true /des*/*\n"
append commands "set_attribute physical_aware_structuring true /des*/*\n"
append commands "set_attribute physical_aware_mapping true /des*/*\n"
}
#### OPTIMIZATION EFFORT CONTROL
if {$vars(high_timing_effort)} {
set command "\nset_attribute tns_opto true /\n"
append command "set_attribute iopt_enable_parallelization true /\n"
append command "set_attribute ultra_global_mapping true /\n"
append command "set_attribute iopt_ultra_optimization true /\n"
append commands [FF::wrap_command $vars(step),set_high_effort_attributes $command]
}
set command "#set_attribute optimize_merge_flops false /\n"
append command "#set_attribute optimize_constant_0_flops true /\n"
append command "#set_attribute optimize_constant_1_flops false /\n"
append command "#set_attribute optimize_constant_latches false /\n"
append command "#set_attribute delete_unloaded_seqs true /\n"
append command "#set_attribute optimize_net_area false /\n"
append command "#set_attribute dp_area_mode true /\n"
append command "#set_attribute auto_ungroup none /\n"
append command "#set_attribute auto_ungroup_min_effort low /\n"
append command "#set_attribute ungroup_separator /\n"
append commands [FF::wrap_command $vars(step),set_opt_attributes $command]
### Detail Stats while running
# append commands "#set iopt_stats 1\n"
#-----------------------------------------------------------------------
# Max leakage power ?
#-----------------------------------------------------------------------
# append commands "#set_attribute max_leakage_power ? /designs/*\n"
set command "\nsynthesize -to_mapped -effort high -incr\n\n"
append commands [FF::wrap_command $vars(step),syn2incr $command]
append commands [FF::source_plug post_syn_incr_tcl]
append commands "foreach cg \[find / -cost_group *\] {\n"
append commands " report timing -cost_group \$cg >> $vars(rpt_dir)/syn_incr_\[file tail \$cg\].rpt\n"
append commands "}\n"
set command "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).db\n"
# append command "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).db\n"
append commands [FF::wrap_command $vars(step),write_db $command]
set command "write_hdl \[find / -design $vars(design)\] > $vars(dbs_dir)/$vars(step).v.gz\n"
append command "write_hdl \[find / -design $vars(design)\] -lec > $vars(lec_dir)/$vars(step).LECONLY.v.gz\n"
append commands [FF::wrap_command $vars(step),write_hdl $command]
if {$vars(capture_metrics)} {
append commands "um::pop_snapshot_stack\n"
if {[lindex [split $vars(version) "."] 0] > 16} {
if {[info exists vars(compute_metrics)] && $vars(compute_metrics)} {
append commands "create_snapshot -name $vars(step) -categories \[dict get \[get_attr metric_category_status_map\] \[get_attr state \[find / -design *\]\]\]\n"
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
} else {
append commands "create_snapshot -name $vars(step)\n"
}
append commands "um::save_metric_file $vars(dbs_dir)/$vars(step).um\n"
append commands "um::report_metric -file $vars(rpt_dir)/$vars(design).html -format html\n"
}
if {!$vars(enable_rcp)} {
set command "\nwrite_design -innovus -gzip -basename $vars(dbs_dir)/$vars(step)/$vars(step)\n"
append command "set file \[open $vars(dbs_dir)/$vars(step)/$vars(step).novus_setup.tcl w\]\n"
append command "puts \$file \"eval_enc \{source $vars(dbs_dir)/$vars(step)/$vars(step).enc_setup.tcl\}\"\n"
append command "close \$file\n\n"
append commands [FF::wrap_command $vars(step),write_design $command]
}
# Write out RTL versus mapped LEC dofile
append commands "write_do_lec -revised $vars(lec_dir)/$vars(step).LECONLY.v.gz -logfile rtl2incr.log > $vars(lec_dir)/rtl2incr.dof\n"
set command "redirect $vars(lec_dir)/deleted_sequentials.rpt {report sequential -deleted_seqs}\n"
append command "redirect -tee $vars(rpt_dir)/$vars(step).qor.rpt { report qor -nopower }\n"
append command "redirect -append $vars(rpt_dir)/$vars(step).qor.rpt { report timing -full -num 250 -end }\n"
append command "redirect -append $vars(rpt_dir)/$vars(step).qor.rpt { report timing -full -num 25 }\n"
append command "generate_reports -tag $vars(step) -outdir $vars(rpt_dir)/generate_reports\n"
append commands [FF::wrap_command $vars(step),generate_reports $command]
if {[info exists vars(mail,to)]} {
set summary_file $vars(step).qor.rpt
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[sh pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " exec gunzip -c $vars(rpt_dir)/${summary_file}.gz \| /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[sh pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
return $commands
}
proc run_syn_place {{format 1}} {
global vars
global env
global errors
set vars(step) syn_place
set commands ""
append commands "proc Puts {args} {puts \$args}\n"
append commands "puts \[get_attr program_version /\]\n"
## enable multi processing
append commands "set hostlist \[lrepeat $vars(local_cpus) localhost\]\n"
append commands "set_attribute super_thread_servers \$hostlist /\n"
if {$vars(capture_metrics)} {
append commands "\um::nenable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
if {[info exists vars(postload_syn_place_tcl)]} {
append commands "set_attribute enc_postload_script $vars(postload_syn_place_tcl) /\n"
}
if {[info exists vars(preexport_syn_place_tcl)]} {
append commands "set_attribute enc_preexport_script $vars(preexport_syn_place_tcl) /\n"
}
if {[info exists vars(preannotation_syn_placed_tcl)]} {
append commands "set_attribute enc_preannotation_tcl $vars(preannotation_syn_placed_tcl) /\n"
}
append commands "set_attribute enc_temp_dir ./INNOVUS/rcp_run /\n"
append commands "set_attribute enc_gzip_interface_files true /\n"
append commands "set_attribute pqos_placement_effort no_value /\n"
append commands "set ::phys::pqos_tns_opt 1\n"
append commands "set_attribute iopt_enable_parallelization false /\n"
# if {[info exists vars(def_files)]} {
# foreach file $vars(def_files) {
# if {[file exists $file]} {
# set command "read_def $vars(def_files)\n"
# append commands [FF::wrap_command $vars(step),read_def $command]
# }
# }
# }
append commands [FF::source_plug pre_syn_place_tcl]
set command "\nsynthesize -to_placed -effort high -pqos_only\n\n"
append command "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).db\n"
append commands [FF::wrap_command $vars(step),syn2place $command]
set command "\nsynthesize -to_placed -effort high -incr\n\n"
append commands [FF::wrap_command $vars(step),syn2place_incr $command]
append commands [FF::source_plug post_syn_place_tcl]
append commands "::phys::qos_stats -quiet -tag syn2placed\n"
append commands "::phys::qos_write_stats_array > $vars(rpt_dir)/qos_stats.qdb\n"
append commands "::phys::qos_summary\n"
append commands "foreach cg \[find / -cost_group *\] {\n"
append commands " report timing -cost_group \$cg >> $vars(rpt_dir)/syn_place_\[file tail \$cg\].rpt\n"
append commands "}\n"
if {$vars(capture_metrics)} {
append commands "um::pop_snapshot_stack\n"
if {[lindex [split $vars(version) "."] 0] > 16} {
if {[info exists vars(compute_metrics)] && $vars(compute_metrics)} {
append commands "create_snapshot -name $vars(step) -categories \[dict get \[get_attr metric_category_status_map\] \[get_attr state \[find / -design *\]\]\]\n"
} else {
append commands "create_snapshot -name $vars(step) -categories design\n"
}
} else {
append commands "create_snapshot -name $vars(step)\n"
}
append commands "um::save_metric_file $vars(dbs_dir)/$vars(step).um\n"
append commands "um::report_metric -file $vars(rpt_dir)/$vars(design).html -format html\n"
}
set command "write_db $vars(design) -script $vars(dbs_dir)/$vars(step)_db_scr.tcl -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).db\n"
append command "write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).db\n"
append commands [FF::wrap_command $vars(step),write_db $command]
set command "write_hdl \[find / -design $vars(design)\] > $vars(dbs_dir)/$vars(step).v.gz\n"
append command "write_hdl \[find / -design $vars(design)\] -lec > $vars(lec_dir)/$vars(step).LECONLY.v.gz\n"
append commands [FF::wrap_command $vars(step),write_hdl $command]
if {$vars(enable_rcp)} {
set command "\nwrite_design -innovus -gzip -basename $vars(dbs_dir)/$vars(step)/$vars(step)\n"
append command "set file \[open $vars(dbs_dir)/$vars(step)/$vars(step).novus_setup.tcl w\]\n"
append command "puts \$file \"eval_enc \{source $vars(dbs_dir)/$vars(step)/$vars(step).enc_setup.tcl\}\"\n"
append command "close \$file\n\n"
append commands [FF::wrap_command $vars(step),write_design $command]
}
# Write out RTL versus mapped LEC dofile
append commands "write_do_lec -revised $vars(lec_dir)/$vars(step).LECONLY.v.gz -logfile rtl2incr.log > $vars(lec_dir)/rtl2incr.dof\n"
set command "redirect $vars(lec_dir)/deleted_sequentials.rpt {report sequential -deleted_seqs}\n"
append command "redirect -tee $vars(rpt_dir)/$vars(step).qor.rpt { report qor -nopower }\n"
append command "redirect -append $vars(rpt_dir)/$vars(step).qor.rpt { report timing -full -num 250 -end }\n"
append command "redirect -append $vars(rpt_dir)/$vars(step).qor.rpt { report timing -full -num 25 }\n"
append command "generate_reports -tag $vars(step) -outdir $vars(rpt_dir)/generate_reports\n"
append commands [FF::wrap_command $vars(step),generate_reports $command]
if {[info exists vars(mail,to)]} {
set summary_file $vars(step).qor.rpt
if {![info exists vars(mail,steps)] || \
([info exists vars(mail,steps)] && ([lsearch $vars(mail,steps) $vars(step)] != -1))} {
append commands "puts \"<FF> MAILING RESULTS TO $vars(mail,to)\"\n"
append commands "if {\[file exists $vars(rpt_dir)/$summary_file\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[sh pwd\])\" < $vars(rpt_dir)/$summary_file $vars(mail,to)\n"
append commands "} elseif {\[file exists $vars(rpt_dir)/${summary_file}.gz\]} {\n"
append commands " exec gunzip -c $vars(rpt_dir)/${summary_file}.gz \| /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" $vars(mail,to)\n"
append commands "} else {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[sh pwd\])\" < /dev/null $vars(mail,to)\n"
append commands "}\n"
}
}
append commands [FF::wrap_command $vars(step),schedule_flow $command]
append commands "if {\[info exists env(VPATH)\]} {"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)"
append commands "}\n"
return $commands
}
proc run_init {{format 1}} {
global vars
global env
global errors
global warnings
global env
set commands ""
set ucomments ""
set comments ""
if {[info exists vars(view_definition_tcl)]} {
append comments "# - vars(view_definition_tcl)\n"
}
if {![info exists vars(step)] || (($vars(step) != "partition_place") && ($vars(step) != "model_gen") && ($vars(step) != "prototype"))} {
append commands "set vars(step) init\n"
set vars(step) init
}
if {$vars(report_run_time)} {
append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
append comments "# - vars(report_run_time)\n"
} else {
append ucomments "# - vars(report_run_time)\n"
}
if {[info exists vars($vars(step),rpt_dir)]} {
set vars(rpt_dir) $vars($vars(step),rpt_dir)
file mkdir $vars($vars(step),rpt_dir)
} else {
set vars(rpt_dir) $vars(orig_rpt_dir)
}
###############################################################################
# Make sure necessary data is defined
# Create make directory if it doesn't exists
###############################################################################
if {!$vars(codegen)} {
set command "FF_EDI::check_setup\n"
append command "sleep 3\n"
uplevel #0 eval $command
}
###############################################################################
# Make sure necessary data is defined
###############################################################################
if {![info exists env(VPATH)]} {
set env(VPATH) "make"
}
append commands "exec mkdir -p \$env(VPATH)\n"
if {$vars(backup_data)} {
puts "# <FF> BACKING UP PRIOR RUN DATA IF IT EXISTS...\n"
set date [string toupper [clock format [clock seconds] -format {%h%d_%H:%M}]]
exec mkdir -p BACKUP/$date
# BCL: Added subst to handle dererencing variables
foreach dir "[subst $vars(dbs_dir)] [subst $vars(rpt_dir)] [subst $vars(log_dir)]" {
if {[file isdirectory $dir]} {
exec mv $dir BACKUP/$date
# BCL: Changed to file mkdir
puts "Making $dir"
file mkdir $dir
}
}
# append commands "sleep 5\n"
}
# BCL: Added subst to handle dererencing variables
foreach dir "[subst $vars(dbs_dir)] [subst $vars(rpt_dir)] [subst $vars(log_dir)]" {
set newDir [subst $dir]
if {![file exists $newDir]} {
file mkdir $newDir
}
}
###############################################################################
# Load pre-initializatiaon plug-in script
###############################################################################
append commands [FF::source_plug pre_init_tcl]
###############################################################################
# These flow scripts support the following:
# - Flat chip or block
# - Hierarchical partition
# - Top level partition
#
# The data loading mechanism are slightly different for each so we determine
# first if we are in a hierarchical flow (i.e. vars(partition_list) is
# defined and, if so, whether we are in a hierarchical partition flow
# or a top partition flow (i.e. cwd == $vars(design) - see below)
#
###############################################################################
FF_EDI::check_flow
# append commands "#---------------------------------------------------------------------\n"
# append commands "# EXECUTING FLOW\n"
# append commands "#---------------------------------------------------------------------\n"
set hier 0
if {[info exists vars($vars(step),starting_dbs)]} {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
# Interpret the starting DBS as an OA triple
set restore_command "[list restoreDesign -cellview $vars($vars(step),starting_dbs)]\n"
} else {
if {[file isdirectory $vars($vars(step),starting_dbs)]} {
set restore_command "restoreDesign $vars($vars(step),starting_dbs) $vars(design)\n"
} elseif {[file exists $vars($vars(step),starting_dbs)]} {
set restore_command "restoreDesign $vars($vars(step),starting_dbs).dat $vars(design)\n"
} else {
puts "<FF> Starting DBS ($vars($vars(step),starting_dbs)) defined but does not exist"
set restore_command "restoreDesign $vars($vars(step),starting_dbs).dat $vars(design)\n"
set warnings($vars(warning_count)) "Starting DBS ($vars($vars(step),starting_dbs)) defined but does not exist"
incr vars(warning_count)
}
}
append commands [FF::wrap_command $vars(step),restore_design $restore_command]
} else {
if {![info exists vars(partition_list)] || ([info exists vars(partition_list)] && \
([file tail [file dirname [pwd]]] != "$vars(partition_dir)"))} {
###############################################################################
# Partition step or flat init step
###############################################################################
if {[info exists vars(partition_list)]} {
set hier 1
}
if {$vars(verbose)} {
if {![info exists vars(partition_list)]} {
append commands "#\n"
append commands "# FLAT IMPLEMENTATION FLOW\n"
append commands "#\n"
} else {
append commands "#\n"
append commands "# PARTITIONING FLOW\n"
append commands "#\n"
}
}
if {$vars(verbose)} {
append commands "#\n"
append commands "# LOADING DESIGN DATA\n"
append commands "#\n"
}
###############################################################################
# Load design configuration file
###############################################################################
if {[lindex [split $vars(version) "."] 0] <= 10} {
source $vars(script_path)/ETC/INNOVUS/generic.conf
}
if {$vars(ilm)} {
set ilm_list $vars(ilm_list)
append comments "# - vars(ilm_list) \"<list of ILMs>\"\n"
if {$vars(mode) == "bottom_up"} {
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)]} {
append comments "# - vars(<ilm>,ilm_dir) \"<path to ILM directory>\"\n"
if {[lsearch $ilm_list $part] == -1} {
lappend ilm_list $part
}
}
}
}
foreach ilm $ilm_list {
if {[info exists vars($ilm,lef_file)] && [file exists $vars($ilm,lef_file)]} {
append comments "# - vars(<ilm>,lef_file) \"<LEF file for block associated with ILM>\"\n"
if {[lindex [split $vars(version) "."] 0] <= 10} {
lappend rda_Input(ui_leffile) $vars($ilm,lef_file)
} else {
if {[string compare $vars(dbs_format) "fe"]==0} {
lappend vars(lef_files) $vars($ilm,lef_file)
}
}
} else {
puts "<FF> WARNING: LEF file either not defined or doesn't exist for $ilm"
puts "<FF> Please make sure it is in your vars(lef_files) list"
set warnings($vars(warning_count)) "LEF file either not defined or doesn't exist for $ilm\n\tPlease make sure it is in your vars(lef_files) list"
incr vars(warning_count)
}
if {[info exists vars($ilm,setup_lib)] && [file exists $vars($ilm,setup_lib)]} {
append comments "# - vars(<ilm>,setup_lib) \"<LIB file for block associated with ILM>\"\n"
if {[lindex [split $vars(version) "."] 0] <= 10} {
lappend rda_Input(ui_timelib) $vars($ilm,setup_lib)
} else {
if {[string compare $vars(dbs_format) "fe"]==0} {
foreach set $vars(library_sets) {
if {[lsearch $vars($set,timing) $vars($ilm,setup_lib)] == -1} {
lappend vars($set,timing) $vars($ilm,setup_lib)
}
}
}
}
} else {
puts "<FF> WARNING: LIB file either not defined or doesn't exist for $ilm"
puts "<FF> Please make sure it is in your library set definitions"
set warnings($vars(warning_count)) "LIB file either not defined or doesn't exist for $ilm\n\tPlease make sure it is in your library set definitions"
incr vars(warning_count)
}
}
} else {
append ucomments "# - vars(ilm_list) \"<list of ILMs>\"\n"
append ucomments "# - vars(<ilm>,ilm_dir) \"<path to ILM directory>\"\n"
append ucomments "# - vars(<ilm>,lef_file) \"<LEF file for block associated with ILM>\"\n"
append ucomments "# - vars(<ilm>,setup_lib) \"<LIB file for block associated with ILM>\"\n"
}
FF_EDI::dump_config
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadConfig \$vars(script_dir)/run.conf\n"
append commands [FF::wrap_command $vars(step),load_config $command]
} else {
if {[string compare -nocase $vars(netlist_type) "verilog"]>=0} {
# set command "source \$vars(script_dir)/init.tcl\n"
if {$vars(generate_flow_steps)} {
set command ""
set ip [open $vars(script_dir)/init.tcl r]
while {[gets $ip line]>=0} {
append command "$line\n"
}
} else {
set command "source $vars(script_dir)/init.tcl\n"
}
append command "init_design\n"
append commands [FF::wrap_command $vars(step),init_design $command]
} else {
if {$hier} {
if {$vars(step) == "partition_place"} {
set command "restoreDesign -cellview \[list $vars(oa_design_lib) $vars(oa_design_cell) $vars(oa_design_view)\]\n"
} else {
set command "restoreDesign -cellview \[list $vars(oa_partition_lib) $vars(oa_design_cell) $vars(oa_design_view)\]\n"
}
} else {
set command "restoreDesign -cellview \[list $vars(oa_design_lib) $vars(oa_design_cell) $vars(oa_design_view)\]\n"
}
append commands [FF::wrap_command $vars(step),restore_design $command]
}
# if {!$vars(codegen)} {
# Puts "<FF> ---------------------------------------"
# Puts "<FF> $commands"
# Puts "<FF> ---------------------------------------"
# uplevel #0 eval $commands
# set commands ""
# }
}
if {$vars(capture_metrics)} {
# if {($vars(step) != "partition_place") && ($vars(step) != "model_gen") && ($vars(step) != "prototype")} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append commands "um::enable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
# }
}
###############################################################################
# Load "always source" plug-in script
###############################################################################
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Check for the existence of either a floorplan file, a
# DEF file, or both and load them
###############################################################################
set command ""
if {[info exists vars(fp_tcl_file)] || [info exists vars(fp_tcl_proc)]} {
append comments "# - vars(fp_tcl_file)\n"
append comments "# - vars(fp_tcl_proc)\n"
if {[info exists vars(fp_tcl_file)] && ![info exists vars(fp_tcl_proc)]} {
append command "ff_procs::source_file $vars(fp_tcl_file)\n"
} elseif {![info exist vars(fp_tcl_file)] && [info exists vars(fp_tcl_proc)]} {
append command "$vars(fp_tcl_proc)\n"
} else {
append command "# ERROR: Both fp_tcl_file and fp_tcl_proc are defined but are mutually exclusive\n"
set errors($vars(error_count)) "Both fp_tcl_file and fp_tcl_proc are defined but are mutually exclusive"
incr vars(error_count)
}
} else {
append ucomments "# - vars(fp_tcl_file)\n"
append ucomments "# - vars(fp_tcl_proc)\n"
if {[info exists vars(fp_file)]} {
if {[file exists $vars(fp_file)]} {
# append command "Puts \"<FF> LOADING FP FILE $vars(fp_file)\"\n"
append command "loadFPlan $vars(fp_file)\n"
}
append comments "# - vars(fp_file)\n"
} else {
append ucomments "# - vars(fp_file)\n"
}
if {[info exists vars(oa_fp)]} {
append command "oaIn $vars(oa_fp)\n"
append comments "# - vars(oa_fp)\n"
} else {
append ucomments "# - vars(oa_fp)\n"
}
if {[info exists vars(def_files)]} {
append comments "# - vars(def_files)\n"
if {$vars(rc)} {
if {$vars(enable_rcp)} {
set vars(netlist) $vars(dbs_dir)/syn_place/syn_place.v.gz
set vars(def_files) $vars(dbs_dir)/syn_place/syn_place.def.gz
if {[info exists vars(insert_dft)] && $vars(insert_dft)} {
lappend vars(def_files) $vars(dbs_dir)/syn_place/syn_place.scan.def.gz
}
} else {
set vars(netlist) $vars(dbs_dir)/syn_incr/syn_incr.v.gz
# set vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.def.gz
if {[info exists vars(insert_dft)] && $vars(insert_dft)} {
lappend vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.scan.def.gz
}
}
foreach def_file $vars(def_files) {
append command "defIn $def_file\n"
}
} else {
foreach def_file $vars(def_files) {
if {[file exists $def_file]} {
append command "defIn $def_file\n"
append comments "# - vars(def_files)\n"
} else {
append ucomments "# - vars(def_files)\n"
}
}
}
} else {
if {$vars(rc)} {
if {$vars(enable_rcp)} {
set vars(netlist) $vars(dbs_dir)/syn_place/syn_place.v.gz
set vars(def_files) $vars(dbs_dir)/syn_place/syn_place.def.gz
if {[info exists vars(insert_dft)] && $vars(insert_dft)} {
lappend vars(def_files) $vars(dbs_dir)/syn_place/syn_place.scan.def.gz
}
} else {
set vars(netlist) $vars(dbs_dir)/syn_incr/syn_incr.v.gz
set vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.def.gz
if {[info exists vars(insert_dft)] && $vars(insert_dft)} {
lappend vars(def_files) $vars(dbs_dir)/syn_incr/syn_incr.scan.def.gz
}
}
} else {
append ucomments "# - vars(def_files)\n"
}
}
}
append commands [FF::wrap_command $vars(step),load_floorplan $command]
if {($vars(parent) == "rc") && $vars(rc)} {
set commands [FF::source_plug always_source_tcl]
if {$vars(report_run_time)} {
append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
}
append commands [FF::source_plug pre_init_tcl]
}
# if {[info exists vars(guides)]} {
# set command "\nbuild_guides\n"
# append commands [FF::wrap_command init,build_guides $command]
# }
# if {[info exists vars(blockages)]} {
# set command "\nadd_blockages\n"
# append commands [FF::wrap_command init,add_blockages $command]
# }
if {[lindex [split $vars(version) "."] 0] < 15} {
if {$vars(generate_tracks)} {
set command "generateTracks\n"
if {[info exists vars(honor_pitch)] && $vars(honor_pitch)} {
set command " generateTracks -honorPitch\n"
}
append commands [FF::wrap_command $vars(step),generate_tracks $command]
append comments "# - vars(generate_tracks)\n"
} else {
append ucomments "# - vars(generate_tracks)\n"
}
} else {
if {$vars(add_tracks)} {
set command "add_tracks\n"
if {[info exists vars(honor_pitch)] && $vars(honor_pitch)} {
set command " add_tracks -honor_pitch\n"
}
append commands [FF::wrap_command $vars(step),add_tracks $command]
append comments "# - vars(add_tracks)\n"
} else {
append ucomments "# - vars(add_tracks)\n"
}
}
###############################################################################
# Specify ILMs if defined
###############################################################################
if {[info exists ilm_list] && ($ilm_list != "")} {
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $cell\n"
} else {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
}
}
} else {
puts "<FF> ERROR: ilm directory missing for $cell"
set errors($vars(error_count)) "ILM directory missing for $cell"
incr vars(error_count)
}
}
append commands [FF::wrap_command $vars(step),derate_timing [FF_EDI::derate_timing mmmc]]
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm "setIlmMode -keepFlatten true\n${command}flattenIlm\n"]
# append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
}
if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
if {[file exists $vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set lcommand "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set lcommand "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $lcommand]
}
append comments "# - vars(ilm_non_sdc_file)\n"
} else {
append ucomments "# - vars(ilm_non_sdc_file)\n"
}
###############################################################################
# Define power intent if it is defined (low power flow)
###############################################################################
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
if {[info exists vars(activity_file)]} {
# append commands $header
# set header ""
set command "readActivityFile -format $vars(activity_file_format) $vars(activity_file)\n"
append commands [FF::wrap_command $vars(step),read_activity_file $command]
append comments "# - vars(activity_file)\n"
append comments "# - vars(activity_file_format)\n"
} else {
append ucomments "# - vars(activity_file)\n"
append ucomments "# - vars(activity_file_format)\n"
}
###############################################################################
# Load timing enviroment based on the flow setting in the
# setup.tcl file. If the flow is mmmc, load the mmmc setup
# here else load the default timing environment
###############################################################################
# append commands "#\n"
# append commands "# SETTING UP TIMING ENVIRONMENT\n"
# append commands "#\n"
if {$vars(flow) == "mmmc"} {
set command [FF_EDI::initialize_timing mmmc]
} else {
set command [FF_EDI::initialize_timing minmax]
}
# foreach var [array name vars] {
# if {($var != "step") && ($var != "mode") && ($var != "ilm") && \
# ($var != "flavor") && ($var != "user_mode") && ($var != "flat") && \
# ($var != "report_run_time") && ($var != "makefile") && ($var != "codegen") && \
# ($var != "backup_data") && ($var != "verbose") && ($var != "format_lines") && \
# ($var != "warning_count") && ($var != "error_count") && ($var != "rc") && \
# ($var != "generate_tracks") && ($var != "fix_hold") && ($var != "honor_pitch") && \
# ($var != "script_path") && ($var != "fix_hold") && ($var != "honor_pitch") && \
# ($var != "steps") && ($var != "sourced") && ($var != "version")} {
# set vars($var) "\\\$vars($var)"
# }
# }
append commands [FF::wrap_command $vars(step),initialize_timing $command]
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "set_power_analysis_mode -analysis_view $vars(power_analysis_view)\n"
append commands [FF::wrap_command $vars(step),set_power_analysis_mode $command]
}
if {!$vars(ilm) && ($vars(flow) == "mmmc")} {
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
###############################################################################
# Load scan DEF if it exists
###############################################################################
if {[info exists vars(scan_def)]} {
if {[file exists $vars(scan_def)]} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# <FF> LOADING SCAN DEF FILE\n"
append commands "#\n"
}
set command "defIn $vars(scan_def)\n"
append commands [FF::wrap_command $vars(step),load_scan $command]
}
append comments "# - vars(scan_def)\n"
} else {
append ucomments "# - vars(scan_def)\n"
}
###############################################################################
# Specify spare gates for placement and optimization consideration; this assumes
# the spare cells are in the netlist.
###############################################################################
set command ""
if {[info exists vars(spare_cells)]} {
foreach spare_cell $vars(spare_cells) {
append command "specifySpareGate -inst $spare_cell\n"
}
append comments "# - vars(spare_cells)\n"
} else {
append ucomments "# - vars(spare_cells)\n"
}
append commands [FF::wrap_command $vars(step),specify_spare_gates $command]
###############################################################################
# Load the recommended command mode settings
###############################################################################
if {$vars(verbose)} {
append commands "#\n"
append commands "# DEFINING MODE SETTINGS\n"
append commands "#\n"
}
###############################################################################
# Set don't use cells; disable some (clock buffers, strong buffers, etc.),
# enable others that may have "dont_use true" in the library (like delay cells
# for hold fixing)
###############################################################################
set command ""
if {[info exists vars(dont_use_list)]} {
foreach cell $vars(dont_use_list) {
append command "setDontUse $cell true\n"
}
append comments "# - vars(dont_use_list)\n"
} else {
append ucomments "# - vars(dont_use_list)\n"
}
if {[info exists vars(dont_use_file)] && [file exists $vars(dont_use_file)]} {
append command "source $vars(dont_use_file)\n"
append comments "# - vars(dont_use_file)\n"
} else {
append ucomments "# - vars(dont_use_file)\n"
}
if {[info exists vars(use_list)]} {
foreach cell $vars(use_list) {
append command "setDontUse $cell false\n"
}
append comments "# - vars(use_list)\n"
} else {
append ucomments "# - vars(use_list)\n"
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),set_dont_use $command]
}
###############################################################################
# Set maximum routing layers
###############################################################################
if {[info exists vars(max_route_layer)]} {
set command "setMaxRouteLayer $vars(max_route_layer)\n"
append commands [FF::wrap_command $vars(step),set_max_route_layer $command]
append comments "# - vars(max_route_layer)\n"
} else {
append ucomments "# - vars(max_route_layer)\n"
}
###############################################################################
# Set design mode
###############################################################################
append commands [lindex [FF_EDI::set_design_mode] 0]
append comments [lindex [FF_EDI::set_design_mode] 1]
append ucomments [lindex [FF_EDI::set_design_mode] 2]
###############################################################################
# Insert welltaps and pre/post endcaps
###############################################################################
if {([FF::get_by_suffix vars "welltaps"] != "") ||
(([FF::get_by_suffix vars "pre_endcap"] != "") &&
([FF::get_by_suffix vars "post_endcap"] != ""))} {
set command [FF_EDI::insert_welltaps_endcaps]
append commands [FF::wrap_command $vars(step),insert_welltaps_endcaps $command]
append comments "# - vars(welltaps)\n"
append comments "# - vars(pre_endcap)\n"
append comments "# - vars(post_endcap)\n"
} else {
append ucomments "# - vars(welltaps)\n"
append ucomments "# - vars(pre_endcap)\n"
append ucomments "# - vars(post_endcap)\n"
}
} else {
###############################################################################
# Partition init step
###############################################################################
set ptn [file tail [pwd]]
set vars(design) $ptn
set skip_cpf false
set skip_1801 false
###############################################################################
if {[lsearch $vars(partition_list) $ptn] == -1} {
append commands "#------------------------------------------------------------\n"
append commands "# TOP ($ptn) IMPLEMENTATION FLOW\n"
append commands "#------------------------------------------------------------\n"
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadConfig $ptn.conf 0\n"
if {[info exists vars(save_ilm_non_sdc_file)]} {
set vars(ilm_non_sdc_file) $vars(save_ilm_non_sdc_file)
}
append command "global rda_Input\n"
foreach part $vars(partition_list) {
append command "lappend rda_Input(ui_leffile) ../$part/$part.antenna.lef\n"
}
append command "commitConfig\n"
append commands [FF::wrap_command $vars(step),load_config $command]
} else {
if {[string compare $vars(dbs_format) "oa"]==0} {
set command "restoreDesign -cellView \[list $vars(oa_partition_lib) $ptn layout\]\n"
} else {
if {$vars(use_flexmodels)} {
if {$vars(flexmodel_as_ptn)} {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "restoreDesign ${ptn}_proto_eco.enc.dat $ptn\n"
} else {
set command "restoreDesign ${ptn}_proto_full.enc.dat $ptn\n"
}
} else {
set command "restoreDesign . $ptn\n"
append command "ff_replace_flexmodel_with_full_netlist\n"
}
} else {
set command "restoreDesign . $ptn\n"
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append commands "um::enable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
}
# foreach part $vars(partition_list) {
# append command "if {\[file exists ../$part/$part.antenna.lef\]} {\n"
# append command "loadLefFile ../$part/$part.antenna.lef\n"
# append command "}\n"
# }
# set command "source $ptn.globals\n"
# foreach part $vars(partition_list) {
# append command "lappend init_lef_file ../$part/$part.antenna.lef\n"
# }
# append command "init_design\n"
}
append commands [FF::wrap_command $vars(step),restore_design $command]
set restore_design true
if {$vars(top)} {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file [file normalize $vars(view_definition_tcl)]
} else {
set mmmc_file [file normalize $vars(script_dir)/view_definition.tcl]
}
if {$vars(enable_flexilm)} {
set command ""
set dirs ""
foreach block $vars(partition_list) {
append dirs "\\\n -flex_ilm {${block} ../${block}/${block}.flexilm}"
}
set command "commit_module_model $dirs\\\n"
if {[info exists vars(cpf_file)]} {
append command " -mmmc_file $vars(mmmc_file)\\\n"
append command " -cpf_file $vars(cpf_file)\n"
set skip_cpf true
} elseif {[info exists vars(ieee1801_file)]} {
append command " -mmmc_file $vars(mmmc_file)\\\n"
append command " -1801 $vars(ieee1801_file)\n"
set skip_1801 true
} else {
append command " -mmmc_file $vars(mmmc_file)\n"
}
append commands [FF::wrap_command $vars(step),commit_module_model $command]
}
}
}
} else {
append commands "#------------------------------------------------------------\n"
append commands "# PARTITION ($ptn) IMPLEMENTATION FLOW\n"
append commands "#------------------------------------------------------------\n"
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadConfig $ptn.conf\n"
append commands [FF::wrap_command $vars(step),load_config $command]
} else {
if {$vars(use_flexmodels)} {
if {$vars(flexmodel_as_ptn)} {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "restoreDesign ${ptn}_proto_eco.enc.dat $ptn\n"
} else {
set command "restoreDesign ${ptn}_proto_full.enc.dat $ptn\n"
}
} else {
set command "restoreDesign . $ptn\n"
append command "ff_replace_flexmodel_with_full_netlist\n"
}
} else {
if {[string compare $vars(dbs_format) "oa"]==0} {
set command "restoreDesign -cellView \[list $vars(oa_partition_lib) $ptn layout\]\n"
} else {
set command "restoreDesign . $ptn\n"
# set command "source $ptn.globals\n"
# append command "init_design\n"
}
}
append commands [FF::wrap_command $vars(step),restore_design $command]
set restore_design true
}
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append commands "um::enable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
}
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load floorplan file or DEF; use defIn to load a DEF file
###############################################################################
if {[string compare $vars(dbs_format) "fe"]==0} {
if {![info exists restore_design]} {
append commands "loadFPlan $ptn.fp\n"
append commands "source $ptn.mode\n"
if {[file exists $ptn.scan.def]} {
append commands "Puts \"<FF> LOADING SCAN DEF FILE $ptn.scan.def\"\n"
append commands "defIn $ptn.scan.def\n"
}
}
}
###############################################################################
# Override maximum routing layer if defined for the partition
###############################################################################
if {[info exists vars($ptn,max_route_layer)]} {
append commands "setMaxRouteLayer $vars($ptn,max_route_layer)\n"
append comments "# - vars(max_route_layer)\n"
} else {
append ucomments "# - vars(max_route_layer)\n"
}
###############################################################################
# Specify the ILM models for the top partition
###############################################################################
if $vars(top) {
if {!$vars(enable_flexilm)} {
set command ""
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)] && ($vars(codegen) || [file isdirectory $vars($part,ilm_dir)])} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
}
}
} else {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
}
}
}
}
append commands [FF::wrap_command $vars(step),setIlmMode "setIlmMode -keepFlatten true\n"]
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
set command ""
foreach part $vars(partition_list) {
append command "if {\[file exists ../$part/$part.antenna.lef\]} {\n"
append command " loadLefFile ../$part/$part.antenna.lef\n"
append command "}\n"
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),load_lef_file $command]
}
if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
if {[file exists $vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
set command [FF_EDI::initialize_timing mmmc]
# if {![info exists vars(cpf_file)]} {
append commands [FF::wrap_command $vars(step),initialize_timing $command]
# } else {
# set defer_commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
}
}
###############################################################################
# Load power intent (if it is defined)
###############################################################################
if {([info exists vars(cpf_file)]) && ($vars(cpf_file) != "") && !$skip_cpf} {
set save $vars(cpf_file)
if {!$vars(top)} {
set vars(cpf_file) "$ptn.cpf"
}
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
set vars(cpf_file) $save
} elseif {[info exists vars(ieee1801_file)] && !$skip_1801} {
set save $vars(ieee1801_file)
if {!$vars(top)} {
# set vars(ieee1801_file) "$ptn.cpf"
set vars(cpf_file) "$ptn.cpfdb"
}
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
# set command "read_power_intent $vars(ieee1801_file) -1801\n"
} else {
append ucomments "# - vars(cpf_file)\n"
append ucomments "# - vars(ieee1801_file)\n"
}
}
}
###############################################################################
# Load post-initialization plug-in script
###############################################################################
append commands [FF::source_plug post_init_tcl 0]
###############################################################################
# Check pre-place timing (and generate timing graph for placement)
###############################################################################
if {($vars(step) != "model_gen") && ($vars(step) != "partition_place") && ($vars(step) != "prototype")} {
if {![info exists vars(time_design_options,setup)]} {
set command "timeDesign -preplace -prefix preplace -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign -preplace -prefix preplace -outDir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
append commands [FF::wrap_command $vars(step),time_design $command]
}
###############################################################################
# Check data setup (sanity check)
###############################################################################
set command "checkDesign -all\n"
append commands [FF::wrap_command $vars(step),check_design $command]
if {!$vars(ilm)} {
set command "check_timing\n"
append commands [FF::wrap_command $vars(step),check_timing $command]
}
###############################################################################
# Generate reports
#------------------------------------------------------------------------------
# Report power domain for level-shifters, isolation and pg nets
#------------------------------------------------------------------------------
if {[FF::is_lp_flow] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 1))} {
# set command "set domains \[FF_EDI::get_power_domains_code\]\n"
set command [FF_EDI::get_power_domains_code]
append command "foreach domain \$domains {\n"
append command " set domain_file \[regsub -all {\[\]\[<>|\\/?*:\]} \$domain _\]\n"
append command " reportPowerDomain -powerDomain \$domain -file $vars(rpt_dir)/\${domain_file}.rpt -shifter -isoInst -pgNet\n"
#------------------------------------------------------------------------------
# Report library binding for power domains
#------------------------------------------------------------------------------
append command " foreach analysis_view \[all_setup_analysis_views\] {\n"
append command " set_default_view -setup \$analysis_view\n"
append command " reportPowerDomain -powerDomain \$domain -file $vars(rpt_dir)/\${domain_file}_\$analysis_view.rpt -bindLib\n"
append command " }\n"
append command " setAnalysisMode -checkType hold\n"
append command " foreach analysis_view \[all_hold_analysis_views\] {\n"
append command " set_default_view -hold \$analysis_view\n"
append command " reportPowerDomain -powerDomain \$domain -file $vars(rpt_dir)/\${domain_file}_\$analysis_view.rpt -bindLib\n"
append command " }\n"
append command " setAnalysisMode -checkType setup\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),report_power_domains $command]
if {$vars(flow) =="mmmc"} {
append commands "set_default_view -setup $vars(default_setup_view) -hold $vars(default_hold_view)\n"
}
}
if {[info exists comments]} {
if {$comments == ""} {
if {[info exists vars(comments)]} {
unset vars(comments)
}
} else {
set vars(comments) $comments
}
}
if {[info exists ucomments]} {
if {$ucomments == ""} {
if {[info exists vars(ucomments)]} {
unset vars(ucomments)
}
} else {
set vars(ucomments) $ucomments
}
}
set fcommands [FF_EDI::insert_comments]
append fcommands $commands
if {$vars(codegen)} {
return $fcommands
} else {
uplevel #0 eval $commands
}
}
proc run_place {{format 1}} {
global vars
global env
global errors
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
set vars(step) rcp
} else {
if {$vars(step) != "partition_place"} {
set vars(step) place
}
}
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step place]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command $vars(step),initialize_step $command]
append commands "Puts \"<FF> RUNNING PLACEMENT ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING PLACEMENT\n"
append commands "#\n"
}
if {[info exists vars(partition_list)] && ($vars(step) != "partition_place") && \
(([lsearch $vars(partition_list) $vars(design)] == -1) && $vars(enable_flexilm))} {
set command ""
append command "setHierMode -optStage preCTS\n"
append commands [FF::wrap_command $vars(step),set_hier_mode $command]
set command ""
foreach block $vars(partition_list) {
append command "setPtnPinStatus -cell $block -pin * -status unplaced\n"
}
append commands [FF::wrap_command $vars(step),set_ptn_pin_status $command]
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "setTrialRouteMode -honorPin false -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode1 $command]
} else {
append command "setRouteMode -earlyGlobalRoutePartitionHonorFence . -earlyGlobalRoutePartitionHonorPin {}\n"
append commands [FF::wrap_command $vars(step),set_route_mode1 $command]
}
set command ""
append command "setOptMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_opt_mode $command]
}
#########################################################################
# Load optional pre placement file (plug-in)
#########################################################################
append commands [FF::source_plug pre_place_tcl]
#########################################################################
# Run standard cell placement or load placement plug-in
#########################################################################
set command ""
if {[info exists vars(place_tcl)]} {
if {[file exists $vars(place_tcl)]} {
append command [FF::source_plug place_tcl]
} else {
set errors($vars(error_count)) "Plug-in vars(place_tcl) defined but the file does not exist"
incr vars(error_count)
# set vars(abort) 1
}
} else {
if {[info exists vars(sdp_files)]} {
foreach file $vars(sdp_files) {
append command "#readSdpFile -file $file -hierPath <instance> -origin <x y> -leftOverGroup <true | false>\n"
}
append command "#planDesign -useSdpGroup\n"
}
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
append command "placeDesign \n"
} else {
if {$vars(place_opt_design) && ($vars(step) != "partition_place")} {
# if {[info exists vars(hier)]} {
# if {($vars(top) && $vars(enable_flexilm))} {
# append command "placeDesign "
# if {[lindex [split $vars(version) "."] 0] < 13} {
# if {[info exists vars(in_place_opt)] && $vars(in_place_opt)} {
# append command " -inPlaceOpt"
# }
# }
# if {[info exists vars(no_pre_place_opt)] && $vars(no_pre_place_opt)} {
# append command " -noPrePlaceOpt"
# }
# append command "\n"
# } else {
# append command "place_opt_design -out_dir $vars(rpt_dir) -prefix $vars(step)\n"
# }
# } else {
append command "place_opt_design -out_dir $vars(rpt_dir) -prefix $vars(step)\n"
# }
} else {
append command "placeDesign "
if {[lindex [split $vars(version) "."] 0] < 13} {
if {[info exists vars(in_place_opt)] && $vars(in_place_opt)} {
append command " -inPlaceOpt"
}
}
if {($vars(step) == "partition_place") && $vars(use_flexmodels)} {
append command " -noPrePlaceOpt"
} else {
if {[info exists vars(no_pre_place_opt)] && $vars(no_pre_place_opt)} {
append command " -noPrePlaceOpt"
}
}
append command "\n"
}
}
}
if {[info exist vars(parent)] && ($vars(parent) != "rc") && $vars(rc) && $vars(enable_rcp)} {
set command "ecoPlace\n"
append commands [FF::wrap_command $vars(step),eco_place $command]
} else {
# if {[info exists vars(hier_case)] && [regexp "^1" $vars(hier_case)]} {
# append commands [FF::wrap_command $vars(step),place_design "placeDesign -noPrePlaceOpt\n"]
# } else {
append commands [FF::wrap_command $vars(step),place_design $command]
# }
}
#########################################################################
# Load optional post placement file (plug-in)
#########################################################################
append commands [FF::source_plug post_place_tcl 0]
#########################################################################
# Add tie cells for logic 0/1 nets
#########################################################################
set command [FF_EDI::add_tie_cells false true]
append commands [FF::wrap_command $vars(step),add_tie_cells $command]
###############################################################################
# Check post-place timing
###############################################################################
if {![regexp "place_opt_design" $commands] && ($vars(step) == "place")} {
if {![info exists vars(time_design_options,setup)]} {
set command "timeDesign -prects -prefix place -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign %s -prects -prefix place -outDir $vars(rpt_dir)\n" $vars(time_design_options,setup)]
}
append commands [FF::wrap_command $vars(step),time_design $command]
}
# if {($vars(step) == "partition_place") && $vars(use_flexmodels)} {
# if {![regexp "proto" $command]} {
# regsub "timeDesign" $command "timeDesign -proto" command
# }
# }
if {($vars(user_mode) == "hier") && $vars(place_opt_design) && ($vars(step) != "partition_place")} {
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1)} {
if {$vars(enable_flexilm)} {
set command "createInterfaceLogic -dir $ptn.flexilm -useType flexIlm -optStage preCTS\n"
append commands [FF::wrap_command $vars(step),create_flex_ilm $command]
} else {
if {!$vars(black_box)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "createInterfaceLogic -modelType timing -dir $ptn.ilm -hold\n"
} else {
set command "createInterfaceLogic -modelType timing -cellview {$vars(oa_partition_lib) $ptn abstract}\n"
}
}
append commands [FF::wrap_command $vars(step),create_ilm $command]
}
} else {
if {$vars(enable_flexilm)} {
set command ""
append command "saveDesign $vars(dbs_dir)/prects_flexilm.enc -compress\n"
append commands [FF::wrap_command $vars(step),save_design $command]
# Re-assign pins based on new netlist changes
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route1 $command]
} else {
append command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route1 $command]
}
set command ""
append command "timeDesign -preCTS -outDir $vars(rpt_dir) -prefix prects_flexilm\n"
append commands [FF::wrap_command $vars(step),time_design_flexilm $command]
set command ""
append command "assignPtnPin\n"
append commands [FF::wrap_command $vars(step),assign_ptn_pin $command]
set command ""
append command "checkPinAssignment\n"
append commands [FF::wrap_command $vars(step),check_pin_assignment $command]
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "setTrialRouteMode -honorPin true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode2 $command]
set command ""
append command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route2 $command]
} else {
append command "setRouteMode -earlyGlobalRoutePartitionHonorPin .\n"
append commands [FF::wrap_command $vars(step),set_route_mode2 $command]
set command ""
append command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route2 $command]
}
# set command ""
# append command "setBudgetingMode -enableMTBudgeting true\n"
# append commands [FF::wrap_command $vars(step),set_budgeting_mode $command]
set command ""
append command "deriveTimingBudget\n"
append commands [FF::wrap_command $vars(step),derive_timing_budget $command]
set command ""
set dirs ""
foreach block $vars(partition_list) {
append dirs "\\\n -goldenBlockDir ../$block/$vars(dbs_dir)/place.enc.dat "
}
append command "update_partition \\\n -flexIlmECO $dirs \\\n -flexIlmDir ../../PARTITION_FLEXILM \\\n -postECOSuffix postECO -pinLocation\n"
# append command "update_partition \\\n -flexIlmECO $dirs \\\n -flexIlmDir ../../PARTITION_FLEXILM \\\n -postECOSuffix postECO -pinLocation -allowPortECO\n"
append commands [FF::wrap_command $vars(step),update_partition $command]
}
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_prects {{format 1}} {
global vars
global env
global errors
global warnings
if {$vars(place_opt_design)} {
# if {!($vars(user_mode) == "hier")} {
return ""
# } else {
# set warnings($vars(warning_count)) "Feature vars(place_opt_design) not support for top level implementation when vars(enable_flexilm) is true"
# incr vars(warning_count)
# }
}
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
set vars(step) rcp
} else {
set vars(step) prects
}
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step prects]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command $vars(step),initialize_step $command]
append commands "Puts \"<FF> RUNNING PRE-CTS OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING PRE-CTS OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load optional pre CTS file (plug-in)
#########################################################################
append commands [FF::source_plug pre_prects_tcl]
if {[info exists vars(parent)] && ($vars(parent) == "rc")} {
return $commands
}
#########################################################################
# Run pre-CTS optimization
#########################################################################
if {([info exists vars(partition_list)]) && ([file tail [file dirname [pwd]]] == "$vars(partition_dir)")} {
set ptn [file tail [pwd]]
if {([lsearch $vars(partition_list) $ptn] == -1) && $vars(enable_flexilm)} {
# Top level flow for flexIlm
set command ""
foreach block $vars(partition_list) {
append command "setPtnPinStatus -cell $block -pin * -status unplaced\n"
}
append commands [FF::wrap_command $vars(step),set_ptn_pin_status $command]
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "setTrialRouteMode -honorPin false -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode1 $command]
} else {
append command "setRouteMode -earlyGlobalRoutePartitionHonorFence . -earlyGlobalRoutePartitionHonorPin {}\n"
append commands [FF::wrap_command $vars(step),set_route_mode1 $command]
}
# set command ""
# append command "setHierMode -optStage preCTS\n"
# append commands [FF::wrap_command $vars(step),set_hier_mode $command]
set command ""
append command "setOptMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_opt_mode $command]
set command ""
append command "optDesign -preCTS -outDir $vars(rpt_dir) -prefix flexilm\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
set command ""
append command "saveDesign $vars(dbs_dir)/prects_flexilm.enc -compress\n"
append commands [FF::wrap_command $vars(step),save_design $command]
} else {
# Non flexIlm top flow and partition flow
set command "optDesign -preCTS -outDir $vars(rpt_dir) -prefix prects\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
}
} else {
# Flat flow
set command "optDesign -preCTS -outDir $vars(rpt_dir) -prefix prects\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
}
#########################################################################
# Load optional post CTS file (plug-in)
#########################################################################
set command ""
append commands [FF::source_plug post_prects_tcl 0]
if {[info exists vars(clock_gate_clone)] && $vars(clock_gate_clone)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING CLOCK GATE CLONING\n"
append commands "#\n"
}
# Set spec_file if one is defined
if {[info exists vars(cts_spec)]} {
set spec_file $vars(cts_spec)
}
if {([info exists vars(partition_list)]) &&
([file tail [file dirname [pwd]]] == "$vars(partition_dir)")} {
set ptn [file tail [pwd]]
# Override with partition spec if defined
if {[info exists vars($ptn,cts_spec)]} {
set spec_file $vars($ptn,cts_spec)
}
}
# Load final spec file or generate one
# if {[info exists spec_file]} {
# append commands "cleanupSpecifyClockTree\n"
# foreach spec $spec_file {
# append commands "specifyClockTree -file $spec\n"
# }
# } else {
# append commands "createClockTreeSpec\n"
# if {[info exists vars(cts_cells)]} {
# append commands "specifyClockTree -update \"AutoCTSRootPin * Buffer \[list $vars(cts_cells)\]\"\n"
# }
# }
# if {[info exists vars(route_clock_nets)] && $vars(route_clock_nets)} {
# append commands "specifyClockTree -update \"AutoCTSRootPin * RouteClkNet YES\"\n"
# }
set command "ckCloneGate -timingDriven -forceReconvergent\n"
append commands [FF::wrap_command $vars(step),ck_clone_gate $command]
}
if {($vars(user_mode) == "hier")} {
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1) && !$vars(place_opt_design)} {
if {$vars(enable_flexilm)} {
set command "createInterfaceLogic -dir $ptn.flexilm -useType flexIlm -optStage preCTS\n"
append commands [FF::wrap_command $vars(step),create_flex_ilm $command]
} else {
if {!$vars(black_box)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "createInterfaceLogic -modelType timing -dir $ptn.ilm -hold\n"
} else {
set command "createInterfaceLogic -modelType timing -cellview {$vars(oa_partition_lib) $ptn abstract}\n"
}
}
append commands [FF::wrap_command $vars(step),create_ilm $command]
}
} else { ; # Top level unconditional (no place_opt_design support) ...
if {$vars(enable_flexilm)} {
# Re-assign pins based on new netlist changes
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route1 $command]
} else {
append command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_route1 $command]
}
set command ""
append command "timeDesign -preCTS -outDir $vars(rpt_dir) -prefix assemble_flexilm\n"
append commands [FF::wrap_command $vars(step),time_design $command]
set command ""
append command "assignPtnPin\n"
append commands [FF::wrap_command $vars(step),assign_ptn_pin $command]
set command ""
append command "checkPinAssignment\n"
append commands [FF::wrap_command $vars(step),check_pin_assignment $command]
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "setTrialRouteMode -honorPin true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode2 $command]
} else {
append command "setRouteMode -earlyGlobalRoutePartitionHonorPin .\n"
append commands [FF::wrap_command $vars(step),set_route_mode2 $command]
}
set command ""
if {[lindex [split $vars(version) "."] 0] < 16} {
append command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route2 $command]
} else {
append command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_route2 $command]
}
# set command ""
# append command "setBudgetingMode -enableMTBudgeting true\n"
# append commands [FF::wrap_command $vars(step),set_budgeting_mode $command]
set command ""
append command "deriveTimingBudget\n"
append commands [FF::wrap_command $vars(step),derive_timing_budget $command]
set command ""
set dirs ""
foreach block $vars(partition_list) {
if {$vars(place_opt_design)} {
append dirs "\\\n -goldenBlockDir ../$block/$vars(dbs_dir)/place.enc.dat "
} else {
append dirs "\\\n -goldenBlockDir ../$block/$vars(dbs_dir)/prects.enc.dat "
}
}
append command "update_partition \\\n -flexIlmECO $dirs \\\n -flexIlmDir ../../PARTITION_FLEXILM \\\n -postECOSuffix postECO -pinLocation\n"
# append command "update_partition \\\n -flexIlmECO $dirs \\\n -flexIlmDir ../../PARTITION_FLEXILM \\\n -postECOSuffix postECO -pinLocation -allowPortECO\n"
append commands [FF::wrap_command $vars(step),update_partition $command]
}
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_cts {{format 1}} {
global vars
global errors
if {$vars(skip_cts)} {
return ""
}
set vars(step) cts
set commands ""
set ucomments ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step cts]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command cts,initialize_step $command]
if {$vars(top) && ($vars(user_mode) == "hier") && ($vars(hier_flow_type) == "2pass") && $vars(enable_flexilm)} {
# Read Power Intent here ...
FF_EDI::normalize_files
# set save $vars(cpf_power_domain)
# set vars(cpf_power_domain) true
# append commands [FF_EDI::load_power_intent]
# set vars(cpf_power_domain) $save
set command ""
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)] && ($vars(codegen) || [file isdirectory $vars($part,ilm_dir)])} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
}
}
} else {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
}
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
set command [FF_EDI::initialize_timing mmmc]
# if {![info exists vars(cpf_file)] || ([info exists vars(cpf_file)] && !$vars(cpf_timing)) } {
append commands [FF::wrap_command $vars(step),initialize_timing $command]
# } else {
# set defer_commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
}
append commands "Puts \"<FF> RUNNING CLOCK TREE SYNTHESIS ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING CLOCK TREE SYNTHESIS\n"
append commands "#\n"
}
#########################################################################
# Load pre-CTS file (plug-in)
#########################################################################
if {$vars(cts_engine) == "cts"} {
append commands [FF::source_plug pre_cts_tcl]
}
#########################################################################
# Run CTS
#------------------------------------------------------------------------
# Generate the clock tree using clockDesign which:
# - loads the clock specification file
# - removes existing buffers in the clock tree (not marked don't touch);
# if a clock tree has been previously inserted, use changeClockStatus
# to unfix the tree so that it can be removed
# - unfixes the clock nets after tree insertion
# Need to make sure the clock gating cells are usable during clockDesign.
# Disable them afterwards.
#########################################################################
set clock_gate_cells [list]
set command ""
if {[info exists vars(clock_gate_cells)]} {
set clock_gate_cells $vars(clock_gate_cells)
foreach cell $clock_gate_cells {
append command "setDontUse $cell false\n"
}
}
append commands [FF::wrap_command cts,enable_clock_gate_cells $command]
#########################################################################
# Run CTS
#########################################################################
set command ""
if {[string tolower $vars(cts_engine)] == "cts"} {
if {[info exists vars(cts_tcl)]} {
if {[file exists $vars(cts_tcl)]} {
append commands [FF::source_plug cts_tcl]
} else {
set errors($vars(error_count)) "Plug-in vars(cts_tcl) defined but the file does not exist"
incr vars(error_count)
# set vars(abort) 1
}
} else {
if {[info exists vars(cts_spec)]} {
append command "cleanupSpecifyClockTree\n"
foreach spec $vars(cts_spec) {
append command "specifyClockTree -file $spec\n"
}
} else {
if {[lindex [split $vars(version) "."] 0] < 15} {
if {!$vars(ilm)} {
append command "createClockTreeSpec\n"
if {[info exists vars(cts_cells)]} {
append command "specifyClockTree -update \"AutoCTSRootPin * Buffer $vars(cts_cells)\"\n"
}
}
}
}
if {[info exists vars(cts_spec)] || (![info exists vars(cts_spec)] && ([lindex [split $vars(version) "."] 0] < 15))} {
if {[info exists vars(route_clock_nets)] && $vars(route_clock_nets)} {
append command "specifyClockTree -update \"AutoCTSRootPin * RouteClkNet YES\"\n"
}
append commands [FF::wrap_command cts,create_clock_tree_spec $command]
set command ""
if {$vars(update_io_latency)} {
append command "clockDesign -skipTimeDesign -updateIoLatency -outDir $vars(rpt_dir)\n"
} else {
append command "clockDesign -skipTimeDesign -outDir $vars(rpt_dir)\n"
}
} else {
append command "clockDesign -skipTimeDesign -outDir $vars(rpt_dir)\n"
}
append commands [FF::wrap_command cts,clock_design $command]
}
set command ""
foreach cell $clock_gate_cells {
append command "setDontUse $cell true\n"
}
append commands [FF::wrap_command cts,disable_clock_gate_cells $command]
#########################################################################
# Run ckECO if requested
#########################################################################
if {[info exists vars(clock_eco)] && (($vars(clock_eco) == "post_cts") || ($vars(clock_eco) == "both"))} {
set command [FF_EDI::run_clock_eco post_cts]
append commands [FF::wrap_command cts,run_clock_eco $command]
}
#########################################################################
# Update timing based on vars(<mode>,incr_cts_sdc) and
# vars(<mode>,post_cts_sdc)
#########################################################################
if {$vars(flow) == "mmmc"} {
set command [FF_EDI::update_timing mmmc]
append commands [FF::wrap_command cts,update_timing $command]
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
} else {
set command [FF_EDI::update_timing minmax]
append commands [FF::wrap_command cts,update_timing $command]
set command [FF_EDI::derate_timing minmax]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
if {[file exists $vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $var(step),load_ilm_non_sdc_file $command]
}
}
###############################################################################
# Check post-cts timing
###############################################################################
if {![info exists vars(time_design_options,setup)]} {
set command "timeDesign -postcts -prefix cts -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign -postcts -prefix cts -outDir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
append commands [FF::wrap_command cts,time_design $command]
} else {
#########################################################################
# Run ccoptDesign ... convert to propagated timing first
#########################################################################
if {[info exists vars(cts_tcl)]} {
if {[file exists $vars(cts_tcl)]} {
append commands [FF::source_plug pre_cts_tcl]
append commands [FF::source_plug cts_tcl]
} else {
set errors($vars(error_count)) "Plug-in vars(cts_tcl) defined but the file does not exist"
incr vars(error_count)
}
} else {
set is_native [expr {$vars(ccopt_integration) == "native"}]
set command [FF_EDI::update_timing mmmc [expr !$is_native]]
append commands [FF::wrap_command cts,update_timing $command]
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
append commands [FF::source_plug pre_cts_tcl]
if {[lindex [split $vars(version) "."] 0] <= 14} {
if {[regexp "^ccopt" $vars(cts_engine)] && ($vars(ccopt_effort) != "low")} {
append commands [FF::source_plug pre_postcts_tcl 0]
if {$vars(postcts_setup_hold)} {
append commands [FF::source_plug pre_postcts_hold_tcl]
}
}
} else {
if {$vars(ccopt_effort) != "low"} {
append commands [FF::source_plug pre_postcts_tcl 0]
if {$vars(postcts_setup_hold)} {
append commands [FF::source_plug pre_postcts_hold_tcl]
}
}
}
if {$vars(ccopt_effort) != "low"} {
# append commands [FF::wrap_command $vars(step),set_ccopt_mode "set_ccopt_mode -effort $vars(ccopt_effort)\n"]
append commands [FF::wrap_command $vars(step),set_ccopt_mode "set_ccopt_effort -$vars(ccopt_effort)\n"]
}
if {$vars(cts_engine) == "ccopt_cts"} {
set ccopt_command "ccopt_design -outDir $vars(rpt_dir) -prefix $vars(step) -cts"
} else {
set ccopt_command "ccopt_design -outDir $vars(rpt_dir) -prefix $vars(step)"
if {$vars(postcts_setup_hold)} {
append ccopt_command " -hold"
}
}
if {$is_native} {
if {[lindex [split $vars(version) "."] 0] <= 14} {
if {$vars(cts_engine) == "ccopt_cts" && [info exists vars(cts_spec)]} {
append command "cleanupSpecifyClockTree\n"
foreach spec $vars(cts_spec) {
append command "specifyClockTree -file $spec\n"
}
append command "set_ccopt_mode -import_edi_cts_spec true\n"
append commands [FF::wrap_command cts,create_ccopt_clock_tree_spec $command]
} else {
set command "create_ccopt_clock_tree_spec\n"
append commands [FF::wrap_command cts,create_ccopt_clock_tree_spec $command]
}
} else {
if {($vars(ccopt_effort) == "low") && [info exists vars(cts_spec)]} {
append command "cleanupSpecifyClockTree\n"
foreach spec $vars(cts_spec) {
append command "specifyClockTree -file $spec\n"
}
append command "set_ccopt_mode -import_edi_cts_spec true\n"
append commands [FF::wrap_command cts,create_ccopt_clock_tree_spec $command]
} else {
set command "create_ccopt_clock_tree_spec\n"
append commands [FF::wrap_command cts,create_ccopt_clock_tree_spec $command]
}
}
}
append ccopt_command "\n"
append commands [FF::wrap_command cts,ccopt_design $ccopt_command]
}
}
#########################################################################
# Load optional post CTS file (plug-in)
#########################################################################
append commands [FF::source_plug post_cts_tcl 0]
if {[lindex [split $vars(version) "."] 0] <= 14} {
if {[regexp "^ccopt" $vars(cts_engine)] && ($vars(ccopt_effort) != "low")} {
append commands [FF::source_plug post_postcts_tcl 0]
if {$vars(postcts_setup_hold)} {
append commands [FF::source_plug post_postcts_hold_tcl]
}
}
} else {
if {$vars(ccopt_effort) != "low"} {
append commands [FF::source_plug post_postcts_tcl 0]
if {$vars(postcts_setup_hold)} {
append commands [FF::source_plug post_postcts_hold_tcl]
}
}
}
#########################################################################
# Reset clock gating cell usage
#########################################################################
if {$vars(hier_flow_type) == "2pass"} {
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1) && !$vars(enable_flexilm)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "createInterfaceLogic -modelType timing -dir $ptn.ilm -hold\n"
} else {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "createInterfaceLogic -modelType timing -cellview {$vars(oa_partition_lib) $ptn abstract}\n"
} else {
set command "createInterfaceLogic -modelType timing -dir $ptn.ilm -hold\n"
}
}
append commands [FF::wrap_command $vars(step),create_ilm $command]
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_preroute {{format 1}} {
global vars
global errors
set vars(step) preroute
set commands ""
set ucomments ""
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step place]
append command [FF_EDI::initialize_step prects]
append command [FF_EDI::initialize_step cts]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command preroute,initialize_step $command]
if {$vars(top) && ($vars(user_mode) == "hier") && ($vars(hier_flow_type) == "2pass") && $vars(enable_flexilm)} {
# Read Power Intent here ...
FF_EDI::normalize_files
set command ""
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)] && ($vars(codegen) || [file isdirectory $vars($part,ilm_dir)])} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
}
}
} else {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
}
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
}
append commands "Puts \"<FF> RUNNING PRE ROUTE OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING PRE ROUTE OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load pre-CTS file (plug-in)
#########################################################################
append commands [FF::source_plug pre_preroute_tcl]
set clock_gate_cells [list]
set command ""
if {[info exists vars(clock_gate_cells)]} {
set clock_gate_cells $vars(clock_gate_cells)
foreach cell $clock_gate_cells {
append command "setDontUse $cell false\n"
}
}
append commands [FF::wrap_command cts,enable_clock_gate_cells $command]
#########################################################################
# Run pre-route optimization flow
#########################################################################
set command ""
#########################################################################
# Update timing based on vars(<mode>,incr_cts_sdc) and
# vars(<mode>,post_cts_sdc)
#########################################################################
set command [FF_EDI::update_timing mmmc]
append commands [FF::wrap_command cts,update_timing $command]
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
if {[file exists $vars(ilm_non_sdc_file)]} {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
append commands [FF::wrap_command $var(step),load_ilm_non_sdc_file $command]
}
}
set command "preroute_opt_design -prefix $vars(step) -out_dir $vars(rpt_dir)\n"
append commands [FF::wrap_command preroute,opt_design $command]
append commands [FF::source_plug post_preroute_tcl]
#########################################################################
# Reset clock gating cell usage
#########################################################################
if {$vars(hier_flow_type) == "2pass"} {
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1) && !$vars(enable_flexilm)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "createInterfaceLogic -modelType timing -dir $ptn.ilm -hold\n"
} else {
set command "createInterfaceLogic -modelType timing -cellview {$vars(oa_partition_lib) $ptn abstract}\n"
}
append commands [FF::wrap_command $vars(step),create_ilm $command]
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postcts {{format 1}} {
global vars
global env
global errors
# if {($vars(skip_cts)) || [regexp "^ccopt" [string tolower $vars(cts_engine)]]} {
# if {$vars(cts_engine) != "ccopt_cts"} {
# return ""
# }
# }
if {$vars(skip_cts)} { return "" }
if {[lindex [split $vars(version) "."] 0] <= 14} {
if {[regexp "^ccopt" [string tolower $vars(cts_engine)]] && ($vars(ccopt_effort) != "low")} {
return ""
}
} else {
if {[string tolower $vars(cts_engine)] == "ccopt"} {
return ""
}
# if {$vars(ccopt_effort) != "low"} {
# return ""
# }
}
set vars(step) postcts
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step postcts]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command postcts,initialize_step $command]
###############################################################################
# Specify the ILM models for the top partition (only for 2pass flow)
###############################################################################
if {$vars(top) && ($vars(user_mode) == "hier") && ($vars(hier_flow_type) == "2pass") && !$vars(enable_flexilm)} {
# if {!$(vars(black_box)} {
set command ""
foreach part $vars(partition_list) {
if {[info exists vars($part,ilm_dir)] && ($vars(codegen) || [file isdirectory $vars($part,ilm_dir)])} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir $vars($part,ilm_dir)\n"
}
}
} else {
if {[lindex [split $vars(version) "."] 0] <= 10} {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
} else {
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
append command "specifyIlm -cell $part\n"
} else {
append command "specifyIlm -cell $part -dir ../$part/$part.ilm\n"
}
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),specify_ilm $command]
}
if {$vars(flow) == "mmmc"} {
set command [FF_EDI::update_timing mmmc]
append commands [FF::wrap_command postcts,update_timing $command]
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
} else {
set command [FF_EDI::update_timing minmax]
append commands [FF::wrap_command postcts,update_timing $command]
set command [FF_EDI::derate_timing minmax]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
if {$vars(ilm) && [info exists vars(ilm_non_sdc_file)]} {
if {[file exists $vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
# }
# set command [FF_EDI::initialize_timing mmmc]
# if {![info exists vars(cpf_file)]} {
# append commands [FF::wrap_command $vars(step),initialize_timing $command]
# } else {
# set defer_commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
}
append commands "Puts \"<FF> RUNNING POST-CTS OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-CTS OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load optional pre postCTS file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postcts_tcl]
if {[lindex [split $vars(version) "."] 0] <= 14} {
if {$vars(cts_engine) == "ccopt" && $vars(ccopt_integration) == "native"} {
set command "Puts \"<FF> NO POST-CTS OPTIMIZATION REQUIRED FOR CCOPT NATIVE INTEGRATION\"\n"
append commands [FF::wrap_command postcts,opt_design $command]
} else {
#########################################################################
# Run post-CTS optimization
#########################################################################
set command "optDesign -postCTS -outDir $vars(rpt_dir) -prefix postcts\n"
append commands [FF::wrap_command postcts,opt_design $command]
}
} else {
if {$vars(cts_engine) == "ccopt_cts"} {
set command "optDesign -postCTS -outDir $vars(rpt_dir) -prefix postcts\n"
append commands [FF::wrap_command postcts,opt_design $command]
}
}
#########################################################################
# Load optional post postCTS file (plug-in)
#########################################################################
append commands [FF::source_plug post_postcts_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postcts_hold {{format 1}} {
global vars
global env
global errors
if {$vars(skip_cts) || ([lsearch $vars(fix_hold) postcts] < 0) || ($vars(postcts_setup_hold) && ($vars(cts_engine) != "ccopt_cts"))} {
return ""
}
set vars(step) postcts_hold
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step postcts_hold]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command postcts_hold,initialize_step $command]
append commands "Puts \"<FF> RUNNING POST-CTS HOLD FIXING ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-CTS HOLD FIXING\n"
append commands "#\n"
}
#########################################################################
# Load pre-postCTS hold file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postcts_hold_tcl]
set command "optDesign -postCTS -hold -outDir $vars(rpt_dir) -prefix postcts_hold\n"
append commands [FF::wrap_command postcts_hold,opt_design $command]
#########################################################################
# Load post-postCTS hold file (plug-in)
#########################################################################
append commands [FF::source_plug post_postcts_hold_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_route {{format 1}} {
global vars
global env
global errors
set vars(step) route
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step route]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command route,initialize_step $command]
set command [FF_EDI::add_filler_cells]
append commands [FF::wrap_command route,add_filler_cells $command]
append commands "Puts \"<FF> RUNNING GLOBAL/DETAIL ROUTING ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING GLOBAL/DETAIL ROUTING\n"
append commands "#\n"
}
#########################################################################
# Load optional pre route file (plug-in)
#########################################################################
append commands [FF::source_plug pre_route_tcl]
set command [FF_EDI::route_secondary_pg_nets]
append commands [FF::wrap_command route,route_secondary_pg_nets $command]
set command "checkPlace $vars(rpt_dir)/$vars(step),check_place.rpt\n"
append commands [FF::wrap_command route,check_place $command]
#########################################################################
# Route the design
#########################################################################
set command ""
set args ""
if {($vars(enable_ocv) == "pre_postroute") || ($vars(enable_ocv) == "pre_postcts")} {
# if {$vars(flow) != "default"} {
append comments "# - vars(enable_ocv)\n"
append args "-analysisType onChipVariation "
# }
if {$vars(enable_aocv)} {
append comments "# - vars(enable_aocv)\n"
append args "-aocv true "
} else {
append ucomments "# - vars(enable_aocv)\n"
}
if {$vars(enable_socv)} {
append comments "# - vars(enable_socv)\n"
append args "-socv true "
} else {
append ucomments "# - vars(enable_socv)\n"
}
} else {
append ucomments "# - vars(enable_ocv) \"pre_postroute\"\n"
append ucomments "# - vars(enable_aocv) \"true\"\n"
append ucomments "# - vars(enable_socv) \"true\"\n"
}
if {$args != ""} {
set command "setAnalysisMode $args\n"
append commands [FF::wrap_command route,set_analysis_mode $command]
}
if {[info exists vars(postroute_spread_wires)] && !$vars(postroute_spread_wires)} {
append commands "setNanoRouteMode -droutePostRouteSpreadWire false\n"
}
set command "routeDesign"
if {$vars(track_opt)} {
append comments "# - vars(track_opt)\n"
append command " -trackOpt"
} else {
append ucomments "# - vars(track_opt)\n"
}
append commands [FF::wrap_command route,route_design "$command\n"]
#########################################################################
# Run ckECO if requested
#########################################################################
if {[info exists vars(clock_eco)] && (($vars(clock_eco) == "post_route") || ($vars(clock_eco) == "both"))} {
set command [FF_EDI::run_clock_eco post_route]
append commands [FF::wrap_command route,run_clock_eco $command]
}
#########################################################################
# Optionally run wire spreading
#########################################################################
if {[regsub "nm" $vars(process) ""] > 16} {
if {[info exists vars(postroute_spread_wires)] && $vars(postroute_spread_wires)} {
set command "setNanoRouteMode -droutePostRouteSpreadWire true -routeWithTimingDriven false\n"
append command "routeDesign -wireOpt\n"
append command "setNanoRouteMode -droutePostRouteSpreadWire false\n"
append commands [FF::wrap_command route,spread_wires $command]
}
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
file mkdir $vars(rpt_dir)/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command route,verify_litho $command]
}
#########################################################################
# Set extraction mode to postroute
#########################################################################
set command "setExtractRCMode -engine postRoute"
if {![catch {set arg $vars(postroute_extraction_effort)}]} {
append comments "# - vars(postroute_extraction_effort)\n"
append command " -effortLevel $arg"
} else {
append ucomments "# - vars(postroute_extraction_effort)\n"
}
if {![catch {set arg $vars(total_c_thresh)}]} {
append comments "# - vars(total_c_thresh)\n"
append command " -total_c_th $arg"
} else {
append ucomments "# - vars(total_c_thresh)\n"
}
if {![catch {set arg $vars(relative_c_thresh)}]} {
append comments "# - vars(relative_c_thresh)\n"
append command " -relative_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(coupling_c_thresh)}]} {
append comments "# - vars(coupling_c_thresh)\n"
append command " -coupling_c_th $arg"
} else {
append ucomments "# - vars(relative_c_thresh)\n"
}
if {![catch {set arg $vars(qrc_layer_map)}]} {
append comments "# - vars(qrc_layer_map)\n"
append command " -lefTechFileMap $arg"
} else {
append ucomments "# - vars(qrc_layer_map)\n"
}
append command "\n"
append commands [FF::wrap_command route,set_extract_rc_mode $command]
#########################################################################
# Load optional post route file (plug-in)
#########################################################################
append commands [FF::source_plug post_route_tcl 0]
#########################################################################
# Update to MMMC if flow is "pr_mmmc"
#########################################################################
if {$vars(flow) != "default"} {
if {$vars(flow) == "pr_mmmc"} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command route,initialize_timing $command]
}
}
if {![info exists vars(time_design_options,setup)]} {
set command "timeDesign -postroute -prefix route -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign -postroute -prefix route -outDir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
append commands [FF::wrap_command route,time_design $command]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postroute {{format 1}} {
global vars
global env
global errors
set vars(step) postroute
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
if {$vars(postroute_setup_hold)} {
set command [FF_EDI::initialize_step postroute_hold]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command postroute_hold,initialize_step $command]
}
set command [FF_EDI::initialize_step postroute]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command postroute,initialize_step $command]
if {$vars(metalfill) == "pre_postroute"} {
set command [FF::source_plug metalfill_tcl]
append commands [FF::wrap_command postroute,add_metalfill $command]
}
#########################################################################
# Run ckECO if requested
#########################################################################
if {[info exists vars(clock_eco)] && (($vars(clock_eco) == "post_route") || ($vars(clock_eco) == "both"))} {
set command [FF_EDI::run_clock_eco post_route]
append commands "Puts \"<FF> RUNNING POST-ROUTE CLOCK ECO ...\"\n"
append commands [FF::wrap_command route,run_clock_eco $command]
}
append commands "Puts \"<FF> RUNNING POST-ROUTE OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-ROUTE OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load optional pre postroute file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postroute_tcl]
if {$vars(high_timing_effort) && [regexp "9.1" $vars(version)]} {
append commands "optLeakagePower -fixTimingOnly\n"
}
if {$vars(postroute_setup_hold)} {
append commands [FF::source_plug pre_postroute_hold_tcl]
set command "optDesign -postRoute -outDir $vars(rpt_dir) -prefix postroute -setup -hold\n"
} else {
set command "optDesign -postRoute -outDir $vars(rpt_dir) -prefix postroute\n"
}
append commands [FF::wrap_command postroute,opt_design $command]
#########################################################################
# Trim metal fill if added
#########################################################################
if {$vars(metalfill) == "pre_postroute"} {
set command "trimMetalFill\n"
append commands [FF::wrap_command postroute,trim_metalfill $command]
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command postroute,verify_litho $command]
}
#########################################################################
# Load optional post postRoute file (plug-in)
#########################################################################
append commands [FF::source_plug post_postroute_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postroute_hold {{format 1}} {
global vars
global env
global errors
if {([lsearch $vars(fix_hold) postroute] < 0) || $vars(postroute_setup_hold)} {
return ""
}
#########################################################################
# Initialize step ...
#########################################################################
set vars(step) postroute_hold
set commands ""
# append commands "set vars(step) $vars(step)\n"
set command [FF_EDI::initialize_step postroute_hold]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command postroute_hold,initialize_step $command]
append commands "Puts \"<FF> RUNNING POST-ROUTE HOLD FIXING ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-ROUTE HOLD FIXING\n"
append commands "#\n"
}
#########################################################################
# Load optional pre postRoute hold file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postroute_hold_tcl]
set command "optDesign -postRoute -hold"
append command " -outDir $vars(rpt_dir) -prefix postroute_hold\n"
append commands [FF::wrap_command postroute_hold,opt_design $command]
#########################################################################
# Trim metal fill if added
#########################################################################
if {$vars(metalfill) == "pre_postroute"} {
set command "trimMetalFill\n"
append commands [FF::wrap_command postroute_hold,trim_metalfill $command]
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command postroute_hold,verify_litho $command]
}
#########################################################################
# Load optional post postRoute hold file (plug-in)
#########################################################################
append commands [FF::source_plug post_postroute_hold_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postroute_si_hold {{format 1}} {
global vars
global env
global errors
if {([lsearch $vars(fix_hold) postroute] < 0) || $vars(postroute_setup_hold)} {
return ""
}
set vars(step) postroute_si_hold
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step postroute_si_hold]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command postroute_si_hold,initialize_step $command]
append commands "Puts \"<FF> RUNNING POST-ROUTE SI-AWARE HOLD FIXING ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-ROUTE SI AWARE HOLD FIXING\n"
append commands "#\n"
}
#########################################################################
# Force celtic based SI delay calculation
#########################################################################
set command "setDelayCalMode -engine signalStorm -siAware false\n"
append commands [FF::wrap_command postroute_si_hold,set_delay_cal_mode $command]
#########################################################################
# Load pre-postRoute SI hold file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postroute_si_hold_tcl]
#########################################################################
# Load optional metalfill plug-in
#########################################################################
if {$vars(metalfill) == "pre_postroute_si"} {
set command [FF::source_plug metalfill_tcl]
append commands [FF::wrap_command postroute_si_hold,add_metalfill $command]
}
#########################################################################
# Run postroute SI hold fixing
#########################################################################
set command "optDesign -postRoute -si -hold"
append command " -outDir $vars(rpt_dir) -prefix postroute_si_hold\n"
append commands [FF::wrap_command postroute_si_hold,opt_design $command]
#########################################################################
# Trim metal fill if added
#########################################################################
if {($vars(metalfill) == "pre_postroute") ||
($vars(metalfill) == "pre_postroute_si")} {
set command "trimMetalFill\n"
append commands [FF::wrap_command postroute_si_hold,trim_metalfill $command]
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command post_postroute_si_hold,verify_litho $command]
}
#########################################################################
# Load optional post postRoute SI hold file (plug-in)
#########################################################################
append commands [FF::source_plug post_postroute_si_hold_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_postroute_si {{format 1}} {
global vars
global env
global errors
set vars(step) postroute_si
set commands ""
# append commands "set vars(step) $vars(step)\n"
#########################################################################
# Initialize step ...
#########################################################################
set command [FF_EDI::initialize_step postroute_si]
append commands [FF_EDI::insert_comments]
append commands [FF::wrap_command postroute_si,initialize_step $command]
#########################################################################
# Force celtic based SI delay calculation
#########################################################################
set command "setDelayCalMode -engine signalStorm -siAware false\n"
append commands [FF::wrap_command postroute_si,set_delay_cal_mode $command]
#########################################################################
# Load optional metalfill plug-in
#########################################################################
if {$vars(metalfill) == "pre_postroute_si"} {
set command [FF::source_plug metalfill_tcl]
append commands [FF::wrap_command postroute_si,add_metalfill $command]
}
append commands "Puts \"<FF> RUNNING POST-ROUTE SI-AWARE OPTIMIZATION ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST-ROUTE SI AWARE OPTIMIZATION\n"
append commands "#\n"
}
#########################################################################
# Load optional pre postRoute SI file (plug-in)
#########################################################################
append commands [FF::source_plug pre_postroute_si_tcl]
#########################################################################
# Run post route setup fixing w/SI
#########################################################################
set command "optDesign -postRoute -si"
append command " -outDir $vars(rpt_dir) -prefix postroute_si\n"
append commands [FF::wrap_command postroute_si,opt_design $command]
#########################################################################
# Trim metal fill if added
#########################################################################
if {($vars(metalfill) == "pre_postroute") ||
($vars(metalfill) == "pre_postroute_si")} {
set command "trimMetalFill\n"
append commands [FF::wrap_command postroute_si_hold,trim_metalfill $command]
}
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command post_postroute_si,verify_litho $command]
}
#########################################################################
# Load optional post postRoute SI file (plug-in)
#########################################################################
append commands [FF::source_plug post_postroute_si_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_signoff {{format 1}} {
global vars
global env
global errors
global env
if {$vars(step) != "assemble"} {
set vars(step) signoff
}
set commands ""
###############################################################################
# Optionally verify/fix litho
###############################################################################
if {$vars(fix_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append command "setNanoRouteMode -droutePostRouteLithoRepair true \\\n"
append command " -drouteMinimizeTopologyChange true\n"
append command "globalDetailRoute\n"
append command "writeHif -file $vars(rpt_dir)/LPA/incr_verify.hif\n"
append command "verifyLitho -signOff \\\n"
append command " -dir $vars(dbs_dir)/LPA2 \\\n"
append command " -cpu $vars(local_cpus) \\\n"
append command " -config $vars(lpa_conf_file) \\\n"
append command " -incrCheck $vars(rpt_dir)/LPA/incr_verify.hif\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA2/DMC/merged.hif\n"
append commands [FF::wrap_command signoff,fix_litho $command]
}
###############################################################################
# Load optional metalfill plug-in
###############################################################################
if {$vars(metalfill) == "pre_signoff"} {
set command [FF::source_plug metalfill_tcl]
append commands [FF::wrap_command signoff,add_metalfill $command]
}
set command [FF_EDI::initialize_step signoff]
append commands [FF_EDI::insert_comments]
# append commands [FF::wrap_command signoff,initialize_step $command]
append commands $command
###############################################################################
# Load optional pre signoff file (plug-in)
###############################################################################
append commands [FF::source_plug pre_signoff_tcl]
###############################################################################
# Run RC Extraction
###############################################################################
append commands "Puts \"<FF> RUNNING FINAL SIGNOFF ...\"\n"
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING FINAL SIGNOFF\n"
append commands "#\n"
}
set command "extractRC\n"
append commands [FF::wrap_command signoff,extract_rc $command]
###############################################################################
# Dump SPEF for signoff STA
###############################################################################
if {$vars(skip_signoff_checks)} {
set command ""
foreach corner $vars(rc_corners) {
append command "rcOut -rc_corner $corner -spef $corner.spef.gz\n"
}
} else {
set command "foreach corner \$vars(active_rc_corners) {\n"
append command " rcOut -rc_corner \$corner -spef \$corner.spef.gz\n"
append command "}\n"
}
append commands [FF::wrap_command signoff,dump_spef $command]
if {(($vars(step) == "assemble") || ($vars(step) == "signoff"))} {
if {[info exists vars(enable_signoff_eco)] && $vars(enable_signoff_eco)} {
set command "signoffTimeDesign -reportOnly -noEcoDb -outDir $vars(rpt_dir)\n"
append commands [FF::wrap_command signoff,signoff_time_design $command]
} else {
if {$vars(enable_si_aware)} {
if {![info exists vars(time_design_options,setup)]} {
set command "timeDesign -prefix signoff -signoff -reportOnly -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign -prefix signoff -signoff -reportOnly -outDir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
} else {
if {![info exists vars(time_design_options,setup)]} {
set command "timeDesign -prefix signoff -signoff -si -reportOnly -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign -prefix signoff -signoff -si -reportOnly -outDir $vars(rpt_dir) %s\n" $vars(time_design_options,setup)]
}
}
append commands [FF::wrap_command signoff,time_design_setup $command]
if {$vars(enable_si_aware)} {
if {![info exists vars(time_design_options,hold)]} {
set command "timeDesign -prefix signoff -signoff -reportOnly -hold -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign -prefix signoff -signoff -reportOnly -hold -outDir $vars(rpt_dir) %s\n" $vars(time_design_options,hold)]
}
} else {
if {![info exists vars(time_design_options,hold)]} {
set command "timeDesign -prefix signoff -signoff -si -reportOnly -hold -outDir $vars(rpt_dir)\n"
} else {
set command [format "timeDesign -prefix signoff -signoff -si -reportOnly -hold -outDir $vars(rpt_dir) %s\n" $vars(time_design_options,hold)]
}
}
append commands [FF::wrap_command signoff,time_design_hold $command]
}
}
###############################################################################
# Dump GDS and/or OA data base
###############################################################################
if {[info exists vars(gds_layer_map)]} {
set command "streamOut $vars(design).gds.gz -mapFile $vars(gds_layer_map) "
if {[info exists vars(gds_files)]} {
append command "-merge { "
foreach file $vars(gds_files) {
if {[file exists $file]} {
append command "$file "
} else {
puts "<FF> WARNING: GDS FILE $file DOES NOT EXIST .... SKIPPING\n"
}
}
append command "}"
}
append command "\n"
append commands [FF::wrap_command signoff,stream_out $command]
}
if {[info exists vars(oasis_layer_map)]} {
set command "oasisOut $vars(design).oasis.gz -mapFile $vars(oasis_layer_map) "
if {[info exists vars(oasis_files)]} {
append command "-merge { "
foreach file $vars(oasis_files) {
if {[file exists $file]} {
append command "$file "
} else {
puts "<FF> WARNING: OASIS FILE $file DOES NOT EXIST .... SKIPPING\n"
}
}
append command "}"
}
append command "\n"
append commands [FF::wrap_command signoff,oasis_out $command]
}
# if {([info exists vars(oa_ref_lib)] && ($vars(oa_ref_lib) != "")) &&
# ([info exists vars(oa_design_lib)] && ($vars(oa_design_lib) != ""))} {
# set command "saveOaDesign $vars(oa_design_lib) $vars(design) signoff\n"
# append commands [FF::wrap_command signoff,save_oa_design $command]
# }
###############################################################################
# Dump Model for Top Level (Hierarchical Flow Only)
###############################################################################
set ptn [file tail [pwd]]
if {[info exists vars(partition_list)]} {
if {([lsearch $vars(partition_list) $ptn] != -1)} {
if {[string compare -nocase $vars(dbs_format) "fe"]==0} {
set command "createInterfaceLogic -dir $ptn.ilm\n"
} else {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "createInterfaceLogic -cellview {$vars(oa_partition_lib) $ptn abstract}\n"
} else {
set command "createInterfaceLogic -dir $ptn.ilm\n"
}
}
append commands [FF::wrap_command signoff,create_ilm $command]
} elseif {$vars(step) != "assemble"} {
append commands [FF::wrap_command signoff,unflattenIlm "unflattenIlm\n"]
}
}
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING VERIFY COMMANDS\n"
append commands "#\n"
}
###############################################################################
# Run verify commands
###############################################################################
if {!([info exists vars(enable_signoff_eco)] && $vars(enable_signoff_eco))} {
set command "summaryReport -outDir $vars(rpt_dir)\n"
append commands [FF::wrap_command signoff,summary_report $command]
}
set command "verifyConnectivity -noAntenna\n"
append commands [FF::wrap_command signoff,verify_connectivity $command]
set command "[verify_geometry_command]\n"
append commands [FF::wrap_command signoff,verify_geometry $command]
set command "verifyMetalDensity\n"
append commands [FF::wrap_command signoff,verify_metal_density $command]
if {[info exists vars(partition_list)] && ([lsearch $vars(partition_list) $ptn] != -1)} {
if {[string compare $vars(dbs_format) "fe"]==0} {
set command "verifyProcessAntenna -leffile $ptn.antenna.lef\n"
} else {
set command "verifyProcessAntenna\n"
# Not sure yet how save_abstract would be called- skip this for now.
}
} else {
set command "verifyProcessAntenna\n"
}
append commands [FF::wrap_command signoff,verify_process_antenna $command]
if {([info exists vars(enable_lvs)] && $vars(enable_lvs)) && ($vars(dbs_format) == "oa")} {
append commands [FF_EDI::create_lvs_data]
}
###############################################################################
# Load optional post signoff file (plug-in)
###############################################################################
append commands [FF::source_plug post_signoff_tcl 0]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_assemble {{format 1}} {
global vars
global errors
global env
set vars(step) assemble
set commands ""
append commands "set vars(step) $vars(step)\n"
FF_EDI::initialize_step assemble
# if {$vars(report_run_time)} {
# append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
# }
if {$vars(verbose)} {
append commands "#\n"
append commands "# ASSEMBLING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre assemble" plug-in script
###############################################################################
append commands [FF::source_plug pre_assemble_tcl]
###############################################################################
# Assemble the design
###############################################################################
set vars(ilm) false
set ilm_list [list]
set pac_list [list]
if {$vars(enable_pac)} {
foreach part $vars(partition_list) {
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "ilm"} {
lappend ilm_list $part
} else {
lappend pac_list $part
}
}
}
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
foreach ilm $vars(ilm_list) {
if {([lsearch $ilm_list $ilm] == -1) && ([lsearch $pac_list $ilm] == -1)} {
lappend ilm_list $ilm
}
}
}
if {$ilm_list != ""} {
set vars(ilm) true
}
# BCL: Added tail of subst of vars(dbs_dir)
# Note - EDIFF Hierarchical flow is currently INCOMPATIBLE with FF dir structure
# The following code appears to rely on vars(dbs_dir) always being under $vars(partition_dir)/$vars(design)
# This needs to be reconciled
if {$vars(hier_flow_type) == "2pass"} {
set partition_dir $vars(partition_dir_pass2)
} else {
set partition_dir $vars(partition_dir)
}
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_EDI::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
if {([string compare -nocase $vars(dbs_format) "oa"]==0) && ([lindex [split $vars(version) "."] 0] > 10)} {
if {[info exists vars($vars(design),assemble_step)]} {
set command "assembleDesign -topDesign {$vars(oa_partition_lib) $vars(design) $vars($vars(design),assemble_step)} -mmmcFile $mmmc_file"
} else {
set command "assembleDesign -topDesign {$vars(oa_partition_lib) $vars(design) signoff} -mmmcFile $mmmc_file"
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,assemble_step)]} {
append command "\\\n -block {$vars(oa_partition_lib) $part $vars($vars($part),assemble_step)}"
} else {
append command "\\\n -block {$vars(oa_partition_lib) $part signoff}"
}
}
}
} else {
# append commands [FF::wrap_command assemble,initialize_timing $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set assemble_command "assembleDesign -cpfFile $vars(cpf_file)"
} else {
set assemble_command "assembleDesign -mmmcFile $mmmc_file"
}
} else {
set assemble_command "assembleDesign"
}
if {[info exists vars($vars(design),assemble_dbs)]} {
set command "$assemble_command -fe -topDir $vars($vars(design),assemble_dbs)"
} elseif {[info exists vars($vars(design),assemble_step)]} {
set command "$assemble_command -fe $partition_dir/$vars(design)/$dir/$vars($vars(design),assemble_step).enc.dat"
} else {
set command "$assemble_command -fe -topDir $partition_dir/$vars(design)/$dir/signoff.enc.dat "
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,assemble_dbs)]} {
append command "\\\n -blockDir $vars($part,assemble_dbs)"
} elseif {[info exists vars($part,assemble_step)]} {
append command "\\\n -blockDir $partition_dir/$part/$dir/$vars($part,assemble_step).enc.dat"
} else {
append command "\\\n -blockDir $partition_dir/$part/$dir/signoff.enc.dat"
}
}
}
}
if {$vars(enable_pac)} {
append command "\\\n -hierDir $vars(pac_scratch_dir)"
}
append command "\n\n"
append commands [FF::wrap_command assemble,assemble_design $command]
if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
append commands "source $mmmc_file\n"
}
if {$vars(flow) == "mmmc"} {
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append commands "um::enable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
}
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load "post assemble" plug-in script
###############################################################################
append commands [FF::source_plug post_assemble_tcl 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command assemble,specify_ilm $command]
if {[info exists vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command assemble,load_ilm_non_sdc_file $command]
}
}
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command assemble,initialize_timing $command]
} elseif {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command assemble,initialize_timing $command]
}
set command [FF_EDI::update_timing mmmc 1 ]
append commands [FF::wrap_command assemble,update_timing $command]
if {[info exists vars(enable_signoff_eco)] && $vars(enable_signoff_eco)} {
append commands [FF::source_plug pre_signoff_eco_tcl 0]
set command "verifyConnectivity\n"
append commands [FF::wrap_command assemble,pre_signoff_eco_verify_connectivity $command]
set command "[verify_geometry_command]\n"
append commands [FF::wrap_command assemble,pre_signoff_eco_verify_geometry $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING SIGN-OFF ECO\n"
append commands "#\n"
}
set command [FF_EDI::delete_filler_cells]
append commands [FF::wrap_command assemble,delete_filler_cells $command]
set command "extractRC\n"
append commands [FF::wrap_command assemble,extract_rc $command]
set op [open ptn.txt w]
# dbForEachHeadPtn [dbgHead] ptr {
# set ptn [dbPtnName $ptr]
# puts $op "$ptn"
# }
foreach ptn $vars(partition_list) {
puts $op "$ptn"
}
close $op
set command "setSignoffOptMode -partitionListFile \"ptn.txt\" -optimizeReplicatedModules true\n"
append commands [FF::wrap_command assemble,signoff_time_design $command]
set command "signoffTimeDesign -reportOnly\n"
append commands [FF::wrap_command assemble,signoff_time_design $command]
set command "signoffOptDesign -setup -noEcoRoute\n"
append commands [FF::wrap_command assemble,signoff_opt_design $command]
# set command "addFiller\n"
# append commands [FF::wrap_command assemble,add_filler_cells $command]
set command "ecoRoute -handlePartition\n"
#set command "ecoRoute\n"
append commands [FF::wrap_command assemble,eco_route $command]
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command assemble,verify_litho $command]
}
append commands [FF::source_plug post_signoff_eco_tcl 0]
set command "verifyConnectivity\n"
append commands [FF::wrap_command assemble,post_signoff_eco_verify_connectivity $command]
set command "[verify_geometry_command]\n"
append commands [FF::wrap_command assemble,post_signoff_eco_verify_geometry $command]
} elseif {$vars(enable_pac)} {
set command "verifyConnectivity\n"
append commands [FF::wrap_command assemble,pre_pac_verify_connectivity $command]
set command "[verify_geometry_command]\n"
append commands [FF::wrap_command assemble,pre_pac_verify_geometry $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# DEFINING PAC MODES\n"
append commands "#\n"
}
append commands [FF::source_plug pre_pac_tcl 0]
set command ""
foreach part $pac_list {
append command "set hinst \[dbHInstName \[dbCellHInst \[dbGetCellByName $part\]\]\]\n"
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "read_only"} { set vars($part,pac_mode) "readOnly" }
append command "setModuleView -hinst \$hinst -type $vars($part,pac_mode)\n"
}
}
append command "getModuleView\n"
append commands [FF::wrap_command assemble,set_module_view $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST ASSEMBLY CLOSURE\n"
append commands "#\n"
}
set command [FF_EDI::delete_filler_cells]
append commands [FF::wrap_command assemble,delete_filler_cells $command]
set command "optDesign -postRoute -outDir $vars(rpt_dir) -prefix pac\n"
append commands [FF::wrap_command assemble,opt_design $command]
set command [FF_EDI::add_filler_cells]
append commands [FF::wrap_command assemble,add_filler_cells $command]
#########################################################################
# Optionally run LPA
#########################################################################
if {$vars(verify_litho)} {
# BCL: Added subst to handle dererencing variables
file mkdir [subst $vars(rpt_dir)]/LPA/DMC
set command "verifyLitho -routingLayersOnly -techFile $vars(lpa_tech_file) -dir $vars(rpt_dir)/LPA\n"
append command "violationBrowser -all -no_display_false\n"
append command "loadViolationReport -type CDNLitho -filename $vars(rpt_dir)/LPA/DMC/merged.hif\n"
append commands [FF::wrap_command assemble,verify_litho $command]
}
append commands [FF::source_plug post_pac_tcl 0]
set command "verifyConnectivity\n"
append commands [FF::wrap_command assemble,post_pac_verify_connectivity $command]
set command "[verify_geometry_command]\n"
append commands [FF::wrap_command assemble,post_pac_verify_geometry $command]
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
append commands [FF_EDI::run_signoff $format]
# if {$vars(makefile)} {
# append commands "if {\[info exists env(VPATH)\]} {\n"
# append commands "exec /bin/touch \$env(VPATH)/assemble\n"
# append commands "}\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_rebudget {{format 1}} {
global vars
global errors
global env
set vars(step) rebudget
set commands ""
# append commands "set vars(step) $vars(step)\n"
FF_EDI::initialize_step $vars(step)
# if {$vars(report_run_time)} {
# append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
# }
if {!$vars(enable_flexilm)} {
append commands "\nif {\[file isfile $vars(pac_scratch_dir)/.pacFlowLock\]} {\n"
append commands " file delete $vars(pac_scratch_dir)/.pacFlowLock\n"
append commands "}\n"
} else {
# append commands "if {\[file isfile $vars(script_dir)/view_definition.tcl]} {\n"
# append commands " file copy -force $vars(script_dir)/view_definition.tcl $vars(partition_dir)/$vars(design)/viewDefinition.tcl\n"
# append commands "}\n"
}
if {$vars(verbose)} {
append commands "#\n"
append commands "# ASSEMBLING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre rebudget" plug-in script
###############################################################################
append commands [FF::source_plug pre_rebudget_tcl]
###############################################################################
# Get the FlexILM ECO paths
###############################################################################
if {$vars(enable_flexilm)} {
append commands "if {\[file isfile \$env(VPATH)/flexilm\]} {\n"
append commands " source \$env(VPATH)/flexilm\n"
append commands "}\n"
}
###############################################################################
# Assemble the design
###############################################################################
set vars(ilm) false
set ilm_list [list]
set pac_list [list]
if {$vars(enable_pac)} {
foreach part $vars(partition_list) {
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "ilm"} {
lappend ilm_list $part
} else {
lappend pac_list $part
}
}
}
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
foreach ilm $vars(ilm_list) {
if {([lsearch $ilm_list $ilm] == -1) && ([lsearch $pac_list $ilm] == -1)} {
lappend ilm_list $ilm
}
}
}
if {$ilm_list != ""} {
set vars(ilm) true
}
# BCL: Added tail of subst of vars(dbs_dir)
# Note - EDIFF Hierarchical flow is currently INCOMPATIBLE with FF dir structure
# The following code appears to rely on vars(dbs_dir) always being under $vars(partition_dir)/$vars(design)
# This needs to be reconciled
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_EDI::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
if {([string compare -nocase $vars(dbs_format) "oa"]==0) && ([lindex [split $vars(version) "."] 0] > 10)} {
if {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "assembleDesign -topDesign {$vars(oa_partition_lib) $vars(design) $vars($vars(design),rebudget_assemble_step)} -mmmcFile $mmmc_file"
} else {
set command "assembleDesign -topDesign {$vars(oa_partition_lib) $vars(design) cts} -mmmcFile $mmmc_file"
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -block {$vars(oa_partition_lib) $part $vars($vars($part),rebudget_assemble_step)}"
} else {
append command "\\\n -block {$vars(oa_partition_lib) $part cts}"
}
}
}
} else {
# append commands [FF::wrap_command rebudget,initialize_timing $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set assemble_command "assembleDesign -cpfFile $vars(cpf_file)"
} else {
set assemble_command "assembleDesign -mmmcFile $mmmc_file"
}
} else {
set assemble_command "assembleDesign"
}
if {[info exists vars($vars(design),rebudget_assemble_dbs)]} {
set command "$assemble_command -fe -topDir $vars($vars(design),rebudget_assemble_dbs)"
} elseif {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "$assemble_command -fe $vars(partition_dir)/$vars(design)/$dir/$vars($vars(design),rebudget_assemble_step).enc.dat"
} else {
if {$vars(enable_flexilm)} {
# set command "$assemble_command \\\n -fe \\\n -topDir $vars(partition_dir_pass2)/$vars(design) "
set command "$assemble_command \\\n -fe \\\n -topDir $vars(partition_dir)_FLEXILM/$vars(design) "
} else {
set command "$assemble_command -fe -topDir $vars(partition_dir)/$vars(design)/$dir/cts.enc.dat "
}
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,rebudget_assemble_dbs)]} {
append command "\\\n -blockDir $vars($part,rebudget_assemble_dbs)"
} elseif {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -blockDir $vars(partition_dir)/$part/$dir/$vars($part,rebudget_assemble_step).enc.dat"
} else {
if {$vars(enable_flexilm)} {
append command "\\\n -blockDir \$vars($part,cdtv) "
} else {
append command "\\\n -blockDir $vars(partition_dir)/$part/$dir/cts.enc.dat"
}
}
}
}
}
if {$vars(enable_pac)} {
append command "\\\n -hierDir $vars(pac_scratch_dir)"
}
append command "\n"
append commands [FF::wrap_command $vars(step),assemble_design $command]
if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
append commands "source $mmmc_file\n"
}
if {$vars(flow) == "mmmc"} {
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load "post rebudget" plug-in script
###############################################################################
append commands [FF::source_plug post_rebudget_tcl 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command $vars(step),specify_ilm $command]
if {[info exists vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
} elseif {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
}
if {!$vars(enable_flexilm)} {
set command [FF_EDI::update_timing mmmc ]
append commands [FF::wrap_command $vars(step),update_timing $command]
}
if {$vars(enable_pac)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# DEFINING PAC MODES\n"
append commands "#\n"
}
append commands [FF::source_plug pre_pac_tcl 0]
set command ""
foreach part $pac_list {
append command "set hinst \[dbHInstName \[dbCellHInst \[dbGetCellByName $part\]\]\]\n"
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "read_only"} { set vars($part,pac_mode) "readOnly" }
append command "setModuleView -hinst \$hinst -type $vars($part,pac_mode)\n"
}
}
append command "getModuleView\n"
append commands [FF::wrap_command $vars(step),set_module_view $command]
if {!$vars(enable_flexilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING POST ASSEMBLY CLOSURE\n"
append commands "#\n"
}
set command "optDesign -postCTS -outDir $vars(rpt_dir) -prefix pac\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
append commands [FF::source_plug post_pac_tcl 0]
}
}
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "setTrialRouteMode -handlePartitionComplex true -honorPin true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode1 $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route1 $command]
} else {
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence . -earlyGlobalRoutePartitionHonorPin .\n"
append commands [FF::wrap_command $vars(step),set_route_mode1 $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route1 $command]
}
append command "deriveTimingBudget -noTrialIPO -noConstantModel\n"
append commands [FF::wrap_command $vars(step),derive_timing_budget $command]
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "saveDesign -cellview {$vars(oa_design_lib) $vars(design) budget}\n"
} else {
set command "saveOaDesign $vars(oa_design_lib) $vars(design) budget\n"
}
} else {
set command "saveDesign $vars(dbs_dir)/budget.enc -compress\n"
}
append commands [FF::wrap_command $vars(step),save_design,budget $command]
###############################################################################
# Partition and save the partitions into the
# directory PARTITION
###############################################################################
# append commands [FF::source_plug pre_partition_tcl]
# set command "set ptngPtnTimingLibFormat lib\npartition -buildScan\n"
set command "partition -buildScan\n"
append commands [FF::wrap_command $vars(step),partition $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {([string compare $vars(dbs_format) "oa"]==0)} {
if {$vars(hier_flow_type) == "1pass"} {
set command "savePartition -ptnLib $vars(oa_partition_lib) -dir $vars(partition_dir)\n"
} else {
set command "savePartition -ptnLib $vars(oa_partition_lib) -dir $vars(partition_dir_pass2)\n"
}
} else {
if {$vars(hier_flow_type) == "1pass"} {
set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
} else {
set command "savePartition -dir $vars(partition_dir_pass2) -def -scanDef\n"
}
}
} else {
set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
}
append commands [FF::wrap_command $vars(step),save_partition $command]
# append commands [FF::source_plug post_partition_tcl]
if {$vars(use_flexmodels) && $vars(flexmodel_as_ptn)} {
# set command "replace_proto_model \\\n"
# append command " -pre_ft_dir $vars(eco_dir)/pre_ft \\\n"
# append command " -post_ft_dir $vars(eco_dir)/post_ft \\\n"
# append command " -ptn_dir $vars(partition_dir) \\\n"
# append command " -ptn_full_netlist_dir ./temp_netlist_dir \\\n"
# append command " -out_dir $vars(partition_dir)\n"
set command "replace_proto_model \\\n"
append command " -ptn_dir $vars(partition_dir) \\\n"
append command " -out_dir $vars(partition_dir)\n"
append commands [FF::wrap_command $vars(step),replace_proto_model $command]
}
append commands "#---------------------------------------------------------------------\n"
append commands "# <FF> GENERATING REPORTS\n"
append commands "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
######################################################################
# Verify power domain
######################################################################
set command "verifyPowerDomain -bind -gconn"
append command " -isoNetPD $vars(rpt_dir)/$vars(step).isonets.rpt"
append command " -xNetPD $vars(rpt_dir)/$vars(step).xnets.rpt\n"
append commands [FF::wrap_command $vars(step),verify_power_domain $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "runCLP "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
# if {$vars(makefile)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
# }
# if {$vars(enable_flexilm)} {
# append commands "# Copy Makefiles in case they get deleted during the flow ...\n"
# foreach part [concat $vars(design) $vars(partition_list)] {
# append commands "file copy -force $vars(script_dir)/$part.Makefile $vars(partition_dir_pass2)/$part/Makefile\n"
# }
# append commands "file copy -force $vars(partition_dir)/Makefile $vars(partition_dir_pass2)/Makefile\n"
# append commands "file copy -force $vars(partition_dir)/Makefile.partition $vars(partition_dir_pass2)/Makefile.partition\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_assemble_flexilm {{format 1}} {
global vars
global errors
global env
set vars(step) assemble_flexilm
set commands ""
# append commands "set vars(step) $vars(step)\n"
FF_EDI::initialize_step $vars(step)
if {$vars(verbose)} {
append commands "#\n"
append commands "# ASSEMBLING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre rebudget" plug-in script
###############################################################################
append commands [FF::source_plug pre_rebudget_tcl]
###############################################################################
# Assemble the design
###############################################################################
set vars(ilm) false
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
set vars(ilm) true
} else {
set vars(ilm_list) ""
}
# BCL: Added tail of subst of vars(dbs_dir)
# Note - EDIFF Hierarchical flow is currently INCOMPATIBLE with FF dir structure
# The following code appears to rely on vars(dbs_dir) always being under $vars(partition_dir)/$vars(design)
# This needs to be reconciled
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_EDI::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
if {([string compare -nocase $vars(dbs_format) "oa"]==0) && ([lindex [split $vars(version) "."] 0] > 10)} {
if {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "assembleDesign -topDesign {$vars(oa_partition_lib) $vars(design) $vars($vars(design),rebudget_assemble_step)} -mmmcFile $mmmc_file"
} else {
set command "assembleDesign -topDesign {$vars(oa_partition_lib) $vars(design) cts} -mmmcFile $mmmc_file"
}
foreach part $vars(partition_list) {
if {[lsearch $ilm_list $part] == -1} {
if {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -block {$vars(oa_partition_lib) $part $vars($vars($part),rebudget_assemble_step)}"
} else {
append command "\\\n -block {$vars(oa_partition_lib) $part cts}"
}
}
}
} else {
# append commands [FF::wrap_command rebudget,initialize_timing $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set assemble_command "assembleDesign -cpfFile $vars(cpf_file)"
} else {
set assemble_command "assembleDesign -mmmcFile $mmmc_file"
}
} else {
set assemble_command "assembleDesign"
}
if {[info exists vars($vars(design),rebudget_assemble_dbs)]} {
set command "$assemble_command -defMerge -topDir $vars($vars(design),rebudget_assemble_dbs)"
} elseif {[info exists vars($vars(design),rebudget_assemble_step)]} {
set command "$assemble_command -defMerge $vars(partition_dir)/$vars(design)/$dir/$vars($vars(design),rebudget_assemble_step).enc.dat"
} else {
if {$vars(enable_flexilm)} {
# set command "$assemble_command \\\n -defMerge \\\n -topDir $vars(partition_dir_pass2)/$vars(design) "
set command "$assemble_command \\\n -defMerge \\\n -topDir $vars(partition_dir)_PRECTS/$vars(design) "
} else {
set command "$assemble_command -defMerge -topDir $vars(partition_dir)/$vars(design)/$dir/cts.enc.dat "
}
}
foreach part $vars(partition_list) {
if {[lsearch $vars(ilm_list) $part] == -1} {
if {[info exists vars($part,rebudget_assemble_dbs)]} {
append command "\\\n -blockDir $vars($part,rebudget_assemble_dbs)"
} elseif {[info exists vars($part,rebudget_assemble_step)]} {
append command "\\\n -blockDir $vars(partition_dir)/$part/$dir/$vars($part,rebudget_assemble_step).enc.dat"
} else {
if {$vars(enable_flexilm)} {
append command "\\\n -blockDir $vars(partition_dir)_PRECTS/$part/${part}_postECO.enc.dat"
} else {
append command "\\\n -blockDir $vars(partition_dir)/$part/$dir/cts.enc.dat"
}
}
}
}
}
append command "\n"
append commands [FF::wrap_command $vars(step),assemble_design $command]
if {$vars(capture_metrics)} {
append commands "um::enable_metrics -on\n"
append commands "um::push_snapshot_stack\n"
}
append commands [FF::source_plug always_source_tcl]
set command ""
# Additional timing setup
if {[info exists vars($vars(design),latency_sdc)]} {
append command "foreach mode \[all_constraint_modes -active\] {\n"
append command " set sdc_files \[get_constraint_mode \$mode -sdc_files\]\n"
append command " set sdc_list \[concat \$sdc_files $vars($vars(design),latency_sdc)\]\n"
append command " update_constraint_mode -name \$mode -sdc_files \$sdc_list\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {[info exists vars($ptn,$view,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,$view,latency_sdc)
} elseif {[info exists vars($ptn,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,latency_sdc)
} else {
set latency($view,$ptn) "none"
}
}
}
set command ""
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {$latency($view,$ptn) != "none"} {
append command " setPtnUserCnsFile -view $view -fileName $latency($view,$ptn) -ptnName $ptn\n"
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),set_ptn_user_cns_file $command]
}
if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
append commands "source $mmmc_file\n"
}
if {$vars(flow) == "mmmc"} {
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
}
###############################################################################
# Load "post assemble_flexilm" plug-in script
###############################################################################
append commands [FF::source_plug post_flexilm 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $vars(ilm_list) {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command $vars(step),specify_ilm $command]
if {[info exists vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
} elseif {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
}
# if {!$vars(enable_flexilm)} {
# set command [FF_EDI::update_timing mmmc ]
# append commands [FF::wrap_command $vars(step),update_timing $command]
# }
set command ""
foreach name $vars(partition_list) {
append command "setPtnPinStatus -cell $name -pin * -status placed\n"
}
append commands [FF::wrap_command $vars(step),set_ptn_pin_status $command]
set command "dbDeleteTrialRoute\n"
append commands [FF::wrap_command $vars(step),delete_trial_route $command]
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "setTrialRouteMode -handlePartitionComplex true -honorPin false\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route $command]
} else {
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence . -earlyGlobalRoutePartitionHonorPin {}\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route $command]
}
set command ""
append command "createActiveLogicView -type flatTop\n"
append command "timeDesign -preCTS -outDir $vars(rpt_dir) -prefix assemble_prects_flexilm\n"
append command "clearActiveLogicView\n"
append commands [FF::wrap_command $vars(step),create_active_logic_view $command]
# append command "deriveTimingBudget -noTrialIPO -noConstantModel\n"
# append commands [FF::wrap_command $vars(step),derive_timing_budget $command]
# if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
# if {[lindex [split $vars(version) "."] 0] > 10} {
# set command "saveDesign -cellview {$vars(oa_design_lib) $vars(design) budget}\n"
# } else {
# set command "saveOaDesign $vars(oa_design_lib) $vars(design) budget\n"
# }
# } else {
# set command "saveDesign $vars(dbs_dir)/budget.enc -compress\n"
# }
# append commands [FF::wrap_command $vars(step),save_design,budget $command]
###############################################################################
# Partition and save the partitions into the
# directory PARTITION
###############################################################################
# append commands [FF::source_plug pre_partition_tcl]
# set command "set ptngPtnTimingLibFormat lib\npartition -buildScan\n"
# set command "partition -buildScan\n"
# append commands [FF::wrap_command $vars(step),partition $command]
# if {[lindex [split $vars(version) "."] 0] > 10} {
# if {([string compare $vars(dbs_format) "oa"]==0)} {
# if {$vars(hier_flow_type) == "1pass"} {
# set command "savePartition -ptnLib $vars(oa_partition_lib) -dir $vars(partition_dir)\n"
# } else {
# set command "savePartition -ptnLib $vars(oa_partition_lib) -dir $vars(partition_dir_pass2)\n"
# }
# } else {
# if {$vars(hier_flow_type) == "1pass"} {
# set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
# } else {
# set command "savePartition -dir $vars(partition_dir_pass2) -def -scanDef\n"
# }
# }
# } else {
# set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
# }
# append commands [FF::wrap_command $vars(step),save_partition $command]
# append commands [FF::source_plug post_partition_tcl]
append commands "#---------------------------------------------------------------------\n"
append commands "# <FF> GENERATING REPORTS\n"
append commands "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
######################################################################
# Verify power domain
######################################################################
set command "verifyPowerDomain -bind -gconn"
append command " -isoNetPD $vars(rpt_dir)/$vars(step).isonets.rpt"
append command " -xNetPD $vars(rpt_dir)/$vars(step).xnets.rpt\n"
append commands [FF::wrap_command $vars(step),verify_power_domain $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "runCLP "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
# if {$vars(makefile)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
# }
# if {$vars(enable_flexilm)} {
# append commands "# Copy Makefiles in case they get deleted during the flow ...\n"
# foreach part [concat $vars(design) $vars(partition_list)] {
# append commands "file copy -force $vars(script_dir)/$part.Makefile $vars(partition_dir_pass2)/$part/Makefile\n"
# }
# append commands "file copy -force $vars(partition_dir)/Makefile $vars(partition_dir_pass2)/Makefile\n"
# append commands "file copy -force $vars(partition_dir)/Makefile.partition $vars(partition_dir_pass2)/Makefile.partition\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_flexilm {{format 1}} {
global vars
global errors
global env
set vars(step) flexilm
set commands ""
# append commands "set vars(step) $vars(step)\n"
FF_EDI::initialize_step flexilm
# if {$vars(report_run_time)} {
# append commands "set vars($vars(step),start_time) \[clock seconds\]\n"
# }
if {$vars(verbose)} {
append commands "#\n"
append commands "# RESTORING DESIGN\n"
append commands "#\n"
}
###############################################################################
# Load "pre flexilm" plug-in script
###############################################################################
append commands [FF::source_plug pre_flexilm_tcl]
###############################################################################
# Restore the design
###############################################################################
set vars(ilm) false
set ilm_list [list]
set pac_list [list]
if {$vars(enable_pac)} {
foreach part $vars(partition_list) {
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "ilm"} {
lappend ilm_list $part
} else {
lappend pac_list $part
}
}
}
}
if {[info exists vars(ilm_list)] && ($vars(ilm_list) != "")} {
foreach ilm $vars(ilm_list) {
if {([lsearch $ilm_list $ilm] == -1) && ([lsearch $pac_list $ilm] == -1)} {
lappend ilm_list $ilm
}
}
}
if {$ilm_list != ""} {
set vars(ilm) true
}
# BCL: Added tail of subst of vars(dbs_dir)
# Note - EDIFF Hierarchical flow is currently INCOMPATIBLE with FF dir structure
# The following code appears to rely on vars(dbs_dir) always being under $vars(partition_dir)/$vars(design)
# This needs to be reconciled
set dir [file tail [subst $vars(dbs_dir)]]
if {[lindex [split $vars(version) "."] 0] > 10} {
set command [FF_EDI::initialize_timing mmmc]
if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set mmmc_file $vars(script_dir)/incr_view_definition.tcl
} else {
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file $vars(view_definition_tcl)
} else {
set mmmc_file $vars(script_dir)/view_definition.tcl
}
}
}
# append commands "setLimitedAccessFeature encFlexILM 1\n"
append commands "file copy -force $vars(script_dir)/view_definition.tcl $vars(partition_dir)/$vars(design)/$vars(dbs_dir)/prects.enc.dat/viewDefinition.tcl\n"
set cwd [exec pwd]
append commands "cd $vars(partition_dir)/$vars(design)\n"
# set command "restoreDesign . $vars(design)\n"
set command "restoreDesign $vars(dbs_dir)/prects.enc.dat $vars(design)\n"
append commands [FF::wrap_command flexilm,restore_design $command]
# if {([lindex [split $vars(version) "."] 0] > 10) && $vars(cpf_timing)} {
# append commands "source $mmmc_file\n"
# }
append commands [FF::source_plug always_source_tcl]
###############################################################################
# Load "post flexilm" plug-in script
###############################################################################
append commands [FF::source_plug post_flexilm 0]
###############################################################################
# Specify ILMs if defined
###############################################################################
if {$vars(ilm)} {
if {$vars(verbose)} {
append commands "#\n"
append commands "# SPECIFYING ILMs\n"
append commands "#\n"
}
set command ""
foreach cell $ilm_list {
if {[info exists vars($cell,ilm_dir)] && [file isdirectory $vars($cell,ilm_dir)]} {
append command "specifyIlm -cell $cell -dir $vars($cell,ilm_dir)\n"
} else {
puts "<FF> WARNING: ILM DIRECTORY MISSING FOR $cell ... SKIPPING"
}
}
append commands [FF::wrap_command $vars(step),specify_ilm $command]
if {[info exists vars(ilm_non_sdc_file)]} {
if {[lindex [split $vars(version) "."] 0] <= 10} {
set command "loadTimingCon -ilmNonSdcFile $vars(ilm_non_sdc_file)\n"
} else {
set command "setIlmNonSdcConstraintFile $vars(ilm_non_sdc_file)\n"
}
append commands [FF::wrap_command $vars(step),load_ilm_non_sdc_file $command]
}
}
if {[lindex [split $vars(version) "."] 0] < 14} {
append commands [FF_EDI::load_power_intent]
} else {
append commands [FF_NOVUS::load_power_intent]
}
# if {[info exists vars(cpf_file)] && $vars(cpf_timing)} {
set command [FF_EDI::initialize_timing mmmc]
append commands [FF::wrap_command $vars(step),initialize_timing $command]
# }
# set command [FF_EDI::update_timing mmmc ]
# append commands [FF::wrap_command $vars(step),update_timing $command]
foreach mode [concat $vars(active_setup_views) $vars(active_hold_views)] {
# exec /bin/touch empty.sdc
# set command "update_constraint_mode -name $mode -sdc_files empty.sdc -ilm_sdc_files \[get_constraint_mode $mode -sdc_files\]\n"
set command "update_constraint_mode -name $mode -ilm_sdc_files \[get_constraint_mode $mode -sdc_files\]\n"
append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
append commands "cd $cwd\n"
set command ""
foreach part $vars(partition_list) {
append command "set_module_model -cell $part \\\n"
append command "-type flexIlm \\\n"
append command "-dir $vars(partition_dir)/$part/$part.flexilm\n"
}
append commands [FF::wrap_command $vars(step),set_module_model $command]
set command "commit_module_model\n"
append commands [FF::wrap_command $vars(step),commit_module_model $command]
set command ""
foreach part $vars(partition_list) {
append command "setModuleView -partition $part -type interface\n"
}
append commands [FF::wrap_command $vars(step),set_module_view $command]
set command "getModuleView\n"
append commands [FF::wrap_command $vars(step),get_module_view $command]
if {$vars(flow) == "mmmc"} {
set command [FF_EDI::derate_timing mmmc]
append commands [FF::wrap_command $vars(step),derate_timing $command]
set command ""
# foreach mode $vars(constraint_modes) {
# append command "update_constraint_mode -name $mode -sdc_files \"$vars($mode,pre_cts_sdc)\"\n"
# }
# append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
#set_analysis_view -setup [all_setup_analysis_views] -hold [all_hold_analysis_views]
#Puts "<FF> SETUP -> [all_setup_analysis_views]"
#Puts "<FF> HOLD -> [all_hold_analysis_views]"
set command "createActiveLogicView -type topCritical -preCTS\n"
append commands [FF::wrap_command $vars(step),create_active_logic_view $command]
set command "setHierMode -optStage preCTS\n"
append commands [FF::wrap_command $vars(step),set_hier_mode $command]
set command "setOptMode -addInstancePreFix FlexILMI_ -addNetPreFix FlexILMN_\n"
append commands [FF::wrap_command $vars(step),set_opt_mode $command]
append commands [FF::source_plug pre_flexilm_tcl 0]
set command ""
foreach part $pac_list {
append command "set hinst \[dbHInstName \[dbCellHInst \[dbGetCellByName $part\]\]\]\n"
if {[info exists vars($part,pac_mode)]} {
if {$vars($part,pac_mode) == "read_only"} { set vars($part,pac_mode) "readOnly" }
append command "setModuleView -hinst \$hinst -type $vars($part,pac_mode)\n"
}
}
append command "getModuleView\n"
append commands [FF::wrap_command $vars(step),set_module_view $command]
if {$vars(verbose)} {
append commands "#\n"
append commands "# RUNNING FLEXILM OPTIMIZATION\n"
append commands "#\n"
}
set command "optDesign -preCTS -outDir $vars(rpt_dir) -prefix flexilm\n"
append commands [FF::wrap_command $vars(step),opt_design $command]
append commands [FF::source_plug post_flexilm_tcl 0]
# set command "setTrialRouteMode -handlePartitionComplex true -honorPin true\n"
# append command "trialRoute\n"
# append command "deriveTimingBudget -noConstantModel\n"
# append commands [FF::wrap_command $vars(step),derive_timing_budget $command]
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "saveDesign -cellview {$vars(oa_design_lib) $vars(design) flexilm}\n"
} else {
set command "saveOaDesign $vars(oa_design_lib) $vars(design) flexilm\n"
}
} else {
set command "saveDesign $vars(dbs_dir)/flexilm.enc -compress\n"
}
append commands [FF::wrap_command $vars(step),save_design $command]
set command "clearActiveLogicView\n"
append commands [FF::wrap_command $vars(step),clear_active_logic_view $command]
### save postOpt data and commit ECO ###
# set command "update_partition -flexIlmECO \\\n"
# append command " -goldenDir $vars(partition_dir) \\\n"
# append command " -flexIlmDir $vars(partition_dir)_FLEXILM\n"
# append commands [FF::wrap_command $vars(step),update_partition $command]
set command "update_partition -flexIlmECO \\\n"
foreach part $vars(partition_list) {
append command " -goldenBlockDir $vars(partition_dir)/$part/$vars(dbs_dir)/prects.enc.dat \\\n"
}
append command " -flexIlmDir $vars(partition_dir)_FLEXILM\n"
append commands [FF::wrap_command $vars(step),update_partition $command]
set command "report_resource -end opt_flexIlm\n"
append commands [FF::wrap_command $vars(step),report_resource $command]
append commands "#---------------------------------------------------------------------\n"
append commands "# <FF> GENERATING REPORTS\n"
append commands "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
if {[info exists vars(power_analysis_view)] && ($vars(power_analysis_view) != "")} {
set command "report_power -view $vars(power_analysis_view) -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
} else {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
}
append commands [FF::wrap_command $vars(step),report_power $command]
}
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
######################################################################
# Verify power domain
######################################################################
set command "verifyPowerDomain -bind -gconn"
append command " -isoNetPD $vars(rpt_dir)/$vars(step).isonets.rpt"
append command " -xNetPD $vars(rpt_dir)/$vars(step).xnets.rpt\n"
append commands [FF::wrap_command $vars(step),verify_power_domain $command]
######################################################################
# Run CLP
######################################################################
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "runCLP "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
} else {
if {![info exists vars(clp_warning)]} {
puts "<FF> WARNING: UNABLE TO RUN CLP ... PLEASE MAKE SURE IT IS IN YOUR PATH"
set vars(clp_warning) true
}
}
}
if {!$vars(codegen)} {
uplevel #0 eval $commands
set commands ""
}
# if {$vars(makefile)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "set op \[open $env(VPATH)/flexilm w\]\n"
foreach part $vars(partition_list) {
append commands "puts \$op \"set vars($part,cdtv) \$::Rda_CDTV::ilmDataInfo($part,blockDir)\"\n"
}
append commands "close \$op\n"
# foreach part $vars(partition_list) {
# append commands "file copy -force $vars(partition_dir_pass2)/$part/Makefile $vars(partition_dir_pass2)/$part.Makefile\n"
# }
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
# }
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_partition_place {{format 1}} {
global vars
global errors
global env
set vars(step) partition_place
set vars(hier) true
if {[info exists vars(time_design_options,setup)]} {
set tmp_time_design_options_setup $vars(time_design_options,setup)
} else {
set vars(time_design_options,setup) ""
}
set commands ""
if {!$vars(use_flexmodels)} {
# Initialise the design if not using flexmodels
if {$vars(codegen)} {
append commands [FF_EDI::run_init $format]
} else {
FF_EDI::run_init $format
}
}
if {$vars(use_proto_net_delay_model)} {
if {!$vars(use_flexmodels)} {
set command "catch {exec rm -rf proto_model_BACKUP}\ncatch {exec mv -f proto_model proto_model_BACKUP}\n"
append commands [FF::wrap_command $vars(step),proto_model_BACKUP $command]
set command "create_ps_per_micron_model\n"
append commands [FF::wrap_command $vars(step),create_ps_per_micron_model $command]
}
set command "timeDesign -proto -prePlace -prefix preplace -outDir $vars(rpt_dir)\n"
append commands [FF::wrap_command $vars(step),time_design $command]
} else {
set command "timeDesign -prePlace -prefix preplace -outDir $vars(rpt_dir)\n"
append commands [FF::wrap_command $vars(step),time_design $command]
}
if {$vars(use_flexmodels)} {
set command "report_proto_model -created\n"
append commands [FF::wrap_command $vars(step),report_proto_model $command]
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "saveDesign -cellview {$vars(oa_design_lib) $vars(design) init}\n"
} else {
set command "saveOaDesign $vars(oa_design_lib) $vars(design) init\n"
}
} else {
if {($vars(step) != "partition_place")} {
set command "saveDesign $vars(dbs_dir)/init.enc -compress\n"
} else {
set command ""
}
}
append commands [FF::wrap_command $vars(step),save_design,init $command]
set command ""
# Additional timing setup
if {[info exists vars($vars(design),latency_sdc)]} {
append command "foreach mode \[all_constraint_modes -active\] {\n"
append command " set sdc_files \[get_constraint_mode \$mode -sdc_files\]\n"
append command " set sdc_list \[concat \$sdc_files $vars($vars(design),latency_sdc)\]\n"
append command " update_constraint_mode -name \$mode -sdc_files \$sdc_list\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),update_constraint_mode $command]
}
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {[info exists vars($ptn,$view,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,$view,latency_sdc)
} elseif {[info exists vars($ptn,latency_sdc)]} {
set latency($view,$ptn) $vars($ptn,latency_sdc)
} else {
set latency($view,$ptn) "none"
}
}
}
set command ""
foreach view [concat $vars(setup_analysis_views) $vars(hold_analysis_views)] {
foreach ptn $vars(partition_list) {
if {$latency($view,$ptn) != "none"} {
append command " setPtnUserCnsFile -view $view -fileName $latency($view,$ptn) -ptnName $ptn\n"
}
}
}
if {$command != ""} {
append commands [FF::wrap_command $vars(step),set_ptn_user_cns_file $command]
}
# Insert feedthrough and trial route, as appropriate
set do_trial_route_time_design 1
# Pre-placement
if {[info exists vars(place,set_place_mode,skip)]} {
set cache_skip_place_mode $vars(place,set_place_mode,skip)
}
set vars(place,set_place_mode,skip) 1
if {[info exists vars(place,place_design,skip)]} {
set cache_skip_place_design $vars(place,place_design,skip)
}
set vars(place,place_design,skip) 1
append command "if {\[dbGet -e top.ptns.clones\] != \"\"} {\n"
append command " alignPtnClone\n"
append command "}\n"
append commands [FF::wrap_command $vars(step),align_partition_clone $command]
set vars(hier_case) "$vars(use_flexmodels)$vars(placement_based_ptn)$vars(abutted_design)$vars(insert_feedthrough)"
# Disable scan reorder for partitioning flow
# set command "setPlaceMode -reorderScan false\n"
# append commands [FF::wrap_command $vars(step),set_place_mode $command]
switch $vars(hier_case) {
"0000" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
}
"0001" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0010" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0011" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0100" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0101" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0110" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"0111" {
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
}
"1000" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true \n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "setTrialRouteMode -floorplanMode true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
}
"1001" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true \n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "setTrialRouteMode -floorplanMode true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
}
"1010" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true \n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "setTrialRouteMode -floorplanMode true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
}
"1011" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true \n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
set command "set_proto_mode -place_effort default\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "setTrialRouteMode -floorplanMode true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
}
"1100" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
}
"1101" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
}
"1110" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
}
}
"1111" {
set command "setPlaceMode -place_global_cong_effort auto -place_global_clock_gate_aware true -place_global_place_io_pins true -fp true\n"
append commands [FF::wrap_command $vars(step),set_place_mode $command]
if {!$vars(flexmodel_as_ptn)} {
set command "set_proto_model_physical_constraint -type soft_guide\n"
append commands [FF::wrap_command $vars(step),set_proto_model_physical_constraint $command]
}
}
}
if {$vars(use_proto_net_delay_model)} {
set command "set_proto_mode -timing_net_delay_model use_actual_wire\n"
append commands [FF::wrap_command $vars(step),set_proto_model $command]
}
# Place design
set save $vars(place_opt_design)
if {$vars(codegen)} {
append commands [FF_EDI::run_place $format]
} else {
uplevel #0 eval $commands
FF_EDI::run_place $format
set commands ""
}
set vars(place_opt_design) $save
if {[info exists cache_skip_place_mode]} {
set vars(place,set_place_mode,skip) $cache_skip_place_mode
} else {
set vars(place,set_place_mode,skip) false
}
if {[info exists cache_skip_place_mode]} {
set vars(place,place_design,skip) $cache_skip_place_design
} else {
set vars(place,place_design,skip) false
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "saveDesign -cellview {$vars(oa_design_lib) $vars(design) place}\n"
} else {
set command "saveOaDesign $vars(oa_design_lib) $vars(design) place\n"
}
} else {
set command "saveDesign $vars(dbs_dir)/place.enc -compress\n"
}
append commands [FF::wrap_command $vars(step),save_design $command]
# Post-placement
switch $vars(hier_case) {
"0000" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "setTrialRouteMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route $command]
} else {
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route $command]
}
}
"0001" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setTrialRouteMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_2 $command]
} else {
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_2 $command]
}
}
"0010" {
# set command "setTrialRouteMode -handlePartitionComplex true\n"
# append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
# set command "trialRoute\n"
# append commands [FF::wrap_command $vars(step),trial_route $command]
}
"0011" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setTrialRouteMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_2 $command]
} else {
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_2 $command]
}
}
"0100" {
# append command "timeDesign -prects -prefix place -outDir $vars(rpt_dir)\n"
# append commands [FF::wrap_command $vars(step),time_design $command]
}
"0101" {
set command "insertPtnFeedthrough -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
}
"0110" {
# append command "timeDesign -prects -prefix place -outDir $vars(rpt_dir)\n"
# append commands [FF::wrap_command $vars(step),time_design $command]
}
"0111" {
set command "insertPtnFeedthrough -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
}
"1000" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "setTrialRouteMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route $command]
} else {
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route $command]
}
}
"1001" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setTrialRouteMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_2 $command]
} else {
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_2 $command]
}
}
"1010" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "setTrialRouteMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route $command]
} else {
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route $command]
}
}
"1011" {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setTrialRouteMode -handlePartitionComplex true\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
set command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route_2 $command]
} else {
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_1 $command]
set command "insertPtnFeedthrough -routeBased -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route_2 $command]
}
}
"1100" {
}
"1101" {
set command "insertPtnFeedthrough -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
}
"1110" {
set do_trial_route_time_design 0
}
"1111" {
set command "insertPtnFeedthrough -saveTopoFile topo.txt -netMapping netmapping.txt -doubleBuffer\n"
append commands [FF::wrap_command $vars(step),insert_ptn_feedthrough $command]
}
}
if {$vars(use_proto_net_delay_model)} {
set command "timeDesign -proto -prects -prefix place -outDir $vars(rpt_dir)\n"
} else {
set command "timeDesign -prects -prefix place -outDir $vars(rpt_dir)\n"
}
append commands [FF::wrap_command $vars(step),time_design $command]
# Output or run the generated commands
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_assign_pin {{format 1}} {
global vars
global errors
global env
set vars(step) assign_pin
set vars(hier) true
set commands ""
###############################################################################
# Assign partition pins via plug-in as this the
# pitch, depth, and layer values are design specific
# Also, verify the pin assignment and fix them
###############################################################################
append commands [FF::source_plug pre_assign_pin_tcl]
set command "assignPtnPin\n"
append commands [FF::wrap_command $vars(step),assign_ptn_pins $command]
append commands [FF::source_plug post_assign_pin_tcl]
set command "checkPinAssignment -outFile pincheck.rpt\n"
append commands [FF::wrap_command $vars(step),check_pin_assignment $command]
set command "reportUnalignedNets -rptFile $vars(rpt_dir)/unaligned.rpt\n"
append commands [FF::wrap_command $vars(step),report_unaligned_nets $command]
if {!([info exists vars(placement_based_ptn)] && $vars(placement_based_ptn))} {
if {[lindex [split $vars(version) "."] 0] < 16} {
set command "setTrialRouteMode -honorPin true -handlePartitionComplex true\n"
append command "trialRoute\n"
append commands [FF::wrap_command $vars(step),trial_route $command]
} else {
set command "setRouteMode -earlyGlobalRoutePartitionHonorFence . -earlyGlobalRoutePartitionHonorPin .\n"
append commands [FF::wrap_command $vars(step),set_route_mode $command]
set command "earlyGlobalRoute\n"
append commands [FF::wrap_command $vars(step),early_global_route $command]
}
}
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_model_gen {{format 1}} {
global vars
global errors
global env
set vars(step) model_gen
set vars(hier) true
set commands ""
# Initialise the design
if {$vars(use_flexmodels)} {
# Initialise the design if not using flexmodel prototype
if {$vars(codegen)} {
append commands [FF_EDI::run_init $format]
} else {
FF_EDI::run_init $format
}
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
set command "saveDesign -cellview {$vars(oa_design_lib) $vars(design) init}\n"
} else {
set command "saveOaDesign $vars(oa_design_lib) $vars(design) init\n"
}
} else {
set command "saveDesign $vars(dbs_dir)/init.enc -compress\n"
}
append commands [FF::wrap_command $vars(step),save_design,init $command]
}
if {$vars(use_proto_net_delay_model) && $vars(use_flexmodels)} {
set command "catch {exec rm -rf proto_model_BACKUP}\ncatch {exec mv -f proto_model proto_model_BACKUP}\n"
append commands [FF::wrap_command $vars(step),proto_model_BACKUP $command]
set command "create_ps_per_micron_model\n"
append commands [FF::wrap_command $vars(step),create_ps_per_micron_model $command]
# set command "timeDesign -proto -prePlace -prefix preplace -outDir $vars(rpt_dir)\n"
# append commands [FF::wrap_command $vars(step),time_design $command]
}
append commands [FF::source_plug pre_model_gen_tcl]
if {$vars(enable_nrgr)} {
set command "setDesignMode -useTurboNRGRFlow true\n"
append commands [FF::wrap_command $vars(step),set_design_mode $command]
}
set vars(hier_case) "$vars(flexmodel_as_ptn)$vars(insert_feedthrough)"
switch $vars(hier_case) {
"00" {
set command "identify_proto_model\n"
append commands [FF::wrap_command $vars(step),identify_proto_model $command]
}
"01" {
set command "identify_proto_model\n"
append commands [FF::wrap_command $vars(step),identify_proto_model $command]
}
"10" {
set command "set_proto_mode -create_partition_as_flexmodel true\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
# if {[info exists vars(partition_list)] && ($vars(partition_list) != "")} {
# foreach ptn $vars(partition_list) {
# set command "set_proto_model -model $ptn -type flex_module\n"
# append commands [FF::wrap_command $vars(step),set_proto_model $command]
# }
# } else {
# puts "<FF> ERROR: Flexmodel partition flow enabled but no partitions are defined"
# set errors($vars(error_count)) "Flexmodel partition flow enabled but no partitions are defined"
# incr vars(error_count)
# }
}
"11" {
set command "set_proto_mode -create_partition_as_flexmodel true\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
# if {[info exists vars(partition_list)] && ($vars(partition_list) != "")} {
# foreach ptn $vars(partition_list) {
# set command "set_proto_model -model $ptn -type flex_module\n"
# append commands [FF::wrap_command $vars(step),set_proto_model $command]
# }
# } else {
# puts "<FF> ERROR: Flexmodel partition flow enabled but no partitions are defined"
# set errors($vars(error_count)) "Flexmodel partition flow enabled but no partitions are defined"
# incr vars(error_count)
# }
# }
}
# if {[info exists vars(model_gen,min_inst)]} {
# set min_inst $vars(model_gen,min_inst)
# } else {
# set min_inst 1000
# }
# set command "setIlmMode -highFanoutPort false\n"
# append commands [FF::wrap_command $vars(step),setIlmMode $command]
set command "setIlmMode -keepHighFanoutPorts false\n"
append commands [FF::wrap_command $vars(step),set_ilm_mode $command]
if {$vars(flexmodel_art_based)} {
set command "create_proto_model -out_dir $vars(dbs_dir)/model_gen.enc\n"
} else {
set command "create_proto_model -partition_based\ncommit_proto_model\n"
}
append commands [FF::wrap_command $vars(step),create_proto_model $command]
if {$vars(create_flexfiller_blockage)} {
set command "create_flexfiller_route_blockage\n"
append commands [FF::wrap_command $vars(step),create_flexfiller_route_blockage $command]
}
append commands [FF::source_plug post_model_gen_tcl]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_prototype {{format 1}} {
global vars
global errors
global env
set vars(step) prototype
set vars(hier) true
set commands ""
append commands [FF::source_plug pre_prototype_tcl]
set command "report_proto_model -created\n"
append commands [FF::wrap_command $vars(step),report_proto_model $command]
set command "ungroup -type flex_model\n"
append commands [FF::wrap_command $vars(step),ungroup_flexilm_1 $command]
set command "timeDesign -proto -preplace \n"
append commands [FF::wrap_command $vars(step),time_design $command]
# set command "definePartition -proto [list $vars(partition_list)]\n"
set command ""
foreach ptn $vars(partition_list) {
append command "definePartition -proto \[dbGet \[dbGetCellByName $ptn\].hinst.name\]\n"
}
append commands [FF::wrap_command $vars(step),define_partition $command]
set command "set_proto_mode -proto_design_level $vars(flexmodel_prototype_flow_style)\n"
append commands [FF::wrap_command $vars(step),set_proto_mode $command]
set command "set_proto_design_mode -reset\n"
if {$vars(flexmodel_prototype_congestion_aware)} {
append command "set_proto_design_mode -congestion_aware true\n"
}
if {$vars(flexmodel_prototype_timing_aware)} {
append command "set_proto_design_mode -timing_aware true\n"
}
# Following 2 settings will be removed
append command "set_proto_design_mode -new_algorithm true\n"
append command "set_proto_design_mode -report_timing false\n"
append commands [FF::wrap_command $vars(step),set_proto_design_mode $command]
if {$vars(flexmodel_prototype_flow_style) == "top_to_bottom"} {
# if {![info exists vars(flexmodel_prototype_max_level)]} {
# set vars(flexmodel_prototype_max_level) 1
# }
# set command "set max_level $vars(flexmodel_prototype_max_level)\n"
set command "set max_level \[get_flexmodel_max_level\]\n"
append command "set level 0\n"
append command "while {\$level < \$max_level} {\n"
append command "set_proto_mode -partition_level_num \$level\n"
append command "proto_design -constraints $vars(flexmodel_prototype_user_contraints)\n"
append command "checkFPlan -outFile $vars(rpt_dir)/check_fplan_proto_design_level_\${level}.rpt \n"
append command "placeDesign -noPrePlaceOpt\n"
append command "timeDesign -proto -prects -prefix proto_design_level_\${level} -outDir $vars(rpt_dir)\n"
append command "load_timing_debug_report -proto \n"
append command "file copy -force $vars(plug_dir)/post_proto_design_level.tcl .post_proto_design_level_\${level}.tcl\n"
append command "source .post_proto_design_level_\${level}.tcl\n"
append command "incr level 1\n"
append command "}\n"
} else {
set command "set level $vars(flexmodel_prototype_flow_style)\n"
append command "proto_design -constraints $vars(flexmodel_prototype_user_contraints)\n"
append command "checkFPlan -outFile $vars(rpt_dir)/check_fplan_proto_design_level_\${level}.rpt \n"
append command "placeDesign\n"
append command "timeDesign -proto -prects -prefix proto_design_level_\${level} -outDir $vars(rpt_dir)\n"
append command "load_timing_debug_report -proto \n"
append command "source $vars(plug_dir)/post_proto_design_level.tcl\n"
}
append commands [FF::wrap_command $vars(step),proto_loop $command]
set command "ungroup -type flex_model -display_all_constraints\n"
append commands [FF::wrap_command $vars(step),ungroup_flexilm_2 $command]
set command "set_proto_timing_settings -reset\n"
append commands [FF::source_plug post_prototype_tcl]
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_partition {{format 1}} {
global vars
global errors
global env
set vars(step) partition
set vars(hier) true
set commands ""
###############################################################################
# Budget the blocks based on the mode
###############################################################################
set command ""
append command "set_global timing_support_hierarchical_pin_constraints true\n"
append command "set tbgPrintExceptionInfoInJustify 1\n"
append commands [FF::wrap_command $vars(step),set_budget_vars $command]
if {$vars(budget_mode) == "proto_net_delay_model" && $vars(use_proto_net_delay_model)} {
set command "timeDesign -proto -prefix budget -outDir $vars(rpt_dir)\n"
append commands [FF::wrap_command $vars(step),time_design $command]
}
# Define budgeting options ...
set command ""
append command "setBudgetingMode -writeLatencyPerClock true\n"
append command "if {\[dbGet -e top.ptns.clones\] != \"\"} {\n"
append command " setBudgetingMode -mergeClones true\n"
append command "}\n"
if {[info exists vars(abutted_design)] && $vars(abutted_design)} {
append command "setBudgetingMode -abutted true\n"
}
switch [string tolower $vars(budget_mode)] {
giga_opt {
# This is default behavior now
# append command "setBudgetingMode -virtualOptEngine gigaOpt\n"
}
trial_ipo {
append command "setBudgetingMode -virtualOptEngine trialIPO\n"
}
proto_net_delay_model {
if {$vars(use_proto_net_delay_model)} {
append command "setBudgetingMode -virtualOptEngine none\n"
}
}
}
# append command "setBudgetingMode -enableMTBudgeting true\n"
append commands [FF::wrap_command $vars(step),set_budgeting_mode $command]
if {([string tolower $vars(budget_mode)] != "proto_net_delay_model") && $vars(use_proto_net_delay_model)} {
set command "set_proto_timing_settings -reset\n"
append commands [FF::wrap_command $vars(step),set_proto_timing_settings $command]
}
set command "deriveTimingBudget -justify\n"
append commands [FF::wrap_command $vars(step),derive_timing_budget $command]
###############################################################################
# Run CLP
###############################################################################
if {[FF::is_lp_flow] && [info exists vars(power_domains)] && [llength $vars(power_domains)] > 1} {
if {$vars(run_clp) && ([auto_execok lec] != "")} {
set command "runCLP "
if {[info exists vars(clp_options)]} {
append command $vars(clp_options)
}
append command "\n"
append commands [FF::wrap_command $vars(step),run_clp $command]
}
}
if {$vars(use_flexmodels) || $vars(placement_based_ptn)} {
set command "set max_layer \[getTrialRouteMode -maxRouteLayer\]\n"
append command "setPlaceMode -reset \n"
append command "setTrialRouteMode -reset \n"
append command "setTrialRouteMode -maxRouteLayer \$max_layer\n"
append commands [FF::wrap_command $vars(step),set_trial_route_mode $command]
}
if {$vars(use_proto_net_delay_model)} {
set command "set_proto_timing_settings -reset\n"
append commands [FF::wrap_command $vars(step),set_proto_timing_settings $command]
}
###############################################################################
# Partition and save the partitions into the
# directory PARTITION
###############################################################################
append commands [FF::source_plug pre_partition_tcl]
# set command "set ptngPtnTimingLibFormat lib\npartition -buildScan\n"
set command "partition -buildScan\n"
append commands [FF::wrap_command $vars(step),partition $command]
if {[lindex [split $vars(version) "."] 0] > 10} {
if {([string compare $vars(dbs_format) "oa"]==0)} {
set command "savePartition -ptnLib $vars(oa_partition_lib) -dir $vars(partition_dir)\n"
} else {
set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
}
} else {
set command "savePartition -dir $vars(partition_dir) -def -scanDef\n"
}
append commands [FF::wrap_command $vars(step),save_partition $command]
if {$vars(use_flexmodels) && $vars(flexmodel_as_ptn)} {
# set command "replace_proto_model \\\n"
# append command " -pre_ft_dir $vars(eco_dir)/pre_ft \\\n"
# append command " -post_ft_dir $vars(eco_dir)/post_ft \\\n"
# append command " -ptn_dir $vars(partition_dir) \\\n"
# append command " -ptn_full_netlist_dir ./temp_netlist_dir \\\n"
# append command " -out_dir $vars(partition_dir)\n"
set command "replace_proto_model \\\n"
append command " -ptn_dir $vars(partition_dir) \\\n"
append command " -out_dir $vars(partition_dir)\n"
append commands [FF::wrap_command $vars(step),replace_proto_model $command]
}
append commands [FF::source_plug post_partition_tcl]
if {!$vars(codegen)} {
uplevel #0 eval $commands
}
set path [file normalize $vars(script_path)]
file mkdir $vars(partition_dir)
if {![file exists $vars(partition_dir)/Makefile.partition]} {
file copy $vars(script_path)/ETC/INNOVUS/Makefile.partition $vars(partition_dir)
}
set op [open $vars(partition_dir)/Makefile w]
if {![info exists env(VPATH)]} {
set env(VPATH) "make"
}
puts $op "VPATH=$env(VPATH)"
puts $op "BLOCKS = $vars(partition_list)"
puts $op ""
puts $op "include Makefile.partition"
close $op
foreach var [array names vars] {
set svars($var) $vars($var)
}
set vars(mode) flat
# set vars(hier) true
set link [file normalize $vars(script_root)]
foreach block [concat $vars(design) $vars(partition_list)] {
exec mkdir -p $vars(partition_dir)/$block
# if {[file exists .ff.tcl]} {
# file copy -force .ff.tcl $vars(partition_dir)/$block
# }
if {[file exists $vars(partition_dir)/$block/Makefile]} {
file delete $vars(partition_dir)/$block/Makefile
}
if {[info exists vars($block,innovus_config_tcl)] && [file exists $vars($block,innovus_config_tcl)]} {
puts "<FF> Sourcing $vars($block,innovus_config_tcl)"
source $vars($block,innovus_config_tcl)
}
set cwd [pwd]
if {([lindex [split $vars(version) "."] 0] > 10) && ([string compare $vars(dbs_format) "oa"]==0)} {
if {[file exists cds.lib]} {
set ip [open cds.lib r]
set i 0
while {[gets $ip line]>=0} {
set cds_lib($i) $line
incr i
}
close $ip
} else {
puts "<FF> ERROR: A cds.lib file is required for open access flows ..."
}
}
cd $vars(partition_dir)/$block
set vars(design) $block
if {$vars(codegen)} {
if {[info exists vars(proc_file)]} {
unset vars(proc_file)
}
unset vars(steps)
}
if {[info exists vars(cts_spec)]} {
unset vars(cts_spec)
}
if {[info exists vars($block,cts_spec)]} {
set vars(cts_spec) $vars($block,cts_spec)
}
if {!$vars(codegen)} {
exec ln -s $link SCRIPTS
exec ln -s SCRIPTS/Makefile.edi.flat Makefile
} else {
set vars(mode) flat
set vars(hier) true
unset vars(step)
execute_flow all $vars(format_lines)
FF::dump_vars
}
cd $cwd
# set actions $vars(actions)
foreach var [array names vars] {
unset vars($var)
}
# set vars(actions) $actions
foreach var [array names svars] {
set vars($var) $svars($var)
}
}
if {$vars(hier_flow_type) == "2pass"} {
foreach block [concat $vars(design) $vars(partition_list)] {
exec mkdir -p $vars(partition_dir_pass2)/$block/$vars(script_dir)/INNOVUS
exec mkdir -p $vars(partition_dir_pass2)/$block/$vars(rpt_dir)
if {[file isdirectory $vars(partition_dir_pass2)/$block/$vars(script_dir)/ETC]} {
file delete -force $vars(partition_dir_pass2)/$block/$vars(script_dir)/ETC
}
# file copy -force $vars(partition_dir)/$block/$vars(script_dir)/ETC $vars(partition_dir_pass2)/$block/$vars(script_dir)/ETC
foreach file [glob $vars(partition_dir)/Make*] {
if {[file isfile $file]} {
file copy -force $file $vars(partition_dir_pass2)
}
}
foreach file [glob $vars(partition_dir)/$block/$vars(script_dir)/*] {
if {[file isfile $file]} {
file copy -force $file $vars(partition_dir_pass2)/$block/$vars(script_dir)
}
}
if {[file isfile $vars(partition_dir)/$block/.ilm_non_sdc_file.tcl]} {
file copy -force $vars(partition_dir)/$block/.ilm_non_sdc_file.tcl $vars(partition_dir_pass2)/$block
}
if {[file isfile $vars(partition_dir)/$block/empty.sdc]} {
file copy -force $vars(partition_dir)/$block/empty.sdc $vars(partition_dir_pass2)/$block
}
if {[file isfile $vars(partition_dir)/$block/Makefile.pass2]} {
file copy -force $vars(partition_dir)/$block/Makefile.pass2 $vars(partition_dir_pass2)/$block/Makefile
file delete $vars(partition_dir)/$block/Makefile.pass2
}
cd $vars(partition_dir_pass2)/$block
if {$vars(enable_flexilm)} {
set index [lsearch [FF::adjust_steps] cts]
} else {
# set index [lsearch [FF::adjust_steps] postcts]
# set index [lsearch [FF::adjust_steps] postcts_hold]
set index [expr [lsearch [FF::adjust_steps] cts]+2]
}
cd $cwd
#puts "SPLIT FLOWS: $index, [FF::adjust_steps]"
foreach step [lrange $vars(steps) $index end] {
if {[lsearch $vars(fsteps) $step] != -1} {
if {[file isfile $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl]} {
#puts "COPY: $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl $vars(partition_dir_pass2)/$block/$vars(script_dir)/INNOVUS"
file copy -force $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl \
$vars(partition_dir_pass2)/$block/$vars(script_dir)/INNOVUS
#puts "DELETE: $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl"
file delete -force $vars(partition_dir)/$block/$vars(script_dir)/INNOVUS/run_$step.tcl
}
}
}
# set adjusted [FF::adjust_steps]
# cd $vars(partition_dir)/$block
#puts "1: $adjusted : [lrange $adjusted 0 $index]"
# FF::gen_makefile [lrange $adjusted $index end] flat
# cd $cwd
# cd $vars(partition_dir_pass2)/$block
#puts "2: $adjusted : [lrange $adjusted $index end]"
# FF::gen_makefile [lrange $adjusted $index end] flat
# cd $cwd
}
}
foreach var [array names vars] {
unset vars($var)
}
foreach var [array names svars] {
set vars($var) $svars($var)
}
if {$vars(codegen)} {
# if {$vars(makefile)} {
# append commands "\nexec /bin/touch $env(VPATH)/partition\n"
# }
return $commands
} else {
exec /bin/touch $env(VPATH)/partition
}
}
proc run_debug {{format 1}} {
global vars
global errors
global env
set vars(step) debug
set commands ""
append commands "\nglobal env\n"
append commands "if {\[info exists env(STEP)\]} {\n"
append commands "[FF_EDI::load_design \$env(STEP)]\n"
append commands "}\n"
# append commands "[FF::source_plug always_source_tcl]\n"
append commands "win\n"
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc run_lec {} {
global vars
global errors
global env
set commands ""
append commands "vpxmode\n"
append commands "set dofile abort exit\n"
append commands "set undefined cell black_box -noascend -both\n"
append commands "tclmode\n"
append commands "// setup variables \n"
append commands "global vars\n"
append commands "proc Puts {args} {\n"
append commands " puts \$args\n"
append commands "}\n"
append command "// Define the netlist to be verify\n"
append commands "if {\[info exists env(STEP)\] && \[file exists $vars(dbs_dir)/LEC/\$env(STEP).v.gz\]} {\n"
append commands " set revisedNetlist $vars(dbs_dir)/LEC/\$env(STEP).v.gz\n"
append commands "} else {\n"
append commands " Puts \"<FF> Failed to find netlist DBS/LEC/\$env(STEP).v.gz\"\n"
append commands "}\n"
if {[info exists vars(threads)]} {
append commands "vpx set compare option -threads $vars(threads)\n"
}
append commands "// read liberty cell definitions\n"
if {[info exists vars($vars(default_setup_view),delay_corner)]} {
if {[info exists vars($vars($vars(default_setup_view),delay_corner),library_set)]} {
set set $vars($vars($vars(default_setup_view),delay_corner),library_set)
} else {
return
}
} else {
return
}
append commands "vpx read library -statetable -both -liberty \[list $vars($set,timing)\]\n"
append commands "// read reference netlist\n"
append commands "vpx read design -verilog -sensitive -golden $vars(netlist)\n"
append commands "// read post-implementation netlist\n"
append commands "vpx read design -verilog -sensitive -revised \$revisedNetlist\n"
append commands "//set top level\n"
append commands "vpx set root module $vars(design) -both\n"
regsub -all "#" [FF::source_plug pre_lec_tcl] "//" temp
append commands $temp
append commands "vpxmode\n"
append commands "report design data\n"
append commands "report black box\n"
append commands "set mapping method -name first\n"
append commands "set flatten model -seq_constant -seq_constant_x_to 0\n"
append commands "set flatten model -nodff_to_dlat_zero -nodff_to_dlat_feedback\n"
append commands "set flatten model -gated_clock\n"
append commands "set system mode lec\n"
append commands "add compare point -all\n"
append commands "compare -gate_to_gate\n"
append commands "usage\n"
append commands "// vpx report compare data"
append commands "report compare data -class nonequivalent -class abort -class notcompared\n"
append commands "report verification -verbose\n"
append commands "report statistics\n"
append commands "tclmode\n"
append commands "set points_count \[get_compare_points -count\]\n"
append commands "set diff_count \[get_compare_points -diff -count\]\n"
append commands "set abort_count \[get_compare_points -abort -count\]\n"
append commands "set unknown_count \[get_compare_points -unknown -count\]\n"
append commands "if {\$points_count == 0} {\n"
append commands " puts \"---------------------------------\"\n"
append commands " puts \"ERROR: No compare points detected\"\n"
append commands " puts \"---------------------------------\"\n"
append commands "}\n"
append commands "if {\$diff_count > 0} {\n"
append commands " puts \"------------------------------------\"\n"
append commands " puts \"ERROR: Different Key Points detected\"\n"
append commands " puts \"------------------------------------\"\n"
append commands "}\n"
append commands "if {\$abort_count > 0} {\n"
append commands " puts \"-----------------------------\"\n"
append commands " puts \"ERROR: Abort Points detected \"\n"
append commands " puts \"-----------------------------\"\n"
append commands "}\n"
append commands "if {\$unknown_count > 0} {\n"
append commands " puts \"----------------------------------\"\n"
append commands " puts \"ERROR: Unknown Key Points detected\"\n"
append commands " puts \"----------------------------------\"\n"
append commands "}\n"
append commands "puts \"No of compare points = \$points_count\"\n"
append commands "puts \"No of diff points = \$diff_count\"\n"
append commands "puts \"No of abort points = \$abort_count\"\n"
append commands "puts \"No of unknown points = \$unknown_count\"\n"
append commands "exit 0\n"
if {$vars(codegen)} {
return $commands
} else {
uplevel #0 eval $commands
}
}
proc dump_config {} {
global vars
global udm
global rda_Input
global rda_defaults
# set commands ""
file mkdir $vars(script_dir)
if {[info command FFF::get_tool] ne "" && [FFF::get_tool] eq "rc"} {
tcl_source $vars(script_path)/ETC/INNOVUS/udm.tcl
} else {
source $vars(script_path)/ETC/INNOVUS/udm.tcl
}
if {[info exists vars(cpf_file)]} {
if {$vars(cpf_timing)} {
unset init(mmmc_file)
} else {
unset init(cpf_file)
}
}
if {[lindex [split $vars(version) "."] 0] > 10} {
if {[info exists vars(view_definition_tcl)]} {
set init(mmmc_file) $vars(view_definition_tcl)
}
set op [open $vars(script_dir)/init.tcl w]
# BCL: Trying to fix embedded paths...
set relativizeMesgLog ""
set relativizeMesgLog "$relativizeMesgLog [FF::remove_outer_braces [FF::relativizeFileOrDir -arr init -vardir ff_exe_dir -relativePathsOk]]"
foreach var [array names init] {
if {[file exists $init($var)]} {
set nvar [list]
foreach file $init($var) {
if {![regexp "oa_" $var]} {
lappend nvar [file normalize $file]
puts $op "set init_$var \"$nvar\""
} else {
puts $op "set init_$var \"$init($var)\""
}
}
} else {
if {$vars(netlist_type) == "verilog"} {
if {$var == "oa_design_lib"} { continue }
if {$var == "oa_design_cell"} { continue }
if {$var == "oa_design_view"} { continue }
}
puts $op "set init_$var \"$init($var)\""
}
}
# foreach var [array names ninit] {
# puts $np "set_db init_$var \"$ninit($var)\""
# }
foreach var [array names conf] {
puts $op "set conf_$var \"$conf($var)\""
}
foreach var [array names cts] {
puts $op "set cts_$var \"$cts($var)\""
}
foreach var [array names delaycal] {
puts $op "set delaycal_$var \"$delaycal($var)\""
}
foreach var [array names extract] {
puts $op "set extract_$var \"$extract($var)\""
}
# foreach var [array names fp] {
# puts $op "set fp_$var \{$fp($var)\}"
# }
foreach var [array names opt] {
puts $op "set opt_$var \"$opt($var)\""
}
# foreach var [array names rda_Input] {
# puts $op "set rda_Input($var) \{$rda_Input($var)\}"
# }
# foreach var [array names rda_defaults] {
# puts $op "set rda_Input($var) \{$vars($var)\}"
# }
} else {
set op [open $vars(script_dir)/run.conf w]
#BCL: Added .ff.tcl sourcing in run.conf in order to pull in codegen variables
puts $op "# Set up codegen variables (possibly) needed to resolve some conf variables"
#puts $op "if {\[file exists .ff.tcl\]} {"
#puts $op " source .ff.tcl"
#puts $op "}"
#BCL: Only enclose in curlies if subst is not part of the netlist name
foreach var [array names rda_Input] {
# BCL: only use curlies if the variable doesn't contain subst (otherwise subst will not be performed)
if {[regexp {subst} $rda_Input($var)]} {
puts $op "set rda_Input($var) \"$rda_Input($var)\""
} else {
puts $op "set rda_Input($var) \{$rda_Input($var)\}"
}
}
# if {$vars(flat) != "full"} {
# puts $op "set rda_Input(ui_view_definition_file) \"$vars(script_dir)/view_definition.tcl\""
# }
}
close $op
# close $np
}
proc get_required_procs {file} {
#
# Given a list of required procedures, return the lines that represent
# those procedures from the utils.tcl file
#
global vars
global errors
#
# Read the file and gather all of the contents
#
set all_lines ""
set length 0
set ip [open $file]
while {[gets $ip line]>=0} {
set utils_lines($length) $line
incr length
}
close $ip
#
# Iterate across each line and pull out relevant procedures
#
set lines ""
set i 0
while {$i < $length} {
set line $utils_lines($i)
foreach proc $vars(required_procs) {
if {[regexp "proc $proc" $line] > 0} {
append lines " $line\n"
incr i
while {$i < $length} {
set line $utils_lines($i)
if {[regexp "proc " $line] > 0} {
incr i -1
break
}
if {![regexp "^#" [string trimleft $line] ] && ($i != [expr $length-1])} {
append lines "$line\n"
}
incr i
}
break
}
}
incr i
}
set lines [string trimright $lines]
return "$lines\n"
}
proc normalize_files {} {
global vars
global errors
if {[info exists vars(normalize_files)] && !$vars(normalize_files)} {
return
}
if {[info exists vars(view_definition_tcl)]} {
set mmmc_file [file normalize $vars(view_definition_tcl)]
} else {
set mmmc_file [file normalize $vars(script_dir)/view_definition.tcl]
}
set vars(mmmc_file) $mmmc_file
foreach file_var [list cpf_file def_files netlist cts_spec lef_files \
gds_files activity_file ilm_non_sdc_file ] {
if {[info exists vars($file_var)]} {
set temp [list]
foreach file $vars($file_var) {
lappend temp [file normalize $file]
}
set vars($file_var) $temp
}
}
}
proc normalize_constraints {} {
global vars
set cwd [pwd]
cd $vars(cwd)
foreach mode $vars(constraint_modes) {
foreach var "pre_cts_sdc pre_cts_ilm_sdc incr_cts_sdc post_cts_sdc" {
if {[info exists vars($mode,$var)]} {
set temp [list]
foreach file $vars($mode,$var) {
lappend temp [file normalize $file]
}
set vars($mode,$var) $temp
}
}
}
cd $cwd
}
proc denormalize_files {} {
global vars
global tvars
foreach var [array names vars] {
if {($var != "setup_path") && ($var != "script_dir") && ($var != "script_path") && ($var == "execute_string")} {
set tvars($var) $vars($var)
}
}
# set op [open .setup.ff.tcl w]
catch {unset path_array}
set path_list [list]
set path_vars [list]
foreach var [array names tvars] {
if [file isdirectory $tvars($var)] {
set path_array($tvars($var)) $var
lappend path_vars $var
lappend path_list $tvars($var)
}
}
set sorted_path_list [lsort -decreasing $path_list]
# puts "-> Found [llength $sorted_path_list]"
foreach path $sorted_path_list {
# puts "$path -> $path_array($path) ([string length $path])"
# puts $op "set vars($path_array($path)) $path"
}
foreach var [array names tvars] {
set found 0
foreach path $sorted_path_list {
if {($var == $path_array($path)) || ([string first "\[" $var] != -1)} {
break
}
# puts $op "[format "regsub -all \"%s\" \"%s\" \\$%s" $path [join $tvars($var)] $path_array($path) temp]"
if {[catch {set command [format "regsub -all \"%s\" \"%s\" \\\$vars(%s) temp" $path [join $tvars($var)] $path_array($path)]}]} {
break
}
set foo [eval $command]
if {$foo > 0} {
# puts $op "set vars($var) \"[join $temp]\""
if {[llength $temp] > 1} {
set vars($var) [join $temp]
} else {
set vars($var) $temp
}
set found 1
}
}
# if {!$found} {
# puts $op "set vars($var) \"[join $vars($var)]\""
# }
}
# foreach path $sorted_path_list {
# set vars($path_array($path)) $path
# }
# close $op
# source .setup.ff.tcl
}
proc source_config_files {} {
global vars
global env
global user_vars
global desc
global errors
puts "<FF> LOADING CONFIGURATION FILES:"
set vars(config_files) [list]
foreach file "setup.tcl innovus_config.tcl lp_config.tcl genus_config.tcl" {
set temp [regsub "\\." $file "_"]
set vars($temp) [list]
if {[file exists $vars(setup_path)/$file]} {
FF::source_file $vars(setup_path)/$file
lappend vars($temp) $vars(setup_path)/$file
lappend vars(config_files) $vars(setup_path)/$file
}
if {($vars(setup_path) != ".") && [file exists $file]} {
FF::source_file $file
lappend vars($temp) $file
lappend vars(config_files) $file
}
if {$vars($temp) != ""} {
puts "<FF> $temp -> $vars($temp)"
}
}
foreach var [array names vars] {
set user_vars($var) $vars($var)
# puts $var
}
if {[FF::is_lp_flow]} {
set vars(required_procs) \
"source_file system_info get_clock_ports get_power_domains modify_power_domains add_power_switches \
route_secondary_pg_nets insert_welltaps_endcaps report_time buffer_always_on_nets \
save_results load_applet get_tool load_path_groups"
} else {
set vars(required_procs) \
"source_file system_info get_clock_ports report_time insert_welltaps_endcaps \
save_results load_applet get_tool load_path_groups "
}
}
proc execute_flow {step {format 1} {abort ""}} {
#
# This is the entry point, responsible for calling functions and
# aggregating results for each step in the flow
#
global vars
global dargs
global fargs
global svars
global env
global errors
if {![info exists vars(sourced)]} { set vars(sourced) 0 }
# if {![info exists vars(single)]} { set vars(single) 0 }
if {![info exists vars(catch_errors)]} { set vars(catch_errors) 0 }
if {![info exists vars(stop_step)]} { set vars(stop_step) "signoff" }
if {![info exists vars(initialized)]} { set vars(initialized) 0 }
if {![info exists vars(loaded)]} { set vars(loaded) 0 }
if {![info exists vars(bsteps)]} { set vars(bsteps) [list] }
if {![info exists env(VPATH)]} { set env(VPATH) make }
#
# If no steps are defined, set the steps to execute based upon the
# mode that the system is running in. We need to do this because the
# hierarchical flow will unset the vars() array before recursively
# calling this routine.
#
if {![info exists vars(steps)]} {
# BCL: Moved the following if / else up (it must always execute)
if {![info exists vars(mode)]} {
if {[info exists fargs(mode)]} {
set vars(mode) $fargs(mode)
} else {
set vars(mode) $dargs(mode)
}
}
# if {[info exists vars(hier)] && !$vars(hier)} {
# FF::set_steps $vars(mode) $format
# unset vars(mode)
# } else {
# FF::set_steps $vars(mode) $format
# }
}
#
# Set the procedures that we will need to include within each file that
# we create to run a step.
#
# set vars(required_procs) \
# "source_plug get_clock_ports get_power_domains report_time"
#
# Make sure that the variables are actually sourced from the
# configuration files
#
if {!$vars(sourced) && ($step != "source")} {
execute_flow "source" $format $abort
}
if {$vars(sourced)} {
if {[info exists vars(hier)] && !$vars(hier)} {
FF::set_steps $vars(mode) $format
unset vars(mode)
} else {
FF::set_steps $vars(mode) $format
}
}
#
# Execute the appropriate step per the command
#
set action ""
switch -- $step {
"source" {
if {!$vars(sourced)} {
FF_EDI::source_config_files
if {[info exists fargs(version)]} {
if {![regexp "^10" $fargs(version)] && ![regexp "^9" $fargs(version)]} {
FF_EDI::denormalize_files
}
} elseif {[info exists dargs(version)]} {
if {![regexp "^10" $dargs(version)] && ![regexp "^9" $dargs(version)]} {
FF_EDI::denormalize_files
}
}
foreach arg [join $vars(arg_list)] {
if {[info exists vars($arg)]} {
if {[info exists fargs($arg)]} {
if {$vars($arg) != $fargs($arg)} {
puts "<FF> WARNING: Overwriting vars($arg) from $vars($arg) to $fargs($arg) ..."
}
set vars($arg) $fargs($arg)
} else {
# Only set the farg if it wasn't set in a config file
if {![info exists vars($arg)]} {
set vars($arg) $dargs($arg)
}
}
} else {
if {[info exists fargs($arg)]} {
set vars($arg) $fargs($arg)
} else {
set vars($arg) $dargs($arg)
}
}
}
FF_EDI::seed_variables
# FF_EDI::check_setup
# FF_EDI::normalize_files
set vars(sourced) true
set vars(top_cell) $vars(design)
}
}
"source_only" {
# BCL: Added this in since i want to source the variables w/out calling check_setup
if {!$vars(sourced)} {
FF_EDI::source_config_files
if {[info exists fargs(version)]} {
if {![regexp "^10" $fargs(version)] && ![regexp "^9" $fargs(version)]} {
FF_EDI::denormalize_files
}
} elseif {[info exists dargs(version)]} {
if {![regexp "^10" $dargs(version)] && ![regexp "^9" $dargs(version)]} {
FF_EDI::denormalize_files
}
}
foreach arg [join $vars(arg_list)] {
if {[info exists vars($arg)]} {
if {[info exists fargs($arg)]} {
if {$vars($arg) != $fargs($arg)} {
puts "<FF> WARNING: Overwriting vars($arg) from $vars($arg) to $fargs($arg) ..."
}
set vars($arg) $fargs($arg)
} else {
# Only set the farg if it wasn't set in a config file
if {![info exists vars($arg)]} {
set vars($arg) $dargs($arg)
}
}
} else {
if {[info exists fargs($arg)]} {
set vars($arg) $fargs($arg)
} else {
set vars($arg) $dargs($arg)
}
}
}
FF_EDI::seed_variables
# FF_EDI::check_setup
# FF_EDI::normalize_files
# set vars(sourced) true
set vars(top_cell) $vars(design)
}
}
"check" {
if {$abort == ""} {
set abort $vars(abort)
}
set save $vars(abort)
set vars(abort) $abort
set vars(abort) $save
if {![info exists vars(mode)]} {
if {[info exists fargs(mode)]} {
set vars(mode) $fargs(mode)
} else {
set vars(mode) $dargs(mode)
}
}
if {$vars(mode) == "hier"} {
if {![info exists vars(partition_list)]} {
puts "<FF> FLOW MODE $vars(mode) SELECTED BUT \$vars(partition_list) NOT DEFINED"
exit 99
}
if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
FF_EDI::check_setup
}
} else {
FF_EDI::check_setup
}
FF::process_file_lists
}
"all" {
#
# We have already sourced in all of the files. Now execute the
# rest of the steps, including check
#
puts "-------------------------------------------------"
puts "<FF> Generating scripts for $vars(design)"
puts "-------------------------------------------------"
execute_flow check $format $abort
# BCL: changed to file mkdir
file mkdir $vars(script_dir)/INNOVUS
set vars(steps) [join $vars(steps)]
set vars(all) true
set commands ""
set top 0
if {$vars(mode) == "hier"} {
if {[file tail [file dirname [pwd]]] == "$vars(partition_dir)"} {
set all_steps $vars(fsteps)
} else {
set all_steps $vars(hsteps)
}
} else {
set fhr [open $vars(script_path)/INNOVUS/run_all.tcl r]
set fhw [open $vars(script_dir)/INNOVUS/run_all.tcl w]
while {[gets $fhr line]>=0} {
regsub "source FF" $line "source $vars(script_dir)" line
puts $fhw " $line"
}
close $fhr
close $fhw
set all_steps $vars(steps)
}
#
# Execute each step of the flow and get a composite list of the
# actual steps that had actions generated for them. Then create
# a Makefile for those steps
#
if {[info exists vars(rc_steps)]} {
set actions $vars(rc_steps)
} else {
set actions [list]
}
#
foreach step $all_steps {
set commands [execute_flow $step $format $abort]
if {$commands != ""} {
lappend actions $commands
}
}
if {($vars(user_mode) == "hier") && ($vars(hier_flow_type) == "2pass")} {
# Only generate steps up to (and including) cts for 2pass flows
# Go ahead and generate both Makefiles as the actions are known
if {$vars(enable_flexilm)} {
if {$vars(place_opt_design)} {
# if {[file tail [pwd]] == $vars(top_cell)} {
# set index [lsearch $actions "prects"]
# } else {
set index [lsearch $actions "place"]
# }
} else {
set index [lsearch $actions "prects"]
}
#puts "1: $actions : [lrange $actions [expr $index+1] end] ([pwd])"
FF::gen_makefile [lrange $actions [expr $index+1] end] $vars(mode)
file copy -force Makefile Makefile.pass2
if {[llength [lrange $actions 0 $index]] != 0} {
#puts "2: $actions : [lrange $actions 0 $index] ([pwd])"
FF::gen_makefile [lrange $actions 0 $index] $vars(mode)
}
} else {
set index [lsearch $actions "cts"]
#puts "3: $actions : [lrange $actions [expr $index+1] end] ([pwd])"
FF::gen_makefile [lrange $actions [expr $index+1] end] $vars(mode)
if {$vars(mode) != "hier"} {
file copy -force Makefile Makefile.pass2
}
if {[llength [lrange $actions 0 $index]] != 0} {
#puts "4: $actions : [lrange $actions 0 $index] ([pwd])"
FF::gen_makefile [lrange $actions 0 $index] $vars(mode)
}
}
} else {
#puts "5: $actions ([pwd])"
FF::gen_makefile $actions $vars(mode)
}
if {$vars(enable_qor_check)} {
FF_EDI::gen_check
}
execute_flow debug $format $abort
if {[info exists vars(run_lec)] && $vars(run_lec)} {
execute_flow lec $format $abort
}
}
"lec" {
# puts "-------------------------------------------------"
# puts "<FF> Generating scripts for $vars(design)"
puts "-------------------------------------------------"
if {![info exists vars(netlist)]} {
puts "<FF> Cannot generate 'lec' step w/o verilog netlist defined"
} else {
# BCL: Changed to tcl file mkdir
file mkdir $vars(script_dir)/INNOVUS
set op [open $vars(script_dir)/INNOVUS/run_lec.tcl w]
puts $op "//"
puts $op "// Innovus Foundation Flow Code Generator, [exec date]"
puts $op "//"
if {$step == "lec"} {
puts $op "tclmode"
}
#puts $op "if {\[file exists .ff.tcl\]} {"
#puts $op " source .ff.tcl"
#puts $op "}"
set varsFile [FF::relPathTo [file normalize $vars(script_dir)/vars.tcl] [file normalize $vars(rundir)]]
puts $op "if {\[file exists $varsFile\]} {"
puts $op " source $varsFile"
puts $op "}"
# puts $op "source \$vars(script_dir)/procs.tcl"
if {![regexp syn_ $step]} {
puts $op "source $vars(script_dir)/procs.tcl"
}
puts "<FF> Generating step $step"
set commands [FF_EDI::run_lec]
puts $op [FF::pretty_print $commands $format]
close $op
}
# FF::gen_makefile lec $vars(mode)
}
"default" {
#
# Run each step either singuarly or recursively
#
#
# Create the list of commands that happen at the begining of
# each script
#
if {([lsearch $vars(steps) $step] == -1) && ($step != "debug")} {
puts "<FF> ERROR: Unknown Foundation Flow step \"$step\"."
exit 99
}
# if {([lsearch $vars(steps) $step] == -1) && ($step != "debug")} {
# puts "<FF> ERROR: Unknown Foundation Flow step \"$step\"."
# exit 99
# } else {
# if {($vars(fix_hold) || (!$vars(fix_hold) && ![regexp "_hold" $step])) &&
# !($vars(skip_cts) && (($step == "cts") || [regexp "postcts" $step]))} {
# puts "<FF> Generating step $step"
# }
# }
#
# We need to ensure that we check the variable contents and
# initialize the flow at least once in a given run, no matter
# what step the user wants to execute
#
# set header "\n#\n# Commands for $step\n#\n\n"
if {![info exists vars(all)]} {
execute_flow check $format $abort
}
# BCL: Changed to tcl file mkdir
file mkdir $vars(script_dir)/INNOVUS
set commands ""
# set commands "post-10.10-b009\n"
if {!$vars(initialized)} {
set vars(step) $step
append commands [FF_EDI::initialize_flow]
# unset vars(step)
set vars(init_commands) $commands
set vars(initialized) 1
if {![info exists vars(warning_count)]} {
set vars(warning_count) 0
}
if {![info exists vars(error_count)]} {
set vars(error_count) 0
}
}
#
# Get the commands to execute the step. We also need to get the
# commands to load the database for that step, assuming that a
# database exists from a prior step. Those load commands are
# prepended to the execution commands. Save commands are
# appended
#
if {[info commands ::FF_EDI::run_$step] ne ""} {
set temp_commands [FF_EDI::run_$step $format]
if {$temp_commands == ""} {
return ""
} else {
if {$vars(step) != "init"} {
set step_commands "\n#-------------------------------------------------------------\n"
if {$vars(report_run_time)} {
append step_commands "set vars(step) ${step}\n"
append step_commands "set vars(${step},start_time) \[clock seconds\]\n"
}
if {$vars(capture_metrics)} {
if {[lindex [split $vars(version) "."] 0] > 13} {
# append step_commands "um::enable_metrics -on\n"
# GG7
# if {![info exists vars(pushed)] || ([info exists vars(pushed)] && !$vars(pushed)) } {
append step_commands "um::push_snapshot_stack\n"
# set vars(pushed) true
# }
}
}
append step_commands "#-------------------------------------------------------------\n\n"
}
append step_commands $temp_commands
append step_commands "#-------------------------------------------------------------\n\n"
puts "<FF> Generating step $step"
}
} elseif {[info exists vars(custom_step_dir)]} {
if {[file isfile $vars(custom_step_dir)/run_${step}.tcl]} {
puts "<FF> Generating step $step"
set fhr [open $vars(custom_step_dir)/run_$step.tcl r]
set step_commands "\n#-------------------------------------------------------------\n"
append step_commands "# Sourcing custom script ...\n"
append step_commands "#-------------------------------------------------------------\n"
if {$vars(report_run_time) && ($step != "init")} {
append step_commands "set vars(step) ${step}\n"
append step_commands "set vars(${step},start_time) \[clock seconds\]\n"
}
if {$vars(capture_metrics) && ($vars(step) != "init")} {
if {[lindex [split $vars(version) "."] 0] > 13} {
append step_commands "um::enable_metric -on\n"
append step_commands "um::push_snapshot_stack\n"
}
}
append step_commands "#-------------------------------------------------------------\n\n"
while {[gets $fhr line]>=0} {
append step_commands "$line\n"
}
# append step_commands "source $vars(custom_step_dir)/run_$step.tcl\n"
append step_commands "#-------------------------------------------------------------\n\n"
} else {
puts "<FF> ERROR: Unable to generate step $step"
set errors($vars(error_count)) "Unable to generate step $step - procedure 'run_$step' must be defined or a \$vars(custom_step_dir)/run_$step.tcl file must be provided"
incr vars(error_count)
return ""
}
} else {
puts "<FF> ERROR: Unable to generate step $step"
set errors($vars(error_count)) "Unable to generate step $step - procedure 'run_$step' must be defined or a \$vars(custom_step_dir)/run_$step.tcl file must be provided"
incr vars(error_count)
return ""
}
# set this_index [lsearch $vars(steps) $step]
# set prior [lindex $vars(steps) [expr $this_index - 1]]
## if {!$vars(fix_hold) && [regexp _hold $prior]} {
## set prior [lindex $vars(steps) [expr $this_index - 2]]
## if {[regexp _hold $prior]} {
## set prior [lindex $vars(steps) [expr $this_index - 3]]
## }
## }
# if {[regexp _hold $prior] && ([lsearch $vars(fix_hold) [regsub _hold $prior ""]]<0)} {
# set prior [lindex $vars(steps) [expr $this_index - 2]]
# if {[regexp _hold $prior] && ([lsearch $vars(fix_hold) [regsub _hold $prior ""]]<0)} {
# set prior [lindex $vars(steps) [expr $this_index - 3]]
# }
# }
# if {($step == "cts") && $vars(place_opt_design)} {
# set prior "place"
# }
# if {($step == "route") && $vars(skip_cts)} {
# set prior "prects"
# }
## if {($step == "route") && [regexp "^ccopt" [string tolower $vars(cts_engine)]]} {
## set prior "cts"
## }
# if {[regexp "^ccopt" [string tolower $vars(cts_engine)]]} {
# if {([string tolower $vars(fix_hold)] != "false")} {
# if {($step == "postcts_hold") && [lsearch $vars(fix_hold) $step]} {
# set prior cts
# } else {
# if {($step == "route")} {
# set prior cts
# }
# }
# } else {
# if {($step == "route")} {
# set prior cts
# }
# }
# }
set this_index [lsearch [FF::adjust_steps] $step]
set prior [lindex [FF::adjust_steps] [expr $this_index - 1]]
set no_db_steps [list "init" "rebudget" "flexilm" "assemble" "assemble_flexilm" "debug"]
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
lappend no_db_steps "model_gen"
} else {
lappend no_db_steps "feedthrough"
}
if {([lsearch $no_db_steps $step] == -1) && ($prior != "")} {
set load_commands [FF_EDI::load_design $prior $step]
# set restore_commands [lindex [FF_EDI::load_design $format $prior] 1]
} else {
set load_commands ""
# set restore_commands ""
}
if {!$vars(loaded)} {
set vars(loaded) 1
append commands $load_commands
}
# model_gen saves its database explicitly
# set no_save_steps [list "debug" "model_gen"]
set no_save_steps [list "debug"]
if {[lsearch $no_save_steps $step] == -1} {
set save_commands [FF_EDI::save_results $step $format]
} else {
set save_commands ""
}
#
# Write the commands to a file, named for the step we are
# executing
#
if {[regexp "^syn" $step]} {
file mkdir $vars(script_dir)/GENUS
set op [open $vars(script_dir)/GENUS/run_${step}.tcl w]
} else {
set op [open $vars(script_dir)/INNOVUS/run_${step}.tcl w]
}
if {$vars(debug)} {
# puts "<DEBUG> Opening file: $vars(script_dir)/INNOVUS/run_${step}.tcl in [exec pwd] -> $op"
}
puts $op [string repeat "#" 68]
puts $op "# Innovus Foundation Flow Code Generator, [exec date]"
puts $op "# Version : 17.10-p003_1"
puts $op [string repeat "#" 68]
if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
set varsFile [FF::relPathTo [file normalize $vars(script_dir)/vars.tcl] [file normalize $vars(rundir)]]
} else {
set varsFile $vars(script_dir)/vars.tcl
}
puts $op "\nif {\[file exists $varsFile\]} {"
puts $op " source $varsFile"
puts $op "}"
#puts $op "if {\[file exists \$vars(script_dir)/vars.tcl\]} {"
#puts $op " source \$vars(script_dir)/vars.tcl"
#puts $op "}\n"
if {!$vars(freeze_vars)} {
if {([file tail [file dirname [pwd]]] != "$vars(partition_dir)") && ![regexp syn_ $step]} {
puts $op "foreach file \$vars(config_files) {"
puts $op " source \$file"
puts $op "}\n"
}
}
# puts $op "source \$vars(script_dir)/procs.tcl"
puts $op "source $vars(script_dir)/procs.tcl"
if {!$format} {
puts $op $header
}
regsub -all "init," $vars(init_commands) "$step," commands
set of [open $vars(script_dir)/INNOVUS/.head w]
puts $of [FF::pretty_print $vars(init_commands) $format]
close $of
append commands $load_commands $step_commands $save_commands
lappend vars(bsteps) $step
set of [open $vars(script_dir)/INNOVUS/.load_$step w]
# puts $of [FF::pretty_print $restore_commands $format]
puts $of [FF::pretty_print $load_commands $format]
close $of
set of [open $vars(script_dir)/INNOVUS/.$step w]
puts $of [FF::pretty_print $step_commands $format]
puts $of [FF::pretty_print $save_commands $format]
close $of
# if {[regexp "postroute_si" $step] && $skip_commands != ""} {
# set commands $skip_commands
# }
if {!$format} {
set commands [FF::strip_lines $commands [list "puts" "#"]]
}
if {$vars(catch_errors) && ($step != "debug")} {
puts $op "\nif { \[catch {\n"
puts $op [FF::pretty_print $commands $format]
puts $op "} step_error\]} {\n"
puts $op " Puts \"<FF> =========== STEP EXECUTION ERROR ============\""
puts $op " Puts \"<FF> ERROR RUNNING STEP '$step'\""
if {$vars(save_on_catch)} {
if {[regexp "^syn" $vars(step)]} {
puts $op " write_db $vars(design) -all_root_attributes -to_file $vars(dbs_dir)/$vars(step).catch.db\n"
} else {
puts $op " Puts \"<FF> ---------------------------------------------\""
puts $op " Puts \"<FF> ... SAVING DESIGN TO $vars(dbs_dir)/$vars(step).catch.enc\""
if {[string compare -nocase $vars(dbs_format) "oa"]==0} {
if {[lindex [split $vars(version) "."] 0] > 10} {
puts $op " saveDesign -cellview {$vars(oa_design_lib) $vars(design) $vars(step).catch}\n"
} else {
puts $op " saveOaDesign $vars(oa_design_lib) $vars(design) $vars(step).catch\n"
}
} else {
puts $op " saveDesign $vars(dbs_dir)/$vars(step).catch.enc -compress\n"
}
}
}
puts $op " Puts \"<FF> ---------------------------------------------\""
puts $op " Puts \"<FF> \$step_error\""
puts $op " Puts \"<FF> ------------------- DETAILS ------------------\""
puts $op " Puts \"<FF> \$errorInfo\""
puts $op " Puts \"<FF> ==============================================\""
if {$vars(batch)} {
# if {$vars(exit_on_error)} {
puts $op " exit -1"
# }
}
puts $op "}"
} else {
puts $op [FF::pretty_print $commands $format]
}
if {$vars(batch) && ($step != "debug")} {
puts $op "if {!\[info exists vars(single)\]} {\n exit 0\n}\n"
}
close $op
set scommands [split $commands "\n"]
if $vars(generate_flow_steps) {
if {[regexp syn_ $step]} {
append vars(flow_steps) "\ncreate_flow_step -name $step \{\n"
} else {
append vars(flow_steps) "\ncreate_flow_step -name $step \{\n eval_legacy \{\n "
}
if {[info exists vars(hsteps)] && ([lsearch $vars(hsteps) $step] != -1)} {
append vars(flow_steps,hier) "\ncreate_flow_step -name $step \{\n eval_legacy \{\n "
} else {
if {[regexp syn_ $step]} {
append vars(flow_steps,flat) "\ncreate_flow_step -name $step \{\n"
} else {
append vars(flow_steps,flat) "\ncreate_flow_step -name $step \{\n eval_legacy \{\n "
}
}
set skip 0
foreach line $scommands {
if {$skip != 0} {
set skip [expr $skip-1]
continue
}
if {[regexp ff_procs $line]} { continue }
if {[regexp "#" $line]} { continue }
if {[regexp "Puts" $line]} { continue }
if {[regexp "VPATH" $line]} { continue }
if {[regexp "set vars" $line] && ![regexp ",post_cts_sdc" $line]} { continue }
if {$step != "init"} {
# if {[regexp "restore_design" $line]} { set skip 7; continue }
if {!(($step == "cts") && $vars(enable_flexilm))} {
if {[regexp "restoreDesign" $line]} { continue }
} else {
if {[regexp "restoreDesign" $line]} {
# set line [string trim [lindex $line 2]]
set line "restoreDesign \[file tail \[pwd\]\]_postECO.enc.dat \[file tail \[pwd\]\]"
}
}
} else {
if {[regexp "restoreDesign" $line]} {
set line "restoreDesign . \[file tail \[pwd\]]"
}
}
if {[regexp "saveDesign" $line]} { continue }
if {[regexp "metric" $line]} { continue }
if {[regexp "snapshot" $line]} { continue }
if {[regexp "report_metric" $line]} { continue }
if {$line == ""} { continue }
append vars(flow_steps) "\t$line\n"
if {[info exists vars(hsteps)] && ([lsearch $vars(hsteps) $step] != -1)} {
append vars(flow_steps,hier) "\t$line\n"
} else {
append vars(flow_steps,flat) "\t$line\n"
}
}
append vars(flow_steps) "\}\n"
if {[info exists vars(hsteps)] && ([lsearch $vars(hsteps) $step] != -1)} {
append vars(flow_steps,hier) "\n \}\n"
if {$step == "partition"} {
foreach p $vars(partition_list) {
# append vars(flow_steps,hier) "\n schedule_flow -flow $p -dir $vars(partition_dir)/$p"
append vars(flow_steps,hier) "\n schedule_flow -flow block -dir $vars(partition_dir)/$p"
}
}
append vars(flow_steps,hier) "\n\}\n"
} else {
if {([file tail [file dirname [pwd]]] == "$vars(partition_dir)") && ($step == "signoff")} {
if {[lsearch $vars(partition_list) $vars(design)] == -1} {
append vars(flow_steps,flat) "\n \}\n"
append vars(flow_steps,flat) "\n schedule_flow -flow final_assembly"
append vars(flow_steps,flat) "\n\}\n"
} else {
append vars(flow_steps,flat) "\n \}\n"
# append vars(flow_steps,flat) "\n schedule_flow -flow $vars(top_cell) -dir $vars(partition_dir)/$vars(top_cell)"
append vars(flow_steps,flat) "\n schedule_flow -flow top -dir $vars(partition_dir)/$vars(top_cell)"
append vars(flow_steps,flat) "\n\}\n"
}
} else {
if {[regexp syn_ $step]} {
if {$vars(rc)} {
if {$vars(enable_rcp) && ($step == "syn_place")} {
append vars(flow_steps,flat) "\n schedule_flow -flow innovus -db \"$vars(dbs_dir)/syn_place/syn_place.novus_setup.tcl\"\n"
} elseif {!$vars(enable_rcp) && ($vars(step) == "syn_incr")} {
append vars(flow_steps,flat) "\n schedule_flow -flow innovus -db \"$vars(dbs_dir)/syn_incr/syn_incr.novus_setup.tcl\"\n"
}
}
append vars(flow_steps,flat) "\}\n"
} else {
append vars(flow_steps,flat) "\}\n\}\n"
}
}
}
}
set action $step
}
}
#
# Create a file that sets up all of the variable settings that were
# used in this invocation
#
# GDG - is this needed anymore
if {0} {
# BCL: Changed to tcl file mkdir
file mkdir $vars(script_dir)
set op [open $vars(script_dir)/vars.tcl w]
puts $op "# this is the one"
puts $op "if {!\[info exists vars\]} {"
puts $op " global vars"
puts $op "}"
# if {[info exists vars(user_arrays)]} {
# foreach array $vars(user_arrays) {
# puts $op "#----------------------------------------------"
# puts $op "global $array"
# set cmd "array names $array"
# set uvars [eval $cmd]
# foreach var $uvars {
# if {[regexp {\$} $vars($var)]} {
# puts $op "set $array($var) \"$$array($var)\""
# } else {
# puts $op "set $array($var) \{$array($var)\}"
# }
# }
# }
# }
## BCL: Added sourcing .ff.tcl to vars.tcl
#puts $op "if {\[file exists .ff.tcl\]} {"
#puts $op " source .ff.tcl"
#puts $op "}"
puts $op "global env\n\n"
puts $op "#----------------------------------------------"
puts $op "set env(VPATH) $env(VPATH)"
puts $op "set vars(rundir) $vars(rundir)"
foreach var [lsort [array names vars]] {
# BCL: Only write out variable values in curlies if not using $vars() in the value of the variable
if {[regexp {\$} $vars($var)]} {
puts $op "set vars($var) \"$vars($var)\""
} else {
puts $op "set vars($var) \{$vars($var)\}"
}
}
puts $op "set vars(restore_design) {true}"
# if {[info exists vars(cpf_file)]} {
# puts $op "catch {alias ff_modify_power_domains FF_EDI::modify_power_domains}"
# puts $op "catch {alias ff_add_power_switches FF_EDI::add_power_switches}"
# puts $op "catch {alias ff_route_secondary_pg_nets FF_EDI::route_secondary_pg_nets}"
# puts $op "catch {alias ff_get_power_domains FF_EDI::get_power_domains}"
# puts $op "catch {alias ff_buffer_always_on_nets FF_EDI::buffer_always_on_nets}"
# puts $op "catch {alias ff_insert_welltaps_endcaps FF_EDI::insert_welltaps_endcaps}"
# }
close $op
}
return $action
}
proc insert_comments {} {
global vars
set comments ""
append comments "######################################################################\n"
append comments "# Variables affecting this step:\n"
append comments "#---------------------------------------------------------------------\n"
if {[info exists vars(comments)]} {
append comments $vars(comments)
unset vars(comments)
} else {
append comments "# No variables defined for this step ...\n"
}
append comments "######################################################################\n"
if {[info exists vars(ucomments)]} {
append comments "# Additional variables for this step:\n"
append comments "#---------------------------------------------------------------------\n"
append comments $vars(ucomments)
append comments "######################################################################\n"
unset vars(ucomments)
}
return $comments
}
# proc run_all {} {
#
# global vars
#
# set time 0
# set index 0
# set stop_step signoff
# set vars(codegen) false
# if {![info exists vars(vpath)]} { set vars(vpath) make }
#
# foreach step $vars(steps) {
# if {[file exists $vars(vpath)/$step]} {
# if {[file mtime $vars(vpath)/$step] > $time} {
# if {[lindex $vars(steps) $index] == "signoff"} {
# Puts "<FF> STEP signoff COMPLETE ... NOTHING TO DO"
# } else {
# set start_step [lindex $vars(steps) [expr $index + 1]]
# }
# }
# } else {
# set start_step $step
# break
# }
# incr index
# }
#
# puts "<FF> -----------------------------------------------------"
# if {$start_step == $stop_step} {
# puts "<FF> RUNNING STEP $start_step ..."
# } else {
# puts "<FF> RUNNING STEP $start_step through $stop_step ..."
# }
# puts "<FF> -----------------------------------------------------"
# sleep 5
#
# #
# # Emulate the functionality of the "make" program. If a file doesn't exist,
# # or if it's predecessor step has executed more recently, run the current
# # step and update the time/date stamps of the files we track progress with
# #
#
# set vars(stop_step) $stop_step
#
# set last_step ""
# set vars(restore_design) 1
# if {$vars(enable_qor_check)} {
# set check_qor $vars(script_dir)/check_qor.tcl
# }
# exec mkdir -p make
# foreach step $vars(steps) {
# set vars(step) $step
# Puts "<FF> STEP $vars(step) ..."
# set this_semaphore "$vars(vpath)/$step"
# set last_semaphore "$vars(vpath)/$last_step"
#
# set run_step false
# if {![file exists $this_semaphore]} {
# set run_step true
# } elseif {$last_step != ""} {
# file stat $this_semaphore this_stat
# file stat $last_semaphore last_stat
# if {$this_stat(mtime) < $last_stat(mtime)} {
# set run_step true
# }
# }
#
# #
# # Check the quality of results from the last step. If the results aren't
# # as expected, don't proceed to the next step
# #
# if {$vars(enable_qor_check)} {
# if {$step != "init"} {
# set qor [catch {exec $check_qor $last_semaphore} msg]
# if {$qor} {
# puts "<FF> ERROR: QOR RESULT CHECK INDICATES A PROBLEM IN STEP $last_step"
# exit -111
# }
# }
# }
#
# set last_step $step
# if {!$run_step} {
# continue
# }
#
# #
# # Source the control file that runs the step. If it had an error, exit
# # immediately. Otherwise, update the time/date stamp of the corresponding
# #
# #
#
# if {[catch {FF_EDI::run_$step} message]} {
# puts $message
# exit -111
# }
# set vars(restore_design) 0
#
# #
# # If there is a QOR check file for this step, execute it and place the
# # result into the make file. Otherwise just touch the file
# #
#
# if {$vars(enable_qor_check)} {
# if {[info exists vars($step,qor_tcl]} {
# set qor_file $vars($step,qor_tcl)
# if {[file exists $qor_file]} {
# set qor [catch {exec $qor_file} msg]
# set make_file [open $this_semaphore w]
# puts $make_file "$qor"
# close $make_file
# }
# }
# }
# exec /bin/touch $this_semaphore
#
# if {$step == $stop_step} {
# Puts "<FF> Done"
# }
# }
# }
proc load_power_intent {} {
global vars
set commands ""
if {[info exists vars(cpf_file)]} {
set command "loadCPF $vars(cpf_file)\n"
append commands [FF::wrap_command $vars(step),load_cpf $command]
set command "commitCPF"
if {$vars(cpf_keep_rows)} {
append command " -keepRows"
}
if {$vars(cpf_power_domain)} {
append command " -powerDomain"
}
if {$vars(cpf_isolation)} {
append command " -isolation"
}
if {$vars(cpf_state_retention)} {
append command " -state_retention"
}
if {$vars(cpf_level_shifter)} {
append command " -level_shifter"
}
if {$vars(cpf_power_switch)} {
append command " -power_switch"
}
append command "\n"
append commands [FF::wrap_command $vars(step),commit_cpf $command]
append comments "# - vars(cpf_file)\n"
append comments "# - vars(cpf_isolation)\n"
append comments "# - vars(cpf_state_retention)\n"
append comments "# - vars(cpf_level_shifter)\n"
append comments "# - vars(cpf_power_switch)\n"
append comments "# - vars(cpf_power_domain)\n"
append comments "# - vars(cpf_keep_rows)\n"
} elseif {[info exists vars(ieee1801_file)]} {
set command "read_power_intent $vars(ieee1801_file) -1801\n"
append commands [FF::wrap_command $vars(step),load_ieee1801 $command]
set command "commit_power_intent"
if {$vars(ieee1801_keep_rows)} {
append command " -keepRows"
}
if {$vars(ieee1801_power_domain)} {
append command " -power_domain"
}
if {$vars(ieee1801_isolation)} {
append command " -isolation"
}
if {$vars(ieee1801_state_retention)} {
append command " -state_retention"
}
if {$vars(ieee1801_level_shifter)} {
append command " -level_shifter"
}
if {$vars(ieee1801_power_switch)} {
append command " -power_switch"
}
append command "\n"
append commands [FF::wrap_command $vars(step),commit_ieee1801 $command]
append comments "# - vars(ieee1801_file)\n"
append comments "# - vars(ieee1801_isolation)\n"
append comments "# - vars(ieee1801_state_retention)\n"
append comments "# - vars(ieee1801_level_shifter)\n"
append comments "# - vars(ieee1801_power_switch)\n"
append comments "# - vars(ieee1801_power_domain)\n"
append comments "# - vars(ieee1801_keep_rows)\n"
} else {
append ucomments "# - vars(cpf_file)\n"
append ucomments "# - vars(cpf_isolation)\n"
append ucomments "# - vars(cpf_state_retention)\n"
append ucomments "# - vars(cpf_level_shifter)\n"
append ucomments "# - vars(cpf_power_switch)\n"
append ucomments "# - vars(cpf_power_domain)\n"
append ucomments "# - vars(cpf_keep_rows)\n"
}
return $commands
}
proc set_design_mode {} {
global vars
set commands ""
set comments ""
set ucomments ""
set process [regsub "nm" $vars(process) ""]
append comments "# - vars(process)\n"
if {[lindex [split $vars(version) "."] 0] < 15} {
if {$vars(high_timing_effort)} {
append comments "# - vars(high_timing_effort)\n"
if {![regexp "9.1" $vars(version)]} {
set command "setDesignMode -process $process -flowEffort high\n"
} else {
set command "setDesignMode -process $process\n"
}
} else {
set command "setDesignMode -process $process\n"
}
} else {
if {[string tolower $vars(flow_effort)] != "standard"} {
set command "setDesignMode -process $process -flowEffort [string tolower $vars(flow_effort)]"
append comments "# - vars(flow_effort)\n"
} else {
set command "setDesignMode -process $process"
}
if {$vars(power_effort) != "none"} {
append comments "# - vars(power_effort)\n"
append command " -powerEffort $vars(power_effort)"
} else {
append ucomments "# - vars(power_effort) \"low or high\"\n"
}
}
# uplevel #0 append commands [FF::wrap_command $vars(step),set_design_mode "$command\n"]
append commands [FF::wrap_command $vars(step),set_design_mode "$command\n"]
return [list $commands $comments $ucomments]
}
#---------------------------------------------------------------------------------------------------
# This script will prepare a digital block for LVS. It can be added to the FF by adding the tag:
#
# set vars(signoff,save_design,post_tcl) <path>/createSymbolAndCDF.tcl
#
# Note, it must be run after the design is saved in the signoff step.
#
# The script does the following:
#
# 1) Creates the SKILL script: ggCreateSymbolAndCDF.il
#
# When this script is called by Virtuoso (later in the flow), it will perform
# the following:
#
# -copy view: <lib> <cell> signoff
# to: <lib> <cell> layout
#
# -Remaster the instances of the view "layout" to reference 'layout' views
# rather than 'abstract' views
#
# -Create ihdl parameter and command files which are used by verilogIn
#
# -Create a verilog stub file from the physical netlist
#
# -Run ihdl (verilogIn) on the stub file to create the 'symbol' view
#
# -Copy the symbol view to create the auCdl view
#
# -Use either v2cdl or v2lvs to convert the verilog netlist to CDL
# and store it in the auCdl view
#
# -Create the base level CDF to support auCdl netlisting
#
#
# 2) Saves a physical netlist that excludes filler cells. This will be used later
# to create the CDL view.
#
# 3) Creates the .simrc file used by ihdl.
#
# 4) Creates the SKILL script: PostProcessInVirtuoso.il.
#
# This script reads/executes the script ggCreateSymbolAndCDF.il.
#
#
# 5) If Virtuoso is in the user's path, it will execute the script:
#
# PostProcessInVirtuoso.il
#
#
#
# Created by: Bill Wareham 01/26/2015
# Vikram Agarwal
# Greg Gorton
#
#---------------------------------------------------------------------------------------------------
proc create_lvs_data {} {
global vars
global infos
global warnings
# Create the ggCreateSymbolAndCDF.il skill code
set infos($vars(info_count)) "Created the $vars(script_dir)/ggCreateSymbolAndSDF.il SKILL script\n"
incr vars(info_count)
set op [open $vars(script_dir)/ggCreateSymbolAndCDF.il w]
puts $op ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op ";;;"
puts $op ";;; Function: ggCreateSymbolAndCDF - performs several functions to prepare a digital"
puts $op ";;; block saved from Innovus in OA for follow on integration in a top level Virtuoso"
puts $op ";;; schematic to support PVS LVS."
puts $op ";;;"
puts $op ";;; Inputs:"
puts $op ";;; library : Name of the library with the digital block"
puts $op ";;; cellName : Name of the digital block"
puts $op ";;; viewName : Name of the digital block unremastered layout view"
puts $op ";;; verilogFile : Name of the verilog netlist"
puts $op ";;; overwrite : Overwrite existing library"
puts $op ";;;"
puts $op ";;; Outputs:"
puts $op ";;; layout view : \"layout\" view with abstracts remastered to type layout"
puts $op ";;; symbol view : \"symbol\" view with pins to match verilogFil"
puts $op ";;; auCdl view : copy of symbol view for cdl netlisting stop and view lists"
puts $op ";;; auCdl CDF : base CDF auCdl simulation properties for netlisting"
puts $op ";;;"
puts $op ";;; ggCreateSymbolAndCDF(\"libname\" \"cellName\" \"viewName\" \"/path_to_file/myname.v\")"
puts $op ";;;"
puts $op ";;; Notes:"
puts $op ";;;"
puts $op ";;; The input layout file from Innovus on OA created with the following comnmand:"
puts $op ";;; saveDesign -cellview { library cellName viewName }"
puts $op ";;; Used viewName \"edi_routed\" to signify routed design from EDI."
puts $op ";;; This file can be used to restore design in Innovus. You can also run oaOut"
puts $op ";;; from Innovus and have it create a layout view with the abstracts remastered."
puts $op ";;; This script will take care of this step in Virtuoso so you don't have to run"
puts $op ";;; the second save from Innovus."
puts $op ";;;"
puts $op ";;; The verilogFile was created from Innovus using the following command:"
puts $op ";;; saveNetlist myname.v -excludeLeafCell -phys -excludeCellInst \"FILL1 ...\""
puts $op ";;; Used \"cellName_phys_nofill.v\" as an example."
puts $op ";;; This creates a physical verilog netlist with power and ground pins, excludes"
puts $op ";;; leaf cells (standard cells) and removes the FILL cells listed."
puts $op ";;;"
puts $op ";;; The script is written to accept the inputs from the command line. This can be"
puts $op ";;; modified to pull from the active window and/or a form."
puts $op ";;;"
puts $op ";;; The layout saved from Innovus should be named something other than \"layout\". It is"
puts $op ";;; assumed that all the instances are of type \"abstract\" and need to be remastered"
puts $op ";;; to type \"layout\". To change the default name for the remastered layout view from"
puts $op ";;; \"layout\", change the \"newView\" variable."
puts $op ";;;"
puts $op ";;; The symbol view is created using VerilogIn. The physical Verilog netlist from EDI"
puts $op ";;; is parsed and a temporary netlist created that only has the module and pins"
puts $op ";;; defined for the digital block \"cellName\". The regular expression checks to start"
puts $op ";;; and stop the parsing of the input verilog netlist to just extract the pin"
puts $op ";;; definitions is basic and specific to the syntax seen in a couple examples from"
puts $op ";;; EDI. See comments in the \"Creating /tmp/ihdl_verilog.v\" section for details."
puts $op ";;;"
puts $op ";;; Two log files are created during VerilogIn:"
puts $op ";;; VerilogIn.log"
puts $op ";;; VerilogIn_stdout.log"
puts $op ";;;"
puts $op ";;; The default is to overwrite the existing symbol during VerilogIn if it was"
puts $op ";;; previously created by VerilogIn \"overwrite_symbol := 1\". To not overwrite the"
puts $op ";;; symbol, regardless of the source set it to \"overwrite_symbol := 0\"."
puts $op ";;;"
puts $op ";;; VerilogIn is run via the unix command line using ihdl. The ihdl input files are"
puts $op ";;; created in /tmp."
puts $op ";;;"
puts $op ";;; See \"Verilog In for Virtuoso Design Environment User Guide and Reference\"."
puts $op ";;;"
puts $op ";;; The auCdl view is just a copy of the symbol view created by VerilogIn."
puts $op ";;;"
puts $op ";;; The CDF auCdl simulation parameters are created at the \"base\" cell level to"
puts $op ";;; enable cdl netlisting of just the subckt name and pins. When running LVS the"
puts $op ";;; associated Verilog netlist and IP cdl views should be included."
puts $op ";;; "
puts $op ";;; Written by: Greg Gorton, 5/18/14"
puts $op ";;;"
puts $op ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op ""
puts $op "procedure(ggCreateSymbolAndCDF(library cellName viewName verilogFile @optional (overwrite nil))"
puts $op ""
puts $op " prog( (cv newView cv2 ihs startString printModule cv3 cv4 cid cdlpath portorder OUTFILE INFILE baseCDFid nextLine)"
puts $op ""
puts $op " ; view name to use for copy of saved Innovus layout view that needs to be remastered"
puts $op " newView=\"layout\""
puts $op ""
puts $op " ; Get library cell and view from the active window"
puts $op " ; Add cw to the let statement"
puts $op " ; cw=hiGetCurrentWindow()"
puts $op " ; cv=cw->cellView"
puts $op " ; library=cv->libName"
puts $op " ; cellName=cv->cellName"
puts $op " ; viewName=cv->viewName"
puts $op " ; verilogFile=\"./SCRIPT/countersTest.v\""
puts $op ""
puts $op " ; Verify the existance of the input parameters"
puts $op " unless(isFile(verilogFile)"
puts $op " printf(\"The verilog file %s does not exist.\\n\" verilogFile)"
puts $op " printf(\"Please fix and run again.\\n\")"
puts $op " return()"
puts $op " )"
puts $op " unless(cv=dbOpenCellViewByType( library cellName viewName )"
puts $op " printf(\"The %s %s %s cell view does not exist.\\n\" library cellName viewName)"
puts $op " printf(\"Please fix and run again.\\n\")"
puts $op " return()"
puts $op " )"
puts $op ""
puts $op " ; Copy present view to a layout view (or value defined by parameter newView)"
puts $op " printf(\" Running ggCreateSymbolAndCDF:\\n\")"
puts $op " printf(\" Copy %s %s %s to %s %s %s.\\n\" library cellName viewName library cellName newView)"
puts $op " unless(dbCopyCellView(cv library cellName newView nil nil overwrite)"
puts $op " printf(\"Can't create the new %s view.\\n\" newView)"
puts $op " printf(\"Please use the overwrite parameter: ggCreateSymbolAndCDF(lib cell view verilogfile t) and check permissions.\\n\")"
puts $op " return()"
puts $op " )"
puts $op ""
puts $op " ; Remaster instances from type abstract to layout in the layout view"
puts $op " cv2=dbOpenCellViewByType( library cellName newView \"maskLayout\" \"a\")"
puts $op " printf(\" Open %s %s %s for edit.\\n\" library cellName newView)"
puts $op ""
puts $op " ihs=setof(ih cv2~>instHeaders ih~>viewName==\"abstract\")"
puts $op " foreach(ih ihs"
puts $op " when(ddGetObj(ih~>libName ih~>cellName \"layout\" )"
puts $op " ih~>master = dbOpenCellViewByType( ih~>libName ih~>cellName \"layout\" )"
puts $op " )"
puts $op " )"
puts $op ""
puts $op " dbSave(cv2)"
puts $op " dbClose(cv2)"
puts $op ""
puts $op " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op " ; Use verilogIn to create a symbol"
puts $op " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op " printf(\" Running VerilogIn to create the %s %s symbol view.\\n\" library cellName)"
puts $op ""
puts $op " ; Create the ihdl command file in /tmp"
puts $op " printf(\" Creating /tmp/ihdl_files_%s\\n\" cellName)"
puts $op " OUTFILE=outfile(strcat(\"/tmp/ihdl_files_\" cellName))"
puts $op " fprintf( OUTFILE \"-param /tmp/ihdl_params_%s\\n\" cellName)"
puts $op " fprintf( OUTFILE \"-cdslib ./cds.lib\\n\")"
puts $op " close(OUTFILE)"
puts $op " OUTFILE=nil"
puts $op ""
puts $op " ; Create the ihdl parameters file in /tmp"
puts $op " ; Need to set power and ground nets to a name not used in the input"
puts $op " ; verilog netlist or the power and ground pins will be changed to"
puts $op " ; global names on the symbol pins."
puts $op " printf(\" Creating /tmp/ihdl_params_%s\\n\" cellName)"
puts $op " OUTFILE=outfile(strcat(\"/tmp/ihdl_params_\" cellName))"
puts $op " fprintf( OUTFILE \"dest_sch_lib := %s\\n\" library)"
puts $op " fprintf( OUTFILE \"ref_lib_list := basic\\n\")"
puts $op " fprintf( OUTFILE \"structural_views := 4\\n\")"
puts $op " fprintf( OUTFILE \"functional_view_name := functional_toponly\\n\")"
puts $op " fprintf( OUTFILE \"symbol_view_name := symbol\\n\")"
puts $op " fprintf( OUTFILE \"overwrite_symbol := 1\\n\")"
puts $op " fprintf( OUTFILE \"power_net := Pxx_dummyValue\\n\")"
puts $op " fprintf( OUTFILE \"ground_net := Gxx_dummyValue\\n\")"
puts $op " fprintf( OUTFILE \"log_file_name := ./VerilogIn.log\\n\")"
puts $op " close(OUTFILE)"
puts $op " OUTFILE=nil"
puts $op ""
puts $op " ; Parse the Verilog file from Innovus and create a Verilog file with just the"
puts $op " ; top module definition for \"cellName\" with only the pins define."
puts $op " ; The regular expression checks to start and stop printing the Verilog"
puts $op " ; module are simple and tied to the syntax from EDI. It starts on the exact"
puts $op " ; string \"module cellName\" where cellName is your cellName. It stops at the"
puts $op " ; first comment line which has been \"// Internal wires\" or"
puts $op " ; \"// Module instantiations\" in my examples. These come after the pin"
puts $op " ; definitions."
puts $op " printf(\" Creating /tmp/ihdl_verilog_%s.v\\n\" cellName)"
puts $op " INFILE=infile(verilogFile)"
puts $op " OUTFILE=outfile(sprintf(nil \"/tmp/ihdl_verilog_%s.v\" cellName))"
puts $op " startString=buildString( list(\"module\" cellName) )"
puts $op " printModule=\"no\""
puts $op " when( INFILE"
puts $op " while( gets(nextLine INFILE)"
puts $op " if((rexMatchp(startString nextLine) || printModule==\"yes\") then"
puts $op " if(rexMatchp(\"//\" nextLine) then"
puts $op " printModule=\"no\""
puts $op " fprintf(OUTFILE \"endmodule\\n\")"
puts $op " else"
puts $op " printModule=\"yes\""
puts $op " fprintf(OUTFILE nextLine)"
puts $op " )"
puts $op " ) ; if module cellName"
puts $op " ) ; while nextLine"
puts $op " close(INFILE)"
puts $op " ) ; when INFILE"
puts $op " close(OUTFILE)"
puts $op " OUTFILE=nil"
puts $op ""
puts $op " ; Run ihdl to create the symbol view and temporary functional view."
puts $op " ; Function will overwrite existing symbol view if previously created by VerilogIn."
puts $op " printf(\" Running ihdl -f /tmp/ihdl_files_%s /tmp/ihdl_verilog_%s.v >& VerilogIn_stdout_%s.log\\n\" cellName cellName cellName)"
puts $op " system(sprintf(nil \"ihdl -f /tmp/ihdl_files_%s /tmp/ihdl_verilog_%s.v >& VerilogIn_stdout_%s.log\" cellName cellName cellName ))"
puts $op ""
puts $op " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op " ; Copy the symbol view to an auCdl view"
puts $op " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op ""
puts $op " printf(\" Copy %s %s symbol to %s %s auCdl.\\n\" library cellName library cellName)"
puts $op " newView=\"auCdl\""
puts $op " cv3=dbOpenCellViewByType( library cellName \"symbol\")"
puts $op " cv4=dbCopyCellView( cv3 library cellName newView nil nil overwrite)"
puts $op " dbCreateProp(cv4 \"CDL_NETLIST_FILE\" 'string \"cdl.netlist\")"
puts $op " portorder = cv4~>portOrder"
puts $op " dbClose(cv3)"
puts $op " dbSave(cv4)"
puts $op " dbClose(cv4)"
puts $op ""
puts $op " ;Convert the verilog netlist to cdl netlist and store it in the auCdl cellview."
puts $op " cdlpath = ddGetObjReadPath(ddGetObj( library cellName newView ))"
puts $op ""
puts $op " let((paths)"
puts $op " paths = parseString(getShellEnvVar(\"PATH\") \":\")"
puts $op " if( isFileName(\"v2cdl\" paths) then"
puts $op " system(sprintf(nil \"v2cdl -v %s -o %s/cdl.netlist -a \\\"\<\>\\\" \>\& v2cdl.log\" verilogFile cdlpath))"
puts $op " else"
puts $op " if( isFileName(\"v2lvs\" paths) then"
puts $op " system(sprintf(nil \"v2lvs -v %s -o %s/cdl.netlist -a \\\"\<\>\\\" \>\& v2cdl.log\" verilogFile cdlpath))"
puts $op " else"
puts $op " printf(\" ERROR: Unable to find Verilog -> CDL translator!!!\\n\")"
puts $op " printf(\" Neither v2cdl nor v2lvs were found in your path.\\n\\n\\n\")"
puts $op " )"
puts $op " )"
puts $op ""
puts $op " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op " ; Create the base level CDF for auCdl netlisting"
puts $op " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts $op " ; The subckt of the top module is netlisted. When running PVS LVS include"
puts $op " ; the top level Verilog netlist and associated IP cdl netlists."
puts $op " printf(\" Create Base level CDF for %s %s to support cdl netlisting.\\n\" library cellName)"
puts $op " cid=ddGetObj(library cellName)"
puts $op " unless(baseCDFid=cdfGetBaseCellCDF(cid)"
puts $op " baseCDFid=cdfCreateBaseCellCDF(cid)"
puts $op " baseCDFid->simInfo = list( nil )"
puts $op " baseCDFid->simInfo->auCdl = '(nil)"
puts $op " )"
puts $op " baseCDFid->simInfo->auCdl->netlistProcedure=\"ansCdlSubcktCall\""
puts $op " baseCDFid->simInfo->auCdl->namePrefix=\"X\""
puts $op " baseCDFid->simInfo->auCdl->componentName=\"subcircuit\""
puts $op " baseCDFid->simInfo->auCdl->termOrder=portorder"
puts $op " ;baseCDFid->simInfo->auCdl->modelName=\"counters\""
puts $op " cdfSaveCDF(baseCDFid)"
puts $op ""
puts $op " ) ; prog"
puts $op ""
puts $op ") ; procedure ggCreateSymbolAndCDF()"
close $op
set commands ""
set netlist $vars(dbs_dir)/$vars(design)_phys_nofill.v
# Create the netlist
#-----------------------------------------------------------------------------------------------
append commands "saveNetlist $netlist -excludeLeafCell -phys -excludeCellInst \[dbGet -u -e top.physInsts.cell.name\]\n"
# Create the .simrc file
#-----------------------------------------------------------------------------------------------
set op [open .simrc w]
puts $op "auCdlEnableNetlistInclusion=t"
puts $op "auCdlCDFPinCntrl=t"
close $op
# Create the Virtuoso replay file
#-----------------------------------------------------------------------------------------------
set op [open $vars(script_dir)/PostProcessInVirtuoso.il w]
puts $op "load(\"$vars(script_dir)/ggCreateSymbolAndCDF.il\")"
puts $op "ggCreateSymbolAndCDF(\"$vars(oa_design_lib)\" \"$vars(design)\" \"signoff\" \"$netlist\" t)"
puts $op "exit()"
close $op
# Call Virtuoso
#-----------------------------------------------------------------------------------------------
if ![string match [auto_execok virtuoso] ""] {
append commands "\nexec virtuoso -replay $vars(script_dir)/PostProcessInVirtuoso.il -nograph -log $vars(log_dir)/PostProcessInVirtuoso.log\n"
return $commands
} else {
set warnings($vars(warning_count)) "Unable to find Virtuoso executable! The remastered layout view, symbol, auCdl views and auCdl CDF will not be created"
incr vars(warning_count)
return $commands
}
}
}