blob: 88191df7b4be9117d7e672a4a7689690da3dd186 [file] [log] [blame]
# %CopyrightNotice
namespace eval ff_procs:: {
###############################################################################
# Procedure to seed certain flow variables to a known default value as well
# as data variables required to seed the generic configuration file
###############################################################################
proc load_path_groups {file} {
read_dc_script $file
}
proc source_plug {plugin {abort 1}} {
global vars
global plugin_error
global errorInfo
global return_code
if {[info exists vars($plugin)]} {
Puts "<FF> LOADING '$plugin' PLUG-IN FILE(s) "
foreach plugin $vars($plugin) {
if {[file exists $plugin]} {
Puts "<FF> -> $plugin"
if { [ catch { uplevel source $plugin } plugin_error ] } {
Puts "<FF> ============= PLUG-IN ERROR =================="
Puts "<FF> $errorInfo"
Puts "<FF> $plugin_error"
Puts "<FF> =============================================="
set return_code 99
if {[info exists vars(mail,to)]} {
set msg "From: [exec whoami] "
append msg \n "To: " [join $vars(mail,to) ,]
append msg \n "Cc: " [join "" ,]
append msg \n "Subject: " "FF: $vars(design), $vars(step) failed ([pwd])"
append msg \n\n $errorInfo
exec /usr/lib/sendmail -oi -t << $msg
}
if {$abort} {
exit $return_code
}
}
} else {
if {[file exists $vars(plug_dir)/$plugin]} {
Puts "<FF> -> $vars(plug_dir)/$plugin"
if { [ catch { uplevel source $vars(plug_dir)/$plugin } plugin_error ] } {
if {[info exists vars(mail,to)]} {
set msg "From: [exec whoami] "
append msg \n "To: " [join $vars(mail,to) ,]
append msg \n "Cc: " [join "" ,]
append msg \n "Subject: " "FF: $vars(design), $vars(step) failed ([pwd])"
append msg \n\n $errorInfo
exec /usr/lib/sendmail -oi -t << $msg
}
set return_code 99
if {$abort} {
exit $return_code
}
}
}
}
}
}
}
proc report_time {} {
global vars
set run_time [expr [clock seconds] - $vars($vars(step),start_time)]
if {$run_time > 86400} {
set days [expr $run_time / 86400]
} else {
set days 0
}
set run_time [clock format $run_time -format %H:%M:%S -gmt true]
Puts "<FF> =============================================="
Puts "<FF> COMPLETED STEP : $vars(step)"
Puts "<FF> ELAPSED RUNTIME : $days days, $run_time"
Puts "<FF> =============================================="
}
proc modify_power_domains {} {
global vars
####################################################################################
### modify power domain
####################################################################################
set vars(power_domains) [ff_procs::get_power_domains]
foreach domain $vars(power_domains) {
if {[info exists vars($domain,bbox)] || \
[info exists vars($domain,rs_exts)] || \
[info exists vars($domain,min_gaps)]} {
Puts "<FF> Modifying power domain $domain ..."
set command "modifyPowerDomainAttr $domain "
if {[info exists vars($domain,bbox)]} {
append command "-box $vars($domain,bbox) "
}
if {[info exists vars($domain,rs_exts)]} {
append command "-rsExts $vars($domain,rs_exts) "
}
if {[info exists vars($domain,min_gaps)]} {
append command "-minGaps $vars($domain,min_gaps) "
}
eval $command
}
}
}
proc add_power_switches {{domains ""}} {
global vars
global map
####################################################################################
### add power switch
####################################################################################
source $vars(script_root)/ETC/EDI/map_options.tcl
if {$domains == ""} {
set domains [ff_procs::get_power_domains]
}
foreach domain $domains {
if {[info exists vars($domain,switchable)] && $vars($domain,switchable)} {
deletePowerSwitch -$vars($domain,switch_type) -powerDomain $domain
set command "addPowerSwitch -powerDomain $domain -$vars($domain,switch_type) "
if {[info exists vars($domain,distribute)] && $vars($domain,distribute)} {
append command "-distribute "
}
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) "
}
}
eval $command
}
}
}
proc get_power_domains {} {
set power_domains [list]
dbForEachPowerDomain [dbgHead] pd {
if {[dbGroupHInstList [dbPowerDomainName $pd]] != "0x0"} {
lappend power_domains [dbPowerDomainName $pd]
}
}
return $power_domains
}
proc route_secondary_pg_nets {} {
Puts "<FF> ROUTING SECONDARY POWER NETS ..."
global vars
# Enable global pin pairs (if defined)
if {[info exists vars(secondary_pg,cell_pin_pairs)]} {
setPGPinUseSignalRoute $vars(secondary_pg,cell_pin_pairs)
# Build commands for individual nets (if defined)
if {[info exists vars(secondary_pg,nets)]} {
foreach net $vars(secondary_pg,nets) {
# Set options to globals if they exist
if {[info exists vars($net,pattern)]} {
set pattern $vars($net,pattern)
} elseif {[info exists vars(secondary_pg,pattern)]} {
set pattern $vars(secondary_pg,pattern)
}
if {[info exists vars($net,max_fanout)]} {
set max_fanout $vars($net,max_fanout)
} elseif {[info exists vars(secondary_pg,max_fanout)]} {
set max_fanout $vars(secondary_pg,max_fanout)
}
if {[info exists vars($net,non_default_rule)]} {
set non_default_rule $vars($net,non_default_rule)
} elseif {[info exists vars(secondary_pg,non_default_rule)]} {
set non_default_rule $vars(secondary_pg,non_default_rule)
}
if {[info exists vars($net,cell_pin_pairs)]} {
setPGPinUseSignalRoute $vars($net,cell_pin_pairs)
}
set vars($net,command) "routePGPinUseSignalRoute -nets $net"
if {[info exists pattern]} {
set vars($net,command) [format "%s -pattern %s" $vars($net,command) $pattern]
}
if {[info exists max_fanout]} {
set vars($net,command) [format "%s -maxFanout %s" $vars($net,command) $max_fanout]
}
if {[info exists non_default_rule]} {
set vars($net,command) [format "%s -nonDefaultRule %s" $vars($net,command) $non_default_rule]
}
}
foreach net $vars(secondary_pg,nets) {
eval $vars($net,command)
}
} else {
set command "routePGPinUseSignalRoute"
# Set options to globals if they exist
if {[info exists vars(secondary_pg,pattern)]} {
set command [format "%s -pattern $vars(secondary_pg,pattern)" $command]
}
if {[info exists vars(secondary_pg,max_fanout)]} {
set command [format "%s -maxFanout $vars(secondary_pg,max_fanout)" $command]
}
if {[info exists vars(secondary_pg,non_default_rule)]} {
set command [format "%s -nonDefaultRule $vars(secondary_pg,non_default_rule)" $command]
}
eval $command
}
} else {
Puts "<FF> ====================================================================="
Puts "<FF> ERROR: No cell/pin pairs defined ... please define cell/pin pairs"
Puts "<FF> in your setup.tcl using vars(secondary_pg,cell_pin_pairs)"
Puts "<FF> ====================================================================="
}
}
proc insert_welltaps_endcaps {} {
global vars
###############################################################################
# Insert welltaps and pre/post endcaps
###############################################################################
if {[info exists vars(cpf_file)] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 0))} {
set vars(power_domains) [::ff_procs::get_power_domains]
foreach domain $vars(power_domains) {
if {[info exists vars($domain,pre_endcap)] &&
[info exists vars($domain,post_endcap)]} {
addEndCap -prefix $domain \
-preCap $vars($domain,pre_endcap) \
-postCap $vars($domain,post_endcap) \
-powerDomain $domain
} elseif {[info exists vars(pre_endcap)] &&
[info exists vars(post_endcap)]} {
addEndCap -prefix $domain \
-preCap $vars(pre_endcap) \
-postCap $vars(post_endcap) \
-powerDomain $domain
}
if {[info exists vars($domain,welltaps)] || [info exists vars(welltaps)]} {
if {[info exists vars($domain,welltaps)]} {
set command "addWellTap -prefix $domain -cell $vars($domain,welltaps) -powerDomain $domain"
set vcommand "verifyWellTap -cells $vars($domain,welltaps) -powerDomain $domain -report $vars(rpt_dir)/welltap.rpt"
} elseif {[info exists vars(welltaps)]} {
set command "addWellTap -prefix $domain -cell $vars(welltaps) -powerDomain $domain"
set vcommand "verifyWellTap -cells $vars(welltaps) -powerDomain $domain -report $vars(rpt_dir)/welltap.rpt"
}
if {[info exists vars($domain,welltaps,max_gap)] || [info exists vars($domain,welltaps,cell_interval)]} {
if {[info exists vars($domain,welltaps,max_gap)]} {
append command " -maxGap $vars($domain,welltaps,max_gap)"
} else {
append command " -cellInterval $vars($domain,welltaps,cell_interval)"
}
} elseif {[info exists vars(welltaps,max_gap)] || [info exists vars(welltaps,cell_interval)]} {
if {[info exists vars(welltaps,max_gap)]} {
append command " -maxGap $vars(welltaps,max_gap)"
} else {
append command " -cellInterval $vars(welltaps,cell_interval)"
}
}
if {[info exists vars($domain,welltaps,row_offset)]} {
if {$vars($domain,welltaps,row_offset)} {
append command " -inRowOffset $vars($domain,welltaps,row_offset)"
}
} elseif {[info exists vars(welltaps,row_offset)]} {
if {$vars(welltaps,row_offset)} {
append command " -inRowOffset $vars(welltaps,row_offset)"
}
}
if {[info exists vars($domain,welltaps,checkerboard)]} {
if {$vars($domain,welltaps,checkerboard)} {
append command " -checkerboard"
}
} elseif {[info exists vars(welltaps,checkerboard)]} {
if {$vars(welltaps,checkerboard)} {
append command " -checkerboard"
}
}
eval $command
if {[info exists vars(welltaps,verify_rule)]} {
append vcommand " -rule $vars(welltaps,verify_rule)"
eval $vcommand
} else {
puts "<FF> Cannot run verifyWellTap because vars(welltaps,verify_rule) is not defined"
}
}
}
} else {
if {[info exists vars(pre_endcap)] &&
[info exists vars(post_endcap)]} {
addEndCap -prefix ENDCAP \
-preCap $vars(pre_endcap) \
-postCap $vars(post_endcap)
}
if {[info exists vars(welltaps)]} {
set command "addWellTap -prefix WELLTAP -cell $vars(welltaps) "
set vcommand "verifyWellTap -cells $vars(welltaps) -report $vars(rpt_dir)/welltap.rpt"
if {[info exists vars(welltaps,max_gap)] || [info exists vars(welltaps,cell_interval)]} {
if {[info exists vars(welltaps,max_gap)]} {
append command " -maxGap $vars(welltaps,max_gap)"
} else {
append command " -cellInterval $vars(welltaps,cell_interval)"
}
}
if {[info exists vars(welltaps,row_offset)]} {
append command " -inRowOffset $vars(welltaps,row_offset)"
}
if {[info exists vars(welltaps,checkerboard)]} {
if {$vars(welltaps,checkerboard)} {
append command " -checkerboard"
}
}
eval $command
if {[info exists vars(welltaps,verify_rule)]} {
append vcommand " -rule $vars(welltaps,verify_rule)"
eval $vcommand
} else {
puts "<FF> CANNOT RUN verifyWellTap BECAUSE vars(welltaps,verify_rule) IS NOT DEFINED"
}
}
}
}
proc buffer_always_on_nets {} {
global vars
global errors
global bts_nets
if {![info exists vars(power_domains)]} {
set vars(power_domains) [::ff_procs::get_power_domains]
}
set pd_buffer_list [list]
foreach domain $vars(power_domains) {
if {[info exists vars($domain,always_on_buffers)]} {
set val [concat $domain $vars($domain,always_on_buffers)]
lappend pd_buffer_list $val
} else {
if {[info exists vars(always_on_buffers)]} {
set val [concat $domain $vars(always_on_buffers)]
lappend pd_buffer_list $val
}
}
}
if {$pd_buffer_list == ""} {
Puts "<FF> ERROR: No always-on buffers defined"
return
}
if {[info exists vars(always_on_nets)]} {
set bts_nets [list]
foreach net $vars(always_on_nets) {
set temp [join [dbFindNetsByName $net]]
lappend bts_nets $temp
}
# set temp [list]
# if {[info exists vars(always_on_nets,max_fanout)]} {
# set max_fanout $vars(always_on_nets,max_fanout)
# foreach net [join $bts_nets] {
# if {[expr [llength [dbFindInstsOnNet $net]] - 1] > $max_fanout} {
# lappend temp $net
# }
# }
# set bts_nets [join $temp]
# }
#
set bts_nets [join $bts_nets]
Puts "<FF> ========================================================="
Puts "<FF> Buffering always-on nets"
Puts "<FF> ========================================================="
Puts "<FF> Nets ..."
foreach net $bts_nets {
Puts "<FF> $net"
}
set command "bufferTreeSynthesis -prefix BTS"
append command " -nets \[list $bts_nets\]"
append command " -powerDomainBufList \[list $pd_buffer_list\]"
if {![catch {set arg $vars(always_on_nets,max_tran)}]} {
append command " -maxTran $arg"
Puts "<FF> Max Tran -> $arg"
}
if {![catch {set arg $vars(always_on_nets,max_fanout)}]} {
append command " -maxFanout $arg"
Puts "<FF> Max Fanout -> $arg"
}
if {![catch {set arg $vars(always_on_nets,max_skew)}]} {
append command " -maxSkew $arg"
Puts "<FF> Max Skew -> $arg"
}
if {![catch {set arg $vars(always_on_nets,max_delay)}]} {
append command " -maxDelay $arg"
Puts "<FF> Max Delay -> $arg"
}
Puts "<FF> ========================================================="
eval $command
} else {
Puts "<FF> No always on nets specified"
Puts "<FF> Please set vars(always_on_nets) in your setup.tcl"
}
}
proc get_icg_pins {} {
global vars
Puts "<FF> INFO: Executing get_icg_pins"
foreach_in_collection pin [get_lib_pins $vars(icg,base_name)*/*] {
if {[get_property $pin direction]=="in"&&[get_property $pin is_clock_gating_enable]=="true"} {
set name [file tail [get_property $pin name]]
if {[info exists enable]==1&&$name!=$enable} {
Puts "<FF> ERROR: While searching all icgs, enable pin for [get_property $pin name] does not match existing $enable"
#exit 99
} else {
set enable $name
}
} elseif {([get_property $pin direction] == "out")} {
set name [file tail [get_property $pin name]]
if {[info exists clkout]==1&&$name!=$clkout} {
Puts "<FF> ERROR: While searching all icgs, clkout pin for [get_property $pin name] does not match existing $clkout"
#exit 99
} else {
set clkout $name
}
} elseif {([get_property $pin direction] == "in") && ([get_property $pin is_clock] == "true")} {
set name [file tail [get_property $pin name]]
if {[info exists clkin]==1&&$name!=$clkin} {
Puts "<FF> ERROR: While searching all icgs, clkin pin for [get_property $pin name] does not match existing $clkin"
#exit 99
} else {
set clkin $name
}
}
}
if {[info exists clkout]==0} {
Puts "<FF> ERROR: output pin of icg $vars(icg,base_name) was not found, exiting"
#exit 99
}
if {[info exists clkin]==0} {
Puts "<FF> ERROR: clk pin of icg $vars(icg,base_name) was not found, exiting"
#exit 99
}
if {[info exists enable]==0} {
Puts "<FF> ERROR: enable pin of icg $vars(icg,base_name) was not found, exiting"
#exit 99
}
set vars(icg,output_pin) $clkout
set vars(icg,input_pin) $enable
set vars(icg,clock_pin) $clkin
Puts "<FF> INFO: Finished executing get_icg_pins"
}
proc get_buf_pins {} {
global vars
Puts "<FF> INFO: Executing get_buf_pins"
foreach_in_collection pin [get_lib_pins $vars(anchor_buffer)/*] {
if {[get_property $pin direction]=="in"} {
set in [file tail [get_property $pin name]]
} elseif {[get_property $pin direction] == "out"} {
set out [file tail [get_property $pin name]]
}
}
if {[info exists out]==0} {
Puts "<FF> ERROR: output pin of anchor buffer $vars(anchor_buffer) was not found, exiting"
#exit 99
}
if {[info exists in]==0} {
Puts "<FF> ERROR: input pin of anchor buffer $vars(anchor_buffer) was not found, exiting"
#exit 99
}
set vars(anchor_buffer,output_pin) $out
set vars(anchor_buffer,input_pin) $in
set vars(buf,output_pin) $out
set vars(buf,input_pin) $in
Puts "<FF> INFO: Finished executing get_buf_pins"
}
proc get_reg_pins {} {
global vars
Puts "<FF> INFO: Executing get_reg_pins"
set got_pin false
foreach_in_collection reg [all_registers] {
if {$got_pin} {
return
}
foreach_in_collection pin [get_pins [get_property $reg hierarchical_name]/*] {
if [get_property $pin is_clock] {
set vars(reg,clock_pin) [file tail [get_property $pin hierarchical_name]]
set got_pin true
}
}
}
Puts "<FF> INFO: Finished executing get_reg_pins"
}
proc get_tech_pin_info {} {
global vars
get_icg_pins
get_buf_pins
get_reg_pins
set op [open .ff.pins.tcl w]
foreach type {icg buf reg} {
foreach pin {clock enable input output} {
if {[info exists vars($type,${pin}_pin)]} {
puts $op "set vars($type,${pin}_pin) $vars($type,${pin}_pin)"
Puts "<FF> INFO: Found $type $pin -> $vars($type,${pin}_pin)"
}
}
}
close $op
}
proc get_all_usable_bufinvs {} {
# Puts "INFO: Executing get_all_usable_bufinvs"
set buf_list ""
set inv_list ""
set cell_types [dbGet head.allCells.name *]
foreach cell $cell_types {
set cell_id [ dbGetCellByName $cell]
if { [dbIsCellDontUse $cell_id] } { continue }
if { [dbIsCellDontTouch $cell_id] } { continue }
if { [dbIsCellSequential $cell_id] } { continue }
if { [::CPF::isAlwaysOnCell $cell] } { continue }
if { [ dbIsCellBuffer $cell_id] } {
lappend buf_list $cell
} elseif { [ dbIsCellInverter $cell_id ] } {
lappend inv_list $cell
}
}
# Puts "INFO: Found [llength $buf_list] buffers and [llength $inv_list] inverters"
# Puts "INFO: Finished executing get_all_usable_bufinvs"
return [list $buf_list $inv_list]
}
proc assign_cts_cells {} {
# Puts "INFO: Executing assign_cts_cells"
global vars
if {![info exists vars(cts_cells)]} {
set rc [::ff_procs::get_all_usable_bufinvs]
set vars(cts_cells) [concat $rc]
} else {
set got_one 0
foreach cell $vars(cts_cells) {
if {[dbGetCellByName $cell]!="0x0"} {
set got_one 1
}
}
if {$got_one==0} {
Puts "<FF> WARNING: there is no valid cell in vars(cts_cells), will auto set to all usable buffers/inverters"
set rc [::ff_procs::get_all_usable_bufinvs]
set vars(cts_cells) [concat $rc]
}
}
set vars(cts_inverter_cells) [list]
set vars(cts_buffer_cells) [list]
foreach cell {$vars(cts_cells)} {
if { [dbIsCellBuffer $cell_id] } {
lappend vars(cts_buffer_cells) $cell
} elseif { [dbIsCellInverter $cell_id] } {
lappend vars(cts_inverter_cells) $cell
}
}
# Puts "INFO: Finished executing assign_cts_cells"
}
proc enable_mmmc {} {
Puts "<FF> INFO: Executing enable_mmmc"
global vars
# confirm default view defined
if {[info exists vars(default_setup_view)]==0} {
Puts "ERROR: default view vars(default_setup_view) not defined, exiting"
#exit 99
}
set view $vars(default_setup_view)
if {[info exists vars($view,delay_corner)]==0} {
Puts "<FF> ERROR: default delay_corner vars($view,delay_corner) not defined, exiting"
#exit 99
}
set dc $vars($view,delay_corner)
if {[info exists vars($dc,library_set)]==0} {
Puts "<FF> ERROR: default library_set vars($dc,library_set) not defined, exiting"
#exit 99
}
set libset $vars($dc,library_set)
if {[info exists vars($dc,rc_corner)]==0} {
Puts "<FF> ERROR: default rc_corner vars($dc,rc_corner) not defined, exiting"
#exit 99
}
set rc $vars($dc,rc_corner)
if {[info exists vars($view,constraint_mode)]==0} {
Puts "<FF> ERROR: default constraint_mode vars($view,constraint_mode) not defined, exiting"
#exit 99
}
set mode $vars($view,constraint_mode)
if {[info exists vars($mode,pre_cts_sdc)]==0} {
Puts "<FF> ERROR: pre_cts_sdc for constraint_mode $mode in vars($mode,pre_cts_sdc), exiting"
#exit 99
}
if {[info exists vars($libset,timing)]==0} {
Puts "<FF> ERROR: library_set $libset libraries not defined in vars($libset,timing), exiting"
#exit 99
}
create_library_set -name $libset -timing $vars($libset,timing)
if {[info exists vars($rc,cap_table)]==0} {
Puts "<FF> ERROR: cap_table for rc_corner $rc not defined, exiting"
#exit 99
}
if {[info exists vars($rc,pre_route_res_factor)]==0} {
Puts "<FF> WARNING: pre_route_res_factor for rc_corner $rc not defined, setting to 1.0"
set vars($rc,pre_route_res_factor) 1.0
}
if {[info exists vars($rc,pre_route_cap_factor)]==0} {
Puts "<FF> WARNING: pre_route_cap_factor for rc_corner $rc not defined, setting to 1.0"
set vars($rc,pre_route_cap_factor) 1.0
}
if {[info exists vars($rc,T)]==0} {
Puts "<FF> WARNING: temperature for rc_corner $rc not defined, setting to 25"
set vars($rc,pre_route_cap_factor) 25
}
create_rc_corner -name $rc \
-cap_table $vars($rc,cap_table) \
-preRoute_res $vars($rc,pre_route_res_factor) \
-preRoute_cap $vars($rc,pre_route_cap_factor) \
-T $vars($rc,T)
create_delay_corner -name $dc -library_set $libset -rc_corner $rc
if {[file isfile [lindex vars($mode,pre_cts_sdc) 0]]} {
if {[lsearch [all_constraint_modes] $mode] == -1} {
create_constraint_mode -name $mode -sdc_files $vars($mode,pre_cts_sdc)
} else {
update_constraint_mode -name $mode -sdc_files $vars($mode,pre_cts_sdc)
}
}
create_analysis_view -name $view -constraint_mode $mode -delay_corner $dc
set_analysis_view -setup [list $view] -hold [list $view]
foreach object "cell net" {
foreach mode "early late" {
foreach type "data clock" {
if {[info exists vars($dc,${type}_${object}_${mode})]} {
set generated 1
set_timing_derate -delay_corner $dc -$type -${object}_delay -$mode $vars($dc,${type}_${object}_${mode})
}
if {[info exists vars($dc,${object}_${type}_${mode})]} {
set_timing_derate -delay_corner $dc -$type -${object}_delay -$mode $vars($dc,${object}_${type}_${mode})
}
}
if {[info exists vars($dc,cell_check_${mode})]} {
set_timing_derate -delay_corner $dc -cell_check -$mode $vars($dc,cell_check_${mode})
}
if {[info exists vars($dc,check_cell_${mode})]} {
set_timing_derate -delay_corner $dc -cell_check -$mode $vars($dc,check_cell_${mode})
}
}
}
if {[info exists vars(derate_tcl)]&&[file isfile $vars(derate_tcl)]} {
source $vars(derate_tcl)
}
if {[info exists vars($dc,derate_tcl)]&&[file isfile $vars($dc,derate_tcl)]} {
source $vars($dc,derate_tcl)
}
Puts "<FF> INFO: Finished executing enable_mmmc"
}
proc build_guides {} {
Puts "<FF> INFO: Creating floorplan guides ..."
global vars
unlogCommand addInstToInstGroup
unlogCommand createInstGroup
unlogCommand deleteInstGroup
unlogCommand setObjFPlanBoxList
suppressMessage ENCSYC-1962
suppressMessage ENCSYC-791
if {[info exists vars(guides)]==1&&[llength $vars(guides)]>0} {
foreach guide $vars(guides) {
# Check to make sure guide has a bound and some includes
if {[info exists vars(guide,$guide,bounds)]==0||[llength $vars(guide,$guide,bounds)]<4} {
Puts "<FF> WARNING: Guide $guide does not have a properly specified bound, guide not created"
} elseif {[info exists vars(guide,$guide,include)]==0||[llength $vars(guide,$guide,include)]<1} {
Puts "<FF> WARNING: Guide $guide does not have any includes, guide not created"
} else {
catch {deleteInstGroup $guide}
catch {unset insts}
if {[info exists vars(guide,$guide,exclude)]==0} {
set vars(guide,$guide,exclude) ""
} else {
regsub -all "\\\*" $vars(guide,$guide,exclude) "\.\*" excludes
}
foreach include $vars(guide,$guide,include) {
foreach i [dbFindInstsByName ${include}*] {
if {[info exists vars(guide,$guide,exclude)]==1&&[llength $vars(guide,$guide,exclude)]>0&&[regexp [join $excludes |] $i]<1} {
set insts($i) 1
} elseif {[llength $vars(guide,$guide,exclude)]<1} {
set insts($i) 1
}
}
}
if {[info exists insts]==1&&[llength [array names insts]]>0} {
set x1 [lindex $vars(guide,$guide,bounds) 0]
set y1 [lindex $vars(guide,$guide,bounds) 1]
set x2 [lindex $vars(guide,$guide,bounds) 2]
set y2 [lindex $vars(guide,$guide,bounds) 3]
createInstGroup $guide -guide $x1 $y1 $x2 $y2
set c 0
foreach i [array names insts] {
addInstToInstGroup $guide $i
incr c
}
set cmd "setObjFPlanBoxList Group $guide"
foreach i $vars(guide,$guide,bounds) {
set cmd "${cmd} $i"
}
catch {eval $cmd}
Puts "<FF> INFO: Added $c instances to guide $guide"
} else {
Puts "<FF> WARNING: Specified guide $guide has no instances, not creating"
}
}
}
} else {
Puts "<FF> INFO: No guides specified ... exiting"
}
logCommand addInstToInstGroup
logCommand createInstGroup
logCommand deleteInstGroup
logCommand setObjFPlanBoxList
Puts "<FF> INFO: Finished executing build_guides"
}
proc add_blockages {} {
Puts "<FF>INFO: Creating blockages ..."
global vars
if {![info exists vars(blockages)]} {
puts "<FF>INFO: No blockages info defined ... existing"
return
}
set commands ""
foreach blockage $vars(blockages) {
switch $vars(blockage,$blockage,type) {
hard {
append commands "createObstruct $vars(blockage,$blockage,bounds) -name $blockage\n"
}
soft {
append commands "createObstruct $vars(blockage,$blockage,bounds) -name $blockage -type soft\n"
}
partial {
append commands "createObstruct $vars(blockage,$blockage,bounds) -name $blockage -type soft\n"
}
}
}
eval $commands
Puts "<FF>INFO: Finished executing add_blockages ..."
}
proc save_results {{step ""}} {
global vars
global errors
global env
if {$step != ""} {
set vars(step) $step
} else {
Puts "<FF> Argument 'step' required ..."
return
}
set commands ""
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"
}
append commands $command
if {![info exists env(VPATH)]} {
set env(VPATH) "make"
}
if {$vars(makefile)} {
append commands "exec /bin/touch $env(VPATH)/$step\n"
}
set header "#---------------------------------------------------------------------\n"
append header "# <FF> GENERATING REPORTS\n"
append header "#---------------------------------------------------------------------\n"
if {$vars(report_power)} {
set command "report_power -outfile $vars(rpt_dir)/$vars(step).power.rpt\n"
append commands $command
}
if {[info exists vars(cpf_file)] && ([info exists vars(power_domains)] && ([llength $vars(power_domains)] > 0))} {
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 $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 $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
}
}
}
# append commands "#\n"
# append commands "# HOUSEKEEPING\n"
# append commands "#\n"
if {[info exists vars(mail,to)]} {
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)/$vars(step).summary\]} {\n"
append commands " exec /bin/mail -s \"FF: $vars(design), $vars(step) completed (\[pwd\])\" < $vars(rpt_dir)/$vars(step).summary $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"
append commands [::FF::source_plug final_always_source_tcl]
if {$vars(makefile)} {
append commands "if {\[info exists env(VPATH)\]} {\n"
append commands "exec /bin/touch \$env(VPATH)/$vars(step)\n"
append commands "}\n"
}
uplevel #0 eval $commands
}
proc load_applet {args} {
set defAppletNS "::applet"
set defSeverity "error"
set defaultLocalInstall $::ns(applet)::localInstall
set defaultLocalServer $::ns(applet)::localServer
set reqAppletVersion ""
switch -- [parse_options [calling_proc] {} $args \
"-version sos required version of applet (equal or greater)" reqAppletVersion \
"-severity sos severity (error|warning|info)" severity \
"-namespace sos namespace to search for applet" appletNS \
"srs name of applet" appletName] {
-2 { return }
0 { return -code error }
}
if {$appletNS eq ""} {
set appletNS $defAppletNS
}
if {$severity eq ""} {
set severity $defSeverity
}
# Check to see if the applet happened to already be loaded. If so, check
# whether there is a minimum version requirement met. If yes, skip the rest of the applet
# If the applet already does not meet the minimum version requirement, unload it (using package forget)
if {![catch {set providedVersion [package present ${appletNS}::$appletName]} errorMessage]} {
if {$reqAppletVersion ne ""} {
if {[package vcompare $providedVersion $reqAppletVersion] == -1} {
puts "load_applet INFO: applet $appletName was already loaded, but it's version ($providedVersion) did not meet the minimum required version ($reqAppletVersion)"
puts "load_applet INFO: This version of the $appletName applet will be removed and the load_applet will search for a newer version of $appletName..."
package forget ${appletNS}::$appletName
} else {
puts "load_applet INFO: Found $appletName already loaded and it's version ($providedVersion) already meets the minimum required version ($reqAppletVersion). Skipping load..."
return
}
} else {
puts "load_applet INFO: Found $appletName already loaded with version ($providedVersion). Skipping applet load..."
return
}
}
# There is no previously loaded applet. Continue with this proc...
set FoundMinVersionPath 0
set finalSearchPath ""
set failedPaths ""
# Because Innovus has it's own get_attribute command now, we need to set this depending on what tool we are in
if {[get_tool] eq "rc"} {
set searchPathList [get_attribute applet_search_path /]
} else {
set searchPathList [$::ns(compat)::get_attribute applet_search_path /]
}
set appletSearchPathCount [llength $searchPathList]
set origappletSearchPathCount $appletSearchPathCount
set origSearchPath ""
# First pass: determine which applet installations meet min required version, if any
# This for loop does not load the applets, it only determines a final search path to use
# If none of the search paths contain the minimum version, and severity code is error, this proc
# will return inside this foreach loop with code error
if {$appletSearchPathCount > 1} {
puts "load_applet INFO: Checking all applet search paths for versions of $appletName"
}
foreach pathComponent $searchPathList {
incr appletSearchPathCount -1
if {$origappletSearchPathCount > 1} {
puts -nonewline " $pathComponent ..."
} else {
puts -nonewline "load_applet INFO: Checking applet_search_path: $pathComponent ..."
}
# If the path component is <default> replace with the applet designated search path value using "UpdateSeachPath"
if {[string match "<default>" $pathComponent]} {
set pathComponent [$::ns(applet)::UpdateSearchPath $pathComponent]
}
lappend origSearchPath $pathComponent
if {[file isdirectory $pathComponent]} {
if {[file isfile $pathComponent/.servInfo]} {
if {[get_tool] eq "rc"} {
set sourceCommand tcl_source
} else {
set sourceCommand source
}
set errorMsg ""
if {[catch {$sourceCommand $pathComponent/.servInfo} errorMsg] || ![info exists appInfo(${appletNS}::${appletName},version)]} {
if {$errorMsg ne ""} {
puts " $errorMsg"
} else {
puts " BAD APPLET SERVER (corrupted .servInfo file)"
}
} else {
if {$reqAppletVersion eq "" } {
lappend minVersionSearchPath $pathComponent
set FoundMinVersionPath 1
} elseif {[package vcompare $appInfo(${appletNS}::${appletName},version) $reqAppletVersion] != -1} {
lappend minVersionSearchPath $pathComponent
set FoundMinVersionPath 1
} else {
lappend failedPaths $pathComponent
set failedPathver($pathComponent) $appInfo(${appletNS}::${appletName},version)
}
puts " Found $appInfo(${appletNS}::${appletName},version)"
}
} else {
puts " BAD APPLET INSTALL"
}
} else {
puts " NONEXISTENT APPLET SERVER"
}
};# end first foreach loop (distilling final minimum version applet_search_path
# Second pass: attempt to load applet in each valid search_path until a successful applet load occurs
# This for loop must lead to a successful outcome (loaded applet) or an error will be issued
if {$FoundMinVersionPath} {
foreach searchPath $minVersionSearchPath {
set_attribute -quiet applet_search_path $searchPath /
if {[catch {applet load $appletName} errorMsg]} {
puts "load_applet INFO: Version check passed on applet install $appletName but applet load failed."
if {$appletSearchPathCount > 0} {
puts "load_applet: Trying next applet_search_path..."
} else {
puts "load_applet: ERROR: Failed to load applet $appletName. Please check your applet_search_path and applet installation(s)."
set_attribute -quiet applet_search_path $origSearchPath /
return -code error
}
} else {
if {[catch {set providedVersion [package present ${appletNS}::$appletName]} errorMessage]} {
puts "load_applet: ERROR: applet $appletName loaded correctly, but the applet did not correctly provide a package version. Trying next search path..."
} else {
puts "load_applet: INFO: Applet $appletName $providedVersion successfully loaded from applet installation at $pathComponent, meeting min version requirement ($reqAppletVersion)"
set_attribute -quiet applet_search_path $origSearchPath /
return
}
}
}
} else {
# Didn't find any searchy paths with minimum applet installed.
switch -exact -- $severity {
error {
puts "load_applet ERROR: Minimum applet version for applet $appletName is $reqAppletVersion, but no applet was found meeting this requirement."
}
warning {
puts "load_applet WARNING: Minimum applet version for applet $appletName is $reqAppletVersion, but no applet was found meeting this requirement."
}
info {
puts "load_applet INFO: Minimum applet version for applet $appletName is $reqAppletVersion, but no applet was found meeting this requirement."
}
}
puts "load_applet INFO: Search results:"
foreach searchPath $failedPaths {
puts " applet_search_path: $searchPath, $appletName version found: $failedPathver($searchPath)"
}
puts "load_applet INFO: Note applet search path that was set:"
puts " $origSearchPath"
switch -exact -- $severity {
error {
set_attribute -quiet applet_search_path $origSearchPath /
return -code 99
}
}
}
set_attribute -quiet applet_search_path $origSearchPath /
}
}