|
####################################################################################
|
|
#
|
|
# write_project_tcl.tcl (write a Vivado project tcl script for re-creating project)
|
|
#
|
|
# Script created on 02/08/2013 by Raj Klair (Xilinx, Inc.)
|
|
#
|
|
# 2014.2 - v2.0 (rev 4)
|
|
# * do not return value from main proc
|
|
# * fixed bug with relative file path calculation (break from loop while comparing
|
|
# directory elements of file paths for file to make relative to o/p script dir)
|
|
# 2014.1 - v2.0 (rev 3)
|
|
# * make source file paths relative to script output directory
|
|
#
|
|
# 2013.4 -
|
|
# 2013.3 -
|
|
# 2013.2 - v1.0 (rev 2)
|
|
# * no change
|
|
#
|
|
# 2013.1 - v1.0 (rev 1)
|
|
# * initial version
|
|
#
|
|
####################################################################################
|
|
#
|
|
# Modified version to better support revision control.
|
|
# Can be called as write_project_tcl_git from the tcl console in Vivado.
|
|
#
|
|
# Differences:
|
|
#
|
|
# 1. The project directory is now relative to the scripts location.
|
|
# Project directory was relative to the tcl console current directory.
|
|
#
|
|
# 2. When recreating a project, the generated files will be put in a "work" directory
|
|
# under the project directory. If the work exists already, it will be rewritten.
|
|
#
|
|
# 3. After recreating a project, the tcl console will change directory to the project directory.
|
|
#
|
|
# 4. No mention to the creation time of the project script, so that it is not different
|
|
# every time it is generated.
|
|
#
|
|
####################################################################################
|
|
package require Vivado 1.2014.1
|
|
|
|
namespace eval ::custom {
|
|
namespace export write_project_tcl_git
|
|
}
|
|
|
|
namespace eval ::custom {
|
|
proc write_project_tcl_git {args} {
|
|
# Summary:
|
|
# Export Tcl script for re-creating the current project
|
|
|
|
# Argument Usage:
|
|
# [-paths_relative_to <arg> = Script output directory path]: Override the reference directory variable for source file relative paths
|
|
# [-target_proj_dir <arg> = Current project directory path]: Directory where the project needs to be restored
|
|
# [-force]: Overwrite existing tcl script file
|
|
# [-all_properties]: Write all properties (default & non-default) for the project object(s)
|
|
# [-no_copy_sources]: Do not import sources even if they were local in the original project
|
|
# [-absolute_path]: Make all file paths absolute wrt the original project directory
|
|
# [-dump_project_info]: Write object values
|
|
# file: Name of the tcl script file to generate
|
|
|
|
# Return Value:
|
|
# true (0) if success, false (1) otherwise
|
|
|
|
# Categories: xilinxtclstore, projutils
|
|
|
|
# reset global variables
|
|
variable a_global_vars
|
|
|
|
reset_global_vars
|
|
|
|
# process options
|
|
for {set i 0} {$i < [llength $args]} {incr i} {
|
|
set option [string trim [lindex $args $i]]
|
|
switch -regexp -- $option {
|
|
"-paths_relative_to" { incr i;set a_global_vars(s_relative_to) [file normalize [lindex $args $i]] }
|
|
"-target_proj_dir" { incr i;set a_global_vars(s_target_proj_dir) [lindex $args $i] }
|
|
"-force" { set a_global_vars(b_arg_force) 1 }
|
|
"-all_properties" { set a_global_vars(b_arg_all_props) 1 }
|
|
"-no_copy_sources" { set a_global_vars(b_arg_no_copy_srcs) 1 }
|
|
"-absolute_path" { set a_global_vars(b_absolute_path) 1 }
|
|
"-dump_project_info" { set a_global_vars(b_arg_dump_proj_info) 1 }
|
|
default {
|
|
# is incorrect switch specified?
|
|
if { [regexp {^-} $option] } {
|
|
send_msg_id Vivado-projutils-001 ERROR "Unknown option '$option', please type 'write_project_tcl -help' for usage info.\n"
|
|
return
|
|
}
|
|
set a_global_vars(script_file) $option
|
|
}
|
|
}
|
|
}
|
|
|
|
# script file is a must
|
|
if { [string equal $a_global_vars(script_file) ""] } {
|
|
send_msg_id Vivado-projutils-002 ERROR "Missing value for option 'file', please type 'write_project_tcl -help' for usage info.\n"
|
|
return
|
|
}
|
|
|
|
# should not be a directory
|
|
if { [file isdirectory $a_global_vars(script_file)] } {
|
|
send_msg_id Vivado-projutils-003 ERROR "The specified filename is a directory ($a_global_vars(script_file)), please type 'write_project_tcl -help' for usage info.\n"
|
|
return
|
|
}
|
|
|
|
# check extension
|
|
if { [file extension $a_global_vars(script_file)] != ".tcl" } {
|
|
set a_global_vars(script_file) $a_global_vars(script_file).tcl
|
|
}
|
|
set a_global_vars(script_file) [file normalize $a_global_vars(script_file)]
|
|
|
|
# error if file directory path does not exist
|
|
set file_path [file dirname $a_global_vars(script_file)]
|
|
if { ! [file exists $file_path] } {
|
|
set script_filename [file tail $a_global_vars(script_file)]
|
|
send_msg_id Vivado-projutils-013 ERROR "Directory in which file ${script_filename} is to be written does not exist \[$a_global_vars(script_file)\]\n"
|
|
return
|
|
}
|
|
|
|
# recommend -force if file exists
|
|
if { [file exists $a_global_vars(script_file)] && !$a_global_vars(b_arg_force) } {
|
|
send_msg_id Vivado-projutils-004 ERROR "Tcl Script '$a_global_vars(script_file)' already exist. Use -force option to overwrite.\n"
|
|
return
|
|
}
|
|
|
|
# set script file directory path
|
|
set a_global_vars(s_path_to_script_dir) [file normalize $file_path]
|
|
|
|
# now write
|
|
if {[write_project_tcl_script]} {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace eval ::custom {
|
|
#
|
|
# write_project_tcl tcl script argument & file handle vars
|
|
#
|
|
variable a_global_vars
|
|
variable l_script_data [list]
|
|
variable l_local_files [list]
|
|
variable l_remote_files [list]
|
|
variable b_project_board_set 0
|
|
|
|
# set file types to filter
|
|
variable l_filetype_filter [list]
|
|
|
|
# Setup filter for non-user-settable filetypes
|
|
set l_filetype_filter [list "ip" "ipx" "embedded design sources" "elf" "coefficient files" "configuration files" \
|
|
"block diagrams" "block designs" "dsp design sources" "text" \
|
|
"design checkpoint" "waveform configuration file"]
|
|
# ip file extension types
|
|
variable l_valid_ip_extns [list]
|
|
set l_valid_ip_extns [list ".xci" ".bd" ".slx"]
|
|
|
|
# set fileset types
|
|
variable a_fileset_types
|
|
set a_fileset_types {
|
|
{{DesignSrcs} {srcset}}
|
|
{{BlockSrcs} {blockset}}
|
|
{{Constrs} {constrset}}
|
|
{{SimulationSrcs} {simset}}
|
|
}
|
|
|
|
proc reset_global_vars {} {
|
|
# Summary: initializes global namespace vars
|
|
# This helper command is used to reset the variables used in the script.
|
|
# Argument Usage:
|
|
# none
|
|
# Return Value:
|
|
# None
|
|
|
|
variable a_global_vars
|
|
|
|
set a_global_vars(s_relative_to) {.}
|
|
set a_global_vars(s_path_to_script_dir) ""
|
|
set a_global_vars(s_target_proj_dir) ""
|
|
set a_global_vars(b_arg_force) 0
|
|
set a_global_vars(b_arg_no_copy_srcs) 0
|
|
set a_global_vars(b_absolute_path) 0
|
|
set a_global_vars(b_arg_all_props) 0
|
|
set a_global_vars(b_arg_dump_proj_info) 0
|
|
set a_global_vars(b_local_sources) 0
|
|
set a_global_vars(curr_time) [clock format [clock seconds]]
|
|
set a_global_vars(fh) 0
|
|
set a_global_vars(dp_fh) 0
|
|
set a_global_vars(def_val_fh) 0
|
|
set a_global_vars(script_file) ""
|
|
|
|
set l_script_data [list]
|
|
set l_local_files [list]
|
|
set l_remote_files [list]
|
|
}
|
|
|
|
proc write_project_tcl_script {} {
|
|
# Summary: write project script
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# none
|
|
# Return Value:
|
|
# true (0) if success, false (1) otherwise
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
variable l_remote_files
|
|
variable l_local_files
|
|
|
|
set l_script_data [list]
|
|
set l_local_files [list]
|
|
set l_remote_files [list]
|
|
|
|
# get the project name
|
|
set tcl_obj [current_project]
|
|
set proj_name [file tail [get_property name $tcl_obj]]
|
|
set proj_dir [get_property directory $tcl_obj]
|
|
set part_name [get_property part $tcl_obj]
|
|
|
|
# output file script handle
|
|
set file $a_global_vars(script_file)
|
|
if {[catch {open $file w} a_global_vars(fh)]} {
|
|
send_msg_id Vivado-projutils-005 ERROR "failed to open file for write ($file)\n"
|
|
return 1
|
|
}
|
|
|
|
# dump project in canonical form
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
set dump_file [file normalize [file join $a_global_vars(s_path_to_script_dir) ${proj_name}_dump.txt]]
|
|
if {[catch {open $dump_file w} a_global_vars(dp_fh)]} {
|
|
send_msg_id Vivado-projutils-006 ERROR "failed to open file for write ($dump_file)\n"
|
|
return 1
|
|
}
|
|
|
|
# default value output file script handle
|
|
set def_val_file [file normalize [file join $a_global_vars(s_path_to_script_dir) ${proj_name}_def_val.txt]]
|
|
if {[catch {open $def_val_file w} a_global_vars(def_val_fh)]} {
|
|
send_msg_id Vivado-projutils-007 ERROR "failed to open file for write ($file)\n"
|
|
return 1
|
|
}
|
|
}
|
|
|
|
# explicitly update the compile order for current source/simset, if following conditions are met
|
|
if { {All} == [get_property source_mgmt_mode [current_project]] &&
|
|
{0} == [get_property is_readonly [current_project]] &&
|
|
{RTL} == [get_property design_mode [current_fileset]] } {
|
|
|
|
|
|
# re-parse source fileset compile order for the current top
|
|
if {[llength [get_files -compile_order sources -used_in synthesis]] > 1} {
|
|
update_compile_order -fileset [current_fileset] -quiet
|
|
}
|
|
|
|
# re-parse simlulation fileset compile order for the current top
|
|
if {[llength [get_files -compile_order sources -used_in simulation]] > 1} {
|
|
update_compile_order -fileset [current_fileset -simset] -quiet
|
|
}
|
|
}
|
|
|
|
# writer helpers
|
|
wr_create_project $proj_dir $proj_name $part_name
|
|
wr_project_properties $proj_dir $proj_name
|
|
wr_filesets $proj_dir $proj_name
|
|
wr_runs $proj_dir $proj_name
|
|
wr_proj_info $proj_name
|
|
|
|
# write header
|
|
write_header $proj_dir $proj_name $file
|
|
|
|
# write script data
|
|
foreach line $l_script_data {
|
|
puts $a_global_vars(fh) $line
|
|
}
|
|
|
|
close $a_global_vars(fh)
|
|
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
close $a_global_vars(def_val_fh)
|
|
close $a_global_vars(dp_fh)
|
|
}
|
|
|
|
set script_filename [file tail $file]
|
|
set out_dir [file dirname [file normalize $file]]
|
|
send_msg_id Vivado-projutils-008 INFO "Tcl script '$script_filename' generated in output directory '$out_dir'\n\n"
|
|
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
send_msg_id Vivado-projutils-016 INFO "Please note that the -absolute_path switch was specified, hence the project source files will be referenced using\n\
|
|
absolute path only, in the generated script. As such, the generated script will only work in the same filesystem where those absolute paths are accessible."
|
|
} else {
|
|
if { "." != $a_global_vars(s_relative_to) } {
|
|
send_msg_id Vivado-projutils-017 INFO "Please note that the -paths_relative_to switch was specified, hence the project source files will be referenced\n\
|
|
wrt the path that was specified with this switch. The 'origin_dir' variable is set to this path in the generated script."
|
|
} else {
|
|
send_msg_id Vivado-projutils-015 INFO "Please note that by default, the file path for the project source files were set wrt the 'origin_dir' variable in the\n\
|
|
generated script. When this script is executed from the output directory, these source files will be referenced wrt this 'origin_dir' path value.\n\
|
|
In case this script was later physically moved to a different directory, the 'origin_dir' value MUST be set manually in the script with the path\n\
|
|
relative to the new output directory to make sure that the source files are referenced correctly from the original project. You can also set the\n\
|
|
'origin_dir' automatically by setting the 'origin_dir_loc' variable in the tcl shell before sourcing this generated script. The 'origin_dir_loc'\n\
|
|
variable should be set to the path relative to the new output directory. Alternatively, if you are sourcing the script from the Vivado command line,\n\
|
|
then set the origin dir using '-tclargs --origin_dir <path>'. For example, 'vivado -mode tcl -source $script_filename -tclargs --origin_dir \"..\"\n"
|
|
}
|
|
}
|
|
|
|
if { $a_global_vars(b_local_sources) } {
|
|
print_local_file_msg "warning"
|
|
} else {
|
|
print_local_file_msg "info"
|
|
}
|
|
|
|
reset_global_vars
|
|
|
|
return 0
|
|
}
|
|
|
|
proc wr_create_project { proj_dir name part_name } {
|
|
# Summary: write create project command
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# proj_dir: project directory path
|
|
# name: project name
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
lappend l_script_data "# Set the reference directory for source file relative paths (by default the value is script directory path)"
|
|
lappend l_script_data "set origin_dir \[file dirname \[info script\]\]"
|
|
lappend l_script_data ""
|
|
set var_name "origin_dir_loc"
|
|
lappend l_script_data "# Use origin directory path location variable, if specified in the tcl shell"
|
|
lappend l_script_data "if \{ \[info exists ::$var_name\] \} \{"
|
|
lappend l_script_data " set origin_dir \$::$var_name"
|
|
lappend l_script_data "\}"
|
|
|
|
lappend l_script_data ""
|
|
|
|
lappend l_script_data "variable script_file"
|
|
lappend l_script_data "set script_file \"[file tail $a_global_vars(script_file)]\"\n"
|
|
lappend l_script_data "# Help information for this script"
|
|
lappend l_script_data "proc help \{\} \{"
|
|
lappend l_script_data " variable script_file"
|
|
lappend l_script_data " puts \"\\nDescription:\""
|
|
lappend l_script_data " puts \"Recreate a Vivado project from this script. The created project will be\""
|
|
lappend l_script_data " puts \"functionally equivalent to the original project for which this script was\""
|
|
lappend l_script_data " puts \"generated. The script contains commands for creating a project, filesets,\""
|
|
lappend l_script_data " puts \"runs, adding/importing sources and setting properties on various objects.\\n\""
|
|
lappend l_script_data " puts \"Syntax:\""
|
|
lappend l_script_data " puts \"\$script_file\""
|
|
lappend l_script_data " puts \"\$script_file -tclargs \\\[--origin_dir <path>\\\]\""
|
|
lappend l_script_data " puts \"\$script_file -tclargs \\\[--help\\\]\\n\""
|
|
lappend l_script_data " puts \"Usage:\""
|
|
lappend l_script_data " puts \"Name Description\""
|
|
lappend l_script_data " puts \"-------------------------------------------------------------------------\""
|
|
lappend l_script_data " puts \"\\\[--origin_dir <path>\\\] Determine source file paths wrt this path. Default\""
|
|
lappend l_script_data " puts \" origin_dir path value is \\\".\\\", otherwise, the value\""
|
|
lappend l_script_data " puts \" that was set with the \\\"-paths_relative_to\\\" switch\""
|
|
lappend l_script_data " puts \" when this script was generated.\\n\""
|
|
lappend l_script_data " puts \"\\\[--help\\\] Print help information for this script\""
|
|
lappend l_script_data " puts \"-------------------------------------------------------------------------\\n\""
|
|
lappend l_script_data " exit 0"
|
|
lappend l_script_data "\}\n"
|
|
lappend l_script_data "if \{ \$::argc > 0 \} \{"
|
|
lappend l_script_data " for \{set i 0\} \{\$i < \[llength \$::argc\]\} \{incr i\} \{"
|
|
lappend l_script_data " set option \[string trim \[lindex \$::argv \$i\]\]"
|
|
lappend l_script_data " switch -regexp -- \$option \{"
|
|
lappend l_script_data " \"--origin_dir\" \{ incr i; set origin_dir \[lindex \$::argv \$i\] \}"
|
|
lappend l_script_data " \"--help\" \{ help \}"
|
|
lappend l_script_data " default \{"
|
|
lappend l_script_data " if \{ \[regexp \{^-\} \$option\] \} \{"
|
|
lappend l_script_data " puts \"ERROR: Unknown option '\$option' specified, please type '\$script_file -tclargs --help' for usage info.\\n\""
|
|
lappend l_script_data " return 1"
|
|
lappend l_script_data " \}"
|
|
lappend l_script_data " \}"
|
|
lappend l_script_data " \}"
|
|
lappend l_script_data " \}"
|
|
lappend l_script_data "\}\n"
|
|
|
|
lappend l_script_data "# Set the directory path for the original project from where this script was exported"
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend l_script_data "set orig_proj_dir \"$proj_dir\""
|
|
} else {
|
|
set rel_file_path "[get_relative_file_path_for_source $proj_dir [get_script_execution_dir]]"
|
|
set path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
|
|
lappend l_script_data "set orig_proj_dir \"$path\""
|
|
}
|
|
lappend l_script_data ""
|
|
|
|
# create project
|
|
lappend l_script_data "# Create project"
|
|
|
|
set tcl_cmd ""
|
|
# set target project directory path if specified. If not, create project dir in current dir.
|
|
set target_dir $a_global_vars(s_target_proj_dir)
|
|
if { {} == $target_dir } {
|
|
set tcl_cmd "create_project $name \$origin_dir/work -part $part_name -quiet -force"
|
|
} else {
|
|
# is specified target proj dir == current dir?
|
|
set cwd [file normalize [string map {\\ /} [pwd]]]
|
|
set dir [file normalize [string map {\\ /} $target_dir]]
|
|
if { [string equal $cwd $dir] } {
|
|
set tcl_cmd "create_project $name -part $part_name"
|
|
} else {
|
|
set tcl_cmd "create_project $name \"$target_dir\" -part $part_name"
|
|
}
|
|
}
|
|
|
|
if { [get_property managed_ip [current_project]] } {
|
|
set tcl_cmd "$tcl_cmd -ip"
|
|
}
|
|
lappend l_script_data $tcl_cmd
|
|
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
puts $a_global_vars(dp_fh) "project_name=$name"
|
|
}
|
|
|
|
lappend l_script_data ""
|
|
lappend l_script_data "# Set the directory path for the new project"
|
|
lappend l_script_data "set proj_dir \[get_property directory \[current_project\]\]"
|
|
|
|
lappend l_script_data ""
|
|
lappend l_script_data "# Reconstruct message rules"
|
|
|
|
set msg_control_rules [ debug::get_msg_control_rules -as_tcl ]
|
|
if { [string length $msg_control_rules] > 0 } {
|
|
lappend l_script_data "${msg_control_rules}"
|
|
} else {
|
|
lappend l_script_data "# None"
|
|
}
|
|
lappend l_script_data ""
|
|
}
|
|
|
|
proc wr_project_properties { proj_dir proj_name } {
|
|
# Summary: write project properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# proj_name: project name
|
|
# Return Value:
|
|
# None
|
|
|
|
variable l_script_data
|
|
variable b_project_board_set
|
|
|
|
# write project properties
|
|
set tcl_obj [current_project]
|
|
set get_what "get_projects"
|
|
|
|
lappend l_script_data "# Set project properties"
|
|
lappend l_script_data "set obj \[$get_what $tcl_obj\]"
|
|
|
|
# is project "board_part" set already?
|
|
if { [string length [get_property "board_part" $tcl_obj]] > 0 } {
|
|
set b_project_board_set 1
|
|
}
|
|
|
|
write_props $proj_dir $proj_name $get_what $tcl_obj "project"
|
|
}
|
|
|
|
proc wr_filesets { proj_dir proj_name } {
|
|
# Summary: write fileset object properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# proj_name: project name
|
|
# Return Value:
|
|
# None
|
|
|
|
variable a_fileset_types
|
|
|
|
# write fileset data
|
|
foreach {fs_data} $a_fileset_types {
|
|
set filesets [get_filesets -filter FILESET_TYPE==[lindex $fs_data 0]]
|
|
write_specified_fileset $proj_dir $proj_name $filesets
|
|
}
|
|
}
|
|
|
|
proc write_specified_fileset { proj_dir proj_name filesets } {
|
|
# Summary: write fileset properties and sources
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# proj_name: project name
|
|
# filesets: list of filesets
|
|
# Return Value:
|
|
# None
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
variable a_fileset_types
|
|
|
|
# write filesets
|
|
set type "file"
|
|
foreach tcl_obj $filesets {
|
|
|
|
# Is this a IP block fileset for a proxy IP that is owned by another composite file?
|
|
# If so, we don't want to write it out as an independent file. The parent will take care of it.
|
|
if { [is_proxy_ip_fileset $tcl_obj] } {
|
|
continue
|
|
}
|
|
|
|
set fs_type [get_property fileset_type [get_filesets $tcl_obj]]
|
|
|
|
# is this a IP block fileset? if yes, do not create block fileset, but create for a pure HDL based fileset (no IP's)
|
|
if { [is_ip_fileset $tcl_obj] } {
|
|
# do not create block fileset
|
|
} else {
|
|
lappend l_script_data "# Create '$tcl_obj' fileset (if not found)"
|
|
lappend l_script_data "if \{\[string equal \[get_filesets -quiet $tcl_obj\] \"\"\]\} \{"
|
|
|
|
set fs_sw_type [get_fileset_type_switch $fs_type]
|
|
lappend l_script_data " create_fileset $fs_sw_type $tcl_obj"
|
|
lappend l_script_data "\}\n"
|
|
}
|
|
|
|
set get_what_fs "get_filesets"
|
|
|
|
# set IP REPO PATHS (if any) for filesets of type "DesignSrcs" or "BlockSrcs"
|
|
if { (({DesignSrcs} == $fs_type) || ({BlockSrcs} == $fs_type)) } {
|
|
# If BlockSet contains only one IP, then this indicates the case of OOC1
|
|
# This means that we should not write these properties, they are read-only
|
|
set blockset_is_ooc1 false
|
|
if { {BlockSrcs} == $fs_type } {
|
|
set current_fs_files [get_files -of_objects [get_filesets $tcl_obj] -norecurse]
|
|
if { [llength $current_fs_files] == 1 } {
|
|
set only_file_in_fs [lindex $current_fs_files 0]
|
|
set file_type [get_property FILE_TYPE $only_file_in_fs]
|
|
set blockset_is_ooc1 [expr {$file_type == {IP}} ? true : false]
|
|
}
|
|
}
|
|
if { $blockset_is_ooc1} {
|
|
# We do not write properties for OOC1
|
|
} elseif { ({RTL} == [get_property design_mode [get_filesets $tcl_obj]]) } {
|
|
set repo_paths [get_ip_repo_paths $tcl_obj]
|
|
if { [llength $repo_paths] > 0 } {
|
|
lappend l_script_data "# Set IP repository paths"
|
|
lappend l_script_data "set obj \[get_filesets $tcl_obj\]"
|
|
set path_list [list]
|
|
foreach path $repo_paths {
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend path_list $path
|
|
} else {
|
|
set rel_file_path "[get_relative_file_path_for_source $path [get_script_execution_dir]]"
|
|
set path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
|
|
lappend path_list $path
|
|
}
|
|
}
|
|
set repo_path_str [join $path_list " "]
|
|
lappend l_script_data "set_property \"ip_repo_paths\" \"${repo_path_str}\" \$obj"
|
|
lappend l_script_data ""
|
|
lappend l_script_data "# Rebuild user ip_repo's index before adding any source files"
|
|
lappend l_script_data "update_ip_catalog -rebuild"
|
|
lappend l_script_data ""
|
|
}
|
|
}
|
|
}
|
|
|
|
# is this a IP block fileset? if yes, then set the current srcset object (IP's will be added to current source fileset)
|
|
if { [is_ip_fileset $tcl_obj] } {
|
|
set srcset [current_fileset -srcset]
|
|
lappend l_script_data "# Set '$srcset' fileset object"
|
|
lappend l_script_data "set obj \[$get_what_fs $srcset\]"
|
|
} else {
|
|
lappend l_script_data "# Set '$tcl_obj' fileset object"
|
|
lappend l_script_data "set obj \[$get_what_fs $tcl_obj\]"
|
|
}
|
|
if { {Constrs} == $fs_type } {
|
|
lappend l_script_data ""
|
|
write_constrs $proj_dir $proj_name $tcl_obj $type
|
|
} else {
|
|
write_files $proj_dir $proj_name $tcl_obj $type
|
|
}
|
|
|
|
# is this a IP block fileset? if yes, do not write block fileset properties (block fileset doesnot exist in new project)
|
|
if { [is_ip_fileset $tcl_obj] } {
|
|
# do not write ip fileset properties
|
|
} else {
|
|
lappend l_script_data "# Set '$tcl_obj' fileset properties"
|
|
lappend l_script_data "set obj \[$get_what_fs $tcl_obj\]"
|
|
write_props $proj_dir $proj_name $get_what_fs $tcl_obj "fileset"
|
|
}
|
|
}
|
|
}
|
|
|
|
proc wr_runs { proj_dir proj_name } {
|
|
# Summary: write runs and properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# proj_name: project name
|
|
# Return Value:
|
|
# None
|
|
|
|
variable l_script_data
|
|
|
|
# write runs (synthesis, Implementation)
|
|
set runs [get_runs -filter {IS_SYNTHESIS == 1}]
|
|
write_specified_run $proj_dir $proj_name $runs
|
|
|
|
if { {RTL} == [get_property design_mode [current_fileset]] } {
|
|
lappend l_script_data "# set the current synth run"
|
|
lappend l_script_data "current_run -synthesis \[get_runs [current_run -synthesis]\]\n"
|
|
}
|
|
|
|
set runs [get_runs -filter {IS_IMPLEMENTATION == 1}]
|
|
write_specified_run $proj_dir $proj_name $runs
|
|
|
|
lappend l_script_data "# set the current impl run"
|
|
lappend l_script_data "current_run -implementation \[get_runs [current_run -implementation]\]"
|
|
lappend l_script_data ""
|
|
lappend l_script_data "# Change current directory to project folder"
|
|
lappend l_script_data "cd \[file dirname \[info script\]\]"
|
|
}
|
|
|
|
proc wr_proj_info { proj_name } {
|
|
# Summary: write generated project status message
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# proj_name: project name
|
|
# Return Value:
|
|
# None
|
|
|
|
variable l_script_data
|
|
|
|
lappend l_script_data "\nputs \"INFO: Project created:$proj_name\""
|
|
}
|
|
|
|
proc write_header { proj_dir proj_name file } {
|
|
# Summary: write script header
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# None
|
|
|
|
variable a_global_vars
|
|
variable l_local_files
|
|
variable l_remote_files
|
|
|
|
set version_txt [split [version] "\n"]
|
|
set version [lindex $version_txt 0]
|
|
set copyright [lindex $version_txt 2]
|
|
set product [lindex [split $version " "] 0]
|
|
set version_id [join [lrange $version 1 end] " "]
|
|
|
|
set tcl_file [file tail $file]
|
|
puts $a_global_vars(fh) "#\n# $product (TM) $version_id"
|
|
puts $a_global_vars(fh) "#\n# $tcl_file: Tcl script for re-creating project '$proj_name'\n#"
|
|
puts $a_global_vars(fh) "# $copyright"
|
|
puts $a_global_vars(fh) "#\n# This file contains the $product Tcl commands for re-creating the project to the state*"
|
|
puts $a_global_vars(fh) "# when this script was generated. In order to re-create the project, please source this"
|
|
puts $a_global_vars(fh) "# file in the $product Tcl Shell."
|
|
puts $a_global_vars(fh) "#"
|
|
puts $a_global_vars(fh) "# * Note that the runs in the created project will be configured the same way as the"
|
|
puts $a_global_vars(fh) "# original project, however they will not be launched automatically. To regenerate the"
|
|
puts $a_global_vars(fh) "# run results please launch the synthesis/implementation runs as needed.\n#"
|
|
puts $a_global_vars(fh) "#*****************************************************************************************"
|
|
puts $a_global_vars(fh) "# NOTE: In order to use this script for source control purposes, please make sure that the"
|
|
puts $a_global_vars(fh) "# following files are added to the source control system:-"
|
|
puts $a_global_vars(fh) "#"
|
|
puts $a_global_vars(fh) "# 1. This project restoration tcl script (${tcl_file}) that was generated."
|
|
puts $a_global_vars(fh) "#"
|
|
puts $a_global_vars(fh) "# 2. The following source(s) files that were local or imported into the original project."
|
|
puts $a_global_vars(fh) "# (Please see the '\$orig_proj_dir' and '\$origin_dir' variable setting below at the start of the script)\n#"
|
|
|
|
if {[llength $l_local_files] == 0} {
|
|
puts $a_global_vars(fh) "# <none>"
|
|
} else {
|
|
foreach line $l_local_files {
|
|
puts $a_global_vars(fh) "# $line"
|
|
}
|
|
}
|
|
puts $a_global_vars(fh) "#"
|
|
puts $a_global_vars(fh) "# 3. The following remote source files that were added to the original project:-\n#"
|
|
if {[llength $l_remote_files] == 0} {
|
|
puts $a_global_vars(fh) "# <none>"
|
|
} else {
|
|
foreach line $l_remote_files {
|
|
puts $a_global_vars(fh) "# $line"
|
|
}
|
|
}
|
|
puts $a_global_vars(fh) "#"
|
|
puts $a_global_vars(fh) "#*****************************************************************************************\n"
|
|
}
|
|
|
|
proc print_local_file_msg { msg_type } {
|
|
# Summary: print warning on finding local sources
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# None
|
|
|
|
puts ""
|
|
if { [string equal $msg_type "warning"] } {
|
|
send_msg_id Vivado-projutils-010 WARNING "Found source(s) that were local or imported into the project. If this project is being source controlled, then\n\
|
|
please ensure that the project source(s) are also part of this source controlled data. The list of these local source(s) can be found in the generated script\n\
|
|
under the header section."
|
|
} else {
|
|
send_msg_id Vivado-projutils-011 INFO "If this project is being source controlled, then please ensure that the project source(s) are also part of this source\n\
|
|
controlled data. The list of these local source(s) can be found in the generated script under the header section."
|
|
}
|
|
puts ""
|
|
}
|
|
|
|
proc get_ip_repo_paths { tcl_obj } {
|
|
# Summary:
|
|
# Iterate over the fileset properties and get the ip_repo_paths (if set)
|
|
# Argument Usage:
|
|
# tcl_obj : fileset
|
|
# Return Value:
|
|
# List of repo paths
|
|
|
|
set repo_path_list [list]
|
|
foreach path [get_property ip_repo_paths [get_filesets $tcl_obj]] {
|
|
lappend repo_path_list $path
|
|
}
|
|
return $repo_path_list
|
|
}
|
|
|
|
proc is_deprecated { prop } {
|
|
# Summary: filter deprecated properties
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# true (1) if found, false (1) otherwise
|
|
|
|
set prop [string toupper $prop]
|
|
if { $prop == "BOARD" } {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
proc filter { prop val { file {} } } {
|
|
# Summary: filter special properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# true (1) if found, false (1) otherwise
|
|
|
|
variable l_filetype_filter
|
|
variable l_valid_ip_extns
|
|
|
|
set prop [string toupper $prop]
|
|
if { [expr { $prop == "BOARD" } || \
|
|
{ $prop == "IS_HD" } || \
|
|
{ $prop == "IS_PARTIAL_RECONFIG" } || \
|
|
{ $prop == "ADD_STEP" }]} {
|
|
return 1
|
|
}
|
|
|
|
if { [string equal type "project"] } {
|
|
if { [expr { $prop == "DIRECTORY" }] } {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
# error reported if file_type is set
|
|
# e.g ERROR: [Vivado 12-563] The file type 'IP' is not user settable.
|
|
set val [string tolower $val]
|
|
if { [string equal $prop "FILE_TYPE"] } {
|
|
if { [lsearch $l_filetype_filter $val] != -1 } {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
# filter readonly is_managed property for ip
|
|
if { [string equal $prop "IS_MANAGED"] } {
|
|
if { [lsearch -exact $l_valid_ip_extns [string tolower [file extension $file]]] >= 0 } {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
# filter ip_repo_paths (ip_repo_paths is set before adding sources)
|
|
if { [string equal -nocase $prop {ip_repo_paths}] } {
|
|
return 1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
proc is_local_to_project { file } {
|
|
# Summary: check if file is local to the project directory structure
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# true (1), if file is local to the project (inside project directory structure)
|
|
# false (0), if file is outside the project directory structure
|
|
|
|
set dir [get_property directory [current_project]]
|
|
set proj_comps [split [string trim [file normalize [string map {\\ /} $dir]]] "/"]
|
|
set file_comps [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set is_local 1
|
|
for {set i 1} {$i < [llength $proj_comps]} {incr i} {
|
|
if { [lindex $proj_comps $i] != [lindex $file_comps $i] } {
|
|
set is_local 0;break
|
|
}
|
|
}
|
|
|
|
return $is_local
|
|
}
|
|
|
|
proc is_ip_readonly_prop { name } {
|
|
# Summary: Return true if dealing with following IP properties that are not settable for an IP in read-only state
|
|
# Argument Usage:
|
|
# name: property name
|
|
# Return Value:
|
|
# true if success, false otherwise
|
|
|
|
if { [regexp -nocase {synth_checkpoint_mode} $name] ||
|
|
[regexp -nocase {is_locked} $name] ||
|
|
[regexp -nocase {generate_synth_checkpoint} $name] } {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
proc write_properties { prop_info_list get_what tcl_obj } {
|
|
# Summary: write object properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# None
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
if {[llength $prop_info_list] > 0} {
|
|
set b_add_closing_brace 0
|
|
foreach x $prop_info_list {
|
|
set elem [split $x "#"]
|
|
set name [lindex $elem 0]
|
|
set value [lindex $elem 1]
|
|
if { [regexp "more options" $name] } {
|
|
set cmd_str "set_property -name {$name} -value {$value} -objects"
|
|
} elseif { ([is_ip_readonly_prop $name]) && ([string equal $get_what "get_files"]) } {
|
|
set cmd_str "if \{ !\[get_property \"is_locked\" \$file_obj\] \} \{"
|
|
lappend l_script_data "$cmd_str"
|
|
set cmd_str " set_property \"$name\" \"$value\""
|
|
set b_add_closing_brace 1
|
|
} else {
|
|
set cmd_str "set_property \"$name\" \"$value\""
|
|
}
|
|
if { [string equal $get_what "get_files"] } {
|
|
lappend l_script_data "$cmd_str \$file_obj"
|
|
if { $b_add_closing_brace } {
|
|
lappend l_script_data "\}"
|
|
set b_add_closing_brace 0
|
|
}
|
|
} else {
|
|
# comment "is_readonly" project property
|
|
if { [string equal $get_what "get_projects"] && [string equal "$name" "is_readonly"] } {
|
|
if { ! $a_global_vars(b_arg_all_props) } {
|
|
send_msg_id Vivado-projutils-012 INFO "The current project is in 'read_only' state. The generated script will create a writable project."
|
|
}
|
|
continue
|
|
}
|
|
lappend l_script_data "$cmd_str \$obj"
|
|
}
|
|
}
|
|
}
|
|
lappend l_script_data ""
|
|
}
|
|
|
|
proc write_props { proj_dir proj_name get_what tcl_obj type } {
|
|
# Summary: write first class object properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
variable b_project_board_set
|
|
|
|
set obj_name [get_property name [$get_what $tcl_obj]]
|
|
set read_only_props [rdi::get_attr_specs -class [get_property class $tcl_obj] -filter {is_readonly}]
|
|
set prop_info_list [list]
|
|
set properties [list_property [$get_what $tcl_obj]]
|
|
|
|
foreach prop $properties {
|
|
if { [is_deprecated $prop] } { continue }
|
|
|
|
# skip read-only properties
|
|
if { [lsearch $read_only_props $prop] != -1 } { continue }
|
|
|
|
set prop_type "unknown"
|
|
if { [string equal $type "run"] } {
|
|
if { [regexp "STEPS" $prop] } {
|
|
# skip step properties
|
|
} else {
|
|
set attr_names [rdi::get_attr_specs -class [get_property class [get_runs $tcl_obj] ]]
|
|
if { [lsearch $attr_names $prop] != -1 } {
|
|
set prop_type [get_property type [lindex $attr_names [lsearch $attr_names $prop]]]
|
|
}
|
|
}
|
|
} else {
|
|
set attr_spec [rdi::get_attr_specs -quiet $prop -object [$get_what $tcl_obj]]
|
|
if { {} == $attr_spec } {
|
|
set prop_lower [string tolower $prop]
|
|
set attr_spec [rdi::get_attr_specs -quiet $prop_lower -object [$get_what $tcl_obj]]
|
|
}
|
|
set prop_type [get_property type $attr_spec]
|
|
}
|
|
set def_val [list_property_value -default $prop $tcl_obj]
|
|
set dump_prop_name [string tolower ${obj_name}_${type}_$prop]
|
|
set cur_val [get_property $prop $tcl_obj]
|
|
|
|
# filter special properties
|
|
if { [filter $prop $cur_val] } { continue }
|
|
|
|
# do not set "runs" or "project" part, if "board_part" is set
|
|
if { ([string equal $type "project"] || [string equal $type "run"]) &&
|
|
[string equal -nocase $prop "part"] &&
|
|
$b_project_board_set } {
|
|
continue
|
|
}
|
|
|
|
# do not set "fileset" target_part, if "board_part" is set
|
|
if { [string equal $type "fileset"] &&
|
|
[string equal -nocase $prop "target_part"] &&
|
|
$b_project_board_set } {
|
|
continue
|
|
}
|
|
|
|
# re-align values
|
|
set cur_val [get_target_bool_val $def_val $cur_val]
|
|
|
|
set prop_entry "[string tolower $prop]#[get_property $prop [$get_what $tcl_obj]]"
|
|
|
|
# fix paths wrt the original project dir
|
|
if {([string equal -nocase $prop "top_file"]) && ($cur_val != "") } {
|
|
set file $cur_val
|
|
|
|
set srcs_dir "${proj_name}.srcs"
|
|
set file_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set src_file [join [lrange $file_dirs [lsearch -exact $file_dirs "$srcs_dir"] end] "/"]
|
|
|
|
if { [is_local_to_project $file] } {
|
|
set proj_file_path "\$proj_dir/$src_file"
|
|
} else {
|
|
set proj_file_path "[get_relative_file_path_for_source $src_file [get_script_execution_dir]]"
|
|
}
|
|
set prop_entry "[string tolower $prop]#$proj_file_path"
|
|
|
|
} elseif {([string equal -nocase $prop "target_constrs_file"] ||
|
|
[string equal -nocase $prop "target_ucf"]) &&
|
|
($cur_val != "") } {
|
|
|
|
set file $cur_val
|
|
set fs_name $tcl_obj
|
|
|
|
set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set src_file [join [lrange $path_dirs [lsearch -exact $path_dirs "$fs_name"] end] "/"]
|
|
set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
|
|
set file_props [list_property $file_object]
|
|
|
|
if { [lsearch $file_props "IMPORTED_FROM"] != -1 } {
|
|
if { $a_global_vars(b_arg_no_copy_srcs) } {
|
|
set proj_file_path "\$orig_proj_dir/${proj_name}.srcs/$src_file"
|
|
} else {
|
|
set proj_file_path "\$proj_dir/${proj_name}.srcs/$src_file"
|
|
}
|
|
} else {
|
|
# is file new inside project?
|
|
if { [is_local_to_project $file] } {
|
|
# is file inside fileset dir?
|
|
if { [regexp "^${fs_name}/" $src_file] } {
|
|
set proj_file_path "\$orig_proj_dir/${proj_name}.srcs/$src_file"
|
|
} else {
|
|
set file_no_quotes [string trim $file "\""]
|
|
set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
|
|
set proj_file_path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
|
|
#set proj_file_path "$file"
|
|
}
|
|
} else {
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
set proj_file_path "$file"
|
|
} else {
|
|
set file_no_quotes [string trim $file "\""]
|
|
set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
|
|
set proj_file_path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
|
|
}
|
|
}
|
|
}
|
|
|
|
set prop_entry "[string tolower $prop]#$proj_file_path"
|
|
}
|
|
|
|
|
|
# re-align compiled_library_dir
|
|
if { [string equal -nocase $prop "compxlib.compiled_library_dir"] ||
|
|
[string equal -nocase $prop "compxlib.modelsim_compiled_library_dir"] ||
|
|
[string equal -nocase $prop "compxlib.questa_compiled_library_dir"] ||
|
|
[string equal -nocase $prop "compxlib.ies_compiled_library_dir"] ||
|
|
[string equal -nocase $prop "compxlib.vcs_compiled_library_dir"] ||
|
|
[string equal -nocase $prop "compxlib.riviera_compiled_library_dir"] ||
|
|
[string equal -nocase $prop "compxlib.activehdl_compiled_library_dir"] } {
|
|
set compile_lib_dir_path $cur_val
|
|
set cache_dir "${proj_name}.cache"
|
|
set path_dirs [split [string trim [file normalize [string map {\\ /} $cur_val]]] "/"]
|
|
if {[lsearch -exact $path_dirs "$cache_dir"] > 0} {
|
|
set dir_path [join [lrange $path_dirs [lsearch -exact $path_dirs "$cache_dir"] end] "/"]
|
|
set compile_lib_dir_path "\$proj_dir/$dir_path"
|
|
}
|
|
set prop_entry "[string tolower $prop]#$compile_lib_dir_path"
|
|
}
|
|
|
|
# process run step tcl pre/post properties
|
|
if { [string equal $type "run"] } {
|
|
if { [regexp "STEPS" $prop] } {
|
|
if { [regexp "TCL.PRE" $prop] || [regexp "TCL.POST" $prop] } {
|
|
if { ($cur_val != "") } {
|
|
set file $cur_val
|
|
|
|
set srcs_dir "${proj_name}.srcs"
|
|
set file_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set src_file [join [lrange $file_dirs [lsearch -exact $file_dirs "$srcs_dir"] end] "/"]
|
|
|
|
set tcl_file_path {}
|
|
if { [is_local_to_project $file] } {
|
|
set tcl_file_path "\$proj_dir/$src_file"
|
|
} else {
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
set tcl_file_path "$file"
|
|
} else {
|
|
set rel_file_path "[get_relative_file_path_for_source $src_file [get_script_execution_dir]]"
|
|
set tcl_file_path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
|
|
}
|
|
}
|
|
set prop_entry "[string tolower $prop]#$tcl_file_path"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if { $a_global_vars(b_arg_all_props) } {
|
|
lappend prop_info_list $prop_entry
|
|
} else {
|
|
if { $def_val != $cur_val } {
|
|
lappend prop_info_list $prop_entry
|
|
}
|
|
}
|
|
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
if { ([string equal -nocase $prop "top_file"] ||
|
|
[string equal -nocase $prop "target_constrs_file"] ||
|
|
[string equal -nocase $prop "target_ucf"] ) && [string equal $type "fileset"] } {
|
|
|
|
# fix path
|
|
set file $cur_val
|
|
|
|
set srcs_dir "${proj_name}.srcs"
|
|
set file_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set src_file [join [lrange $file_dirs [lsearch -exact $file_dirs "$srcs_dir"] end] "/"]
|
|
set cur_val "\$PSRCDIR/$src_file"
|
|
}
|
|
puts $a_global_vars(def_val_fh) "$prop:($prop_type) DEFAULT_VALUE ($def_val)==CURRENT_VALUE ($cur_val)"
|
|
puts $a_global_vars(dp_fh) "${dump_prop_name}=$cur_val"
|
|
}
|
|
}
|
|
|
|
if { {fileset} == $type } {
|
|
set fs_type [get_property fileset_type [get_filesets $tcl_obj]]
|
|
if { {SimulationSrcs} == $fs_type } {
|
|
if { ![get_property is_readonly [current_project]] } {
|
|
add_simulator_props $get_what $tcl_obj prop_info_list
|
|
}
|
|
}
|
|
}
|
|
|
|
# write properties now
|
|
write_properties $prop_info_list $get_what $tcl_obj
|
|
|
|
}
|
|
|
|
proc add_simulator_props { get_what tcl_obj prop_info_list_arg } {
|
|
# Summary: write file and file properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
upvar $prop_info_list_arg prop_info_list
|
|
|
|
set target_simulator [get_property target_simulator [current_project]]
|
|
set simulators [get_simulators]
|
|
foreach simulator [get_simulators] {
|
|
if { $target_simulator == $simulator } { continue }
|
|
set_property target_simulator $simulator [current_project]
|
|
set prefix [string tolower [lindex [split $simulator {.}] 0]]
|
|
write_simulator_props $prefix $get_what $tcl_obj prop_info_list
|
|
}
|
|
set_property target_simulator $target_simulator [current_project]
|
|
}
|
|
|
|
proc write_simulator_props { prefix get_what tcl_obj prop_info_list_arg } {
|
|
# Summary: write non-default simulator properties
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
upvar $prop_info_list_arg prop_info_list
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
set read_only_props [rdi::get_attr_specs -class [get_property class $tcl_obj] -filter {is_readonly}]
|
|
foreach prop [list_property [$get_what $tcl_obj]] {
|
|
if { [lsearch $read_only_props $prop] != -1 } { continue }
|
|
if { [is_deprecated_property $prop] } { continue }
|
|
set sim_prefix [string tolower [lindex [split $prop {.}] 0]]
|
|
if { $prefix != $sim_prefix } { continue }
|
|
|
|
set attr_spec [rdi::get_attr_specs -quiet $prop -object [$get_what $tcl_obj]]
|
|
if { {} == $attr_spec } {
|
|
set prop_lower [string tolower $prop]
|
|
set attr_spec [rdi::get_attr_specs -quiet $prop_lower -object [$get_what $tcl_obj]]
|
|
}
|
|
set prop_type [get_property type $attr_spec]
|
|
set def_val [list_property_value -default $prop $tcl_obj]
|
|
set cur_val [get_property $prop $tcl_obj]
|
|
set cur_val [get_target_bool_val $def_val $cur_val]
|
|
set prop_entry "[string tolower $prop]#[get_property $prop [$get_what $tcl_obj]]"
|
|
if { $def_val != $cur_val } {
|
|
lappend prop_info_list $prop_entry
|
|
}
|
|
}
|
|
}
|
|
|
|
proc is_deprecated_property { property } {
|
|
# Summary: filter old properties
|
|
# Argument Usage:
|
|
# Return Value:
|
|
|
|
set property [string tolower $property]
|
|
|
|
if { [string equal $property "runtime"] ||
|
|
[string equal $property "unit_under_test"] ||
|
|
[string equal $property "xelab.snapshot"] ||
|
|
[string equal $property "xelab.debug_level"] ||
|
|
[string equal $property "xelab.relax"] ||
|
|
[string equal $property "xelab.mt_level"] ||
|
|
[string equal $property "xelab.load_glbl"] ||
|
|
[string equal $property "xelab.rangecheck"] ||
|
|
[string equal $property "xelab.sdf_delay"] ||
|
|
[string equal $property "xelab.unifast"] ||
|
|
[string equal $property "xelab.nosort"] ||
|
|
[string equal $property "xelab.more_options"] ||
|
|
[string equal $property "xsim.view"] ||
|
|
[string equal $property "xsim.wdb"] ||
|
|
[string equal $property "xsim.saif"] ||
|
|
[string equal $property "xsim.more_options"] ||
|
|
[string equal $property "modelsim.custom_do"] ||
|
|
[string equal $property "modelsim.custom_udo"] ||
|
|
[string equal $property "modelsim.vhdl_syntax"] ||
|
|
[string equal $property "modelsim.use_explicit_decl"] ||
|
|
[string equal $property "modelsim.log_all_signals"] ||
|
|
[string equal $property "modelsim.sdf_delay"] ||
|
|
[string equal $property "modelsim.saif"] ||
|
|
[string equal $property "modelsim.incremental"] ||
|
|
[string equal $property "modelsim.unifast"] ||
|
|
[string equal $property "modelsim.64bit"] ||
|
|
[string equal $property "modelsim.vsim_more_options"] ||
|
|
[string equal $property "modelsim.vlog_more_options"] ||
|
|
[string equal $property "modelsim.vcom_more_options"] } {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
proc write_files { proj_dir proj_name tcl_obj type } {
|
|
# Summary: write file and file properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
set l_local_file_list [list]
|
|
set l_remote_file_list [list]
|
|
|
|
# return if empty fileset
|
|
if {[llength [get_files -quiet -of_objects [get_filesets $tcl_obj]]] == 0 } {
|
|
lappend l_script_data "# Empty (no sources present)\n"
|
|
return
|
|
}
|
|
|
|
set fs_name [get_filesets $tcl_obj]
|
|
|
|
set import_coln [list]
|
|
set add_file_coln [list]
|
|
|
|
foreach file [get_files -norecurse -of_objects [get_filesets $tcl_obj]] {
|
|
if { [file extension $file] == ".xcix" } { continue }
|
|
set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set begin [lsearch -exact $path_dirs "$proj_name.srcs"]
|
|
set src_file [join [lrange $path_dirs $begin+1 end] "/"]
|
|
|
|
# fetch first object
|
|
set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
|
|
set file_props [list_property $file_object]
|
|
|
|
if { [lsearch $file_props "IMPORTED_FROM"] != -1 } {
|
|
|
|
# import files
|
|
set imported_path [get_property "imported_from" $file]
|
|
set rel_file_path [get_relative_file_path_for_source $file [get_script_execution_dir]]
|
|
set proj_file_path "\$origin_dir/$rel_file_path"
|
|
|
|
set file "\"[file normalize $proj_dir/${proj_name}.srcs/$src_file]\""
|
|
|
|
if { $a_global_vars(b_arg_no_copy_srcs) } {
|
|
# add to the local collection
|
|
lappend l_remote_file_list $file
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend add_file_coln "$file"
|
|
} else {
|
|
lappend add_file_coln "\"\[file normalize \"$proj_file_path\"\]\""
|
|
}
|
|
} else {
|
|
# add to the import collection
|
|
lappend l_local_file_list $file
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend import_coln "$file"
|
|
} else {
|
|
lappend import_coln "\"\[file normalize \"$proj_file_path\"\]\""
|
|
}
|
|
}
|
|
|
|
} else {
|
|
set file "\"$file\""
|
|
|
|
# is local? add to local project, add to collection and then import this collection by default unless -no_copy_sources is specified
|
|
if { [is_local_to_project $file] } {
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
set src_file "\$PSRCDIR/$src_file"
|
|
}
|
|
|
|
# add to the import collection
|
|
set file_no_quotes [string trim $file "\""]
|
|
set org_file_path "\$origin_dir/[get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]"
|
|
lappend import_coln "\"\[file normalize \"$org_file_path\"\]\""
|
|
lappend l_local_file_list $file
|
|
} else {
|
|
lappend l_remote_file_list $file
|
|
}
|
|
|
|
# add file to collection
|
|
if { $a_global_vars(b_arg_no_copy_srcs) && (!$a_global_vars(b_absolute_path))} {
|
|
set file_no_quotes [string trim $file "\""]
|
|
set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
|
|
set file1 "\"\[file normalize \"\$origin_dir/$rel_file_path\"\]\""
|
|
lappend add_file_coln "$file1"
|
|
} else {
|
|
lappend add_file_coln "$file"
|
|
}
|
|
|
|
# set flag that local sources were found and print warning at the end
|
|
if { !$a_global_vars(b_local_sources) } {
|
|
set a_global_vars(b_local_sources) 1
|
|
}
|
|
}
|
|
}
|
|
|
|
if {[llength $add_file_coln]>0} {
|
|
lappend l_script_data "set files \[list \\"
|
|
foreach file $add_file_coln {
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend l_script_data " $file\\"
|
|
} else {
|
|
if { $a_global_vars(b_arg_no_copy_srcs) } {
|
|
lappend l_script_data " $file\\"
|
|
} else {
|
|
set file_no_quotes [string trim $file "\""]
|
|
set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
|
|
lappend l_script_data " \"\[file normalize \"\$origin_dir/$rel_file_path\"\]\"\\"
|
|
}
|
|
}
|
|
}
|
|
lappend l_script_data "\]"
|
|
lappend l_script_data "add_files -norecurse -fileset \$obj \$files"
|
|
lappend l_script_data ""
|
|
}
|
|
|
|
# now import local files if -no_copy_sources is not specified
|
|
if { ! $a_global_vars(b_arg_no_copy_srcs)} {
|
|
if { [llength $import_coln] > 0 } {
|
|
lappend l_script_data "# Import local files from the original project"
|
|
lappend l_script_data "set files \[list \\"
|
|
foreach ifile $import_coln {
|
|
lappend l_script_data " $ifile\\"
|
|
}
|
|
lappend l_script_data "\]"
|
|
# is this a IP block fileset? if yes, import files into current source fileset
|
|
if { [is_ip_fileset $tcl_obj] } {
|
|
lappend l_script_data "set imported_files \[import_files -fileset [current_fileset -srcset] \$files\]"
|
|
} else {
|
|
lappend l_script_data "set imported_files \[import_files -fileset $tcl_obj \$files\]"
|
|
}
|
|
lappend l_script_data ""
|
|
}
|
|
}
|
|
|
|
# write fileset file properties for remote files (added sources)
|
|
write_fileset_file_properties $tcl_obj $fs_name $proj_dir $l_remote_file_list "remote"
|
|
|
|
# write fileset file properties for local files (imported sources)
|
|
write_fileset_file_properties $tcl_obj $fs_name $proj_dir $l_local_file_list "local"
|
|
|
|
}
|
|
|
|
proc write_constrs { proj_dir proj_name tcl_obj type } {
|
|
# Summary: write constrs fileset files and properties
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
set fs_name [get_filesets $tcl_obj]
|
|
|
|
# return if empty fileset
|
|
if {[llength [get_files -quiet -of_objects [get_filesets $tcl_obj]]] == 0 } {
|
|
lappend l_script_data "# Empty (no sources present)\n"
|
|
return
|
|
}
|
|
|
|
foreach file [get_files -norecurse -of_objects [get_filesets $tcl_obj]] {
|
|
lappend l_script_data "# Add/Import constrs file and set constrs file properties"
|
|
set constrs_file {}
|
|
set file_category {}
|
|
set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set begin [lsearch -exact $path_dirs "$proj_name.srcs"]
|
|
set src_file [join [lrange $path_dirs $begin+1 end] "/"]
|
|
set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
|
|
set file_props [list_property $file_object]
|
|
|
|
# constrs sources imported?
|
|
if { [lsearch $file_props "IMPORTED_FROM"] != -1 } {
|
|
set imported_path [get_property "imported_from" $file]
|
|
set rel_file_path [get_relative_file_path_for_source $file [get_script_execution_dir]]
|
|
set proj_file_path "\$origin_dir/$rel_file_path"
|
|
set file "\"[file normalize $proj_dir/${proj_name}.srcs/$src_file]\""
|
|
# donot copy imported constrs in new project? set it as remote file in new project.
|
|
if { $a_global_vars(b_arg_no_copy_srcs) } {
|
|
set constrs_file $file
|
|
set file_category "remote"
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
add_constrs_file "$file"
|
|
} else {
|
|
set str "\"\[file normalize \"$proj_file_path\"\]\""
|
|
add_constrs_file $str
|
|
}
|
|
} else {
|
|
# copy imported constrs in new project. Set it as local file in new project.
|
|
set constrs_file $file
|
|
set file_category "local"
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
import_constrs_file $tcl_obj "$file"
|
|
} else {
|
|
set str "\"\[file normalize \"$proj_file_path\"\]\""
|
|
import_constrs_file $tcl_obj $str
|
|
}
|
|
}
|
|
} else {
|
|
# constrs sources were added, so check if these are local or added from remote location
|
|
set file "\"$file\""
|
|
set constrs_file $file
|
|
|
|
# is added constrs local to the project? import it in the new project and set it as local in the new project
|
|
if { [is_local_to_project $file] } {
|
|
# file is added from within project, so set it as local in the new project
|
|
set file_category "local"
|
|
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
set src_file "\$PSRCDIR/$src_file"
|
|
}
|
|
set file_no_quotes [string trim $file "\""]
|
|
set org_file_path "\$origin_dir/[get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]"
|
|
set str "\"\[file normalize \"$org_file_path\"\]\""
|
|
if { $a_global_vars(b_arg_no_copy_srcs)} {
|
|
add_constrs_file "$str"
|
|
} else {
|
|
import_constrs_file $tcl_obj $str
|
|
}
|
|
} else {
|
|
# file is added from remote location, so set it as remote in the new project
|
|
set file_category "remote"
|
|
|
|
# find relative file path of the added constrs if no_copy in the new project
|
|
if { $a_global_vars(b_arg_no_copy_srcs) && (!$a_global_vars(b_absolute_path))} {
|
|
set file_no_quotes [string trim $file "\""]
|
|
set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
|
|
set file_1 "\"\[file normalize \"\$origin_dir/$rel_file_path\"\]\""
|
|
add_constrs_file "$file_1"
|
|
} else {
|
|
add_constrs_file "$file"
|
|
}
|
|
}
|
|
|
|
# set flag that local sources were found and print warning at the end
|
|
if { !$a_global_vars(b_local_sources) } {
|
|
set a_global_vars(b_local_sources) 1
|
|
}
|
|
}
|
|
write_constrs_fileset_file_properties $tcl_obj $fs_name $proj_dir $constrs_file $file_category
|
|
}
|
|
}
|
|
|
|
proc add_constrs_file { file_str } {
|
|
# Summary: add constrs file
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend l_script_data "set file $file_str"
|
|
} else {
|
|
if { $a_global_vars(b_arg_no_copy_srcs) } {
|
|
lappend l_script_data "set file $file_str"
|
|
} else {
|
|
set file_no_quotes [string trim $file_str "\""]
|
|
set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
|
|
lappend l_script_data "set file \"\[file normalize \"\$origin_dir/$rel_file_path\"\]\""
|
|
}
|
|
}
|
|
lappend l_script_data "set file_added \[add_files -norecurse -fileset \$obj \$file\]"
|
|
}
|
|
|
|
proc import_constrs_file { tcl_obj file_str } {
|
|
# Summary: import constrs file
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
# now import local files if -no_copy_sources is not specified
|
|
if { ! $a_global_vars(b_arg_no_copy_srcs)} {
|
|
lappend l_script_data "set file $file_str"
|
|
lappend l_script_data "set file_imported \[import_files -fileset $tcl_obj \$file\]"
|
|
}
|
|
}
|
|
|
|
proc write_constrs_fileset_file_properties { tcl_obj fs_name proj_dir file file_category } {
|
|
# Summary: write constrs fileset file properties
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
variable l_local_files
|
|
variable l_remote_files
|
|
|
|
set file_prop_count 0
|
|
|
|
# collect local/remote files for the header section
|
|
if { [string equal $file_category "local"] } {
|
|
lappend l_local_files $file
|
|
} elseif { [string equal $file_category "remote"] } {
|
|
lappend l_remote_files $file
|
|
}
|
|
|
|
set file [string trim $file "\""]
|
|
|
|
# fix file path for local files
|
|
if { [string equal $file_category "local"] } {
|
|
set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set src_file [join [lrange $path_dirs end-1 end] "/"]
|
|
set src_file [string trimleft $src_file "/"]
|
|
set src_file [string trimleft $src_file "\\"]
|
|
set file $src_file
|
|
}
|
|
|
|
set file_object ""
|
|
if { [string equal $file_category "local"] } {
|
|
set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list "*$file"]] 0]
|
|
} elseif { [string equal $file_category "remote"] } {
|
|
set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
|
|
}
|
|
|
|
# get the constrs file properties
|
|
set file_props [list_property $file_object]
|
|
set prop_info_list [list]
|
|
set prop_count 0
|
|
foreach file_prop $file_props {
|
|
set is_readonly [get_property is_readonly [rdi::get_attr_specs $file_prop -object $file_object]]
|
|
if { [string equal $is_readonly "1"] } {
|
|
continue
|
|
}
|
|
set prop_type [get_property type [rdi::get_attr_specs $file_prop -object $file_object]]
|
|
set def_val [list_property_value -default $file_prop $file_object]
|
|
set cur_val [get_property $file_prop $file_object]
|
|
|
|
# filter special properties
|
|
if { [filter $file_prop $cur_val $file] } { continue }
|
|
|
|
# re-align values
|
|
set cur_val [get_target_bool_val $def_val $cur_val]
|
|
|
|
set dump_prop_name [string tolower ${fs_name}_file_${file_prop}]
|
|
set prop_entry ""
|
|
if { [string equal $file_category "local"] } {
|
|
set prop_entry "[string tolower $file_prop]#[get_property $file_prop $file_object]"
|
|
} elseif { [string equal $file_category "remote"] } {
|
|
set prop_value_entry [get_property $file_prop $file_object]
|
|
set prop_entry "[string tolower $file_prop]#$prop_value_entry"
|
|
}
|
|
# include all properties?
|
|
if { $a_global_vars(b_arg_all_props) } {
|
|
lappend prop_info_list $prop_entry
|
|
incr prop_count
|
|
} else {
|
|
# include only non-default (default behavior)
|
|
if { $def_val != $cur_val } {
|
|
lappend prop_info_list $prop_entry
|
|
incr prop_count
|
|
}
|
|
}
|
|
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
puts $a_global_vars(def_val_fh) "[file tail $file]=$file_prop ($prop_type) :DEFAULT_VALUE ($def_val)==CURRENT_VALUE ($cur_val)"
|
|
puts $a_global_vars(dp_fh) "$dump_prop_name=$cur_val"
|
|
}
|
|
}
|
|
|
|
# write properties now
|
|
if { $prop_count>0 } {
|
|
if { {remote} == $file_category } {
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend l_script_data "set file \"$file\""
|
|
} else {
|
|
lappend l_script_data "set file \"\$origin_dir/[get_relative_file_path_for_source $file [get_script_execution_dir]]\""
|
|
lappend l_script_data "set file \[file normalize \$file\]"
|
|
}
|
|
} else {
|
|
lappend l_script_data "set file \"$file\""
|
|
}
|
|
|
|
lappend l_script_data "set file_obj \[get_files -of_objects \[get_filesets $tcl_obj\] \[list \"*\$file\"\]\]"
|
|
set get_what "get_files"
|
|
write_properties $prop_info_list $get_what $tcl_obj
|
|
incr file_prop_count
|
|
}
|
|
|
|
if { $file_prop_count == 0 } {
|
|
lappend l_script_data "# None"
|
|
}
|
|
}
|
|
|
|
proc write_specified_run { proj_dir proj_name runs } {
|
|
# Summary: write the specified run information
|
|
# This helper command is used to script help.
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
|
|
set get_what "get_runs"
|
|
foreach tcl_obj $runs {
|
|
# is block fileset based run that contains IP? donot create OOC run
|
|
if { [is_ip_run $tcl_obj] } {
|
|
continue
|
|
}
|
|
# fetch run attributes
|
|
set part [get_property part [$get_what $tcl_obj]]
|
|
set parent_run [get_property parent [$get_what $tcl_obj]]
|
|
set src_set [get_property srcset [$get_what $tcl_obj]]
|
|
set constrs_set [get_property constrset [$get_what $tcl_obj]]
|
|
set strategy [get_property strategy [$get_what $tcl_obj]]
|
|
set parent_run_str ""
|
|
if { $parent_run != "" } {
|
|
set parent_run_str " -parent_run $parent_run"
|
|
}
|
|
|
|
set def_flow_type_val [list_property_value -default flow [$get_what $tcl_obj]]
|
|
set cur_flow_type_val [get_property flow [$get_what $tcl_obj]]
|
|
set def_strat_type_val [list_property_value -default strategy [$get_what $tcl_obj]]
|
|
set cur_strat_type_val [get_property strategy [$get_what $tcl_obj]]
|
|
|
|
lappend l_script_data "# Create '$tcl_obj' run (if not found)"
|
|
lappend l_script_data "if \{\[string equal \[get_runs -quiet $tcl_obj\] \"\"\]\} \{"
|
|
set cmd_str " create_run -name $tcl_obj -part $part -flow {$cur_flow_type_val} -strategy \"$cur_strat_type_val\""
|
|
lappend l_script_data "$cmd_str -constrset $constrs_set$parent_run_str"
|
|
lappend l_script_data "\} else \{"
|
|
lappend l_script_data " set_property strategy \"$cur_strat_type_val\" \[get_runs $tcl_obj\]"
|
|
lappend l_script_data " set_property flow \"$cur_flow_type_val\" \[get_runs $tcl_obj\]"
|
|
lappend l_script_data "\}"
|
|
|
|
lappend l_script_data "set obj \[$get_what $tcl_obj\]"
|
|
write_props $proj_dir $proj_name $get_what $tcl_obj "run"
|
|
}
|
|
}
|
|
|
|
proc get_fileset_type_switch { fileset_type } {
|
|
# Summary: Return the fileset type switch for a given fileset
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# Fileset type switch name
|
|
|
|
variable a_fileset_types
|
|
|
|
set fs_switch ""
|
|
foreach {fs_data} $a_fileset_types {
|
|
set fs_type [lindex $fs_data 0]
|
|
if { [string equal -nocase $fileset_type $fs_type] } {
|
|
set fs_switch [lindex $fs_data 1]
|
|
set fs_switch "-$fs_switch"
|
|
break
|
|
}
|
|
}
|
|
return $fs_switch
|
|
}
|
|
|
|
proc get_target_bool_val { def_val cur_val } {
|
|
# Summary: Resolve current boolean property value wrt its default value
|
|
# Argument Usage:
|
|
# Return Value:
|
|
# Resolved boolean value
|
|
|
|
set target_val $cur_val
|
|
|
|
if { [string equal $def_val "false"] && [string equal $cur_val "0"] } { set target_val "false" } \
|
|
elseif { [string equal $def_val "true"] && [string equal $cur_val "1"] } { set target_val "true" } \
|
|
elseif { [string equal $def_val "false"] && [string equal $cur_val "1"] } { set target_val "true" } \
|
|
elseif { [string equal $def_val "true"] && [string equal $cur_val "0"] } { set target_val "false" } \
|
|
elseif { [string equal $def_val "{}"] && [string equal $cur_val ""] } { set target_val "{}" }
|
|
|
|
return $target_val
|
|
}
|
|
|
|
proc write_fileset_file_properties { tcl_obj fs_name proj_dir l_file_list file_category } {
|
|
# Summary:
|
|
# Write fileset file properties for local and remote files
|
|
# Argument Usage:
|
|
# tcl_obj: object to inspect
|
|
# fs_name: fileset name
|
|
# l_file_list: list of files (local or remote)
|
|
# file_category: file catwgory (local or remote)
|
|
# Return Value:
|
|
# none
|
|
|
|
variable a_global_vars
|
|
variable l_script_data
|
|
variable l_local_files
|
|
variable l_remote_files
|
|
|
|
# is this a IP block fileset? if yes, set current source fileset
|
|
if { [is_ip_fileset $tcl_obj] } {
|
|
lappend l_script_data "# Set '[current_fileset -srcset]' fileset file properties for $file_category files"
|
|
} else {
|
|
lappend l_script_data "# Set '$tcl_obj' fileset file properties for $file_category files"
|
|
}
|
|
set file_prop_count 0
|
|
|
|
# collect local/remote files
|
|
foreach file $l_file_list {
|
|
if { [string equal $file_category "local"] } {
|
|
lappend l_local_files $file
|
|
} elseif { [string equal $file_category "remote"] } {
|
|
lappend l_remote_files $file
|
|
} else {}
|
|
}
|
|
|
|
foreach file $l_file_list {
|
|
set file [string trim $file "\""]
|
|
|
|
# fix file path for local files
|
|
if { [string equal $file_category "local"] } {
|
|
set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
|
|
set src_file [join [lrange $path_dirs end-1 end] "/"]
|
|
set src_file [string trimleft $src_file "/"]
|
|
set src_file [string trimleft $src_file "\\"]
|
|
set file $src_file
|
|
}
|
|
|
|
set file_object ""
|
|
if { [string equal $file_category "local"] } {
|
|
set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list "*$file"]] 0]
|
|
} elseif { [string equal $file_category "remote"] } {
|
|
set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
|
|
}
|
|
|
|
set file_props [list_property $file_object]
|
|
set prop_info_list [list]
|
|
set prop_count 0
|
|
|
|
foreach file_prop $file_props {
|
|
set is_readonly [get_property is_readonly [rdi::get_attr_specs $file_prop -object $file_object]]
|
|
if { [string equal $is_readonly "1"] } {
|
|
continue
|
|
}
|
|
|
|
set prop_type [get_property type [rdi::get_attr_specs $file_prop -object $file_object]]
|
|
set def_val [list_property_value -default $file_prop $file_object]
|
|
set cur_val [get_property $file_prop $file_object]
|
|
|
|
# filter special properties
|
|
if { [filter $file_prop $cur_val $file] } { continue }
|
|
|
|
# re-align values
|
|
set cur_val [get_target_bool_val $def_val $cur_val]
|
|
|
|
set dump_prop_name [string tolower ${fs_name}_file_${file_prop}]
|
|
set prop_entry ""
|
|
if { [string equal $file_category "local"] } {
|
|
set prop_entry "[string tolower $file_prop]#[get_property $file_prop $file_object]"
|
|
} elseif { [string equal $file_category "remote"] } {
|
|
set prop_value_entry [get_property $file_prop $file_object]
|
|
set prop_entry "[string tolower $file_prop]#$prop_value_entry"
|
|
} else {}
|
|
|
|
if { $a_global_vars(b_arg_all_props) } {
|
|
lappend prop_info_list $prop_entry
|
|
incr prop_count
|
|
} else {
|
|
if { $def_val != $cur_val } {
|
|
lappend prop_info_list $prop_entry
|
|
incr prop_count
|
|
}
|
|
}
|
|
|
|
if { $a_global_vars(b_arg_dump_proj_info) } {
|
|
puts $a_global_vars(def_val_fh) "[file tail $file]=$file_prop ($prop_type) :DEFAULT_VALUE ($def_val)==CURRENT_VALUE ($cur_val)"
|
|
puts $a_global_vars(dp_fh) "$dump_prop_name=$cur_val"
|
|
}
|
|
}
|
|
|
|
# write properties now
|
|
if { $prop_count>0 } {
|
|
if { {remote} == $file_category } {
|
|
if { $a_global_vars(b_absolute_path) } {
|
|
lappend l_script_data "set file \"$file\""
|
|
} else {
|
|
lappend l_script_data "set file \"\$origin_dir/[get_relative_file_path_for_source $file [get_script_execution_dir]]\""
|
|
lappend l_script_data "set file \[file normalize \$file\]"
|
|
}
|
|
} else {
|
|
lappend l_script_data "set file \"$file\""
|
|
}
|
|
# is this a IP block fileset? if yes, get files from current source fileset
|
|
if { [is_ip_fileset $tcl_obj] } {
|
|
lappend l_script_data "set file_obj \[get_files -of_objects \[get_filesets [current_fileset -srcset]\] \[list \"*\$file\"\]\]"
|
|
} else {
|
|
lappend l_script_data "set file_obj \[get_files -of_objects \[get_filesets $tcl_obj\] \[list \"*\$file\"\]\]"
|
|
}
|
|
set get_what "get_files"
|
|
write_properties $prop_info_list $get_what $tcl_obj
|
|
incr file_prop_count
|
|
}
|
|
}
|
|
|
|
if { $file_prop_count == 0 } {
|
|
lappend l_script_data "# None"
|
|
}
|
|
lappend l_script_data ""
|
|
}
|
|
|
|
proc get_script_execution_dir { } {
|
|
# Summary: Return script directory path from where the script will be executed
|
|
# Argument Usage:
|
|
# none
|
|
# Return Value:
|
|
# Path to the script direc
|
|
|
|
variable a_global_vars
|
|
|
|
# default: return script directory path
|
|
set scr_exe_dir $a_global_vars(s_path_to_script_dir)
|
|
|
|
# is -path_to_relative specified and the path exists? return this dir
|
|
set rel_to_dir $a_global_vars(s_relative_to)
|
|
if { ("." != $rel_to_dir) } {
|
|
set rel_to_dir [file normalize $rel_to_dir]
|
|
if { [file exists $rel_to_dir] } {
|
|
set scr_exe_dir $rel_to_dir
|
|
}
|
|
}
|
|
return $scr_exe_dir
|
|
}
|
|
|
|
# TODO: This is the same as xcs_get_relative_file_path for simulators, see common/utils.tcl
|
|
# Remember to add the 'source .../common/utils.tcl' in the write_project_tcl proc to load the common file
|
|
proc get_relative_file_path_for_source { file_path_to_convert relative_to } {
|
|
# Summary: Get the relative path wrt to path specified
|
|
# Argument Usage:
|
|
# file_path_to_convert: input file to make relative to specfied path
|
|
# Return Value:
|
|
# Relative path wrt the path specified
|
|
|
|
variable a_xport_sim_vars
|
|
|
|
# make sure we are dealing with a valid relative_to directory. If regular file or is not a directory, get directory
|
|
if { [file isfile $relative_to] || ![file isdirectory $relative_to] } {
|
|
set relative_to [file dirname $relative_to]
|
|
}
|
|
|
|
set cwd [file normalize [pwd]]
|
|
|
|
if { [file pathtype $file_path_to_convert] eq "relative" } {
|
|
# is relative_to path same as cwd?, just return this path, no further processing required
|
|
if { [string equal $relative_to $cwd] } {
|
|
return $file_path_to_convert
|
|
}
|
|
# the specified path is "relative" but something else, so make it absolute wrt current working dir
|
|
set file_path_to_convert [file join $cwd $file_path_to_convert]
|
|
}
|
|
|
|
# is relative_to "relative"? convert to absolute as well wrt cwd
|
|
if { [file pathtype $relative_to] eq "relative" } {
|
|
set relative_to [file join $cwd $relative_to]
|
|
}
|
|
|
|
# normalize
|
|
set file_path_to_convert [file normalize $file_path_to_convert]
|
|
set relative_to [file normalize $relative_to]
|
|
|
|
set file_path $file_path_to_convert
|
|
set file_comps [file split $file_path]
|
|
set relative_to_comps [file split $relative_to]
|
|
|
|
set found_match false
|
|
set index 0
|
|
|
|
set fc_comps_len [llength $file_comps]
|
|
set rt_comps_len [llength $relative_to_comps]
|
|
|
|
# compare each dir element of file_to_convert and relative_to, set the flag and
|
|
# get the final index till these sub-dirs matched. Break if limit reaches.
|
|
while { [lindex $file_comps $index] == [lindex $relative_to_comps $index] } {
|
|
if { !$found_match } { set found_match true }
|
|
incr index
|
|
if { ($index == $fc_comps_len) || ($index == $rt_comps_len) } {
|
|
break;
|
|
}
|
|
}
|
|
|
|
# any common dirs found? convert path to relative
|
|
if { $found_match } {
|
|
set parent_dir_path ""
|
|
set rel_index $index
|
|
# keep traversing the relative_to dirs and build "../" levels
|
|
while { [lindex $relative_to_comps $rel_index] != "" } {
|
|
set parent_dir_path "../$parent_dir_path"
|
|
incr rel_index
|
|
}
|
|
|
|
#
|
|
# at this point we have parent_dir_path setup with exact number of sub-dirs to go up
|
|
#
|
|
|
|
# now build up part of path which is relative to matched part
|
|
set rel_path ""
|
|
set rel_index $index
|
|
|
|
while { [lindex $file_comps $rel_index] != "" } {
|
|
set comps [lindex $file_comps $rel_index]
|
|
if { $rel_path == "" } {
|
|
# first dir
|
|
set rel_path $comps
|
|
} else {
|
|
# append remaining dirs
|
|
set rel_path "${rel_path}/$comps"
|
|
}
|
|
incr rel_index
|
|
}
|
|
|
|
# prepend parent dirs, this is the complete resolved path now
|
|
set resolved_path "${parent_dir_path}${rel_path}"
|
|
|
|
return $resolved_path
|
|
}
|
|
|
|
# no common dirs found, just return the normalized path
|
|
return $file_path
|
|
}
|
|
|
|
proc is_ip_fileset { fileset } {
|
|
# Summary: Find IP's if any from the specified fileset and return true if 'generate_synth_checkpoint' is set to 1
|
|
# Argument Usage:
|
|
# fileset: fileset name
|
|
# Return Value:
|
|
# true (1) if success, false (0) otherwise
|
|
|
|
# make sure fileset is block fileset type
|
|
if { {BlockSrcs} != [get_property fileset_type [get_filesets $fileset]] } {
|
|
return false
|
|
}
|
|
|
|
set ip_filter "FILE_TYPE == \"IP\" || FILE_TYPE==\"Block Designs\""
|
|
set ips [get_files -all -quiet -of_objects [get_filesets $fileset] -filter $ip_filter]
|
|
set b_found false
|
|
foreach ip $ips {
|
|
if { [get_property generate_synth_checkpoint [lindex [get_files -all $ip] 0]] } {
|
|
set b_found true
|
|
break
|
|
}
|
|
}
|
|
|
|
if { $b_found } {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
proc is_proxy_ip_fileset { fileset } {
|
|
# Summary: Determine if the fileset is an OOC run for a proxy IP that has a parent composite
|
|
# Argument Usage:
|
|
# fileset: fileset name
|
|
# Return Value:
|
|
# true (1) if the fileset contains an IP at its root with a parent composite, false (0) otherwise
|
|
|
|
# make sure fileset is block fileset type
|
|
if { {BlockSrcs} != [get_property fileset_type [get_filesets $fileset]] } {
|
|
return false
|
|
}
|
|
|
|
set ip_with_parent_filter "FILE_TYPE == IP && PARENT_COMPOSITE_FILE != \"\""
|
|
if {[llength [get_files -norecurse -quiet -of_objects [get_filesets $fileset] -filter $ip_with_parent_filter]] == 1} {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
|
|
proc is_ip_run { run } {
|
|
# Summary: Find IP's if any from the fileset linked with the block fileset run
|
|
# Argument Usage:
|
|
# run: run name
|
|
# Return Value:
|
|
# true (1) if success, false (0) otherwise
|
|
|
|
set fileset [get_property srcset [get_runs $run]]
|
|
return [is_ip_fileset $fileset]
|
|
}
|
|
}
|