blob: e1152601eb1ef5ff05733a42f8e9649228ded850 [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 FFMM:: {
set validModes [list "flat" "hier" "top_down" "bottom_up" "user"]
set missingFiles "<FF> ERROR: Could not find Foundation Flow script files in directory \"%s\""
set missingSetupFile "<FF> ERROR: Could not find setup.tcl in directory \"%s\""
set missingRC "<FF> ERROR: Could not find 'rc' executable"
set noMode "<FF> ERROR: \"-m\" option specified without a runtime mode"
set noFlat "<FF> ERROR: \"-f\" option specified without a valid option"
set noVersion "<FF> ERROR: \"-v\" option specified without a valid option"
set noPath "<FF> ERROR: \"-d\" option specified without a directory path"
set noStyle "<FF> ERROR: \"-y\" option specified without a style option \[date|increment\]"
set noRundir "<FF> ERROR: \"-u\" option specified without a directory path"
set noSetupPath "<FF> ERROR: \"-s\" option specified without a directory path"
set noAppletPath "<FF> ERROR: \"-a\" option specified without a directory path"
set nosynth_flow "<FF> WARNING: \"-r\" option specified without a synthesis flow"
set noSuchPath "<FF> ERROR: Directory path \"%s\" not found."
set unknownMode "<FF> ERROR: Unknown runtime mode specified \"%s\" "
set unknownOption "<FF> ERROR: Unrecognized option \"%s\" "
set usage "
Usage: tclsh <path_to>/SCRIPTS/gen_flow.tcl <options> step ?step? ... ?step?
The \"step\" is the portion of the flow that you want to execute. To find
the valid list of steps for a given mode, simply omit the step from the
command-line invocation. You can also specify step as either of the two
forms:
a-b : Execute all steps between step a and b, inclusive
a- : Execute all steps in the flow from step a, inclusive
Obviously, \"a\" and \"b\" should be valid steps for the specific mode.
Options may be one or more of the following:
-h | --help : Print this message
-H | --Help : Print step help
-m | --mode : Set the script mode. The default is \"flat\".
Valid modes are: $validModes
-d | --dir : Output directory for generated scripts.
-f | --flat : Level of unrolling ... full, partial, none
-n | --nomake : Skip Makefile generation
-y | --style : Rundir naming style \[date|increment\]
-r | --rtl : Enable RTL Script Generation
-N | --Novus : Enable novus_ui flowkit generation
-s | --setup : Provide the directory containing the setup.tcl setup file
-u | --rundir : Directory to execute the flow
requried to run the Foundation Flow.
-v | --version : Target version (17.1.0, 16.2.0, 16.1.0, 15.2.0, 15.1.0, ...)
-V | --Verbose : Verbose mode
Examples:
---------
tclsh SCRIPTS/gen_innovus_flow.tcl all
tclsh SCRIPTS/gen_innovus_flow.tcl -m top_down all
tclsh SCRIPTS/gen_innovus_flow.tcl -d prects_scripts init-prects
tclsh SCRIPTS/gen_innovus_flow.tcl -u work/run -y date -r default_synthesis_flow_3step all
"
}
namespace eval FF:: {
variable valid_versions {
17.1.0
16.2.0 16.1.0
15.2.0 15.1.0
14.2.0 14.1.0
13.2.0 13.1.0
12.1.0
11.1.3 11.1.2 11.1.1 11.1.0
10.1.3 10.1.2 10.1.1 10.1.0
9.1.3 9.1.2
}
proc wrap_command {tag command} {
global vars
global env
global errors
# if {$vars(debug)} {
# puts "<FF> Wrapping command: $command in step $vars(step) ..."
# }
if {![info exists vars(tags,verbose)]} {
set verbose FALSE
} else {
set verbose $vars(tags,verbose)
}
if {![info exists vars(tags,verbosity_level)]} {
set verbosity_level LOW
} else {
switch [string toupper $vars(tags,verbosity_level)] {
"LOW" {
set verbosity_level LOW
}
"HIGH" {
set verbosity_level HIGH
}
default {
set verbosity_level LOW
}
}
}
if {[info exists vars($tag,pre_tcl)] || \
[info exists vars($tag,post_tcl)] || \
[info exists vars($tag,skip)] || \
[info exists vars($tag,replace_tcl)]} {
if {![info exists vars(tagged)]} {
set vars(tagged) [list]
}
}
if {$verbosity_level == "HIGH"} {
set commands "# <BEGIN TAG> $tag\n"
} else {
set commands ""
}
# set commands ""
if {[info exists vars($tag,skip)] && $vars($tag,skip)} {
lappend vars(tagged) $tag,skip
regsub -all "\\\n" "\n\n$command\n" "\n# " skip
# append skip "\n"
if {$verbose} {
append commands "\n# <begin tag $tag,skip>"
}
append commands $skip
if {$verbose} {
append commands "<end tag $tag,skip>\n\n"
}
append commands "\n"
if {$verbose} {
return $commands
} else {
return
}
}
if {[info exists vars($tag,pre_tcl)]} {
if {[file exists $vars($tag,pre_tcl)]} {
lappend vars(tagged) $tag,pre_tcl
if {$vars(flat) == "full"} {
set ip [open $vars($tag,pre_tcl) r]
if {$verbose} {
append commands "\n# <begin tag $tag,pre_tcl>\n"
}
while {[gets $ip line]>=0} {
append commands "$line\n"
}
close $ip
if {$verbose} {
append commands "# <end tag $tag,pre_tcl>\n\n"
}
} else {
append commands "source $vars($tag,pre_tcl)\n"
}
} else {
puts "<FF> ERROR: $tag pre_tcl file ($vars($tag,pre_tcl)) not found"
set errors($vars(error_count)) "$tag pre_tcl file ($vars($tag,pre_tcl)) not found"
incr vars(error_count)
if {$verbose} {
append commands "# <end tag $tag,pre_tcl>\n\n"
}
}
}
if {[info exists vars($tag,replace_tcl)]} {
if {[file exists $vars($tag,replace_tcl)]} {
lappend vars(tagged) $tag,replace_tcl
set ip [open $vars($tag,replace_tcl) r]
if {$verbose} {
append commands "\n# <begin tag $tag,replace_tcl>\n"
}
while {[gets $ip line]>=0} {
append commands "$line\n"
}
close $ip
} else {
puts "<FF> ERROR: $tag replace_tcl file ($vars($tag,replace_tcl)) not found"
set errors($vars(error_count)) "$tag replace_tcl file ($vars($tag,replace_tcl)) not found"
incr vars(error_count)
}
if {$verbose} {
append commands "# <end tag $tag,replace_tcl>\n\n"
}
} else {
# Insert original command here
append commands $command
}
if {[info exists vars($tag,post_tcl)]} {
if {[file exists $vars($tag,post_tcl)]} {
lappend vars(tagged) $tag,post_tcl
if {$verbose} {
append commands "\n# <begin tag $tag,post_tcl>\n"
}
if {$vars(flat) == "full"} {
set ip [open $vars($tag,post_tcl) r]
while {[gets $ip line]>=0} {
append commands "$line\n"
}
close $ip
# if {$verbose} {
# append commands "#<<<\n"
# }
} else {
append commands "source $vars($tag,post_tcl)\n"
}
} else {
puts "<FF> ERROR: $tag post_tcl file ($vars($tag,post_tcl)) not found"
set errors($vars(error_count)) "$tag post_tcl file ($vars($tag,post_tcl)) not found"
incr vars(error_count)
}
if {$verbose} {
append commands "# <end tag $tag,post_tcl>\n\n"
}
}
if {$verbosity_level == "HIGH"} {
append commands "\n# <END TAG> $tag\n"
}
return $commands
}
proc get_line_match {pattern file} {
set ip [open $file r]
while {[gets $ip line]>=0} {
if {[regexp "$pattern" $line]>0} {
set match $line
}
}
return $match
}
proc singular {val {false "s"} {true ""}} {
if {$val==1} { return $true } else { return $false }
}
proc size {val {suffix "byte"}} {
set level 0
set prefixes [list "" kilo mega giga tera peta]
while {$val>1024} {
set val [expr $val/1024.0]
incr level
}
set val [expr int($val+0.5)]
return "$val [lindex $prefixes $level]$suffix[singular $val]"
}
proc system_info {} {
global vars
set uname [exec uname]
if {[lsearch "Linux" $uname] != -1} {
set inFile "$vars(script_root)/ETC/status.dat"
if {![file exists $inFile]} {
return
}
set upId [open "/proc/uptime" r]
set info(uptime) [lindex [split [gets $upId] .] 0]
close $upId
foreach {var val} {mon 2592000 wks 604800 day 86400 hrs 3600 min 60 sec 1} {
set info(uptime.${var}) [expr $info(uptime)/${val}]
set info(uptime) [expr $info(uptime)-($info(uptime.${var})*${val})]
}
set info(host.fqdn) [info hostname]
set info(host.name) [lindex [split $info(host.fqdn) .] 0]
set info(host.domain) [string range $info(host.fqdn) [expr [string length $info(host.name)]+1] end]
set info(host.os) $::tcl_platform(os)
set info(host.osver) $::tcl_platform(osVersion)
set info(host.machine) $::tcl_platform(machine)
if {$info(host.os)=="Linux"} {
if {[file exists /etc/slackware-version]} { set info(host.distribution) "Slackware" }
if {[file exists /etc/redhat-release]} { set info(host.distribution) "RedHat" }
if {[file exists /etc/mandrake-release]} { set info(host.distribution) "Mandrake" }
if {![info exists info(host.distribution)]} { set info(host.distribution) "Unknown" }
} else {
return
}
set cpuId [open "/proc/cpuinfo" r]
set info(cpu.total) 0
set info(cpu.cpucores) 1
while {![eof $cpuId]} {
gets $cpuId ln
set ln [split $ln :]
set item [string trim [lindex $ln 0]]
set value [string trim [lindex $ln 1]]
set info(cpu.[lindex $item 0][lindex $item 1]) $value
if {[lindex $item 0] == "processor"} {incr info(cpu.total)}
}
close $cpuId
set memId [open "/proc/meminfo" r]
set info(mem.free) 0
while {![eof $memId]} {
gets $memId ln
set ln [split $ln :]
set item [string trim [lindex $ln 0]]
catch { set value [expr [string trim [lindex [lindex $ln 1] 0]]*1024] }
switch -- "$item" {
MemTotal { set info(mem.total) $value }
SwapTotal { set info(mem.swap.total) $value }
SwapFree { set info(mem.swap.free) $value }
MemFree { incr info(mem.free) $value }
Cached { incr info(mem.free) $value }
Buffers { incr info(mem.free) $value }
}
}
set parseId [open $inFile r]
while 1 {
gets $parseId ln
if {[eof $parseId]} { break }
catch { puts [subst $ln] } err
}
close $parseId
}
}
############################################################################
# This routine iterates over variables that maintain lists of files. If
# any element of the list is a wildcard, that entry is replaced with the
# Tcl command that will expand the name at runtime
############################################################################
proc process_file_lists {} {
global vars
if {![info exists vars(globbed)]} {
set vars(globbed) false
}
if {$vars(globbed)} {
return
}
set vars(globbed) true
if {[regexp "^11" $vars(version)]} {
return
}
# BCL: Removed def_files from this list
set var_indices [list "cts_spec" "lef_files" \
"timing" "si" "ecsm" "cts_sdc"]
# BCL: Add def_files to list only if it doesn't have [subst] in the name (other wise we need to keep [subst... unexpanded)
if {[info exists vars(def_files)] && ![regexp {\[subst \$vars} $vars(def_files)]} {lappend var_indices def_files}
foreach index $var_indices {
set all_names [array names vars -glob "*$index"]
foreach name $all_names {
set expanded_files ""
# BCL: Added subst around final variable to resolve vars(rundir) references
foreach file [subst $vars($name)] {
if {([string first "*" $file] != -1) ||
([string first "?" $file] != -1)} {
if {![catch {set files [glob $file]}]} {
lappend expanded_files $files
}
} else {
lappend expanded_files $file
}
}
set vars($name) $expanded_files
}
}
}
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} {
if {[info exists vars(novus)] && $vars(novus)} {
set utils_lines($length) [regsub "Puts" $line "puts"]
} else {
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 source_plug {plugin {abort 1}} {
global vars
global env
global warnings
global plugin_error
global errorInfo
global return_code
# Added for ETS/EPS
if {![info exists vars(flat)]} {
set vars(flat) full
}
if {[info exists vars(codegen)] && !$vars(codegen)} {
set vars(flat) full
}
set flat $vars(flat)
if {$vars(generate_flow_steps)} {
#set vars(flat) full
}
if {[info exists vars(verbose)] && $vars(verbose)} {
set verbose true
} else {
set verbose false
}
set commands "puts \"<FF> Plugin -> $plugin\"\n"
set no_comments ""
if {[info exists vars($plugin)]} {
if {![info exists vars(plugins)]} {
set vars(plugins) [list]
}
if {[lsearch $vars(plugins) $plugin] == -1} {
set suffix [lindex [split $plugin ","] 1]
if {($suffix != "derate_tcl") && ($suffix != "scale_tcl")} {
lappend vars(plugins) $plugin
}
}
set found 0
set plug_list []
foreach plug_file $vars($plugin) {
if {[file exists $plug_file]} {
set found 1
lappend plug_list $plug_file
continue
} elseif {[file exists $vars(plug_dir)/$plug_file]} {
set found 1
# lappend plug_list $plug_file
lappend plug_list $vars(plug_dir)/$plug_file
continue
} else {
if {[file exists $vars(cwd)/$plug_file]} {
set found 1
lappend plug_list $vars(cwd)/$plug_file
continue
}
}
}
if {!$found} {
if {![info exists vars(missing_plugins)]} {
set vars(missing_plugins) [list]
}
if {[lsearch $vars(missing_plugins) $plugin] == -1} {
lappend vars(missing_plugins) $plugin
set warnings($vars(warning_count)) "Plug-in $plugin defined but file(s) not found"
incr vars(warning_count)
}
}
if {$vars(flat) == "partial"} {
foreach plug_file $plug_file {
if {[file exists $plug_file]} {
append commands "puts \"<FF> LOADING \'$plug_file\' PLUG-IN FILE(s) \"\n"
append commands "if { \[ catch { source $plug_file } plugin_error \] } {\n"
append commands " puts \"<FF> ============= PLUG-IN ERROR ==================\"\n"
append commands " puts \"<FF> \$errorInfo\"\n"
append commands " puts \"<FF> \$plugin_error\"\n"
append commands " puts \"<FF> ==============================================\"\n"
append commands " set return_code 99\n"
if {$abort} {
append commands " exit \$return_code\n"
}
append commands "}\n"
}
}
} elseif {$vars(flat) == "full"} {
if {!$found} {
append commands "ff_procs::source_plug $plugin\n"
} else {
if {$verbose && ![regexp "," $plugin]} {
set commands "\n# <begin plug-in $plugin>\n"
}
if {![info exists vars(plug_files)]} {
set vars(plug_files) [list]
}
foreach plug_file $plug_list {
if {[file exists $plug_file]} {
# if {$verbose} {
# append commands "#>>>\n"
# }
append commands "# <begin $plug_file>\n"
if {[info exists vars(old_plugins)] && $vars(old_plugins) && ([lsearch $vars(edi_plugins) $plugin] != -1)} {
append commands "eval_enc \{\n"
}
if {[lsearch $vars(plug_files) $plugin] == -1} {
set suffix [lindex [split $plugin ","] 1]
if {($suffix != "derate_tcl") && ($suffix != "scale_tcl")} {
lappend vars(plug_files) "$plugin"
}
}
set ip [open $plug_file r]
while {[gets $ip line]>=0} {
# if {![regexp "^$" $line]} {
if {$vars(generate_flow_steps)} {
append commands " $line\n"
} else {
append commands "$line\n"
}
if {![regexp "^#" $line]} {
append no_comments " $line\n"
}
# }
}
close $ip
append commands "# <end $plug_file>\n"
if {[info exists vars(old_plugins)] && $vars(old_plugins) && ([lsearch $vars(edi_plugins) $plugin] != -1)} {
append commands "\}\n"
}
# if {$verbose} {
# append commands "#<<<\n"
# }
} elseif {[file exists $vars(plug_dir)/$plug_file]} {
# if {$verbose} {
# append commands "#>>>\n"
# }
if {[lsearch $vars(plug_files) $plugin] == -1} {
set suffix [lindex [split $plugin ","] 1]
if {($suffix != "derate_tcl") && ($suffix != "scale_tcl")} {
lappend vars(plug_files) "$plugin"
}
}
set ip [open $vars(plug_dir)/$plug_file r]
while {[gets $ip line]>=0} {
if {![regexp "^$" $line]} {
append commands "$line\n"
}
if {![regexp "^#" $line]} {
append no_comments " $line\n"
}
}
close $ip
# if {$verbose} {
# append commands "#<<<\n"
# }
}
}
if {$verbose && ![regexp "," $plugin]} {
append commands "# <end plug-in $plugin>\n\n"
}
}
} else {
append commands "ff_procs::source_plug $plugin\n"
}
}
set vars(flat) $flat
if {$vars(generate_flow_steps) && ($no_comments != "") && ![regexp ff_procs $commands] && ![regexp derate_tcl $plugin]} {
if {$no_comments == ""} {
set commands ""
}
if {[lindex [split $vars(version) "."] 0] > 14} {
if {![file exists $vars(cwd)/.plugins]} {
set op [open $vars(cwd)/.plugins w]
} else {
set op [open $vars(cwd)/.plugins a]
}
if {[regexp "^pre_$vars(step)" $plugin] && ($vars(step) != "partition_place")} {
set type begin_tcl
} else {
if {[regexp "^post_$vars(step)" $plugin] && ($vars(step) != "partition_place")} {
set type end_tcl
} else {
if {[regexp "^syn" $plugin] || [regexp "^always" $plugin] || [regexp "^final_always" $plugin] || [regexp "^pre_syn" $plugin]} {
set type import
} else {
if {$vars(step) != "partition_place"} {
set type skip
} else {
set type import
}
}
}
}
set step_plug [format %s_%s $vars(step) $plugin]
if {![info exists vars(processed_plugins)]} {
set vars(processed_plugins) [list]
lappend vars(processed_plugins) $step_plug
} else {
# puts "$vars(processed_plugins) : $step_plug"
if {[lsearch $vars(processed_plugins) $step_plug] == -1} {
lappend vars(processed_plugins) $step_plug
} else {
if {($vars(step) != "partition_place") && ![regexp "always" $plugin]} {
set type skip
}
}
}
if {$type != "skip"} {
# if {$type == "import"} {
# set ip [open $plug_file r]
# while {[gets $ip line]>=0} {
# if {![regexp "^$" $line]} {
# append commands " $line\n"
# if {![regexp "^#" $line]} {
# append no_comments " $line\n"
# }
# }
# }
# close $ip
return $commands
} else {
if {[info exists vars(old_plugins)] && ![regexp syn_ $vars(step)]} {
set temp "set_db flow_step:$vars(step) .$type { eval_enc {\n"
append temp $no_comments
append temp "}}\n"
puts $op $temp
} else {
set temp "set_db flow_step:$vars(step) .$type {\n"
append temp $no_comments
append temp "}\n"
puts $op $temp
}
}
} else {
puts "Skipping plugin $plugin as it cannot be (or already has been) tied to a flow_step attribute"
}
close $op
} else {
return $commands
}
} else {
return $commands
}
}
namespace export get_tool
proc get_tool {} {
set tool_name ""
set path_to_exe [info nameofexecutable]
if {[regexp {/rc(64)?(-\w)?$} $path_to_exe]} {
set tool_name "rc"
} elseif {[regexp {/genus(64)?(-\w)?$} $path_to_exe]} {
set tool_name "rc"
} elseif {[regexp {.*\/(LEC|lec)} $path_to_exe]} {
set tool_name "lec"
} elseif {[regexp {.*\/verify} $path_to_exe]} {
set tool_name "clp"
} elseif {[regexp {.*\/CCD} $path_to_exe]} {
set tool_name "ccd"
} elseif {[regexp {.*\/ctos} $path_to_exe]} {
set tool_name "ctos"
} elseif {[regexp {.*\/tclsh} $path_to_exe]} {
set tool_name "tclsh"
} elseif {[regexp {.*\/innovus} $path_to_exe]} {
set tool_name "edi"
} elseif {[regexp {.*\/encounter} $path_to_exe]} {
set tool_name "edi"
} elseif {[regexp {.*\/velocity} $path_to_exe]} {
set tool_name "edi"
} elseif {[regexp {.*\/ncsim} $path_to_exe]} {
set tool_name "ies"
}
return $tool_name
}
proc source_file {file {abort 1}} {
global vars
global source_error
global errorInfo
global return_code
# puts "<FF> LOADING '$file' FILE"
if {[file exists $file]} {
if {[info command FF::get_tool] ne "" && [FF::get_tool] eq "rc" } {
set sourceResult [catch { uplevel tcl_source $file } source_error ]
} else {
set sourceResult [catch { uplevel source $file } source_error ]
}
if { $sourceResult } {
puts "<FF> =============== TCL ERROR ===================="
puts "<FF> Error loading $file file"
puts "<FF> $errorInfo"
puts "<FF> $source_error"
puts "<FF> =============================================="
set return_code 99
if {$abort} {
exit $return_code
}
}
}
}
proc get_by_suffix {passed_array {suffix ""}} {
#
# Get the list of array indices that have a suffix of the
# passed string sequence
#
upvar $passed_array the_array
#
# If there is no suffix, return every name
#
if {[string length $suffix] == 0} {
return array names the_array
}
#
# If there is a suffix, find the matching names and return
# the list of those names (without the suffix attached to it).
# This is most helpful when looking for "multi-dimensional array
# indices" (in quotes because Tcl doesn't support multiple
# dimensions for array indices)
#
set suffix_length [string length $suffix]
set all_names [array names the_array -glob "*$suffix"]
set names [list]
foreach name $all_names {
set length [string length $name]
set index [string range $name 0 [expr $length - $suffix_length - 1]]
lappend names $index
}
return $names
}
###########################################################################
# Utility procedures on lists
###########################################################################
proc lintersection {lista listb} {
#
# Return the intersection of lista and listb, removing any duplicates
#
set intersect [list]
foreach a $lista {
if {([lsearch $listb $a] != -1) && \
([lsearch $intersect $a] == -1)} {
lappend intersect $a
}
}
return $intersect
}
proc lunion {lista listb} {
#
# Return the union of lista and listb, removing any duplicates
#
set union [list]
foreach a $lista {
if {[lsearch $union $a] == -1} {
lappend union $a
}
}
foreach b $listb {
if {[lsearch $union $b] == -1} {
lappend union $b
}
}
return $union
}
###########################################################################
# Utilities to handle different control structure output (if-then-else,
# foreach, etc.)
###########################################################################
proc for_each {var var_list code_block} {
#
# Return a string for a Tcl foreach block
#
set code ""
if {![llength $code_block]} {
return $code
}
set code "foreach $var $var_list \{\n"
foreach line [getLines $code_block] {
append code " $line"
}
append code "\}\n"
return $code
}
proc get_lines {code_block} {
#
# Return a list of lines from the strings in code_block
#
set block [list]
while {[llength $code_block]} {
set index [string first "\n" $code_block]
if {$index == -1} {
set index [string length $code_block]
}
set line [string range $code_block 0 $index]
set code_block [string range $code_block [expr $index + 1] end]
if {[string index $line end] != "\n"} {
append line "\n"
}
lappend block $line
}
return $block
}
proc if_else {cond then_block {else_block ""}} {
#
# Output a Tcl if-then-else block with the passed data.
#
set command "if \{$cond\} \{\n"
foreach line [get_lines $then_block] {
append command " $line"
}
if {[llength $else_block]} {
append command "\} else \{\n"
foreach line [get_lines $else_block] {
append command " $line"
}
}
append command "\}\n"
return $command
}
proc pretty_print_lists {line debug} {
#
# If there is an explicit Tcl list in the line, we may want to
# separate it out into multiple lines. It will turn a list from
# [list a b c]
# into
# [list a \
# b \
# c]
# That may not look like much, but for lists that have really *big*
# text entries, it makes it look a lot nicer
#
# If there is no list in the line, do nothing
#
set endChar [string index $line end]
set line [string trimright $line]
if {$endChar == "\n"} {
append line "\n"
}
set listPos [string first "\[list " $line]
if {$listPos == -1} {
return $line
}
set original $line
#
# Initialize the line with the contents of the line up to and including
# the "[list " text. Also determine the amount of indentation in the
# line so that we know what to do for subsequent lines
#
incr listPos 5
set nextLine [string range $line 0 $listPos]
set indent [string repeat " " [string length $nextLine]]
set line [string trimleft [string range $line $listPos end]]
#
# Make sure that there is no space between the close brace in the list
# and the last text in the list. This will help with processing (below)
#
set line [string trimright $line]
if {[string index $line end] != "\]"} {
return $original
}
set line [string range $line 0 [expr [string length $line] - 2]]
set line [string trimright $line]
append line "\]\n"
#
# Parse each element in the list
#
set printString ""
while {[string length $line]} {
#
# Get the next item in the list
#
set space [string first " " $line]
if {$space == -1} {
set space [string length $line]
}
set arg [string range $line 0 $space]
append nextLine $arg
#
# Remove that item from the line
#
set line [string range $line [expr $space + 1] end]
set line [string trimleft $line]
if {[string length $line]} {
if {[string length $nextLine] > 80} {
append printString "$nextLine\\\n"
set nextLine $indent
}
}
}
append printString $nextLine
return $printString
}
proc pretty_print {commands format_options {debug 0}} {
global vars
#
# Pretty print the lines, one by one. The following will be done:
# o If the line is greater than 80 columns, we will break it up
# along the options (-option) and indent
# o Fix any indentation
#
if {[info exists vars(catch_errors)] && $vars(catch_errors)} {
set indent 3
} else {
set indent 0
}
set lines ""
set len [string length $commands]
while {$len > 0} {
#
# Handle the simple case. If the leading character is a carriage
# return, append a blank line to the pretty-printed lines and
# continue on
#
set cr [string first "\n" $commands]
if {!$cr} {
set commands [string range $commands 1 end]
incr len -1
append lines "\n"
continue
}
#
# If we didn't find a carriage return in the string, the entire thing
# is a single line. Otherwise, remove the next line from the set of
# lines. If it still ends up being a blank line, append the blank
# line to the pretty-printed string and continue on
#
if {$cr == -1} {
set line $commands
set commands ""
set len 0
} else {
set line [string range $commands 0 $cr]
set commands [string range $commands [incr cr] end]
set len [expr $len - $cr]
}
set line [string trimright $line]
if {![string length $line]} {
append lines "\n"
continue
}
#
# We have a real line with real text. If there is no quote in the
# string, compress multiple blank spaces to a single blank space
#
set line [string trimleft $line]
if {[string first "\"" $line] == -1} {
set line [regsub -all {\s+} $line " "]
}
#
# Apply the proper amount of indentation
#
set isPut [string equal -nocase -length 5 $line "puts "]
set firstChar [string index $line 0]
if {$firstChar == "\}"} {
incr indent -3
}
set blanks [string repeat " " $indent]
set line "${blanks}${line}"
if {[string index $line end] == "\{"} {
incr indent 3
}
#
# If the first character is a dash, we have already broken the line
# up for pretty printing.
#
if {$firstChar == "-"} {
append lines " $line\n"
continue
}
#
# Don't bother formatting comments or short lines. Also, if the
# routine has been told not to format the command line options, just
# output the line
#
set lineLen [string length $line]
if {$isPut || ($firstChar == "\#") ||
($lineLen < 80) || !$format_options} {
append lines "$line\n"
continue
}
#
# The line length is over 80, and it's a real Innovus command, and it's
# not a print (puts) statement. Start indenting on the -option
# options. The first "-option" should be on the same line as the
# command. All subsequent options should be on their own line,
# slightly indented from the basic command
#
set firstDash [string first " -" $line]
if {$firstDash == -1} {
append lines "$line\n"
continue
}
set dash [string first " -" $line [incr firstDash]]
set leading ""
while {$dash != -1} {
set fragment [string range $line 0 [expr $dash - 1]]
append lines \
[pretty_print_lists "${leading}${fragment} \\\n" $debug]
set leading "$blanks "
set line [string range $line [expr $dash + 1] end]
set line [string trimleft $line]
set dash [string first " -" $line]
}
append lines [pretty_print_lists "${leading}${line}\n" $debug]
}
return $lines
}
proc strip_lines {commands markers} {
#
# This routine strips out lines from $commands when they start with
# any of the list elements in $markers
#
set lines ""
while {[string length $commands] > 0} {
#
# Get the next line from the set of commands
#
set cr [string first "\n" $commands]
if {$cr == -1} {
set line $commands
set commands ""
} else {
set line [string range $commands 0 $cr]
set commands [string range $commands [incr cr] end]
}
#
# If the line starts with a marker, ignore the line
#
set trimmed [string trimleft $line]
set matched false
foreach marker $markers {
set len [string length $marker]
if {[string equal -nocase -length $len $marker $trimmed]} {
set matched true
break
}
}
if {$matched} {
continue
}
append lines $line
}
return $lines
}
proc gen_makefile {steps type} {
global vars
global desc
global env
global errors
if {!$vars(makefile)} {
return
}
set desc(syn_map) "Technology Mapping"
set desc(syn_incr) "Incremental Synthesis"
set desc(syn_place) "Placement/Physical Synthesis"
set desc(init) "Design Import / Initialization"
if {$vars(rc)} {
set desc(place) "Legalization"
} else {
set desc(place) "Cell Placement"
}
set desc(prects) "PreCTS Optimization"
set desc(cts) "Clock Tree Synthesis"
set desc(postcts) "PostCTS Optimization"
set desc(postcts_hold) "PostCTS Hold Fixing"
set desc(route) "Global/Detail Route"
set desc(postroute) "PostRoute Optimization"
set desc(postroute_hold) "PostRoute Hold Fixing"
set desc(postroute_si_hold) "SI Hold Fixing"
set desc(postroute_si) "SI Optimization"
set desc(signoff) "Signoff Timing / Verify"
if {$vars(debug)} {
puts "<DEBUG> Generating $type makefile in [exec pwd] for steps $steps ..."
# if {[info exists vars(partition_dir)]} {
# puts "vars(partition_dir) -> $vars(partition_dir)"
# puts "[file tail [file dirname [exec pwd]]] == $vars(partition_dir)"
# puts "[file dirname [exec pwd]] == [file normalize $vars(partition_dir)]"
# }
}
puts "-------------------------------------------------"
puts "<FF> Generating $type Makefile for [llength $steps] steps"
puts "<FF> Directory: [pwd]"
puts "<FF> Steps: $steps"
# puts "-------------------------------------------------"
# BCL: Note - the Makefile needs to be fixed to the rundir here, as it will be dumped in the final exported
# vars.tcl
if {$vars(make) == "all"} {
if {([file tail [file dirname [exec pwd]]] == $vars(partition_dir)) || \
([file tail [file dirname [exec pwd]]] == $vars(partition_dir_pass2))} {
set vars(makefile_name) "Makefile"
} else {
set vars(makefile_name) "\$vars(rundir)/Makefile"
}
} else {
if {[file tail [file dirname [exec pwd]]] == $vars(partition_dir)} {
set vars(makefile_name) "Makefile.$vars(argv)"
} else {
set vars(makefile_name) "\$vars(rundir)/Makefile.$vars(argv)"
}
}
regsub -all " " $vars(makefile_name) "_" vars(makefile_name)
set op [open [subst $vars(makefile_name)] w]
# if {$vars(debug)} {
# puts "<DEBUG> Opening file: $vars(makefile_name) in [exec pwd] -> $op"
# }
# set stop signoff
set stop [lindex $vars(steps) [expr [llength $vars(steps)]-1]]
if {$vars(rc) && [info exists vars(rc_steps)]} {
set start [lindex $vars(rc_steps) 0]
} else {
set start [lindex $vars(steps) 0]
}
if {$type == "hier"} {
set type top_down
if {$vars(hier_flow_type) == "2pass"} {
set type 2pass
if {$vars(enable_flexilm)} {
set type flexilm
}
}
}
if {$type == "user"} { set type flat }
switch $type {
"flat" {
set execute_string [join $vars(execute_string)]
puts $op "VERSION=17.10-p003_1"
puts $op "VPATH=$env(VPATH)"
puts $op "TCLSH=[lindex $execute_string 0]"
puts $op "GEN_FLOW=[::FF::relPathTo [file normalize [subst [lindex $execute_string 1]]] [file normalize [subst $vars(rundir)]]]"
puts $op "SETUP_PATH=[relPathTo [file normalize [subst $vars(setup_path)]] [file normalize [subst $vars(rundir)]]]"
puts $op "TOOL=$vars(make_tool)"
puts $op "ARGS=$vars(make_tool_args)"
puts $op "FSTEPS=$steps"
if {$vars(rc)} {
puts $op "SYN_TOOL=$vars(make_syn_tool)"
puts $op "SYN_ARGS=$vars(make_syn_tool_args)"
if {[info exists vars(syn_log_dir)]} {
puts $op "SYN_LOG=[relPathTo [file normalize [subst $vars(syn_log_dir)]] [file normalize $vars(rundir)]]"
}
}
if {[regexp $vars(partition_dir) [file tail [file dirname [pwd]]]]} {
puts $op "SCRIPTS=$vars(script_dir)"
puts $op "LOG=$vars(log_dir)"
} else {
# BCL: Added the following in order to fix the difference in location between the rundir and scripts location
puts $op "SCRIPTS=[relPathTo [file normalize $vars(script_dir)] [file normalize $vars(rundir)]]"
# BCL: Added subst to resolve vars(rundir)
# BCL: Then modified to make relative to the rundir
puts $op "LOG=[relPathTo [file normalize [subst $vars(log_dir)]] [file normalize $vars(rundir)]]"
}
puts $op "BROWSER=$vars(make_browser)"
if {[info exists vars(make_update)]} {
puts $op "UPDATE=$vars(make_update)"
} elseif {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
puts $op "UPDATE=yes"
}
puts $op ""
puts $op "STEPS = [format "version setup %s do_cleanup" $steps]"
puts $op "FF_START = $start"
puts $op "FF_STOP = $stop"
puts $op ""
puts $op [format "all: version setup %s do_cleanup" $steps]
puts $op ""
puts $op "version:"
puts $op "\t@echo \"\# Foundation Flows Version \$(VERSION)\""
puts $op ""
puts $op "help:"
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" \$(VERSION) Foundation Flows\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Targets\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" setup : Setup Run Directory\""
if {$vars(rc) && [info exists vars(rc_steps)]} {
foreach step $vars(rc_steps) {
puts $op "\t@echo \" $step : $desc($step)\""
}
}
foreach step $steps {
# puts $op "\t@echo \" $step : $desc($step)\""
if {![info exists desc($step)]} {
set desc($step) "No information for this step"
}
set temp [format "%+21s : %-45s" $step $desc($step)]
puts $op "\t@echo $temp"
}
puts $op "\t@echo \"---------------------------------------------------\""
puts $op "\t@echo \" all : All design steps\""
puts $op "\t@echo \" simple : Single script (all steps in a single session) - no stop/start\""
puts $op "\t@echo \" single : Single script (all steps in a single session)\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Options\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" VPATH : Make directory (default make)\""
if {$vars(novus)} {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
} else {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
}
if {$vars(rc)} {
puts $op "\t@echo \"SYN_TOOL : GENUS executable (default genus)\""
puts $op "\t@echo \"SYN_ARGS : GENUS arguments (default -64)\""
puts $op "\t@echo \"SYN_LOG : GENUS log dir (default RC/logs/<stage>.log)\""
}
if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
puts $op "\t@echo \" UPDATE : Update scripts (default yes)\""
}
puts $op "\t@echo \" SCRIPTS : Script directory (default $vars(script_dir))\""
puts $op "\t@echo \" LOG : Logfile directory (default [subst $vars(log_dir))]\""
puts $op "\t@echo \"===================================================\""
puts $op ""
# if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
# if {[info exists vars(plug_files)]} {
# puts $op "flow: $vars(config_files) $vars(plug_files)"
# } else {
# puts $op "flow: $vars(config_files)"
# }
# puts $op "\t@if \[ \$(UPDATE) == yes ] ; then \\"
# puts $op "\t\t[lindex $execute_string 0] [lindex $execute_string 1] -m flat all ; \\"
# puts $op "\t\t/bin/touch \$(VPATH)/\$@ ; \\"
# puts $op "\telse \\"
# puts $op "\t\techo 'SKIPPING FLOW UPDATE ...' ; \\"
# puts $op "\tfi"
# } else {
# puts $op "flow:"
# }
puts $op "\nsimple: setup"
if {$vars(step_arg) == "all"} {
puts $op "\tFF_STOP=\$(FF_STOP); VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_simple.tcl -log \$(LOG)/simple.log \$(ARGS)"
} else {
puts $op "\tFF_STOP=\$(FF_STOP); VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_simple.$vars(step_arg).tcl -log \$(LOG)/simple.$vars(step_arg).log \$(ARGS)"
}
puts $op ""
puts $op "\nsingle: setup"
puts $op "\tFF_STOP=\$(FF_STOP); VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_all.tcl -log \$(LOG)/single.log \$(ARGS)"
puts $op ""
puts $op "setup:"
puts $op "\t@/bin/mkdir -p \$(VPATH) \$(LOG)"
puts $op "\t@/bin/touch \$(VPATH)/\$@"
if {[info exists vars(enable_ldb)] && $vars(enable_ldb)} {
puts $op "\t\$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_compile.tcl -log \$(LOG)/compile.log -win \$(ARGS)"
}
puts $op ""
set prior_step "setup"
set arg_list "-n "
# if {$vars(novus)} {
# append arg_list "-N "
# }
if {$vars(verbose)} {
append arg_list "-V "
}
if {$vars(edi)} {
append arg_list "-e "
}
if {$vars(rc)} {
append arg_list "-r "
}
# RC Steps, if any, always go first
if {[info exists vars(rc_steps)] && $vars(rc_steps) ne ""} {
foreach step $vars(rc_steps) {
puts $op "$step: $prior_step"
puts $op "\t@mkdir -p \$(SYN_LOG);"
if {![regexp $vars(partition_dir) [file tail [file dirname [pwd]]]]} {
puts $op "\t@if \[ \"\$(UPDATE)\" = \"yes\" ] ; then \\"
if {[file normalize .] ne [file normalize $vars(rundir)]} {
puts $op "\t\tcd [relPathTo [file normalize .] [file normalize $vars(rundir)]]; [lindex $execute_string 0] [::FF::relPathTo [file normalize [subst [lindex $execute_string 1]]] [file normalize [subst $vars(rundir)]]] -m flat -d [relPathTo [file normalize $vars(script_dir)] [file normalize $vars(rundir)]] -v $vars(version) -s [relPathTo [file normalize [subst $vars(setup_path)]] [file normalize [subst $vars(rundir)]]] -y none -u [relPathTo [file normalize $vars(rundir)] [file normalize .]] $arg_list $step ; \\"
} else {
puts $op "\t\t[lindex $execute_string 0] [::FF::relPathTo [file normalize [subst [lindex $execute_string 1]]] [file normalize [subst $vars(rundir)]]] -m flat -d [relPathTo [file normalize $vars(script_dir)] [file normalize $vars(rundir)]] -v $vars(version) -s [relPathTo [file normalize [subst $vars(setup_path)]] [file normalize [subst $vars(rundir)]]] -y none $arg_list $step ; \\"
}
puts $op "\tfi"
}
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(SYN_TOOL) -f \$(SCRIPTS)/GENUS/$step.tcl -logfile \$(SYN_LOG)/$step.log -cmdfile \$(SYN_LOG)/$step.cmd \$(SYN_ARGS)"
set prior_step $step
}
}
foreach step $steps {
# These steps should not also be rc_steps:
if {![info exists vars(rc_steps)] || [lsearch $vars(rc_steps) $step] == "-1"} {
puts $op "$step: $prior_step"
puts $op "\t@mkdir -p \$(LOG);"
# puts $op "\t@\$(MAKE) -f Makefile flow"
if {![regexp $vars(partition_dir) [file tail [file dirname [pwd]]]]} {
puts $op "\t@if \[ \"\$(UPDATE)\" = \"yes\" ] ; then \\"
# cd to ff_exe_dir here only if vars(rundir) ne vars(ff_exe_dir)
if {[file normalize .] ne [file normalize $vars(rundir)]} {
puts $op "\t\tcd [relPathTo [file normalize .] [file normalize $vars(rundir)]]; [lindex $execute_string 0] [::FF::relPathTo [file normalize [subst [lindex $execute_string 1]]] [file normalize [subst $vars(rundir)]]] -m $vars(mode) -d [relPathTo [file normalize $vars(script_dir)] [file normalize $vars(rundir)]] -v $vars(version) -s [relPathTo [file normalize [subst $vars(setup_path)]] [file normalize [subst $vars(rundir)]]] -y none -u [relPathTo [file normalize $vars(rundir)] [file normalize .]] $arg_list $step ; \\"
} else {
puts $op "\t\t[lindex $execute_string 0] [::FF::relPathTo [file normalize [subst [lindex $execute_string 1]]] [file normalize [subst $vars(rundir)]]] -m $vars(mode) -d [relPathTo [file normalize $vars(script_dir)] [file normalize $vars(rundir)]] -v $vars(version) -s [relPathTo [file normalize [subst $vars(setup_path)]] [file normalize [subst $vars(rundir)]]] -y none $arg_list $step ; \\"
}
# Need to add code to cd back to rundir here
puts $op "\tfi"
}
if {[regexp "^syn" $step]} {
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(SYN_TOOL) -f \$(SCRIPTS)/GENUS/run_$step.tcl -logfile \$(LOG)/$step.log -cmdfile \$(LOG)/$step.cmd \$(SYN_ARGS)"
} else {
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_$step.tcl -log \$(LOG)/$step.log -overwrite \$(ARGS)"
}
# puts $op "\t/bin/touch \$(VPATH)/$step\n"
set prior_step $step
}
}
# puts $op "html:"
# puts $op "\tFFVARS=$vars(script_dir)/vars.tcl; export FFVARS; /usr/bin/tclsh \$(SCRIPTS)/INNOVUS/gen_html.tcl .; cd $vars(html_dir); \$(BROWSER) file:`pwd`/index.html"
# puts $op ""
puts $op "debug_%:"
puts $op "\tVPATH=\$(VPATH); export STEP=\$* ; export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_debug.tcl -log \$(LOG)/\$@.log -win \$(ARGS:-nowin=)"
puts $op ""
puts $op "lec_%:"
puts $op "\texport STEP=\$* ; lec -64 -xl -Dofile \$(SCRIPTS)/INNOVUS/run_lec.tcl -NOGui -LOGfile \$(LOG)/\$@.log"
puts $op ""
puts $op "help_%:"
puts $op "\t[lindex $execute_string 0] \$(GEN_FLOW) -H \$*"
puts $op ""
# puts $op ".PHONY: clean html"
puts $op ".PHONY: clean"
puts $op ""
puts $op "clean:"
puts $op "\t/bin/mv *.rpt $vars(rpt_dir) ;\\"
puts $op "\t/bin/rm -fr extLogDir* __qrc.log *cts_trace *.rpt.old *delete* placementReports* *.rguide *_mmmc \\\n\t*_constr.pt .constr* .FE* .routing* .timing_file* .tdrlog*"
puts $op ""
puts $op "do_cleanup: signoff"
puts $op "\t\$(MAKE) clean"
puts $op "\t/bin/touch \$(VPATH)/\$@"
puts $op ""
puts $op "reset : version"
puts $op "\t/bin/rm -fr \$(VPATH)/* extLogDir* __qrc.log *cts_trace *.rpt.old *delete* placementReports* *.rguide *_mmmc"
puts $op "\t@for file in \$(STEPS) ; \\"
puts $op "\tdo \\"
puts $op "\t\tif \[ -r \$(VPATH)/\$\$file \] ; then \\"
puts $op "\t\t\t/bin/rm \$(VPATH)/\$\$file ; \\"
puts $op "\t\tfi \\"
puts $op "\tdone"
puts $op ""
puts $op "block_%: setup"
puts $op "\t@if \[ \"x\$*\" = \"xsingle\" \] ; then \\"
puts $op "\t\tff_stop=\$(FF_STOP); \\"
puts $op "\t\ttarget=\"\$@ (from: \$(FF_START) to: \$(FF_STOP))\"; \\"
puts $op "\telse \\"
puts $op "\t\tff_stop=\$* ; \\"
puts $op "\t\ttarget=\$@; \\"
puts $op "\tfi; \\"
puts $op "\tif \[ -r \$(VPATH)/.RUNNING \] ; then \\"
puts $op "\t\techo \"INFO: A build seems to be running already... check \$(VPATH)/.RUNNING file and remove that file if the process is dead\" ; \\"
puts $op "\t\t/bin/head -1 \$(VPATH)/.RUNNING ; \\"
puts $op "\t\texit -1 ; \\"
puts $op "\telse \\"
puts $op "\t\t/bin/rm -f \$(VPATH)/block_\$\$\{ff_stop\}.DONE \$(VPATH)/block_\$\$\{ff_stop\}.FAILED \$(VPATH)/block_\$\$\{ff_stop\}.PASS ; \\"
puts $op "\t\t(echo \"# Started building \$\$\{target\} at \"`/bin/date`\" on \"`/bin/hostname`\" PID: \$\$\$\$\" ; \$(MAKE) \$(TARGET) ) &>\$(VPATH)/.RUNNING ; \\"
puts $op "\t\tif \[ -r \$(VPATH)/\$\$\{ff_stop\} \] ; then \\"
puts $op "\t\t\tif \[ -r \$(VPATH)/.RUNNING \] ; then \\"
puts $op "\t\t\t\t/bin/mv \$(VPATH)/.RUNNING \$(VPATH)/block_\$\$\{ff_stop\}.PASS ; \\"
puts $op "\t\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\} ; \\"
puts $op "\t\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\}.DONE ; \\"
puts $op "\t\t\telse \\"
puts $op "\t\t\t\techo \"# Something did not work properly\" > \$(VPATH)/block_\$\$\{ff_stop\}.FAILED ; \\"
puts $op "\t\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\}.DONE ; \\"
puts $op "\t\t\t\texit -1; \\"
puts $op "\t\t\tfi ; \\"
puts $op "\t\telse \\"
puts $op "\t\t\tif \[ -r \$(VPATH)/.RUNNING \] ; then \\"
puts $op "\t\t\t\t/bin/mv \$(VPATH)/.RUNNING \$(VPATH)/block_\$\$\{ff_stop\}.FAILED ; \\"
puts $op "\t\t\telse \\"
puts $op "\t\t\t\techo \"# Something did not work properly\" > \$(VPATH)/block_\$\$\{ff_stop\}.FAILED ; \\"
puts $op "\t\t\tfi ; \\"
puts $op "\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\}.DONE ; \\"
puts $op "\t\t\texit -1 ; \\"
puts $op "\t\tfi ; \\"
puts $op "\tfi"
if {$vars(generate_flow_steps) && [info exists vars(flow_steps)]} {
if {[info exists vars(flow_steps,flat)]} {
set fp1 [open $vars(script_dir)/flow_config.tcl w]
set fp2 [open $vars(script_dir)/flow_steps.tcl w]
puts $fp1 "set_db flow_database_directory $vars(dbs_dir)"
puts $fp1 "set_db flow_report_directory $vars(rpt_dir)"
puts $fp1 "set_db flow_log_directory $vars(log_dir)"
puts $fp2 [regsub "create_flow_step -name init " $vars(flow_steps,flat) "create_flow_step -name init_design "]
puts $fp1 "\nset_db flow_mail_to [exec whoami]"
puts $fp1 "set_db flow_mail_on_error true\n"
if {$vars(top)} {
set vars(flow_name) top
} else {
set vars(flow_name) block
}
if {[file exists $vars(cwd)/.plugins]} {
set ip [open $vars(cwd)/.plugins r]
while {[gets $ip line]>=0} {
puts $fp1 $line
}
close $ip
# file delete $vars(cwd)/.plugins
}
close $fp1
puts $fp2 "create_flow_step -name init_floorplan { }"
close $fp2
if {[info exists vars(partition_list)]} {
if {($vars(design) == [lindex $vars(partition_list) 0]) || $vars(top)} {
set hp [open $vars(script_dir)/.hiersteps.tcl w]
if {$vars(top)} {
set temp [regsub -all "create_flow_step -name init" $vars(flow_steps,flat) "create_flow_step -name top_init"]
set temp2 [regsub -all "create_flow_step -name prects" $temp "create_flow_step -name top_prects"]
set temp3 [regsub -all "create_flow_step -name place" $temp2 "create_flow_step -name top_place"]
set temp4 [regsub -all "create_flow_step -name cts" $temp3 "create_flow_step -name top_cts"]
set vars(flow_steps,flat) [regsub -all "create_flow_step -name signoff" $temp4 "create_flow_step -name top_signoff"]
}
puts $hp $vars(flow_steps,flat)
close $hp
}
}
unset vars(flow_steps)
}
}
if {$vars(generate_flow_steps)} {
if {[lsearch $steps "assemble"] != -1} {
set steps [lreplace $steps end end]
}
set fp [open run_flow.tcl w]
puts $fp "source $vars(script_dir)/flow_steps.tcl"
puts $fp "if \{\[file exists $vars(script_dir)/plug_steps.tcl\]\} \{"
puts $fp " source $vars(script_dir)/plug_steps.tcl"
puts $fp "\}"
if {[file tail [pwd]] == $vars(top_cell)} {
if {[file tail [file dirname [pwd]]] == "$vars(partition_dir)"} {
set vars(flow_name) "top"
} else {
set vars(flow_name) "top_pass2"
}
set top_steps " $steps"
foreach s "init place prects cts signoff" {
set temp [regsub " $s" $top_steps " top_$s"]
set top_steps $temp
}
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $top_steps\]\n"
} else {
set dir [file tail [pwd]]
set pdir [file tail [file tail $dir]]
if {[info exists vars(partition_list)]} {
if {([file tail [pwd]] == [lindex $vars(partition_list) 0])} {
if {[file tail [file dirname [pwd]]] == "$vars(partition_dir)"} {
set vars(flow_name) "block"
} else {
set vars(flow_name) "block_pass2"
}
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $steps\]\n"
}
} else {
if {!$vars(rc)} {
set vars(flow_name) "innovus"
puts $fp "source $vars(script_dir)/flow_config.tcl"
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $steps\]\n"
} else {
set rc_steps [list]
set edi_steps [list]
foreach s $steps {
if {[regexp syn_ $s]} {
lappend rc_steps $s
} else {
lappend edi_steps $s
}
}
set vars(flow_name) "genus"
# puts $fp "source $vars(script_dir)/flow_steps.tcl"
puts $fp "source $vars(script_dir)/flow_config.tcl"
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_syn_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $rc_steps\]\n"
set vars(flow_name) "innovus"
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $edi_steps\]\n"
}
}
}
close $fp
}
}
"bottom_up" {
puts $op "VERSION=17.10-p003_1"
puts $op "VPATH=$env(VPATH)"
puts $op "TOOL=$vars(make_tool)"
puts $op "SCRIPTS=$vars(script_dir)"
puts $op "LOG=$vars(log_dir)"
puts $op "BROWSER=$vars(make_browser)"
if {[info exists vars(make_update)]} {
puts $op "UPDATE=$vars(make_update)"
} elseif {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
puts $op "UPDATE=yes"
}
puts $op ""
puts $op "ARGS=$vars(make_tool_args)"
puts $op "STEPS = [format "version setup %s do_cleanup" $steps]"
puts $op "FF_STOP = signoff"
puts $op "FF_START = init"
puts $op ""
puts $op [format "all: version setup %s do_cleanup" $steps]
puts $op ""
puts $op "version:"
puts $op "\t@echo \"\# Foundation Flows Version \$(VERSION)\""
puts $op ""
puts $op "help:"
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" \$(VERSION) Foundation Flows\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Targets\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" setup : Setup Run Directory\""
puts $op "\t@echo \" init : Create Initial Database\""
puts $op "\t@echo \" place : Cell Placement\""
puts $op "\t@echo \" prects : PreCTS Optimization\""
puts $op "\t@echo \" cts : Clock Tree Synthesis\""
puts $op "\t@echo \" postcts : PostCTS Optimization\""
puts $op "\t@echo \" postcts_hold : PostCTS Oold Fixing\""
puts $op "\t@echo \" route : Global/Detail Route\""
puts $op "\t@echo \" postroute : PostRoute Optimization\""
puts $op "\t@echo \" postroute_hold : PostRoute Hold Fixing\""
puts $op "\t@echo \" postroute_si_hold : SI Hold Fixing\""
puts $op "\t@echo \" postroute_si : SI Optimization\""
puts $op "\t@echo \" signoff : Signoff Timing / Verify\""
puts $op "\t@echo \" assemble : Design Assembly / Verify\""
puts $op "\t@echo \"---------------------------------------------------\""
puts $op "\t@echo \" all : All design steps\""
puts $op "\t@echo \" simple : Single script (all steps in a single session) - no stop/start\""
puts $op "\t@echo \" single : Single script (all steps in a single session)\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Options\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" VPATH : Make directory (default make)\""
if {$vars(novus)} {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
} else {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
}
if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
puts $op "\t@echo \" UPDATE : Update scripts (default yes)\""
}
# puts $op "\t@echo \" BROWSER : HTML browser (default netscape)\""
puts $op "\t@echo \" SCRIPTS : Script directory (default $vars(script_dir))\""
puts $op "\t@echo \" LOG : Logfile directory (default $vars(log_dir))\""
puts $op "\t@echo \"===================================================\""
puts $op ""
# if {[file tail [file dirname [pwd]]] != "$vars(partition_dir)"} {
# if {[info exists vars(plug_files)]} {
# puts $op "flow: $vars(config_files) $vars(plug_files)"
# } else {
# puts $op "flow: $vars(config_files)"
# }
# puts $op "\t@if \[ \$(UPDATE) == yes ] ; then \\"
# puts $op "\t\t[lindex $execute_string 0] [lindex $execute_string 1] -m flat all ; \\"
# puts $op "\t\t/bin/touch \$(VPATH)/\$@ ; \\"
# puts $op "\telse \\"
# puts $op "\t\techo 'SKIPPING FLOW UPDATE ...' ; \\"
# puts $op "\tfi"
# } else {
# puts $op "flow:"
# }
puts $op "\nsimple: setup"
if {$vars(step_arg) == "all"} {
puts $op "\tFF_STOP=\$(FF_STOP); VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_simple.tcl -log \$(LOG)/simple.log \$(ARGS)"
} else {
puts $op "\tFF_STOP=\$(FF_STOP); VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_simple.$vars(step_arg).tcl -log \$(LOG)/simple.$vars(step_arg).log \$(ARGS)"
}
puts $op ""
puts $op "\nsingle: setup"
puts $op "\tFF_STOP=\$(FF_STOP); VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_all.tcl -log \$(LOG)/single.log \$(ARGS)"
puts $op ""
puts $op "setup:"
puts $op "\t@/bin/mkdir -p \$(VPATH) \$(LOG)"
puts $op "\t@/bin/touch \$(VPATH)/\$@"
if {[info exists vars(enable_ldb)] && $vars(enable_ldb)} {
puts $op "\t\$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_compile.tcl -log \$(LOG)/compile.log -win \$(ARGS)"
}
puts $op ""
set prior_step "setup"
foreach step $steps {
puts $op "$step: $prior_step"
# puts $op "\t@\$(MAKE) -f Makefile flow"
if {[file dirname [pwd]] != "$vars(partition_dir)"} {
puts $op "\t@if \[ \$(UPDATE) == yes ] ; then \\"
puts $op "\t\t[lindex $execute_string 0] [lindex $execute_string 1] -n -m bottom_up $step ; \\"
puts $op "\tfi"
}
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_$step.tcl -log \$(LOG)/$step.log -overwrite \$(ARGS)"
puts $op "\t/bin/touch \$(VPATH)/$step\n"
set prior_step $step
}
# puts $op "html:"
# puts $op "\tFFSTEPS=\$(STEPS); export FFSTEPS; FFLOGDIR=\$(LOG); export FFLOGDIR; /usr/bin/tclsh \$(SCRIPTS)/INNOVUS/gen_html.tcl .; cd HTML; \$(BROWSER) file:`pwd`/index.html"
# puts $op ""
puts $op "debug_%:"
puts $op "\tVPATH=\$(VPATH); export STEP=\$* ; export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_debug.tcl -log \$(LOG)/\$@.log -win \$(ARGS:-nowin=)"
puts $op ""
puts $op "lec_%:"
puts $op "\texport STEP=\$* ; lec -64 -xl -Dofile \$(SCRIPTS)/INNOVUS/run_lec.tcl -NOGui -LOGfile \$(LOG)/\$@.log"
puts $op ""
# puts $op ".PHONY: clean html"
puts $op ".PHONY: clean"
puts $op ""
puts $op "clean:"
puts $op "\t/bin/mv *.rpt $vars(rpt_dir) ;\\"
puts $op "\t/bin/rm -fr extLogDir* __qrc.log *cts_trace *.rpt.old *delete* placementReports* *.rguide *_mmmc \\\n\t*_constr.pt .constr* .FE* .routing* .timing_file* .tdrlog*"
puts $op ""
puts $op "do_cleanup: signoff"
puts $op "\t\$(MAKE) clean"
puts $op "\t/bin/touch \$(VPATH)/\$@"
puts $op ""
puts $op "reset : version"
puts $op "\t/bin/rm -fr \$(VPATH)/* extLogDir* __qrc.log *cts_trace *.rpt.old *delete* placementReports* *.rguide *_mmmc"
puts $op "\t@for file in \$(STEPS) ; \\"
puts $op "\tdo \\"
puts $op "\t\tif \[ -r \$(VPATH)/\$\$file \] ; then \\"
puts $op "\t\t\t/bin/rm \$(VPATH)/\$\$file ; \\"
puts $op "\t\tfi \\"
puts $op "\tdone"
puts $op ""
puts $op "block_%: setup"
puts $op "\t@if \[ \"x\$*\" = \"xsingle\" \] ; then \\"
puts $op "\t\tff_stop=\$(FF_STOP); \\"
puts $op "\t\ttarget=\"\$@ (from: \$(FF_START) to: \$(FF_STOP))\"; \\"
puts $op "\telse \\"
puts $op "\t\tff_stop=\$* ; \\"
puts $op "\t\ttarget=\$@; \\"
puts $op "\tfi; \\"
puts $op "\tif \[ -r \$(VPATH)/.RUNNING \] ; then \\"
puts $op "\t\techo \"INFO: A build seems to be running already... check \$(VPATH)/.RUNNING file and remove that file if the process is dead\" ; \\"
puts $op "\t\t/bin/head -1 \$(VPATH)/.RUNNING ; \\"
puts $op "\t\texit -1 ; \\"
puts $op "\telse \\"
puts $op "\t\t/bin/rm -f \$(VPATH)/block_\$\$\{ff_stop\}.DONE \$(VPATH)/block_\$\$\{ff_stop\}.FAILED \$(VPATH)/block_\$\$\{ff_stop\}.PASS ; \\"
puts $op "\t\t(echo \"# Started building \$\$\{target\} at \"`/bin/date`\" on \"`/bin/hostname`\" PID: \$\$\$\$\" ; \$(MAKE) \$(TARGET) ) &>\$(VPATH)/.RUNNING ; \\"
puts $op "\t\tif \[ -r \$(VPATH)/\$\$\{ff_stop\} \] ; then \\"
puts $op "\t\t\tif \[ -r \$(VPATH)/.RUNNING \] ; then \\"
puts $op "\t\t\t\t/bin/mv \$(VPATH)/.RUNNING \$(VPATH)/block_\$\$\{ff_stop\}.PASS ; \\"
puts $op "\t\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\} ; \\"
puts $op "\t\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\}.DONE ; \\"
puts $op "\t\t\telse \\"
puts $op "\t\t\t\techo \"# Something did not work properly\" > \$(VPATH)/block_\$\$\{ff_stop\}.FAILED ; \\"
puts $op "\t\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\}.DONE ; \\"
puts $op "\t\t\t\texit -1; \\"
puts $op "\t\t\tfi ; \\"
puts $op "\t\telse \\"
puts $op "\t\t\tif \[ -r \$(VPATH)/.RUNNING \] ; then \\"
puts $op "\t\t\t\t/bin/mv \$(VPATH)/.RUNNING \$(VPATH)/block_\$\$\{ff_stop\}.FAILED ; \\"
puts $op "\t\t\telse \\"
puts $op "\t\t\t\techo \"# Something did not work properly\" > \$(VPATH)/block_\$\$\{ff_stop\}.FAILED ; \\"
puts $op "\t\t\tfi ; \\"
puts $op "\t\t\t/bin/touch \$(VPATH)/block_\$\$\{ff_stop\}.DONE ; \\"
puts $op "\t\t\texit -1 ; \\"
puts $op "\t\tfi ; \\"
puts $op "\tfi"
if {$vars(generate_flow_steps) && [info exists vars(flow_steps)]} {
if {[info exists vars(flow_steps,flat)]} {
set fp1 [open $vars(script_dir)/flow_config.tcl w]
set fp2 [open $vars(script_dir)/flow_steps.tcl w]
puts $fp1 "set_db flow_database_directory $vars(dbs_dir)"
puts $fp1 "set_db flow_report_directory $vars(rpt_dir)"
puts $fp1 "set_db flow_log_directory $vars(log_dir)"
puts $fp2 $vars(flow_steps,flat)
puts $fp1 "\nset_db flow_mail_to [exec whoami]"
puts $fp1 "set_db flow_mail_on_error true\n"
if {$vars(top)} {
set vars(flow_name) top
} else {
set vars(flow_name) block
}
# puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list [FF::adjust_steps]\]\n"
# puts $hp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $steps\]\n"
# puts $fp "run_flow -flow $vars(flow_name)"
if {[file exists $vars(cwd)/.plugins]} {
set ip [open $vars(cwd)/.plugins r]
while {[gets $ip line]>=0} {
puts $fp1 $line
}
close $ip
file delete $vars(cwd)/.plugins
}
close $fp1
close $fp2
if {[info exists vars(partition_list)]} {
if {($vars(design) == [lindex $vars(partition_list) 0]) || $vars(top)} {
set hp [open $vars(script_dir)/.hiersteps.tcl w]
if {$vars(top)} {
set temp [regsub -all "create_flow_step -name init" $vars(flow_steps,flat) "create_flow_step -name top_init"]
set temp2 [regsub -all "create_flow_step -name cts" $temp "create_flow_step -name top_cts"]
set vars(flow_steps,flat) [regsub -all "create_flow_step -name signoff" $temp2 "create_flow_step -name top_signoff"]
}
puts $hp $vars(flow_steps,flat)
if {$vars(top)} {
set top_steps " $steps"
foreach s " init prects cts signoff" {
set temp [regsub " $s" $top_steps " top_$s"]
set top_steps $temp
}
## set temp [regsub "init" [FF::adjust_steps] "top_init"]
# set temp [regsub "init" $steps "top_init"]
# set temp2 [regsub " prects " $temp " top_prects "]
# set temp3 [regsub " cts " $temp2 " top_cts "]
# set top_steps [regsub "signoff" $temp3 "top_signoff"]
puts $hp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $top_steps\]\n"
} else {
# puts $hp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list [FF::adjust_steps]\]\n"
puts $hp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $steps\]\n"
}
close $hp
}
}
unset vars(flow_steps)
}
}
}
"top_down" {
puts $op "VERSION=17.10-p003_1"
puts $op "VPATH=./make"
puts $op "TOOL=$vars(make_tool)"
puts $op "SCRIPTS=$vars(script_dir)"
puts $op "LOG=$vars(log_dir)"
puts $op "ARGS=$vars(make_tool_args)"
puts $op "PARALLEL=-j2"
puts $op "SUBMIT=\"\""
puts $op "TARGET=signoff"
puts $op "FF_STOP=signoff"
puts $op "STEPS = [format "version setup %s do_cleanup" $steps]"
puts $op ""
# puts $op "TOP=`/bin/grep \"^set vars(design)\" $vars(setup_tcl) | /bin/awk ' { printf(\"%s\\n\",\$\$3) } '`"
puts $op "TOP=$vars(design)"
puts $op ""
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op "all: setup model_gen prototype partition_place assign_pin partition blocks.\$(TARGET) top.\$(TARGET) assemble"
} else {
puts $op "all: setup model_gen partition_place assign_pin partition blocks.\$(TARGET) top.\$(TARGET) assemble"
}
} else {
puts $op "all: setup partition_place assign_pin partition blocks.\$(TARGET) top.\$(TARGET) assemble"
}
puts $op ""
puts $op "help:"
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" \$(VERSION) Foundation Flows\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Targets\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" all : Run complete flow (default)\""
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
puts $op "\t@echo \" model_gen : Generate flexmodels\""
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op "\t@echo \" prototype : Flexmodel prototype\""
}
}
puts $op "\t@echo \" partition_place : Initial placement & feedthrough\""
puts $op "\t@echo \" assign_pin : Pin assignment\""
puts $op "\t@echo \" partition : Partition design\""
puts $op "\t@echo \" blocks.<target> : Implement blocks\""
puts $op "\t@echo \" assemble : Assemble design\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Options\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" VPATH : Make directory (default make)\""
puts $op "\t@echo \" SUBMIT : LSF launch command (default '')\""
puts $op "\t@echo \" PARALLEL : Number of machines (default -j2)\""
if {$vars(novus)} {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
} else {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
}
puts $op "\t@echo \" SCRIPTS : Script directory (default $vars(script_dir))\""
puts $op "\t@echo \" LOG : Logfile directory (default $vars(log_dir))\""
puts $op "\t@echo \"===================================================\""
puts $op ""
# puts $op "flow: $vars(config_files)"
# puts $op "\texecute_string"
# puts $op "\t@/bin/touch \$(VPATH)/\$@"
puts $op "assemble: top.\$(TARGET)"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_assemble.tcl -log \$(LOG)/assemble.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/assemble"
puts $op ""
puts $op "top.\$(TARGET) : blocks.\$(TARGET)"
puts $op "\tcd $vars(partition_dir)/\$(TOP); \$(MAKE) -f Makefile FF_STOP=\$(FF_STOP) \$(TARGET) "
puts $op "\t/bin/touch \$(VPATH)/\$@"
puts $op ""
puts $op "blocks.\$(TARGET) : partition"
puts $op "\tcd $vars(partition_dir); VPATH=\$(VPATH); export VPATH; \$(MAKE) \$(PARALLEL) blocks FF_STOP=\$(FF_STOP) TARGET=\$(TARGET)"
puts $op "\t/bin/touch \$(VPATH)/\$@"
puts $op ""
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
puts $op "model_gen : setup"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_model_gen.tcl -log \$(LOG)/model_gen.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/model_gen"
puts $op ""
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op "prototype : model_gen"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_prototype.tcl -log \$(LOG)/prototype.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/prototype"
puts $op ""
puts $op "partition_place : prototype"
} else {
puts $op "partition_place : model_gen"
}
} else {
puts $op "partition_place : setup"
}
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_partition_place.tcl -log \$(LOG)/partition_place.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/partition_place"
puts $op ""
puts $op "assign_pin : partition_place"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_assign_pin.tcl -log \$(LOG)/assign_pin.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/assign_pin"
puts $op ""
puts $op "partition : assign_pin"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_partition.tcl -log \$(LOG)/partition.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/partition"
puts $op ""
puts $op "single:"
puts $op "\t@\$(MAKE) TARGET=single FF_STOP=\$(FF_STOP)"
puts $op ""
puts $op "debug_%:"
puts $op "\texport STEP=\$* ; VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_debug.tcl -log \$(LOG)/\$@.log -win \$(ARGS:-nowin=)"
puts $op ""
puts $op "reset:"
puts $op "\t@/bin/rm -f \$(VPATH)/* $vars(partition_dir)/*/\$(VPATH)/* $vars(partition_dir)/*/\$(VPATH)/.RUNNING"
puts $op ""
puts $op "setup:"
puts $op "#\t/bin/rm -fr $vars(partition_dir) \$(VPATH) LOG"
puts $op "\t/bin/mkdir -p \$(VPATH) LOG"
puts $op "\t/bin/touch \$(VPATH)/setup"
if {$vars(generate_flow_steps) && [info exists vars(flow_steps)]} {
set fp [open run_flow.tcl w]
# puts $fp "source $vars(script_dir)/flow_steps.tcl"
set fp1 [open $vars(script_dir)/flow_config.tcl w]
set fp2 [open $vars(script_dir)/flow_steps.tcl w]
# puts $fp1 "set_db flow_step:assemble .skip_db true"
# puts $fp1 "set_db flow_step:partition .skip_db true"
puts $fp1 "set_db flow_database_directory $vars(dbs_dir)"
puts $fp1 "set_db flow_report_directory $vars(rpt_dir)"
puts $fp1 "set_db flow_log_directory $vars(log_dir)"
puts $fp1 "\nset_db flow_mail_to [exec whoami]"
puts $fp1 "set_db flow_mail_on_error true\n"
foreach p [concat $vars(partition_list) $vars(design)] {
# set vars(flow_name) $p
if {[file exists $vars(partition_dir)/$p/$vars(script_dir)/.hiersteps.tcl]} {
puts $fp2 "#-------------------------- $p --------------------------"
set ip [open $vars(partition_dir)/$p/$vars(script_dir)/.hiersteps.tcl r]
if {$p != $vars(design)} {
while {[gets $ip line]>=0} {
puts $fp2 $line
}
} else {
while {[gets $ip line]>=0} {
if {[regexp "create_flow_step -name top_" $line]} {
puts $fp2 $line
while {[gets $ip line]>=0} {
if {[regexp "^\}" $line]} {
puts $fp2 $line
break
} else {
puts $fp2 $line
}
}
}
}
}
}
if {[file exists $vars(partition_dir)/$p/run_flow.tcl]} {
set ip [open $vars(partition_dir)/$p/run_flow.tcl r]
while {[gets $ip line]>=0} {
puts $fp $line
}
}
if {[info exists vars(partition_dir_pass2)] && [file exists $vars(partition_dir_pass2)/$p/run_flow.tcl]} {
set ip [open $vars(partition_dir_pass2)/$p/run_flow.tcl r]
while {[gets $ip line]>=0} {
puts $fp $line
}
}
}
puts $fp2 "#-------------------------- HIER STEPS --------------------------"
puts $fp2 $vars(flow_steps,hier)
set asteps [FF::adjust_steps]
# set vars(flow_name) $vars(design)
# puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $asteps\]\n"
set psteps [list]
set bsteps [list]
foreach s $asteps {
if {([lsearch $vars(fsteps) $s] != -1) && ($s != "assemble")} {
lappend bsteps $s
} else {
if {$s != "assemble"} {
lappend psteps $s
}
}
}
set vars(flow_name) final_assembly
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list assemble\]\n"
set vars(flow_name) partitioning
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $psteps\]\n"
unset vars(flow_steps)
# set vars(flow_name) $vars(design)
# puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $bsteps\]\n"
if {[file exists $vars(cwd)/.plugins]} {
set ip [open $vars(cwd)/.plugins r]
while {[gets $ip line]>=0} {
puts $fp1 $line
}
close $ip
file delete $vars(cwd)/.plugins
}
if {![info exists vars(run_flow)]} {
puts $fp "source $vars(script_dir)/flow_config.tcl"
set vars(run_flow) DONE
}
close $fp
close $fp1
close $fp2
}
}
"2pass" {
set op1 [open Makefile.pass1 w]
puts $op1 "VERSION=17.10-p003_1"
puts $op1 "VPATH=./make"
puts $op1 "TOOL=$vars(make_tool)"
puts $op1 "SCRIPTS=$vars(script_dir)"
puts $op1 "LOG=$vars(log_dir)"
puts $op1 "ARGS=$vars(make_tool_args)"
puts $op1 "PARALLEL=-j2"
puts $op1 "SUBMIT=\"\""
puts $op1 "TARGET=cts"
puts $op1 "FF_STOP=cts"
puts $op1 "STEPS = [format "version setup %s do_cleanup" $steps]"
puts $op1 ""
# puts $op1 "TOP=`/bin/grep \"^set vars(design)\" $vars(setup_tcl) | /bin/awk ' { printf(\"%s\\n\",\$\$3) } '`"
puts $op1 "TOP=$vars(design)"
puts $op1 ""
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op1 "all: setup prototype model_gen partition_place assign_pin partition blocks.\$(TARGET) top.\$(TARGET)"
} else {
puts $op1 "all: setup model_gen partition_place assign_pin partition blocks.\$(TARGET) top.\$(TARGET)"
}
} else {
puts $op1 "all: setup partition_place assign_pin partition blocks.\$(TARGET) top.\$(TARGET)"
}
puts $op1 "\t@echo \" Makefile Targets\""
puts $op1 "\t@echo \"===================================================\""
puts $op1 "\t@echo \" all : Run complete flow (default)\""
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op "\t@echo \" prototype : Flexmodel prototype\""
}
puts $op "\t@echo \" model_gen : Generate flexmodels\""
}
puts $op1 "\t@echo \" partition_place : Initial placement & feedthrough\""
puts $op1 "\t@echo \" assign_pin : Pin assignment\""
puts $op1 "\t@echo \" partition : Partition design\""
puts $op1 "\t@echo \" blocks.<target> : Implement blocks\""
if {$vars(enable_flexilm)} {
puts $op1 "\t@echo \" flexilm : PreCTS DLM flow\""
} else {
puts $op1 "\t@echo \" rebudget : Rebudget constraints\""
}
puts $op1 "\t@echo \"===================================================\""
puts $op1 "\t@echo \" Makefile Options\""
puts $op1 "\t@echo \"===================================================\""
puts $op1 "\t@echo \" VPATH : Make directory (default make)\""
puts $op1 "\t@echo \" SUBMIT : LSF launch command (default '')\""
puts $op1 "\t@echo \" PARALLEL : Number of machines (default -j2)\""
if {$vars(novus)} {
puts $op1 "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op1 "\t@echo \" ARGS : INNOVUS arguments (default -novus_ui -64)\""
} else {
puts $op1 "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op1 "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
}
puts $op1 "\t@echo \" SCRIPTS : Script directory (default $vars(script_dir))\""
puts $op1 "\t@echo \" LOG : Logfile directory (default $vars(log_dir))\""
puts $op1 "\t@echo \"===================================================\""
puts $op1 ""
# puts $op1 "flow: $vars(config_files)"
# puts $op1 "\texecute_string"
# puts $op1 "\t@/bin/touch \$(VPATH)/\$@"
puts $op1 "top.\$(TARGET) : blocks.\$(TARGET)"
puts $op1 "\tcd $vars(partition_dir)/\$(TOP); \$(MAKE) -f Makefile FF_STOP=\$(FF_STOP) \$(TARGET) "
puts $op1 "\t/bin/touch \$(VPATH)/\$@"
puts $op1 ""
puts $op1 "blocks.\$(TARGET) : partition"
puts $op1 "\tcd $vars(partition_dir); VPATH=\$(VPATH); export VPATH; \$(MAKE) \$(PARALLEL) blocks FF_STOP=\$(FF_STOP) TARGET=\$(TARGET)"
puts $op1 "\t/bin/touch \$(VPATH)/\$@"
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op1 "prototype : setup"
puts $op1 "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_prototype.tcl -log \$(LOG)/prototype.log -overwrite"
puts $op1 "\t/bin/touch \$(VPATH)/prototype"
puts $op1 ""
puts $op1 "model_gen : prototype"
} else {
puts $op1 "model_gen : setup"
}
puts $op1 "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_model_gen.tcl -log \$(LOG)/model_gen.log -overwrite"
puts $op1 "\t/bin/touch \$(VPATH)/model_gen"
puts $op1 ""
puts $op1 "partition_place : model_gen"
} else {
puts $op1 "partition_place : setup"
}
puts $op1 "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_partition_place.tcl -log \$(LOG)/partition_place.log -overwrite"
puts $op1 "\t/bin/touch \$(VPATH)/partition_place"
puts $op1 ""
puts $op1 "assign_pin : partition_place"
puts $op1 "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_assign_pin.tcl -log \$(LOG)/assign_pin.log -overwrite"
puts $op1 "\t/bin/touch \$(VPATH)/assign_pin"
puts $op1 ""
puts $op1 "partition : assign_pin"
puts $op1 "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_partition.tcl -log \$(LOG)/partition.log -overwrite"
puts $op1 "\t/bin/touch \$(VPATH)/partition"
puts $op1 ""
puts $op1 "single:"
puts $op1 "\t@\$(MAKE) TARGET=single FF_STOP=\$(FF_STOP)"
puts $op1 ""
puts $op1 "debug_%:"
puts $op1 "\texport STEP=\$* ; VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_debug.tcl -log \$(LOG)/\$@.log -win \$(ARGS:-nowin=)"
puts $op1 ""
puts $op1 "reset:"
puts $op1 "\t@/bin/rm -f \$(VPATH)/* $vars(partition_dir)/*/\$(VPATH)/* $vars(partition_dir)/*/\$(VPATH)/.RUNNING"
puts $op1 ""
puts $op1 "setup:"
puts $op1 "#\t/bin/rm -fr $vars(partition_dir) \$(VPATH) LOG"
puts $op1 "\t/bin/mkdir -p \$(VPATH) LOG"
puts $op1 "\t/bin/touch \$(VPATH)/setup"
close $op1
set op2 [open Makefile.pass2 w]
puts $op2 "VERSION=17.10-p003_1"
puts $op2 "VPATH=./make"
puts $op2 "TOOL=$vars(make_tool)"
puts $op2 "SCRIPTS=$vars(script_dir)"
puts $op2 "LOG=$vars(log_dir)"
puts $op2 "ARGS=$vars(make_tool_args)"
puts $op2 "PARALLEL=-j2"
puts $op2 "SUBMIT=\"\""
puts $op2 "TARGET=signoff"
puts $op2 "FF_STOP=signoff"
puts $op2 "STEPS = [format "version setup %s do_cleanup" $steps]"
puts $op2 ""
# puts $op2 "TOP=`/bin/grep \"^set vars(design)\" $vars(setup_tcl) | /bin/awk ' { printf(\"%s\\n\",\$\$3) } '`"
puts $op2 "TOP=$vars(design)"
puts $op2 ""
if {$vars(enable_flexilm)} {
puts $op2 "all: setup rebudget blocks.\$(TARGET) top.\$(TARGET) assemble"
} else {
puts $op2 "all: setup rebudget blocks.\$(TARGET) top.\$(TARGET) assemble"
}
puts $op2 ""
puts $op2 "help:"
puts $op2 "\t@echo \"===================================================\""
puts $op2 "\t@echo \" \$(VERSION) Foundation Flows\""
puts $op2 "\t@echo \"===================================================\""
puts $op2 "\t@echo \" Makefile Targets\""
puts $op2 "\t@echo \"===================================================\""
puts $op2 "\t@echo \" all : Run complete flow (default)\""
if {$vars(enable_flexilm)} {
puts $op2 "\t@echo \" rebudget : Rebudget design\""
}
puts $op2 "\t@echo \" blocks.<target> : Implement blocks\""
puts $op2 "\t@echo \" assemble : Assemble design\""
puts $op2 "\t@echo \"===================================================\""
puts $op2 "\t@echo \" Makefile Options\""
puts $op2 "\t@echo \"===================================================\""
puts $op2 "\t@echo \" VPATH : Make directory (default make)\""
puts $op2 "\t@echo \" SUBMIT : LSF launch command (default '')\""
puts $op2 "\t@echo \" PARALLEL : Number of machines (default -j2)\""
if {$vars(novus)} {
puts $op2 "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op2 "\t@echo \" ARGS : INNOVUS arguments (default -novus_ui -64)\""
} else {
puts $op2 "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op2 "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
}
puts $op2 "\t@echo \" SCRIPTS : Script directory (default $vars(script_dir))\""
puts $op2 "\t@echo \" LOG : Logfile directory (default $vars(log_dir))\""
puts $op2 "\t@echo \"===================================================\""
puts $op2 ""
# puts $op2 "flow: $vars(config_files)"
# puts $op2 "\texecute_string"
# puts $op2 "\t@/bin/touch \$(VPATH)/\$@"
puts $op2 "assemble: top.\$(TARGET)"
puts $op2 "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_assemble.tcl -log \$(LOG)/assemble.log -overwrite"
puts $op2 "\t/bin/touch \$(VPATH)/assemble"
puts $op2 ""
puts $op2 "top.\$(TARGET) : blocks.\$(TARGET)"
puts $op2 "\tcd $vars(partition_dir_pass2)/\$(TOP); \$(MAKE) -f Makefile FF_STOP=\$(FF_STOP) \$(TARGET) "
puts $op2 "\t/bin/touch \$(VPATH)/\$@"
puts $op2 ""
puts $op2 "blocks.\$(TARGET) : rebudget"
puts $op2 "\tcd $vars(partition_dir_pass2); VPATH=\$(VPATH); export VPATH; \$(MAKE) \$(PARALLEL) blocks FF_STOP=\$(FF_STOP) TARGET=\$(TARGET)"
puts $op2 "\t/bin/touch \$(VPATH)/\$@"
puts $op2 ""
puts $op1 "rebudget : top.cts"
puts $op1 "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_rebudget.tcl -log \$(LOG)/rebudget.log -overwrite"
puts $op1 "\t/bin/touch \$(VPATH)/rebudget"
puts $op1 ""
puts $op2 "single:"
puts $op2 "\t@\$(MAKE) TARGET=single FF_STOP=\$(FF_STOP)"
puts $op2 ""
puts $op2 "debug_%:"
puts $op2 "\texport STEP=\$* ; VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_debug.tcl -log \$(LOG)/\$@.log -win \$(ARGS:-nowin=)"
puts $op2 ""
puts $op2 "reset:"
puts $op2 "\t@/bin/rm -f \$(VPATH)/* $vars(partition_dir_pass2)/*/\$(VPATH)/* $vars(partition_dir_pass2)/*/\$(VPATH)/.RUNNING"
puts $op2 ""
puts $op2 "setup:"
puts $op2 "#\t/bin/rm -fr $vars(partition_dir_pass2) \$(VPATH) LOG"
puts $op2 "\t/bin/mkdir -p \$(VPATH) LOG"
close $op2
puts $op "include Makefile.pass1"
puts $op "include Makefile.pass2"
if {$vars(generate_flow_steps) && [info exists vars(flow_steps)]} {
set fp1 [open $vars(script_dir)/flow_config.tcl w]
set fp2 [open $vars(script_dir)/flow_steps.tcl w]
puts $fp1 "set_db flow_database_directory $vars(dbs_dir)"
puts $fp1 "set_db flow_report_directory $vars(rpt_dir)"
puts $fp1 "set_db flow_log_directory $vars(log_dir)"
puts $fp1 "\nset_db flow_mail_to [exec whoami]"
puts $fp1 "set_db flow_mail_on_error true\n"
# puts $fp $vars(flow_steps)
foreach p [concat $vars(partition_list) $vars(design)] {
# set vars(flow_name) $p
if {[file exists $vars(partition_dir)/$p/$vars(script_dir)/.hiersteps.tcl]} {
# puts $fp2 "#-------------------------- $p --------------------------"
set ip [open $vars(partition_dir)/$p/$vars(script_dir)/.hiersteps.tcl r]
if {$p != $vars(design)} {
while {[gets $ip line]>=0} {
puts $fp2 $line
}
} else {
while {[gets $ip line]>=0} {
if {[regexp "create_flow_step -name top_" $line]} {
puts $fp2 $line
while {[gets $ip line]>=0} {
if {[regexp "^\}" $line]} {
puts $fp2 $line
break
} else {
puts $fp2 $line
}
}
}
}
}
}
if {[file exists $vars(partition_dir)/$p/run_flow.tcl]} {
set ip [open $vars(partition_dir)/$p/run_flow.tcl r]
while {[gets $ip line]>=0} {
puts $fp $line
}
}
if {[info exists vars(partition_dir_pass2)] && [file exists $vars(partition_dir_pass2)/$p/run_flow.tcl]} {
set ip [open $vars(partition_dir_pass2)/$p/run_flow.tcl r]
while {[gets $ip line]>=0} {
puts $fp $line
}
}
}
puts $fp2 "#-------------------------- HIER STEPS --------------------------"
puts $fp2 $vars(flow_steps,hier)
set vars(flow_name) $vars(design)
set asteps [FF::adjust_steps]
# puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $asteps\]\n"
set psteps [list]
set bsteps [list]
foreach s $asteps {
if {([lsearch $vars(fsteps) $s] != -1) && ($s != "assemble")} {
lappend bsteps $s
} else {
if {$s != "assemble"} {
lappend psteps $s
}
}
}
set vars(flow_name) final_assembly
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list assemble\]\n"
set vars(flow_name) partitioning
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $psteps\]\n"
# puts $fp "run_flow -flow $vars(flow_name)"
unset vars(flow_steps)
# set vars(flow_name) $vars(design)
# puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $bsteps\]\n"
if {[file exists $vars(cwd)/.plugins]} {
set ip [open $vars(cwd)/.plugins r]
while {[gets $ip line]>=0} {
puts $fp1 $line
}
close $ip
file delete $vars(cwd)/.plugins
}
close $fp
close $fp1
close $fp2
}
}
"flexilm" {
puts $op "VERSION=17.10-p003_1"
puts $op "VPATH=./make"
puts $op "TOOL=$vars(make_tool)"
puts $op "SCRIPTS=FF"
puts $op "LOG=LOG"
puts $op "ARGS=$vars(make_tool_args)"
puts $op "PARALLEL=-j2"
puts $op "SUBMIT=\"\""
puts $op "TARGET=assemble"
puts $op "FF_STOP=assemble"
puts $op "STEPS = version setup do_cleanup"
puts $op ""
# puts $op "TOP=`/bin/grep \"^set vars(design)\" $vars(setup_tcl) | /bin/awk ' { printf(\"%s\\n\",\$\$3) } '`"
puts $op "TOP=$vars(design)"
puts $op ""
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op "all: setup prototype model_gen partition_place assign_pin partition blocks.prects top.prects assemble_flexilm blocks.signoff top.signoff assemble"
} else {
puts $op "all: setup model_gen partition_place assign_pin partition blocks.prects top.prects assemble_flexilm blocks.signoff top.signoff assemble"
}
} else {
puts $op "all: setup partition_place assign_pin partition blocks.prects top.prects assemble_flexilm blocks.signoff top.signoff assemble"
}
puts $op ""
puts $op "help:"
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" \$(VERSION) Foundation Flows\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Targets\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" all : Run complete flow (default)\""
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op "\t@echo \" prototype : Flexmodel prototype\""
}
puts $op "\t@echo \" model_gen : Generate flexmodels\""
}
puts $op "\t@echo \" partition_place : Initial placement & feedthrough\""
puts $op "\t@echo \" assign_pin : Pin assignment\""
puts $op "\t@echo \" partition : Partition design\""
puts $op "\t@echo \" block.prects : Implement blocks to preCTS and generate flexIlm\""
puts $op "\t@echo \" top.prects : flexIlm prects optimization and flexIlm ECO\""
puts $op "\t@echo \" assemble_flexilm : Check assembled preCTS timing\""
puts $op "\t@echo \" block.signoff : implement blocks\""
puts $op "\t@echo \" top.signoff : implement top\""
puts $op "\t@echo \" assemble : final chip assembly\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" Makefile Options\""
puts $op "\t@echo \"===================================================\""
puts $op "\t@echo \" VPATH : Make directory (default make)\""
puts $op "\t@echo \" SUBMIT : LSF launch command (default '')\""
puts $op "\t@echo \" PARALLEL : Number of machines (default -j2)\""
if {$vars(novus)} {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -novus_ui -64)\""
} else {
puts $op "\t@echo \" TOOL : INNOVUS executable (default innovus)\""
puts $op "\t@echo \" ARGS : INNOVUS arguments (default -nowin -64)\""
}
puts $op "\t@echo \" SCRIPTS : Script directory (default FF)\""
puts $op "\t@echo \" LOG : Logfile directory (default LOG)\""
puts $op "\t@echo \"===================================================\""
puts $op "assemble: top.signoff"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_assemble.tcl -log \$(LOG)/assemble.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/assemble"
puts $op ""
puts $op "top.signoff : blocks.signoff"
puts $op "\tcd PARTITION_PRECTS/\$(TOP); \$(MAKE) -f Makefile FF_STOP=signoff signoff"
puts $op " /bin/touch \$(VPATH)/\$@"
puts $op ""
puts $op "blocks.signoff : assemble_flexilm"
puts $op "\tcd PARTITION_PRECTS; VPATH=\$(VPATH); export VPATH; \$(MAKE) \$(PARALLEL) blocks FF_STOP=signoff TARGET=signoff"
puts $op " /bin/touch \$(VPATH)/\$@"
puts $op ""
puts $op "assemble_flexilm : top.prects"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_assemble_flexilm.tcl -log \$(LOG)/assemble_flexilm.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/assemble_flexilm"
puts $op ""
puts $op "top.prects : blocks.prects"
if {$vars(place_opt_design)} {
puts $op "\tcd PARTITION/\$(TOP); \$(MAKE) -f Makefile FF_STOP=place place "
} else {
puts $op "\tcd PARTITION/\$(TOP); \$(MAKE) -f Makefile FF_STOP=prects prects "
}
puts $op "\t/bin/touch \$(VPATH)/\$@"
puts $op "\t/bin/cp -rf PARTITION_FLEXILM/* PARTITION_PRECTS"
puts $op "\t/bin/rm -rf PARTITION_FLEXILM"
puts $op ""
puts $op "blocks.prects : partition"
if {$vars(place_opt_design)} {
puts $op "\tcd PARTITION; VPATH=\$(VPATH); export VPATH; \$(MAKE) \$(PARALLEL) blocks FF_STOP=place TARGET=place"
} else {
puts $op "\tcd PARTITION; VPATH=\$(VPATH); export VPATH; \$(MAKE) \$(PARALLEL) blocks FF_STOP=prects TARGET=prects"
}
puts $op "\t/bin/touch \$(VPATH)/\$@"
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
puts $op "prototype : setup"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_prototype.tcl -log \$(LOG)/prototype.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/prototype"
puts $op ""
puts $op "model_gen : prototype"
} else {
puts $op "model_gen : setup"
}
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_model_gen.tcl -log \$(LOG)/model_gen.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/model_gen"
puts $op ""
puts $op "partition_place : model_gen"
} else {
puts $op "partition_place : setup"
}
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_partition_place.tcl -log \$(LOG)/partition_place.log -overwrite"
puts $op "\t/bin/touch \$(VPATH)/partition_place"
puts $op ""
puts $op "assign_pin : partition_place"
puts $op " VPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_assign_pin.tcl -log \$(LOG)/assign_pin.log -overwrite"
puts $op " /bin/touch \$(VPATH)/assign_pin"
puts $op ""
puts $op "partition : assign_pin"
puts $op "\tVPATH=\$(VPATH); export VPATH; \$(TOOL) \$(ARGS) -init \$(SCRIPTS)/INNOVUS/run_partition.tcl -log \$(LOG)/partition.log -overwrite"
puts $op " /bin/touch \$(VPATH)/partition"
puts $op ""
puts $op "single:"
puts $op "\t@\$(MAKE) TARGET=single FF_STOP=signoff"
puts $op ""
puts $op "debug_%:"
puts $op "\texport STEP=\$* ; VPATH=\$(VPATH); export VPATH; \$(TOOL) -init \$(SCRIPTS)/INNOVUS/run_debug.tcl -log \$(LOG)/\$@.log -win \$(ARGS:-nowin=)"
puts $op ""
puts $op "reset:"
puts $op "\t@/bin/rm -f \$(VPATH)/* PARTITION/*/\$(VPATH)/* PARTITION/*/\$(VPATH)/.RUNNING"
puts $op "\t@/bin/rm -f \$(VPATH)/* PARTITION_PRECTS/*/\$(VPATH)/* PARTITION_PRECTS/*/\$(VPATH)/.RUNNING"
puts $op ""
puts $op "setup:"
puts $op "#\t/bin/rm -fr PARTITION \$(VPATH) LOG"
puts $op "\t/bin/mkdir -p \$(VPATH) LOG"
puts $op "\t/bin/touch \$(VPATH)/setup"
if {$vars(generate_flow_steps) && [info exists vars(flow_steps)]} {
set fp [open run_flow.tcl w]
if {![info exists vars(run_flow)]} {
# puts $fp "source $vars(script_dir)/flow_steps.tcl"
puts $fp "source $vars(script_dir)/flow_config.tcl"
set vars(run_flow) DONE
}
set fp1 [open $vars(script_dir)/flow_config.tcl w]
set fp2 [open $vars(script_dir)/flow_steps.tcl w]
puts $fp1 "set_db flow_database_directory $vars(dbs_dir)"
puts $fp1 "set_db flow_report_directory $vars(rpt_dir)"
puts $fp1 "set_db flow_log_directory $vars(log_dir)"
puts $fp1 "\nset_db flow_mail_to [exec whoami]"
puts $fp1 "set_db flow_mail_on_error true\n"
# puts $fp $vars(flow_steps)
foreach p [concat $vars(partition_list) $vars(design)] {
# set vars(flow_name) $p
if {[file exists $vars(partition_dir)/$p/$vars(script_dir)/.hiersteps.tcl]} {
# puts $fp2 "#-------------------------- $p --------------------------"
set ip [open $vars(partition_dir)/$p/$vars(script_dir)/.hiersteps.tcl r]
if {$p != $vars(design)} {
while {[gets $ip line]>=0} {
puts $fp2 $line
}
} else {
while {[gets $ip line]>=0} {
if {[regexp "create_flow_step -name top_" $line]} {
puts $fp2 $line
while {[gets $ip line]>=0} {
if {[regexp "^\}" $line]} {
puts $fp2 $line
break
} else {
puts $fp2 $line
}
}
}
}
}
}
if {[file exists $vars(partition_dir)/$p/run_flow.tcl]} {
set ip [open $vars(partition_dir)/$p/run_flow.tcl r]
while {[gets $ip line]>=0} {
puts $fp $line
}
}
if {[info exists vars(partition_dir_pass2)] && [file exists $vars(partition_dir_pass2)/$p/run_flow.tcl]} {
set ip [open $vars(partition_dir_pass2)/$p/run_flow.tcl r]
while {[gets $ip line]>=0} {
puts $fp $line
}
}
}
puts $fp2 "#-------------------------- HIER STEPS --------------------------"
puts $fp2 $vars(flow_steps,hier)
set vars(flow_name) $vars(design)
set asteps [FF::adjust_steps]
# puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $asteps\]\n"
set psteps [list]
set bsteps [list]
foreach s $asteps {
if {([lsearch $vars(fsteps) $s] != -1) && ($s != "assemble")} {
lappend bsteps $s
} else {
if {![regexp "^assemble" $s]} {
lappend psteps $s
}
}
}
set vars(flow_name) intermediate_assembly
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list assemble_flexilm\]\n"
set vars(flow_name) final_assembly
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list assemble\]\n"
set vars(flow_name) partitioning
puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $psteps\]\n"
# puts $fp "run_flow -flow $vars(flow_name)"
unset vars(flow_steps)
# set vars(flow_name) $vars(design)
# puts $fp "create_flow \\\n -name $vars(flow_name)\\\n -tool $vars(make_tool)\\\n -tool_options {-log $vars(flow_name).log}\\\n \[list $bsteps\]\n"
if {[file exists $vars(cwd)/.plugins]} {
set ip [open $vars(cwd)/.plugins r]
while {[gets $ip line]>=0} {
puts $fp1 $line
}
close $ip
file delete $vars(cwd)/.plugins
}
close $fp
close $fp1
close $fp2
}
}
}
close $op
}
proc set_steps {mode format} {
#
# Sets the vars() array based on the mode/format passed in
#
global vars
global errors
if {$mode == "hier" } {
set mode "top_down"
if {$vars(hier_flow_type) == "2pass"} {
set mode "2pass"
}
}
switch $mode {
"user" {
if {![info exists vars(steps)]} {
puts "<FF> ERROR: For user mode, vars(steps) must be provided"
exit
}
}
"flat" {
set vars(steps) [list "init" "place" "prects" "cts" "postcts" \
"postcts_hold" "route" "postroute" \
"postroute_hold" "postroute_si_hold" \
"postroute_si" "signoff"]
if {$vars(preroute_opt_design)} {
set vars(steps) [lreplace $vars(steps) [lsearch $vars(steps) "place"] [lsearch $vars(steps) "cts"] preroute]
}
# if {$vars(route_opt_design)} {
# set vars(steps) [lreplace $vars(steps) [lsearch $vars(steps) "route"] [lsearch $vars(steps) "postroute"] route_opt_design]
# }
if $vars(rc) {
if {$vars(enable_rcp)} {
set vars(steps) [concat "syn_map" "syn_incr" "syn_place" $vars(steps)]
} else {
set vars(steps) [concat "syn_map" "syn_incr" $vars(steps)]
}
}
}
"top_down" {
set vars(steps) [list "partition_place" "assign_pin" "partition" "init" "place" "prects" \
"cts" "postcts" "postcts_hold" "route" \
"postroute" "postroute_hold" \
"postroute_si_hold" "postroute_si" \
"signoff" "assemble"]
set vars(hsteps) [list "assemble" "partition_place" "assign_pin" "partition"]
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
# Insert the model_gen step before partition_place
foreach varname {steps hsteps} {
set old $vars($varname)
set vars($varname) [linsert $old [lsearch $old "partition_place"] "model_gen"]
}
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
# Insert the prototype step before partition_place
foreach varname {steps hsteps} {
set old $vars($varname)
set vars($varname) [linsert $old [lsearch $old "partition_place"] "prototype"]
}
}
}
set vars(fsteps) [list "init" "place" "prects" "cts" "postcts" \
"postcts_hold" "route" "postroute" \
"postroute_hold" "postroute_si_hold" \
"postroute_si" "signoff"]
}
"1pass" {
set vars(steps) [list "partition_place" "assign_pin" "partition" "init" "place" "prects" \
"cts" "postcts" "postcts_hold" "route" \
"postroute" "postroute_hold" \
"postroute_si_hold" "postroute_si" \
"signoff" "assemble"]
set vars(hsteps) [list "assemble" "partition_place" "assign_pin" "partition"]
set vars(fsteps) [list "init" "place" "prects" "cts" "postcts" \
"postcts_hold" "route" "postroute" \
"postroute_hold" "postroute_si_hold" \
"postroute_si" "signoff"]
}
"2pass" {
if {$vars(enable_flexilm)} {
set vars(steps) [list "partition_place" "assign_pin" "partition" "init" "place" "prects" "assemble_flexilm" \
"cts" "postcts" "postcts_hold" "route" \
"postroute" "postroute_hold" \
"postroute_si_hold" "postroute_si" \
"signoff" "assemble"]
set vars(hsteps) [list "assemble" "assemble_flexilm" "partition_place" "assign_pin" "partition"]
} else {
set vars(steps) [list "partition_place" "assign_pin" "partition" "init" "place" "prects" \
"cts" "rebudget" "postcts" "postcts_hold" "route" \
"postroute" "postroute_hold" \
"postroute_si_hold" "postroute_si" \
"signoff" "assemble"]
set vars(hsteps) [list "assemble" "rebudget" "partition_place" "assign_pin" "partition"]
}
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
# Insert the model_gen step before partition_place
foreach varname {steps hsteps} {
set old $vars($varname)
set vars($varname) [linsert $old [lsearch $old "partition_place"] "model_gen"]
}
if {[info exists vars(flexmodel_prototype)] && $vars(flexmodel_prototype)} {
# Insert the prototype step before partition_place
foreach varname {steps hsteps} {
set old $vars($varname)
set vars($varname) [linsert $old [lsearch $old "partition_place"] "prototype"]
}
}
}
set vars(fsteps) [list "init" "place" "prects" "cts" "postcts" \
"postcts_hold" "route" "postroute" \
"postroute_hold" "postroute_si_hold" \
"postroute_si" "signoff"]
}
"bottom_up" {
set vars(steps) [list "init" "place" "prects" "cts" "postcts" \
"postcts_hold" "route" "postroute" \
"postroute_hold" "postroute_si_hold" \
"postroute_si" "signoff" "assemble"]
set vars(hsteps) [list "assemble"]
set vars(fsteps) [list "init" "place" "prects" "cts" "postcts" \
"postcts_hold" "route" "postroute" \
"postroute_hold" "postroute_si_hold" \
"postroute_si" "signoff"]
}
"default" {
puts "Internal error: Unknown mode \"$vars(mode)\". Aborting."
exit -111
}
}
if {!$vars(enable_celtic_steps) } {
foreach step [list "postroute_si" "postroute_si_hold"] {
set index [lsearch $vars(steps) $step]
if {$index != -1} {
set vars(steps) [lreplace $vars(steps) $index $index]
}
}
}
}
proc flatten_curlies_in_list list {string map {\{ "" \} ""} $list}
#
# gen_incr_filename(scriptNameBase)
# Buda Leung, 11/2011
# args:
# $scriptNameBase: <path>/basename of dir
# @return: new base name
#
# Description: Generates a new output file name using the input
# argument as a basename. This proc looks for all files in the
# same directory as the argument with a matching basename.
# It then looks for a trailing integer suffix, and compares
# all matching files to find the largest integer.
# It returns a new file name of the form <path>/<basename><largest int + 1>
#
# Example Usage: input argument setup.tcl
# files in dir: setup.tcl setup.tcl1
# @return: setup.tcl2
#
proc gen_incr_filename {scriptNameBase} {
set file_list [glob -nocomplain [set scriptNameBase]*]
if {[llength $file_list] > 0} {
set highNum 1
foreach file $file_list {
set re "[set scriptNameBase](\[\[:digit:\]\]+)\$"
if {[regexp $re $file full num]} {
if {$num >= $highNum} {
set highNum [incr num]
}
}
}
set scriptName $scriptNameBase$highNum
} else {
set scriptName "[set scriptNameBase]"
}
return $scriptName
}
#
# gen_new_rundir {args}
# Buda Leung, 11/2011
# args:
# -dir <string>: dir name to change
# -style [increment|date|custom]: naming style to use [increment|date|custom]
# -date_style <string> (required when style=date): tcl commands to create a date string
# -custom <string> (optional): a custom string to prepend or postpend to the dir
# -name_change_order [prefix|suffix] (required when customString is defined): [prefix|suffix]
# @return: new dir name
#
# Description: Generates a new directory name based on the basename
# and options provided. The options allowed are:
#
# style:
# * increment: add an integer to the rundir based on dirs found in [dirname $dir]
# * date: add a date string to the rundir name, using vars(date_style) to control the formatting
# * custom: add a custom string to the rundir name
# nameChangeOrder:
# * prefix: add the custom string to the beginning of the rundir
# * suffix: add the custom string to the end of the rundir
#
# NOTE: increment, date, and custom are mutually exclusive options
#
# Example Usage:
# gen_new_rundir work/run increment
# (dirs with matching basename : work/run1 work/run2)
# @return: work/run3
#
# gen_new_rundir work/run date
# @return: work/run_2011-11-23_12_09_58
#
# gen_new_rundir work/run custom rcp_high_eff prefix
# @return: work/rcp_high_eff_run
proc gen_new_rundir {argv} {
global vars
global dargs
global fargs
#
# Proc defaults
# Note that defaults live in the default_setup.tcl, but when gen_new_rundir is called, that setup.tcl has not yet been loaded
# These defaults must stay synchronized to the default_setup.tcl vars() equivalents
#
set def_date_style "\[clock format \[clock seconds\] -format \"%Y-%m-%d_%H_%M_%S\" \]"
# Use the following if you want a custom prefix/suffix added to the rundir
set def_custom_rundir_name_append ""
# vars(rundir_namechange_method) [prefix|suffix]
set def_rundir_namechange_method "suffix"
#
# Arg processing
#
while {[llength $argv] > 0} {
set option [lindex $argv 0]
set argv [lreplace $argv 0 0]
switch -regexp -- $option {
^-(d|-dir)$ {
set dash_d_script_dir [lindex $argv 0]
set argv [lreplace $argv 0 0]
}
^-(y|-style)$ {
set dash_y_style_type [lindex $argv 0]
set argv [lreplace $argv 0 0]
}
^-(u|-rundir)$ {
set dash_u_rundir_base [lindex $argv 0]
set argv [lreplace $argv 0 0]
}
}
} ; # end while (processing args)
set dbgMsg "<FF-INT> gen_new_rundir(): "
#
# Load vars. This will overwrite any FF defaults, but not the -u/-y options
# Only looking for the following:
# vars(rundir_base) (-u takes precedence)
# vars(rundir) - overrides vars(rundir_base) and -u/-y
# vars(auto_increment_rundir_style) (-y takes precedence)
# vars(date_style) (no gen_innovus_flow.tcl option)
# vars(custom_rundir_name_append) (no gen_innovus_flow.tcl option)
# vars(rundir_namechange_method) (no gen_innovus_flow.tcl option)
#
FF_NOVUS::execute_flow "source_only" true ""
# NOTE: after the above executes, dargs and fargs have all been analyzed, and vars exist for all those entries
# in other words, we no longer care about dargs(rundir), only vars(rundir)...
# In case the user defined these in their setup.tcl
if {![info exists vars(date_style)]} {
set date_style $def_date_style
}
if {![info exists vars(custom_rundir_name_append)]} {
set vars(custom_rundir_name_append) $def_custom_rundir_name_append
}
if {![info exists vars(rundir_namechange_method)]} {
set vars(rundir_namechange_method) $def_rundir_namechange_method
}
#
# Set the rundir original name
# Priority:
# 1) vars(rundir)
# 2) dash_u_rundir_base
# 3) vars(rundir_base)
# 4) def_rundir
# if vars(rundir) eq dargs(rundir), then basically the user has not specified a vars(rundir), or they set it to .
# use file normalize to handle "./" vs "."
if {[file normalize $vars(rundir)] eq [file normalize $dargs(rundir)]} {
if {![info exists dash_u_rundir_base]} {
if {![info exists vars(rundir_base)]} {
set rundir_origname $dargs(rundir)
} else {
set rundir_origname $vars(rundir_base)
}
} else {
if {[info exists vars(rundir_base)] && $vars(rundir_base) ne $dash_u_rundir_base} {
# Conflict between -u and setup.tcl. -u wins
puts "<FF> WARNING \"-u $dash_u_rundir_base\" overriding config variable vars(rundir_base) ($vars(rundir_base))"
puts " To prevent this behavior, do not use the \"-u\" option (FF will use vars(rundir_base) from your config file)."
}
set rundir_origname $dash_u_rundir_base
}
} else {
# The following handle conflicts between vars(rundir) and -u or vars(rundir_base)
if {[info exists dash_u_rundir_base]} {
if {$vars(rundir) ne $dargs(rundir) && $vars(rundir) ne $dash_u_rundir_base} {
puts "<FF> WARNING vars(rundir) \"$vars(rundir)\" overriding \"-u $dash_u_rundir_base\" option."
puts " To prevent this behavior, do not set vars(rundir) in your config file."
} elseif {[info exists vars(rundir_base)]} {
puts "<FF> WARNING vars(rundir) \"$vars(rundir)\" overriding config variable vars(rundir_base) \"$vars(rundir_base)\""
puts " To prevent this behavior, do not set vars(rundir) in your config file."
}
}
set rundir_origname $vars(rundir)
}
#
# Set the rundir naming style
# Priority:
# 1) vars(auto_increment_rundir_style)
# 2) dash_y_style_type
# 3) def_auto_increment_rundir_style
if {![info exists vars(auto_increment_rundir_style)]} {
if {![info exists dash_y_style_type]} {
set styleType $dargs(style)
} else {
set styleType $dash_y_style_type
}
} else {
# vars(auto_increment_rundir_style) was set in the setup.tcl
if {[info exists dash_y_style_type] && $dash_y_style_type ne $vars(auto_increment_rundir_style)} {
# Conflict between -y and setup.tcl. -y wins
puts "<FF> WARNING \"-y $dash_y_style_type\" overriding config variable vars(auto_increment_rundir_style) ($vars(auto_increment_rundir_style))"
puts " To prevent this behavior, do not use the \"-y\" option (FF will use vars(auto_increment_rundir_style) from your config file)."
set styleType $dash_y_style_type
} else {
set styleType $vars(auto_increment_rundir_style)
}
}
#
# If increment is specified, -u / vars(rundir) is required ; otherwise error and exit:
#
if {$styleType eq "increment" && ([file tail $rundir_origname] eq "" || [file normalize $rundir_origname] eq [file normalize .])} {
puts "<FF> ERROR: Rundir naming style was set to \"increment\", but rundir evaluated to \".\" due to:"
if {[info exists vars(rundir)] && [file normalize $vars(rundir)] eq [file normalize .]} {
puts " setting vars(rundir) to \"$vars(rundir)\" in your configuration file."
} elseif {[info exists dash_u_rundir_base] && [file normalize $dash_u_rundir_base] eq [file normalize .]} {
puts " the \"-u\" $dash_u_rundir_base argument to gen_innovus_flow.tcl"
} elseif {[info exists vars(rundir_base)] && [file normalize $vars(rundir_base)] eq [file normalize .]} {
puts " setting vars(rundir_base) to \"$vars(rundir_base)\" in your configuration file."
} else {
puts " the default rundir setting which is \"$def_rundir\""
}
puts " To prevent this error, use the -u argument to specify a rundir base, or specify a vars(rundir_base) in your setup.tcl"
exit 99
}
#
# Generate new rundir if valid style defined
#
# -date_style <string> (required when style=date): tcl commands to create a date string
# -custom <string> (optional): a custom string to prepend or postpend to the dir
# -name_change_order [prefix|suffix] (required when customString is defined): [prefix|suffix]
# Remove any "//" in the path
regsub -all {\/\/} $rundir_origname {/} rundir_origname
set rundir_basename [file tail $rundir_origname]
set rundir_dirname [file dirname $rundir_origname]
if {$styleType ne "none"} {
switch -exact -- $styleType {
date {
if {$vars(rundir_namechange_method) eq "prefix"} {
set new_basename [subst $date_style]_${rundir_basename}
} elseif {$vars(rundir_namechange_method) eq "suffix"} {
set new_basename ${rundir_basename}_[subst $date_style]
}
}
increment {
set new_basename [file tail [FF::gen_incr_filename $rundir_origname]]
}
custom {
if {$vars(custom_rundir_name_append) ne ""} {
if {$vars(rundir_namechange_method) eq "prefix"} {
set new_basename [subst $vars(custom_rundir_name_append)]_${rundir_basename}
} elseif {$vars(rundir_namechange_method) eq "suffix"} {
set new_basename ${rundir_basename}_[subst $vars(custom_rundir_name_append)]
}
} else {
puts "<FF> NOTE: vars(custom_rundir_name_append) set to \"\". No modification to rundir will occur."
set new_basename $rundir_basename
}
}
default {
# This should never happen! (indicates incorrect usage within gen_innovus_flow.tcl!)
puts "$dbgMsg WARNING: Unknown option for styleType. Using default (none)"
}
}
set vars(rundir) [file normalize [join "$rundir_dirname $new_basename" "/"]]
set vars(new_rundir_basename) $new_basename
} else {
set vars(rundir) [file normalize $rundir_origname]
}
return $vars(rundir)
};# end proc gen_new_rundir
proc relPathTo {target current} {
#puts "calling relPathTo $target $current"
set cc [file split [file normalize $current]]
set tt [file split [file normalize $target]]
if {![string equal [lindex $cc 1] [lindex $tt 1]]} {
# not on *n*x then
#return -code error "FF::relPathTo(): ERROR $target not on same volume as $current"
return [file normalize $target]
}
set prefix ""
while {[string equal [lindex $cc 0] [lindex $tt 0]] && [llength $cc] > 0} {
# discard matching components from the front (but don't
# do the last component in case the two files are the same)
set cc [lreplace $cc 0 0]
set tt [lreplace $tt 0 0]
}
#if {[llength $cc] == 1} {
# # just the file name, so target is lower down (or in same place)
# set prefix "."
#}
# step up the tree (start from 1 to avoid counting file itself
for {set i 1} {$i <= [llength $cc]} {incr i} {
append prefix " .."
}
# stick it all together (the eval is to flatten the target list)
if {$cc eq $tt} {
return "."
} else {
return [eval file join $prefix $tt]
}
}
proc flatten_list list {string map {\{ "" \} ""} $list}
proc remove_outer_braces {args} {
if {[regsub {^\{} $args "" tmp]} {set args $tmp}
if {[regsub {\}$} $args "" tmp]} {set args $tmp}
return $args
}
proc relativizeFileOrDir {args} {
#puts "relativizeFileOrDir $args"
set NewDirName ""
set arrName "vars"
set VarDirName ""
set skipVariableUsageInReference 0
set mustExist 0
set skipList {}
set exactVar ""
set exactSubDirMatch ""
set varToSub ""
set skipDirList ""
while {[llength $args] > 0} {
set option [lindex $args 0]
set args [lreplace $args 0 0]
switch -exact -- $option {
-arr {
set arrName [lindex $args 0]
set args [lreplace $args 0 0]
}
-vardir {
set VarDirName [lindex $args 0]
set args [lreplace $args 0 0]
}
-newdir {
set NewDirName [lindex $args 0]
set args [lreplace $args 0 0]
}
-skipVariableUsageInReference {
set skipVariableUsageInReference 1
}
-mustExist {
set mustExist 1
}
-skipVar {
lappend skipList [lindex $args 0]
set args [lreplace $args 0 0]
}
-skipDir {
lappend skipDirList [lindex $args 0]
set args [lreplace $args 0 0]
}
-var {
set varToSub [lindex $args 0]
set args [lreplace $args 0 0]
}
-exactSubDirMatch {
set exactSubDirMatch [lindex $args 0]
set args [lreplace $args 0 0]
}
}
};# end while (processing args)
# Always skip the VarDirName when analyzing variables in the array
lappend skipList $VarDirName
# Need to convert a list of files to relative paths (TBD)
global $arrName
# Check if the vardir (key) exists in the array. If not, exit
if {$VarDirName eq ""} {
return -code error "relativizeFileOrDir() called w/out -vardir argument. Exiting ..."
}
if {$NewDirName eq ""} {
set NewDirName $VarDirName
}
set relativizeConvMesgList {}
if {[info exists ${arrName}($VarDirName)]} {
foreach arg [lsort -dictionary [array names $arrName]] {
if {$varToSub eq "" || $varToSub eq $arg} {
# foreach key (entry) in the array, look for files/folders
set re ""
#puts "lsearch $skipList $arg"
# First check black list
if {[lsearch $skipList $arg] == -1} {
if {![regexp {\[} [set ${arrName}($arg)]]} {
# only continue if the variable is not the vardir (key) itself, and the value of the variable doesn't have a $ in it
#puts "relativizeFileOrDir() checking ${arrName}($arg) (current: ->[set ${arrName}($arg)]<-)"
set tmpValue ""
#
# Process all members of the $arrName(arg) (could be a list), and subst each one
#
set fileFound 0
set re "[file normalize [set ${arrName}($VarDirName)]]\/(.*)"
foreach possibleFile [set ${arrName}($arg)] {
if {$mustExist} {
# The file or dir must exist after normalization
#puts "Checking for existence of [file normalize [subst $possibleFile]]"
if {![catch {file exists [file normalize [subst $possibleFile]]}]} {
if {[file exists [file normalize [subst $possibleFile]]]} {
#puts "Exists: [file normalize [subst $possibleFile]]"
set file [file normalize [subst $possibleFile]]
set size [file size $file]
set mtime [file mtime $file]
set type [file type $file]
#puts "file $file size: $size, mtime: $mtime type: $type"
set fileFound 1
#puts "Checking for path to file: ->[file normalize [subst $possibleFile]]<- from ->[file normalize [set ${arrName}($VarDirName)]]<-"
set relPathValue [relPathTo [file normalize [subst $possibleFile]] [file normalize [subst [set ${arrName}($VarDirName)]]]]
#puts "relPathValue: $relPathValue"
set skipDueToSkipDir 0
if {$skipDirList ne ""} {
foreach dir $skipDirList {
set re3 "[file normalize [subst $dir]]/(.*)"
if {[regexp $re3 [file normalize [subst $possibleFile]] full relativePortion]} {
set skipDueToSkipDir 1
}
}
}
if {!$skipDueToSkipDir} {
if {$exactSubDirMatch ne ""} {
set re2 "$exactSubDirMatch/(.*)"
# the normalized path of the possible file has to match the normalized path of the subdir...
if {[regexp $re2 [file normalize [subst $possibleFile]] full relativePortion]} {
if {$relPathValue ne [file normalize $possibleFile]} {
if {$skipVariableUsageInReference} {
lappend tmpValue $relPathValue
} else {
lappend tmpValue "\$${arrName}($VarDirName)/$relPathValue"
}
} else {
lappend tmpValue $possibleFile
}
} else {
lappend tmpValue $possibleFile
}
} else {
#puts "skipVariableUsageInReference: $skipVariableUsageInReference"
if {$relPathValue ne [file normalize $possibleFile]} {
if {$skipVariableUsageInReference} {
lappend tmpValue $relPathValue
} else {
lappend tmpValue "\$${arrName}($VarDirName)/$relPathValue"
}
} else {
lappend tmpValue $possibleFile
}
#puts "final value: ->$tmpValue<-"
}
} else {
lappend tmpValue $possibleFile
}
} else {
# could not be tested as a file, so just lappend the entire string
lappend tmpValue $possibleFile
}
} else {
# could not be tested as a file, so just lappend the entire string
lappend tmpValue $possibleFile
}
} else {
# The file or dir need not exist, but the vardir must be a subdir (i.e., there must be a subdir that does exist)
#puts "Checking possible file: ->[subst $possibleFile]<- against regular expression ->$re<-"
if {[regexp $re [subst $possibleFile] full relativizedPortion]} {
if {$relativizedPortion eq ""} { set relativizedPortion "."}
set fileFound 1
if {$skipVariableUsageInReference} {
lappend tmpValue $relativizedPortion
} else {
lappend tmpValue "\$${arrName}($VarDirName)/$relativizedPortion"
}
if {[flatten_list $possibleFile] ne [flatten_list $tmpValue]} {
#puts "<FF> INFO Converted file $possibleFile to use a relative path to determine it's location: $tmpValue"
}
} else {
lappend tmpValue $possibleFile
}
}
}
# If the above for loop didn't find any files, simply reset the arrName(arg) statement
if {$fileFound} {
# Clean up original arrName(arg) and subb'ed value to prepare for comparison
set testArg [flatten_list [set ${arrName}($arg)]]
regsub -all {[ \r\t\n\\]+} $testArg " " testArg
regsub {^\s+(.*)} $testArg {\1} testArg
regsub {(.*)\s+$} $testArg {\1} testArg
set tmpValue [flatten_list $tmpValue]
regsub -all {[ \r\t\n]+} $tmpValue " " tmpValue
regsub {^\s+(.*)} $tmpValue {\1} tmpValue
regsub {(.*)\s+$} $tmpValue {\1} tmpValue
if {$tmpValue ne "" && $tmpValue ne $testArg} {
#puts "<FF> INFO Original value for arrName($arg): ->$testArg<-"
if {$relativizeConvMesgList eq ""} {
lappend relativizeConvMesgList "# Variable conversion for paths relative to \$${arrName}($VarDirName) ([set ${arrName}($VarDirName)])"
}
lappend relativizeConvMesgList "<FF> INFO Converted file variable [subst $arrName]($arg) from [set ${arrName}($arg)] to $tmpValue"
set ${arrName}($arg) $tmpValue
#puts "<FF> INFO Final value for arrName($arg): ->$tmpValue<-"
}
}
}
}
}
}
}
if {[llength $relativizeConvMesgList] > 1} {
lappend relativizeConvMesgList "# Total converted for variable [set ${arrName}($VarDirName)]:[expr {[llength $relativizeConvMesgList]-1}]"
}
return $relativizeConvMesgList
}
proc denormalize_rundir {} {
global vars
#set op [open $vars(rundir)/.ff.tcl w]
## BCL: added Foundation Flow execution dir
#puts $op "# Foundation Flow Codegen Record."
#puts $op "# Executed on [exec date] by user: [exec whoami]"
#puts $op "# Copyright 2011, Cadence Design Systems, Inc."
#puts $op "# All Rights Reserved"
#puts $op ""
#puts $op "# Inputs to code generation:"
#puts $op "# ----------------------------------------------"
#puts $op "set vars(ff_exe_dir) \"[exec pwd]\""
##puts $op "set vars(ff_dir) [file dirname $vars(script_path)]"
## BCL: removed ff_dir, changed to script_path (ff_dir was really redundant)
#puts $op "set vars(script_path) \"[file normalize $vars(script_path)]\""
## BCL: added variable referencing of config_files
#set cwd ""
#catch {set cwd [exec pwd]}
#foreach configFile [subst $vars(config_files)] {
# #puts "Processing $configFile"
# if {[file dirname [file normalize $configFile]] eq $cwd} {
# lappend configFileList "\[subst \$vars(ff_exe_dir)\]/[file tail $configFile]"
# } elseif {[FF::relPathTo [file normalize $configFile] $cwd] eq [file normalize [subst $configFile]]} {
# lappend configFileList [file normalize $configFile]
# } else {
# # Use the relative path name from ff_exe_dir
# lappend configFileList "\[subst \$vars(ff_exe_dir)\]/[FF::relPathTo [file normalize [subst $configFile]] $cwd]"
# }
#}
#puts $op "set vars(config_files) \"[FF::flatten_list $configFileList]\""
## BCL: added variable referencing of plug dirs
#if {[file dirname [file normalize $vars(plug_dir)]] eq $cwd} {
# # plug_dir is located in ff_exe_dir
# puts $op "set vars(plug_dir) \"\$vars(ff_exe_dir)/$vars(plug_dir)\""
#} elseif {[FF::relPathTo [file normalize $vars(plug_dir)] $cwd] eq [file normalize $vars(plug_dir)]} {
# # plug_dir cannot be referenced using a relative path
# puts $op "set vars(plug_dir) \"[file normalize $vars(plug_dir)]\""
#} else {
# # Use the relative path name from ff_exe_dir
# puts $op "set vars(plug_dir) \"\$vars(ff_exe_dir)/[FF::relPathTo [file normalize $vars(plug_dir)] $cwd]\""
#}
#if {[info exists vars(rc_plug_dir)]} {
# if {[file dirname [file normalize $vars(rc_plug_dir)]] eq $cwd} {
# # rc_plug_dir is located in ff_exe_dir
# puts $op "set vars(rc_plug_dir) \"\$vars(ff_exe_dir)/$vars(rc_plug_dir)\""
# } elseif {[FF::relPathTo [file normalize $vars(rc_plug_dir)] $cwd] eq [file normalize $vars(rc_plug_dir)]} {
# # rc_plug_dir cannot be referenced using a relative path
# puts $op "set vars(rc_plug_dir) \"[file normalize $vars(rc_plug_dir)]\""
# } else {
# # Use the relative path name from ff_exe_dir
# puts $op "set vars(rc_plug_dir) \"\$vars(ff_exe_dir)/[FF::relPathTo [file normalize $vars(rc_plug_dir)] $cwd]\""
# }
#}
## BCL: added vars(rundir)
#puts $op ""
#puts $op "# Outputs from code generation:"
#puts $op "# ----------------------------------------------"
#puts $op "set vars(rundir) \"\[file normalize \[file dirname \[info script\]\]\]\""
#puts $op "set vars(codegen_dir) \"[FF::relPathTo [file normalize $vars(script_dir)] [file normalize $vars(rundir)]]\""
#puts $op "set vars(script_dir) \"[FF::relPathTo [file normalize $vars(script_dir)] [file normalize $vars(rundir)]]\""
#close $op
if {$vars(user_mode) == "hier"} {
#foreach block [concat $vars(design) $vars(partition_list)] {
# file copy -force .ff.tcl $vars(partition_dir)/$block
#}
# if {($vars(hier_flow_type) == "2pass") && !$vars(enable_flexilm)} {
# foreach block [concat $vars(design) $vars(partition_list)] {
# file copy -force $vars(partition_dir)/$block/Makefile.pass2 $vars(partition_dir_pass2)/$block/Makefile
# file copy -force $vars(partition_dir)/$block/Makefile.pass2 $vars(script_dir)/$block.Makefile
# file delete $vars(partition_dir)/$block/Makefile.pass2
# }
# }
}
}
proc check_tcl_version {} {
set tcl_version [info tclversion]
set tversion [split $tcl_version "."]
set major [lindex $tversion 0]
set minor [lindex $tversion 1]
set valid_version 1
if {$major != "8"} {
set valid_version 0
} else {
if {[expr $minor] < 4} {
set valid_version 0
}
}
if {!$valid_version} {
puts "-------------------------------------------------"
puts "<FF> ERROR: TCL VERSION MUST BE 8.4 OR GREATER."
puts " YOUR TCL VERSION IS $tcl_version."
# puts " PLEASE RUN THE FLOW GENERATOR USING"
# puts " INNOVUS (WITH -e OPTION)"
puts "-------------------------------------------------"
exit -1
} else {
# puts "-------------------------------------------------"
# puts "<FF> TCL VERSION -> $tcl_version"
# puts "-------------------------------------------------"
}
}
proc create_flow {argv} {
global vars
global infos
global warnings
global errors
global check
global dargs
global fargs
global argv0
global env
set orig_argv $argv
interp alias {} Puts {} puts
##############################################################################
# Parse the arguments passed in to the script. These set up the environment #
# for the rest of the system #
##############################################################################
set vars(arg_list) [list \
codegen \
edi \
flat \
makefile \
mode \
rc \
novus \
synth_flow \
rundir \
script_dir \
style \
user_mode \
verbose \
version \
]
set vars(check_setup) 1
if {![info exists vars(script_path)]} {
set vars(script_path) ""
}
set normalized [file normalize $argv0]
if {[file isdirectory $normalized]} {
set default_script_path $normalized
} elseif {[file isdirectory [file dirname $normalized]]} {
set default_script_path [file dirname $normalized]
}
if {[info exists env(FF_SETUP_PATH)] && [file exists $env(FF_SETUP_PATH)]} {
set setup_path $env(FF_SETUP_PATH)
} else {
set setup_path "."
}
if {![info exists argv] || ![llength $argv]} {
set argv "-h"
}
set vars(format_lines) true
while {[string match "-*" [lindex $argv 0]]} {
if {![llength $argv]} {
break
}
set option [lindex $argv 0]
set argv [lreplace $argv 0 0]
switch -regexp -- $option {
^-(h|-help)$ {
puts $FFMM::usage
exit 0
}
^-(m|-mode)$ {
#
# Specify the runtime mode.
#
if {[llength $argv]} {
set newMode [lindex $argv 0]
set argv [lreplace $argv 0 0]
} else {
puts $FFMM::noMode
puts $FFMM::usage
exit -1
}
#
# The mode needs to be one of the recognized modes
#
if {[lsearch [concat "user" "hier" $FFMM::validModes] $newMode] == -1} {
puts [format $FFMM::unknownMode $newMode]
puts $FFMM::usage
exit -111
}
set mode $newMode
puts "<FF> FLOW MODE == $mode"
}
^-(n|-nomake)$ {
#
# Skip Makefile generation
#
set makefile false
puts "<FF> GENERATE MAKEFILE == $makefile"
}
^-(r|-rtl)$ {
#
# Enable Genus Codegen
#
set rc true
puts "<FF> RTl SCRIPTS == $rc"
}
^-(N|-Novus)$ {
#
# Enable Novus Syntax
#
set novus true
puts "<FF> NOVUS SCRIPTS == $novus"
}
# ^-(l|-flow)$ {
# if {[llength $argv]} {
# set synth_flow [lindex $argv 0]
# set argv [lreplace $argv 0 0]
# } else {
# puts $FFMM::nosynth_flow
# }
# }
# ^-(a|applets)$ {
# #
# # Define the applets directory path
# #
#
# if {[llength $argv]} {
# set appletsDir [lindex $argv 0]
# set argv [lreplace $argv 0 0]
# } else {
# puts $FFMM::noAppletPath
# exit -1
# }
#
# puts "<FF> APPLETS DIRECTORY == $appletsDir"
# set vars(applets_dir) $appletsDir
# }
^-(v|-version)$ {
#
# Set the target Innovus version
#
if {[llength $argv]} {
set version [lindex $argv 0]
set argv [lreplace $argv 0 0]
} else {
puts $FFMM::noVersion
exit -1
}
if {([lsearch $FF::valid_versions $version] < 0)} {
puts $FFMM::noVersion
exit -1
}
# puts "<FF> VERSION == $version"
}
^-(f|-flat)$ {
#
# Get the path to the scripts.
#
if {[llength $argv]} {
set newFlat [lindex $argv 0]
set argv [lreplace $argv 0 0]
} else {
puts $FFMM::noFlat
exit -1
}
if {($newFlat != "full") && ($newFlat != "partial") && ($newFlat != "none")} {
puts $FFMM::noFlat
exit -1
}
puts "<FF> FLAT == $newFlat"
set flat $newFlat
}
^-(e|-edi)$ {
#
# Enable Innovus mode
#
if {[llength $argv]} {
set edi true
# set argv [lreplace $argv 0 0]
}
puts "<FF> INNOVUS == $vars(edi)"
}
^-(d|-dir)$ {
#
# Define output directory path
#
if {[llength $argv]} {
set scriptDir [lindex $argv 0]
set argv [lreplace $argv 0 0]
} else {
puts $FFMM::noPath
exit -1
}
puts "<FF> OUTPUT DIRECTORY == $scriptDir"
}
^-(y|-style)$ {
#
# Define rundir directory naming style
# -d must be provided, since this will redefine vars(script_dir)
#
if {[llength $argv]} {
set styleType [lindex $argv 0]
switch -regexp -- $styleType {
(increment|date|none) {
set argv [lreplace $argv 0 0]
}
default {
puts [format $FFMM::unknownOption "-y $styleType"]
puts $FFMM::usage
exit -1
}
}
} else {
puts $FFMM::noStyle
exit -1
}
puts "<FF> DIRECTORY NAMING STYLE == $styleType"
}
^-(u|-rundir)$ {
#
# Define execution (run) dir
# This option superceeds -d ($vars(script_dir) is overridden to $vars(rundir)/FF)
#
if {[llength $argv]} {
set runDir [lindex $argv 0]
set argv [lreplace $argv 0 0]
} else {
puts $FFMM::noRundir
exit -1
}
puts "<FF> RUNDIR BASE == $runDir"
}
^-(s|-setup)$ {
#
# Get the path to the directory containing the setup.tcl control
# file
#
if {[llength $argv]} {
set newPath [lindex $argv 0]
set argv [lreplace $argv 0 0]
} else {
puts $FFMM::noSetupPath
puts $FFMM::usage
exit -1
}
#
# Does the path exist? If not, error out. Make sure that the path
# exists and contains the source files
#
if {![file exists $newPath]} {
puts [format $FFMM::noSuchPath $newPath]
puts $FFMM::usage
exit -1
}
set setup_path $newPath
puts "<FF> SETUP PATH == $setup_path"
}
^-(V|-Verbose)$ {
#
# Enable Verbose mode
#
if {[llength $argv]} {
set vars(verbose) true
}
puts "<FF> VERBOSE == $vars(verbose)"
}
^-(H|-Help)$ {
#
# Print step help
#
if {[llength $argv]} {
set vars(help) true
}
# puts "<FF> HELP == $vars(help)"
}
default {
puts [format $FFMM::unknownOption $option]
puts $FFMM::usage
exit -1
}
}
}
if {![file exists $setup_path/setup.tcl]} {
puts [format $FFMM::missingSetupFile $setup_path]
exit -1
} else {
set vars(setup_path) $setup_path
}
#
# Source the other Tcl files to execute the flow. Then do so
#
source "$vars(script_path)/ETC/utils.tcl"
#
# Get new rundir (using -u/-y and possibly user variables)
#
# NOTE: dargs: default args
# fargs: flow args specified on command line
if {![info exists first]} {
# BCL: Moved this code before gen_new_rundir since dargs(mode) must be set before executing execute_flow
if {![info exists mode]} {
set mode flat
set dargs(user_mode) flat
set dargs(mode) flat
} else {
if {$mode == "flat" || $mode == "user"} {
set fargs(user_mode) flat
} else {
set fargs(user_mode) hier
}
# set fargs(user_mode) flat
}
if {![info exists makefile]} {
set dargs(makefile) true
} else {
set fargs(makefile) $makefile
}
if {![info exists rc]} {
set dargs(rc) false
set rc false
} else {
set fargs(rc) $rc
}
if {![info exists novus]} {
set dargs(novus) false
set novus false
} else {
set fargs(novus) $novus
}
if {![info exists synth_flow]} {
set dargs(synth_flow) default_synthesis_flow_3step
} else {
set fargs(synth_flow) $synth_flow
}
if {![info exists version]} {
set dargs(version) 17.1.0
} else {
set fargs(version) $version
}
if {![info exists edi]} {
set dargs(edi) false
} else {
set fargs(edi) $edi
}
if {![info exists flat]} {
set dargs(flat) off
} else {
set fargs(flat) $flat
}
if {![info exists verbose]} {
set dargs(verbose) false
} else {
set fargs(verbose) $verbose
}
if {![info exists scriptDir]} {
set dargs(script_dir) FF
} else {
set fargs(script_dir) $scriptDir
}
set dargs(rundir) [file normalize .]
if {[info exists runDir]} {
# BCL: if runDir is set, it's a flow arg
set fargs(rundir) $runDir
}
if {![info exists styleType]} {
set dargs(style) none
} else {
set fargs(style) $styleType
}
# BCL: We are running codegen, so set fargs(codegen) to true
set fargs(codegen) true
set fargs(mode) $mode
set vars(cwd) [pwd]
set first 0
# BCL: (potentially) generate a new rundir
set fargs(rundir) [file normalize [FF::gen_new_rundir $orig_argv]]
# # If the user passed a -y and -u, move the -y (codegen dir output) to underneith the -u (rundir)
# # and message user
# if {[info exists fargs(rundir)] && $vars(rundir) ne "" && [file normalize $fargs(rundir)] ne [file normalize .]} {
# if {[info exists scriptDir]} {
# puts "<FF> NOTE: codegen output dir (-y $scriptDir) used with rundir specification of: $fargs(rundir)."
# puts "<FF> FF will move the codegen dir under the rundir: $vars(rundir)/[file tail $vars(script_dir)]"
# set fargs(script_dir) [file normalize $vars(rundir)/[file tail $vars(script_dir)]]
# set vars(script_dir) $fargs(script_dir)
# } elseif {[info exists vars(script_dir)] && $vars(script_dir) eq "FF"} {
# # vars(script_dir) is the default, so just move it
# set fargs(script_dir) [file normalize $vars(rundir)/FF]
# set vars(script_dir) $fargs(script_dir)
# }
# } else {
# # rundir is ./, so set
# if {![info exists scriptDir]} {
# set dargs(script_dir) "FF"
# set vars(script_dir) $dargs(script_dir)
# } else {
# set vars(script_dir) $scriptDir
# }
# }
# BCL: Added subst to resolve vars(rundir)
# GDG - this is done multiple times
#catch {file mkdir [subst $vars(script_dir)]}
}
#
# Determine the steps that can be executed based upon the mode passed in
#
FF::set_steps $mode $vars(format_lines)
set user_steps [list]
if {![llength $argv]} {
#
# If there is no argument, print out the list of valid steps for the mode
#
# set step all
# puts "Valid steps are: source check all $vars(steps)"
# exit
puts $FFMM::usage
puts " Step argument missing ... valid steps are:\n"
foreach s "$vars(steps) all" {
puts " $s"
}
exit
} else {
#
# Create a list of the user-specified steps. They can be in the form of
# <step1> <step2> ... <stepn>
# <step1> <step3>-<step5> <step7> ...
# <step1>-<stepn>
# There are, of course, additional variants. The thing is, if there is a
# dash between two steps, we want to expand the dash into the set of all
# steps between the two listed.
#
set vars(step_arg) $argv
foreach step $argv {
set dash [string first "-" $step]
if {$dash == -1} {
lappend user_steps $step
} else {
set first_step [string range $step 0 [expr $dash - 1]]
set last_step [string range $step [expr $dash + 1] end]
if {$last_step == ""} {
set last_step [lindex $vars(steps) end]
}
set first_index [lsearch $vars(steps) $first_step]
set last_index [lsearch $vars(steps) $last_step]
if {$first_index == -1} {
puts "Error: Unknown step $first_step for mode $mode"
exit -111
}
if {$last_index == -1} {
puts "Error: Unknown step $last_step for mode $mode"
exit -111
}
set steps [lrange $vars(steps) $first_index $last_index]
set user_steps [concat $user_steps $steps]
}
}
}
if {[info exists vars(help)] && $vars(help)} {
foreach step $user_steps {
FF::help $step
}
exit
}
set vars(make) $user_steps
set vars(argv) $argv
#set user_steps [FF::setup_flow $argv ]
#
# Execute the flow for every step that the user specified.
#
if {[info exists vars(rundir)]} {
set cwd [exec pwd]
file mkdir $vars(rundir)
foreach file [list setup.tcl innovus_config.tcl lp_config.tcl rc_config.tcl] {
if {[file isfile $file]} {
file copy -force $file $vars(rundir)
}
}
cd $vars(rundir)
}
set mode $vars(mode)
foreach step $user_steps {
if {$mode == "hier"} { set mode top_down }
switch $mode {
"user" {
if {$vars(novus)} {
FF_NOVUS::execute_flow $step $vars(format_lines)
} else {
FF_EDI::execute_flow $step $vars(format_lines)
}
}
"flat" {
if {$vars(novus)} {
FF_NOVUS::execute_flow $step $vars(format_lines)
} else {
FF_EDI::execute_flow $step $vars(format_lines)
}
}
"top_down" {
if {$vars(novus)} {
FF_NOVUS::execute_flow $step $vars(format_lines)
} else {
FF_EDI::execute_flow $step $vars(format_lines)
}
}
"bottom_up" {
if {$vars(novus)} {
FF_NOVUS::execute_flow $step $vars(format_lines)
} else {
FF_EDI::execute_flow $step $vars(format_lines)
}
}
"default" {
puts [format $FFMM::unknownMode mode]
puts $FFMM::usage
exit -111
}
}
}
if {[info exists vars(flow_steps)]} {
unset vars(flow_steps)
}
if {[file isfile $vars(script_dir)/INNOVUS/.head]} {
if {$vars(step_arg) == "all"} {
set op [open $vars(script_dir)/INNOVUS/run_simple.tcl w]
} else {
set op [open $vars(script_dir)/INNOVUS/run_simple.$vars(step_arg).tcl w]
}
puts $op "#####################################################################"
puts $op "# SINGLE SCRIPT FLOW"
puts $op "#####################################################################"
puts $op "\nsource $vars(script_dir)/vars.tcl"
puts $op "source $vars(script_dir)/procs.tcl\n"
set ip [open $vars(script_dir)/INNOVUS/.head]
while {[gets $ip line]>=0} {
puts $op $line
}
close $ip
set ip [open $vars(script_dir)/INNOVUS/.load_[lindex $vars(bsteps) 0]]
while {[gets $ip line]>=0} {
puts $op $line
}
close $ip
foreach step $vars(bsteps) {
if {($step == "lec") || ($step == "debug")} {
continue
}
set ip [open $vars(script_dir)/INNOVUS/.$step]
while {[gets $ip line]>=0} {
puts $op $line
}
close $ip
file delete $vars(script_dir)/INNOVUS/.$step
file delete $vars(script_dir)/INNOVUS/.load_$step
}
puts $op "exit"
close $op
# file mkdir $vars(script_dir)/INNOVUS/SIMPLE
# foreach step $vars(bsteps) {
# if {($step == "lec") || ($step == "debug")} {
# continue
# }
# set op [open $vars(script_dir)/INNOVUS/SIMPLE/run_$step.tcl w]
# puts $op "#####################################################################"
# puts $op "# SIMPLE STEP SCRIPT"
# puts $op "#####################################################################"
# puts $op "\nsource $vars(script_dir)/vars.tcl"
# puts $op "source $vars(script_dir)/procs.tcl\n"
# set ip [open $vars(script_dir)/INNOVUS/.head]
# while {[gets $ip line]>=0} {
# puts $op $line
# }
# close $ip
## file delete $vars(script_dir)/INNOVUS/.head
# set ip [open $vars(script_dir)/INNOVUS/.load_$step]
# while {[gets $ip line]>=0} {
# puts $op $line
# }
# close $ip
# set ip [open $vars(script_dir)/INNOVUS/.$step]
# while {[gets $ip line]>=0} {
# puts $op $line
# }
# close $ip
# puts $op "exit"
# close $op
# file delete $vars(script_dir)/INNOVUS/.$step
# file delete $vars(script_dir)/INNOVUS/.load_$step
# }
file delete $vars(script_dir)/INNOVUS/.head
}
# -----------
# if {[info exists vars(script_dir)]} {
# file delete $vars(script_dir)/INNOVUS/gen_html.tcl
# file copy [subst $vars(script_path)/INNOVUS/gen_html.tcl] [subst $vars(script_dir)/INNOVUS/gen_html.tcl]
# }
puts "-------------------------------------------------"
if {[info exists vars(plug_files)] && ($vars(plug_files) != "")} {
puts "\n Plug-ins Imported"
puts " ------------------"
foreach file $vars(plug_files) {
puts " > $file"
}
}
if {[info exists vars(plugins_defined)] && ($vars(plugins_defined) != "")} {
set plugins_defined [llength $vars(plugins_defined)]
if {$vars(verbose)} {
puts "\n Plug-ins Defined"
puts " ------------------"
foreach file [join $vars(plugins_defined)] {
puts " > $file"
}
}
} else {
set plugins_defined 0
}
if {[info exists vars(plugins_found)] && ($vars(plugins_found) != "")} {
set plugins_found [llength $vars(plugins_found)]
if {$vars(verbose)} {
puts "\n Plug-ins Found"
puts " ------------------"
foreach file [join $vars(plugins_found)] {
puts " > $file"
}
}
} else {
set plugins_found 0
}
if {[info exists vars(missing_plugins)] && ($vars(missing_plugins) != "")} {
set missing_plugins [llength $vars(missing_plugins)]
puts "\n Missing Plug-ins"
puts " ------------------"
foreach file [join $vars(missing_plugins)] {
puts " > $file"
}
} else {
set missing_plugins 0
}
# puts "-------------------------------------------------"
if {[info exists vars(tagged)] && ($vars(tagged) != "")} {
puts "\n Tagged Commands"
puts " ------------------"
foreach file $vars(tagged) {
puts " > $file"
}
set vars(missing_tags) [list]
foreach var [array names vars] {
if {[llength [split $var ","]] == 3} {
set suffix [lindex [split $var ","] 2]
if {($suffix == "pre_tcl") || ($suffix == "post_tcl") || ($suffix == "replace_tcl")} {
if {[lsearch $vars(tagged) $var] == -1} {
lappend vars(missing_tags) $var
}
}
}
}
if {[llength $vars(missing_tags)] > 0} {
puts "\n Unrecognized Tags"
puts " ------------------"
foreach tag $vars(missing_tags) {
puts " > $tag"
}
}
}
if {[info exists vars(info_count)] && ($vars(info_count) > 0)} {
puts "\n Info Summary"
puts " ---------------"
for {set i 0} {$i<$vars(info_count)} {incr i} {
puts " ([expr $i + 1]) $infos($i)"
}
}
if {[info exists vars(warning_count)] && ($vars(warning_count) > 0)} {
puts "\n Warning Summary"
puts " ---------------"
for {set i 0} {$i<$vars(warning_count)} {incr i} {
puts " ([expr $i + 1]) $warnings($i)"
}
}
if {[info exists vars(error_count)] && ($vars(error_count) > 0)} {
puts "\n Error Summary"
puts " ---------------"
for {set i 0} {$i<$vars(error_count)} {incr i} {
puts " ([expr $i + 1]) $errors($i)"
}
if {$vars(abort)} {
puts "\n"
puts "-------------------------------------------------"
puts "<FF> CODE GENERATION FAILED"
puts "-------------------------------------------------"
exit 1
}
}
if {$vars(make) != "all"} {
if {[info exists vars(custom_steps)]} {
FF::gen_makefile $vars(custom_steps) $vars(mode)
} else {
FF::gen_makefile $vars(make) $vars(mode)
}
}
# if {($vars(user_mode) == "hier") && $vars(enable_flexilm)} {
# foreach part $vars(partition_list) {
# file copy $vars(partition_dir_pass2)/$part/Makefile $vars(partition_dir_pass2)/$part.Makefile
# }
# }
puts "\n"
puts "-------------------------------------------------"
puts "<FF> CODE GENERATION COMPLETE"
puts "<FF> ... VERSION -> $vars(version)"
if {[info exists vars(rundir)]} {
puts "<FF> ... RUN DIRECTORY -> $vars(rundir)"
}
puts "<FF> ... SCRIPTS -> $vars(script_dir)"
puts "<FF> ... PLUGINS -> $plugins_defined defined, $plugins_found found"
if {[info exists vars(check_vars)] && $vars(check_vars)} {
puts "<FF> ... REPORTS -> $vars(script_dir)/check.rpt"
puts "<FF> ... -> $vars(script_dir)/check_vars.rpt"
} else {
puts "<FF> ... REPORT -> $vars(script_dir)/check.rpt"
}
if {[info exists vars(makefile_name)] && [file isfile [subst $vars(makefile_name)]]} {
puts "<FF> ... MAKEFILE -> [relPathTo [subst $vars(makefile_name)] [subst $vars(rundir)]]"
}
puts "-------------------------------------------------"
FF::dump_vars
if {[info exists vars(rundir)]} {
cd $cwd
}
}
proc dump_vars {} {
global vars
global env
#
# Create a procs.tcl file with ff utilities that are need by the flow
#
if {![info exists vars(proc_file)]} {
puts "<FF> Creating $vars(script_dir)/procs.tcl"
set save $vars(required_procs)
set of [open $vars(script_dir)/procs.tcl w]
set ff_procs "\nnamespace eval ff_procs:: {\n"
append ff_procs [get_required_procs $vars(script_path)/ETC/INNOVUS/utils.tcl]
append ff_procs [get_required_procs $vars(script_path)/ETC/utils.tcl]
set vars(required_procs) "source_plug"
append ff_procs [get_required_procs $vars(script_path)/ETC/INNOVUS/utils.tcl]
# append ff_procs " namespace export load_applet\n"
append ff_procs "}\n"
puts $of $ff_procs
if {[info exists vars(use_flexmodels)] && $vars(use_flexmodels)} {
puts $of {
# Flexmodel defaults
catch {
setPlaceDesignMode_ff -clonePlace noPostPlace ;#REMOVE after fixing CCR 974103
set mib::FE_major_version [string range [getVersion] 0 1]
set mib::FE_minor_version [string range [getVersion] 3 4]
#################### Default private var settings for proto flow #########################
set trialRoutePrivate::honorPtnPinSpec 1 ;#so TR adds blockages straddling ptn boundary before routing
set trialRoutePrivate::enableFlexCell 1 ;#enable flexfiller_route_blockage for better congestion/placement correlation to full netlist.
set trialRoutePrivate::useColorMap 1 ;#enable much faster handlePartitionComplex algorithm
set trialRoutePrivate::overflowLimit 4 ;#Giving up phase 1 trialRoute prematurely when the overflow is more than 10%
################### Hide setting variables in the prototyping script #######################
setVar timing_library_support_mismatched_arcs 0
##########################################################################################
# Procedure to check for using correct prototyping kit
#########################################################################################
proc mib::check_protokit_version {{current_kit_version ""}} {
if {[lsearch $mib::protokit_version $current_kit_version] == -1} {
Puts "*WARN* Correct prototyping kit should be used to avoid un-expected problems"
Puts " This Innovus build requires prototyping kit version [lrange $mib::protokit_version 0 4]"
}
}
mib::check_protokit_version "EDI13.20-0"
}
}
}
set vars(required_procs) $save
if {[info exists vars(cpf_file)]} {
puts $of "#----------------------------------------------"
puts $of "# Backwards compatibility ..."
puts $of "#----------------------------------------------"
puts $of "catch {alias ff_modify_power_domains ff_procs::modify_power_domains}"
puts $of "catch {alias ff_add_power_switches ff_procs::add_power_switches}"
puts $of "catch {alias ff_route_secondary_pg_nets ff_procs::route_secondary_pg_nets}"
puts $of "catch {alias ff_get_power_domains ff_procs::get_power_domains}"
puts $of "catch {alias ff_buffer_always_on_nets ff_procs::buffer_always_on_nets}"
puts $of "catch {alias ff_insert_welltaps_endcaps ff_procs::insert_welltaps_endcaps}"
if {$vars(novus)} {
puts $of "catch {alias FF_NOVUS::modify_power_domains ff_procs::modify_power_domains}"
puts $of "catch {alias FF_NOVUS::add_power_switches ff_procs::add_power_switches}"
puts $of "catch {alias FF_NOVUS::route_secondary_pg_nets ff_procs::route_secondary_pg_nets}"
puts $of "catch {alias FF_NOVUS::get_power_domains ff_procs::get_power_domains}"
puts $of "catch {alias FF_NOVUS::buffer_always_on_nets ff_procs::buffer_always_on_nets}"
puts $of "catch {alias FF_NOVUS::insert_welltaps_endcaps ff_procs::insert_welltaps_endcaps}"
} else {
puts $of "catch {alias FF_EDI::modify_power_domains ff_procs::modify_power_domains}"
puts $of "catch {alias FF_EDI::add_power_switches ff_procs::add_power_switches}"
puts $of "catch {alias FF_EDI::route_secondary_pg_nets ff_procs::route_secondary_pg_nets}"
puts $of "catch {alias FF_EDI::get_power_domains ff_procs::get_power_domains}"
puts $of "catch {alias FF_EDI::buffer_always_on_nets ff_procs::buffer_always_on_nets}"
puts $of "catch {alias FF_EDI::insert_welltaps_endcaps ff_procs::insert_welltaps_endcaps}"
}
}
close $of
set vars(proc_file) 1
}
# if {[file tail [file dirname [pwd]]] == "$vars(partition_dir)"} {
# set op [open $vars(script_dir)/vars.tcl a]
# if {$vars(user_mode) == "hier"} {
# if {[file tail [file dirname [exec pwd]]] == $vars(partition_dir)} {
# puts $op "source $vars(norm_script_path)/ETC/applet.tcl"
# #puts $op "source ../../$vars(script_path)/ETC/compatibility.tcl"
# puts $op "set_attribute applet_search_path $vars(norm_script_path)/ETC/applets /"
# } else {
# puts $op "source $vars(script_path)/ETC/applet.tcl"
# #puts $op "source ../../$vars(script_path)/ETC/compatibility.tcl"
# puts $op "set_attribute applet_search_path $vars(script_path)/ETC/applets /"
# }
# }
# puts $op "applet load measure"
# puts $op "applet load time_info"
# close $op
# return
# }
if {[file normalize $vars(rundir)] ne [file normalize .]} {
set relativizeVar 1
} else {
set relativizeVar 0
}
# if {$relativizeVar} {
# puts "<FF> Finalizing Foundation Flow Variables for final rundir: [relPathTo [file normalize $vars(rundir)] [file normalize .]]"
# }
# BCL: substitute plugdirs and codegen dir with variable referencing (i.e., replace actual dir with [subst $vars(<dir>)]) before writing vars.tcl
if {![info exists vars(ff_exe_dir)]} {
set vars(ff_exe_dir) [exec pwd]
}
# BCL: The following are set using variables in the generated .ff.tcl, and are therefore pulled out of the generated vars.tcl
set skipVarList {ff_exe_dir rundir plug_dir rc_plug_dir lec_plug_dir script_dir flow_steps flow_steps,flat flow_steps,hier}
# BCL: Changed to tcl file mkdir
file mkdir $vars(script_dir)
#GG
if {[info exists vars(stylus_convert)] && $vars(stylus_convert)} {
set anchor(place) "before run_place_opt"
set anchor(prects) "before run_place_opt"
set anchor(cts) "before add_clock_spec"
set anchor(postcts) "before add_clock_spec"
set anchor(postcts_hold) "before add_clock_spec"
set anchor(route) "before run_route"
set anchor(postroute) "before run_opt_postroute"
set anchor(postroute_hold) "before run_opt_postroute"
set op [open $vars(script_dir)/flow_steps.tcl w]
foreach step [FF::adjust_steps] {
if {![info exists anchor($step)]} {
if {[info exists vars($step,commands)]} {
unset vars($step,commands)
continue
}
}
if {[info exists vars($step,commands)]} {
puts $op "create_flow_step -name pre_$step -owner cadence \{"
puts $op $vars($step,commands)
puts $op "\}"
unset vars($step,commands)
puts $of "edit_flow -append flow_step:pre_$step -[lindex $anchor($step) 0] flow_step:[lindex $anchor($step) 1]"
}
}
# set op [open scripts/flow_config.tcl a]
# puts $op "source $vars(script_dir)/flow_steps.tcl"
close $op
FF::create_codegen_file
set op [open codegen_create.txt a]
puts $op "codegen::template ./scripts/flow_config.template \{"
puts $op " placeholder \{<< PLACEHOLDER: PARASITIC LOAD OPTIONS >>\} \{ -all_rc_corner -rcdb rcdb/$vars(design).rcdb.d \}"
puts $op " append \{"
puts $op "create_flow_step -name write_parasitics -owner cadence \{"
puts $op " file mkdir rcdb"
puts $op " write_rc rcdb/$vars(design).rcdb.d"
puts $op "\}"
puts $op "edit_flow -after flow_step:run_opt_postroute -append flow_step:write_parasitics"
foreach file "$vars(script_dir)/flow_steps.tcl $vars(script_dir)/plug_steps.tcl" {
if {[file exists $file]} {
set ip [open $file r]
while {[gets $ip line]>=0} {
puts $op "$line"
}
close $ip
}
}
puts $op " \}"
puts $op "\}"
close $op
}
foreach var [array names vars] {
if {[regexp ",commands$" $var]} {
unset vars($var)
}
}
# foreach step $vars(steps) {
# if {[info exists vars($step,commands)]} {
# unset vars($step,commands)
# }
# }
set op [open $vars(script_dir)/vars.tcl w]
puts $op "# ############################################################################ #"
puts $op "# Foundation Flow Codegen Vars Record"
puts $op "# Executed on [clock format [clock seconds] -format "%I:%M:%S %p(%b%d)"] by user: [exec whoami]"
puts $op "# Copyright 2008-2012, Cadence Design Systems, Inc."
puts $op "# All Rights Reserved"
puts $op "# ############################################################################ #"
puts $op ""
puts $op "# This file contains all default (seeded) variables and user-defined variables that were resolved during code generation."
puts $op "if {!\[info exists vars\]} {"
puts $op " global vars"
puts $op "}"
puts $op "global env"
# if {[info exists vars(user_arrays)]} {
# foreach array $vars(user_arrays) {
# puts $op "global $array"
# }
# }
# Print variables which may be referenced by other variables
# Note: General methodology is to not use more than one variable reference (i.e., don't allow multiple variable dereferencing)
puts $op "set env(VPATH) $env(VPATH)"
puts $op "set vars(ff_exe_dir) \"$vars(ff_exe_dir)\""
puts $op "set vars(rundir) \"$vars(rundir)\""
puts $op "set vars(script_dir) \"$vars(script_dir)\""
puts $op ""
# GDG ...
# if {$relativizeVar} {
# set relativizeMesgLog ""
# # First relativize ff_exe_dir. Ignore plug variables for now (maybe this can be relaxed?)
# # All files in this first relativization task must exist. Skip anything that is located in vars(rundir).
# set relativizeMesgLog "$relativizeMesgLog [FF::remove_outer_braces \
# [FF::relativizeFileOrDir -vardir ff_exe_dir -mustExist -skipVar script_dir -skipVar ff_exe_dir \
# -skipVar rc_plug_dir -skipVar lec_plug_dir -skipVar plug_dir -skipVar rundir -skipDir [file normalize $vars(rundir)]]]"
# # Relativize all files in rundir. Skip variable referencing, meaning do not include $vars(rundir) in the final variable value
# set relativizeMesgLog "$relativizeMesgLog [FF::remove_outer_braces [FF::relativizeFileOrDir -vardir rundir -skipVariableUsageInReference -skipVar script_dir]]"
# # Swap out the invidiual plug dir variables
# foreach dir "rc_plug_dir lec_plug_dir plug_dir" {
# if {[info exists vars($dir)]} {
# # Relativize the plugin (syn_load_rtl goes from ./plug/GENUS/syn_load_rtl.tcl to $vars(rc_plug_dir)/syn_load_rtl.tcl)
# set relativizeMesgLog "$relativizeMesgLog [FF::remove_outer_braces \
# [FF::relativizeFileOrDir -vardir $dir -mustExist \
# -exactSubDirMatch [file normalize $vars($dir)]]]"
# # normalize the plug dirs
# set vars($dir) [file normalize [subst $vars($dir)]]
# }
# }
# }
# Print plugin variables
if {[info exists vars(plug_dir)]} {puts $op "set vars(plug_dir) \"$vars(plug_dir)\""}
if {[info exists vars(rc_plug_dir)]} {puts $op "set vars(rc_plug_dir) \"$vars(rc_plug_dir)\""}
if {[info exists vars(lec_plug_dir)]} {puts $op "set vars(lec_plug_dir) \"$vars(lec_plug_dir)\""}
puts $op "\n"
# Actually print out all the other variables
if {[info exists vars(init_commands)]} {unset vars(init_commands)}
foreach var [lsort [array names vars]] {
# BCL: Only write out variable values in curlies if not using [subst ...]
if {[lsearch $skipVarList $var] == -1} {
if {[regexp {\$} $vars($var)]} {
puts $op "set vars($var) \"$vars($var)\""
} else {
puts $op "set vars($var) \{$vars($var)\}"
}
}
}
# Print aliases
puts $op "set vars(restore_design) {true}"
# Load applets
# puts $op "source $vars(script_path)/ETC/applet.tcl"
# puts $op "source ../../$vars(script_path)/ETC/compatibility.tcl"
# puts $op "set_attribute applet_search_path $vars(script_path)/ETC/applets /"
# puts $op "applet load generate_report"
# puts $op "applet load measure"
# puts $op "applet load time_info"
close $op
# if {$relativizeVar} {
# # Write out messaging related to relativizeFileOrDir output
# set op [open $vars(script_dir)/relativize_vars.rpt w]
# puts $op "# ############################################################################ #"
# puts $op "# Foundation Flow Variable Relativization Report"
# puts $op "# Executed on [clock format [clock seconds] -format "%I:%M:%S %p(%b%d)"] by user: [exec whoami]"
# puts $op "# Copyright 2008-2012, Cadence Design Systems, Inc."
# puts $op "# All Rights Reserved"
# puts $op "# ############################################################################ #"
# foreach line $relativizeMesgLog {
# puts $op $line
# }
# close $op
# }
}
proc cleanup_dotfiles {} {
global vars
if {$vars(user_mode) != "hier"} {
return
}
if {[info exists vars(rundir)]} {
cd $vars(rundir)
}
foreach file [glob $vars(script_dir)/INNOVUS/.*] {
if {[file isfile $file] && (![regexp ".nfs" $file])} {
file delete $file
if {$vars(debug)} {
puts "<FF> Deleting $file ..."
}
}
}
if {[info exists vars(partition_dir)] && [info exists vars(partition_list)]} {
if {[file isdirectory $vars(partition_dir)]} {
foreach part [concat $vars(design) $vars(partition_list)] {
foreach file [glob $vars(partition_dir)/$part/$vars(script_dir)/INNOVUS/.*] {
if {[file isfile $file] && (![regexp ".nfs" $file])} {
file delete $file
if {$vars(debug)} {
puts "<FF> Deleting $file ..."
}
}
}
if {($vars(hier_flow_type) == "2pass")} {
if {[file isdirectory $vars(partition_dir_pass2)]} {
catch {set dotfiles [glob $vars(partition_dir_pass2)/$part/$vars(script_dir)/INNOVUS/.*]}
if {[info exists dotfiles]} {
foreach file [glob $vars(partition_dir_pass2)/$part/$vars(script_dir)/INNOVUS/.*] {
if {[file isfile $file] && (![regexp ".nfs" $file])} {
file delete $file
if {$vars(debug)} {
puts "<FF> Deleting $file ..."
}
}
}
}
}
}
}
}
}
}
proc gen_flow {args} {
global vars
if {![info exists vars(execute_string)]} {
set vars(execute_string) "FF::gen_flow $args"
}
# Allow re-entrance
set var_list [list sourced bsteps warnings errors infos warning_count error_count info_count \
plugins_defined plugins_found missing_plugins tagged missing_tags]
if {[info exists vars(arg_list)]} {
set reset_list [concat $vars(arg_list) $var_list]
} else {
set reset_list $var_list
}
foreach var $reset_list {
if {[info exists vars($var)]} {
unset vars($var)
}
if {[info exists dargs($var)]} {
unset vars($var)
}
if {[info exists dargs($var)]} {
unset vars($var)
}
}
if {[info exists vars(flat)]} {
set save $vars(flat)
}
puts "================================================="
puts "<FF> Foundation Flow Code Generator"
puts "<FF> Version : 17.10-p003_1"
puts "================================================="
# Check TCL version
FF::check_tcl_version
# Create flow scripts
FF::create_flow $args
# Adjust variables so the run dir can be relocated
FF::denormalize_rundir
if {[info exists save]} {
set vars(flat) $save
} else {
unset vars(flat)
}
FF::cleanup_dotfiles
if {([info command FF::get_tool] ne "") && ([FF::get_tool] eq "edi")} {
puts "<FF> Loading $vars(script_dir)/procs.tcl ..."
uplevel #0 source $vars(script_dir)/procs.tcl
}
if {$vars(generate_flow_steps)} {
file delete -force $vars(script_dir)/INNOVUS
if {[info exists vars(partition_dir)] && [info exists vars(partition_list)]} {
if {[file isdirectory $vars(partition_dir)]} {
foreach part [concat $vars(design) $vars(partition_list)] {
if [file isdirectory $vars(partition_dir)/$part/$vars(script_dir)/INNOVUS] {
file delete -force $vars(partition_dir)/$part/$vars(script_dir)/INNOVUS
}
}
}
}
}
}
proc seed_all_vars {} {
# defaults
set script_path ""
set script_dir ""
set setup_path ""
set synth_flow ""
set format_lines ""
set step ""
# arg processing
while {[llength $args] > 0} {
set option [lindex $args 0]
set args [lreplace $args 0 0]
switch -exact -- $option {
-script_path {
set script_path [lindex $args 0]
set args [lreplace $args 0 0]
}
-script_dir {
set script_dir [lindex $args 0]
set args [lreplace $args 0 0]
}
-setup_path {
set setup_path [lindex $args 0]
set args [lreplace $args 0 0]
}
-synth_flow {
set synth_flow [lindex $args 0]
set args [lreplace $args 0 0]
}
-format_lines {
set synth_flow [lindex $args 0]
set args [lreplace $args 0 0]
}
-step {
set step [lindex $args 0]
set args [lreplace $args 0 0]
}
}
};# end while (processing args)
}
namespace export load_applet
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 ""
array unset appInfo
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 /
}
proc generate_reports {args} {
eval [format "%s %s" generate_report $args]
}
proc runtime_info {args} {
eval [format "%s %s" time_info $args]
}
proc capture_metrics {} {
global vars
set commands ""
append commands "measure qor -name $vars(step) $vars(html_summary)\n"
append commands "time_info -table ff_ext -stamp $vars(step)\n"
append commands "time_info -table ff_ext -report\n"
append commands "redirect $vars(time_info_rpt) {time_info -table ff_ext -report}\n"
append commands "time_info -quiet -table ff_ext -save $vars(time_info_db)\n"
return $commands
}
proc help {step} {
global vars
source $vars(script_path)/ETC/INNOVUS/mapped_vars.tcl
if {![info exists help($step,categories)]} {
puts "<FF> ERROR: Invalid step/category ... valid options are:"
foreach cat $help(categories) {
puts " $cat"
}
return
}
set length [string length $step]
puts " [string repeat = 110]"
puts [format " %+55s : %-42s" "variable (command)" values]
# puts " Variables affecting '$step' => variable (command) : values"
# puts " [string repeat = 110]"
# puts " [string repeat - [expr 53-($length/2)]] $step [string repeat - [expr 47-($length/2)]]"
foreach cat $help($step,categories) {
set length [string length $cat]
puts " [string repeat - [expr 53-($length/2)]] $cat [string repeat - [expr 47-($length/2)]]"
foreach var [lsort [array names help]] {
if {[regexp $cat, $var]} {
if {$cat ne [lindex [split $var ","] 0]} { continue }
set command [lindex [split $var ","] 1]
if {[llength [split $var ","]] > 3} {
set variable [format "%s,%s" [lindex [split $var ","] 2] [lindex [split $var ","] 3]]
} else {
set variable [lindex [split $var ","] 2]
}
set values $help($var)
if {$command != "categories"} {
puts [format " %+55s : %-42s" "$variable ($command)" $values]
}
}
}
}
puts " [string repeat = 110]"
}
# A procedure to determine if the current flow is low power (i.e., CPF or IEEE 1801 based)
proc is_lp_flow {} {
global vars
return [expr {[info exists vars(cpf_file)] && $vars(cpf_file) != ""} || \
{[info exists vars(ieee1801_file)] && $vars(ieee1801_file) != ""}]
}
proc adjust_steps {} {
global vars
set new_steps [list]
set first 1
foreach step $vars(steps) {
if {[regexp _hold $step]} {
if {([lsearch $vars(fix_hold) [regsub _hold $step ""]]<0)} {
continue
} else {
if {($vars(step) == "postcts_hold") && $vars(skip_cts)} {
continue
}
}
}
if {($step == "prects") && $vars(place_opt_design)} {
if {!(($vars(user_mode) == "hier") && ([file tail [pwd]] == $vars(top_cell)) && $vars(enable_flexilm))} {
continue
}
}
if {($step == "cts") && $vars(skip_cts)} {
continue
}
if {($step == "postcts")} {
if {$vars(skip_cts)} {
continue
}
if {[regexp "^ccopt" [string tolower $vars(cts_engine)]]} {
if {$vars(cts_engine) != "ccopt_cts"} {
continue
}
}
}
if {($step == "postcts_hold") && $vars(postcts_setup_hold) && ($vars(cts_engine) != "ccopt_cts")} {
continue
}
if {($step == "postroute_hold") && $vars(postroute_setup_hold)} {
continue
}
lappend new_steps $step
}
return $new_steps
}
proc create_codegen_file {} {
global vars
if {[info exists vars(stylus_convert)] && $vars(stylus_convert) && [info exists vars(plugins_defined)]} {
FF_NOVUS::convert_plugins
set op [open codegen_create.txt w]
puts $op "#!/grid/common/pkgs/tcltk/v8.5b3/bin/tclsh"
puts $op "source /vols/dsg_tracker/innovus/fe/src/flowkit/tests/codegen_flowkit_template_modifier.lib.tcl"
set timing_libs $vars($vars($vars($vars(default_setup_view),delay_corner),library_set),timing)
set qrc_tech $vars($vars($vars($vars(default_setup_view),delay_corner),rc_corner),qx_tech_file)
if {[info exists vars($vars($vars(default_setup_view),constraint_mode),synth_sdc)]} {
set sdc_files $vars($vars($vars(default_setup_view),constraint_mode),synth_sdc)
} else {
set sdc_files $vars($vars($vars(default_setup_view),constraint_mode),pre_cts_sdc)
}
puts $op "codegen::template ./scripts/design_config.template \{"
puts $op " placeholder \{<< PLACEHOLDER: PATH TO TIMING LIBS >>\} \{ \. \}"
puts $op " placeholder \{<< PLACEHOLDER: PATH TO LEF FILES >>\} \{ \. \}"
puts $op " placeholder \{<< PLACEHOLDER: PATH TO TECH FILES >>\} \{ \. \}"
puts $op " placeholder \{<< PLACEHOLDER: LIST OF TIMING LIBRARIES >>\} \{\{$timing_libs\}\}"
puts $op " placeholder \{<< PLACEHOLDER: LIST OF LEF FILES >>\} \{\{$vars(lef_files)\}\}"
puts $op " placeholder \{<< PLACEHOLDER: PROCESS NODE >>\} \{$vars(process)\}"
puts $op " placeholder \{<< PLACEHOLDER: QRC TECH FILE >>\} \{$qrc_tech\}"
puts $op " delete_placeholder \{<< PLACEHOLDER: pattern >>\}"
puts $op " delete \{operating_condition\}"
if {[info exists vars(syn_load_rtl_tcl)] && [file isfile $vars(syn_load_rtl_tcl)]} {
# puts $op " append_after \{- Read hdl design, Flow Step Name: read_hdl\} \{"
puts $op " append_after \{<< PLACEHOLDER: DESIGN HDL LOAD OPTIONS >>\} \{"
set ip [open $vars(syn_load_rtl_tcl) r]
while {[gets $ip line]>=0} {
puts $op " $line"
}
close $ip
puts $op " \}"
puts $op " delete_placeholder \{<< PLACEHOLDER: DESIGN HDL LOAD OPTIONS >>\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: DESIGN HDL LOAD OPTIONS >>\}"
}
puts $op " placeholder \{<< PLACEHOLDER: ELABORATION OPTIONS >>\} \{$vars(design)\}"
puts $op " placeholder \{<< PLACEHOLDER: SDC FILES >>\} \{$sdc_files\}"
puts $op " placeholder \{<< PLACEHOLDER: PHYSICAL DATA LOAD OPTIONS >>\} \{-lef \{ $vars(lef_files) \}\}"
puts $op " placeholder \{<< PLACEHOLDER: DESIGN DATA LOAD OPTIONS >>\} \{$vars(netlist)\}"
if {[info exists vars(def_files)]} {
puts $op " placeholder \{<< PLACEHOLDER: DEF LOAD OPTIONS >>\} \{$vars(def_files)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: DEF LOAD OPTIONS >>\}"
}
if {[info exists vars(fp_file)]} {
puts $op " placeholder \{<< PLACEHOLDER: FPLAN LOAD OPTIONS >>\} \{$vars(fp_file)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: FPLAN LOAD OPTIONS >>\}"
}
if {[info exists vars(cpf_file)]} {
puts $op " placeholder \{<< PLACEHOLDER: POWER INTENT LOAD OPTIONS >>\} \{$vars(cpf_file)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: POWER INTENT LOAD OPTIONS >>\}"
}
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK LEAF ROUTE RULE >>\}"
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK TRUNK ROUTE RULE >>\}"
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK TOP ROUTE RULE >>\}"
puts $op "\}"
puts $op "codegen::template ./scripts/genus_config.template \{"
puts $op "\}"
puts $op "codegen::template ./scripts/innovus_config.template \{"
if {[info exists vars(process)]} {
puts $op " placeholder \{<< PLACEHOLDER: PROCESS NODE >>\} \{$vars(process)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: PROCESS NODE >>\}"
}
if {[info exists vars(flow_effort)]} {
puts $op " placeholder \{<< PLACEHOLDER: FLOW EFFORT LEVEL >>\} \{$vars(flow_effort)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: FLOW EFFORT LEVEL >>\}"
}
if {[info exists vars(tie_cells)]} {
puts $op " placeholder \{<< PLACEHOLDER: TIEOFF BASE_CELL NAMES >>\} \{\{$vars(tie_cells)\}\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: TIEOFF BASE_CELL NAMES >>\}"
}
if {[info exists vars(cts_target_slew)]} {
puts $op " placeholder \{<< PLACEHOLDER: CLOCK TRANSITION TIME TARGET >>\} \{$vars(cts_target_slew)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK TRANSITION TIME TARGET >>\}"
}
if {[info exists vars(cts_target_skew)]} {
puts $op " placeholder \{<< PLACEHOLDER: CLOCK SKEW TARGET >>\} \{$vars(cts_target_skew)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK SKEW TARGET >>\}"
}
if {[info exists vars(cts_buffer_cells)]} {
puts $op " placeholder \{<< PLACEHOLDER: CLOCK BUFFER BASE_CELLS NAMES >>\} \{\{$vars(cts_buffer_cells)\}\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK BUFFER BASE_CELLS NAMES >>\}"
}
if {[info exists vars(cts_inverter_cells)]} {
puts $op " placeholder \{<< PLACEHOLDER: CLOCK INVERTER BASE_CELLS NAMES >>\} \{\{$vars(cts_inverter_cells)\}\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK INVERTER BASE_CELLS NAMES >>\}"
}
if {[info exists vars(cts_clock_gating_cells)]} {
puts $op " placeholder \{<< PLACEHOLDER: CLOCK GATING BASE_CELLS NAMES >>\} \{\{$vars(cts_clock_gating_cells)\}\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: CLOCK GATING BASE_CELLS NAMES >>\}"
}
puts $op " delete_placeholder \{<< PLACEHOLDER: ROUTE TYPE NAME FOR CLOCK LEAF NETS >>\}"
puts $op " delete_placeholder \{<< PLACEHOLDER: ROUTE TYPE NAME FOR CLOCK TRUNK NETS >>\}"
puts $op " delete_placeholder \{<< PLACEHOLDER: ROUTE TYPE NAME FOR CLOCK TOP NETS >>\}"
if {[info exists vars(filler_cells)]} {
puts $op " placeholder \{<< PLACEHOLDER: FILLER BASE_CELL NAMES >>\} \{\{$vars(filler_cells)\}\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: FILLER BASE_CELL NAMES >>\}"
}
puts $op "\}"
puts $op "codegen::template ./scripts/tempus_config.template \{"
if {[info exists vars(process)]} {
puts $op " placeholder \{<< PLACEHOLDER: PROCESS NODE >>\} \{$vars(process)\}"
} else {
puts $op " delete_placeholder \{<< PLACEHOLDER: PROCESS NODE >>\}"
}
puts $op "\}"
close $op
}
}
};# end namespace FF